/src/org/mt4j/components/visibleComponents/shapes/MTRectangle.java

http://mt4j.googlecode.com/ · Java · 534 lines · 295 code · 63 blank · 176 comment · 31 complexity · b7f690f3a501d3721115472c0655fb01 MD5 · raw file

  1. /***********************************************************************
  2. * mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. ***********************************************************************/
  18. package org.mt4j.components.visibleComponents.shapes;
  19. import org.mt4j.MTApplication;
  20. import org.mt4j.components.TransformSpace;
  21. import org.mt4j.components.bounds.BoundsZPlaneRectangle;
  22. import org.mt4j.components.bounds.IBoundingShape;
  23. import org.mt4j.components.css.style.CSSStyle;
  24. import org.mt4j.util.MT4jSettings;
  25. import org.mt4j.util.math.Vector3D;
  26. import org.mt4j.util.math.Vertex;
  27. import processing.core.PApplet;
  28. import processing.core.PImage;
  29. /**
  30. * A simple rectangular shape.
  31. *
  32. * @author Christopher Ruff
  33. */
  34. public class MTRectangle extends MTPolygon {
  35. /** The current anchor. */
  36. private PositionAnchor currentAnchor;
  37. /**
  38. * The Enum PositionAnchor.
  39. *
  40. * @author Christopher Ruff
  41. */
  42. public enum PositionAnchor{
  43. /** The LOWE r_ left. */
  44. LOWER_LEFT,
  45. /** The LOWE r_ right. */
  46. LOWER_RIGHT,
  47. /** The UPPE r_ left. */
  48. UPPER_LEFT,
  49. /** The CENTER. */
  50. CENTER
  51. }
  52. /**
  53. * Instantiates a new mT rectangle.
  54. *
  55. * @param texture the texture
  56. * @param applet the applet
  57. * @deprecated constructor will be deleted! Please , use the constructor with the PApplet instance as the first parameter.
  58. */
  59. public MTRectangle(PImage texture, PApplet applet) {
  60. this(applet, texture);
  61. }
  62. /**
  63. * Instantiates a new mT rectangle.
  64. * @param applet the applet
  65. * @param texture the texture
  66. */
  67. public MTRectangle(PApplet applet, PImage texture) {
  68. this(applet ,0 ,0, 0, texture.width, texture.height);
  69. //To avoid errors if this is created in non opengl thread so the gl texture wont be created correctly when setting setTexture
  70. this.setUseDirectGL(false);
  71. if (applet instanceof MTApplication) {
  72. MTApplication app = (MTApplication) applet;
  73. if (MT4jSettings.getInstance().isOpenGlMode()){
  74. if (app.isRenderThreadCurrent()){
  75. this.setUseDirectGL(true);
  76. }else{
  77. //IF we are useing OpenGL, set useDirectGL to true
  78. //(=>creates OpenGL texture, draws with pure OpenGL commands)
  79. //in our main thread.
  80. app.invokeLater(new Runnable() {
  81. public void run() {
  82. setUseDirectGL(true);
  83. }
  84. });
  85. }
  86. }else{
  87. if (this.isUseDirectGL()){
  88. this.setUseDirectGL(false);
  89. }
  90. }
  91. }else{
  92. //Cant check if we are in renderthread -> dont use direct gl mode -> dont create Gl texture object
  93. if (this.isUseDirectGL()){
  94. this.setUseDirectGL(false);
  95. }
  96. }
  97. this.setTexture(texture);
  98. this.setTextureEnabled(true);
  99. }
  100. /**
  101. * Instantiates a new mT rectangle.
  102. *
  103. * @param width the width
  104. * @param height the height
  105. * @param pApplet the applet
  106. * @deprecated constructor will be deleted! Please , use the constructor with the PApplet instance as the first parameter.
  107. */
  108. public MTRectangle(float width, float height, PApplet pApplet) {
  109. this(pApplet, width, height);
  110. }
  111. /**
  112. * Instantiates a new mT rectangle with the upper left corner at 0,0,0
  113. * @param pApplet the applet
  114. * @param width the width
  115. * @param height the height
  116. */
  117. public MTRectangle(PApplet pApplet, float width, float height) {
  118. this(pApplet,new Vertex(0,0,0,0,0),width,height);
  119. }
  120. /**
  121. * Instantiates a new mT rectangle.
  122. *
  123. * @param x the x
  124. * @param y the y
  125. * @param width the width
  126. * @param height the height
  127. * @param pApplet the applet
  128. * @deprecated constructor will be deleted! Please , use the constructor with the PApplet instance as the first parameter.
  129. */
  130. public MTRectangle(float x, float y, float width, float height, PApplet pApplet) {
  131. this(pApplet, x, y, width, height);
  132. }
  133. /**
  134. * Instantiates a new mT rectangle.
  135. * @param pApplet the applet
  136. * @param x the x
  137. * @param y the y
  138. * @param width the width
  139. * @param height the height
  140. */
  141. public MTRectangle(PApplet pApplet, float x, float y, float width, float height) {
  142. this(pApplet,new Vertex(x,y,0,0,0),width,height);
  143. }
  144. /**
  145. * Instantiates a new mT rectangle.
  146. *
  147. * @param x the x
  148. * @param y the y
  149. * @param z the z
  150. * @param width the width
  151. * @param height the height
  152. * @param pApplet the applet
  153. * @deprecated constructor will be deleted! Please , use the constructor with the PApplet instance as the first parameter.
  154. */
  155. public MTRectangle(float x, float y, float z, float width, float height, PApplet pApplet) {
  156. this(pApplet, x, y, z, width, height);
  157. }
  158. /**
  159. * Instantiates a new mT rectangle.
  160. * @param pApplet the applet
  161. * @param x the x
  162. * @param y the y
  163. * @param z the z
  164. * @param width the width
  165. * @param height the height
  166. */
  167. public MTRectangle(PApplet pApplet, float x, float y, float z, float width, float height) {
  168. this(pApplet,new Vertex(x,y,z,0,0),width,height);
  169. }
  170. /**
  171. * Instantiates a new mT rectangle.
  172. *
  173. * @param upperLeft the upper left
  174. * @param width the width
  175. * @param height the height
  176. * @param pApplet the applet
  177. * @deprecated constructor will be deleted! Please , use the constructor with the PApplet instance as the first parameter.
  178. */
  179. public MTRectangle(Vertex upperLeft, float width, float height, PApplet pApplet) {
  180. this(pApplet, upperLeft, width, height);
  181. }
  182. /**
  183. * Instantiates a new mT rectangle.
  184. * @param pApplet the applet
  185. * @param upperLeft the upper left
  186. * @param width the width
  187. * @param height the height
  188. */
  189. public MTRectangle(PApplet pApplet, Vertex upperLeft, float width, float height) {
  190. super(pApplet,
  191. new Vertex[]{
  192. new Vertex(upperLeft.x, upperLeft.y, upperLeft.z, 0, 0),
  193. new Vertex(upperLeft.x+width, upperLeft.y, upperLeft.z, 1, 0),
  194. new Vertex(upperLeft.x+width, upperLeft.y+height, upperLeft.z, 1, 1),
  195. new Vertex(upperLeft.x, upperLeft.y+height, upperLeft.z, 0, 1),
  196. new Vertex(upperLeft.x, upperLeft.y, upperLeft.z, 0, 0)});
  197. this.setName("unnamed rectangle");
  198. //
  199. this.setBoundsBehaviour(AbstractShape.BOUNDS_ONLY_CHECK);
  200. currentAnchor = PositionAnchor.CENTER;
  201. }
  202. /* (non-Javadoc)
  203. * @see org.mt4j.components.visibleComponents.shapes.MTPolygon#computeDefaultBounds()
  204. */
  205. @Override
  206. protected IBoundingShape computeDefaultBounds(){
  207. return new BoundsZPlaneRectangle(this);
  208. }
  209. /**
  210. * Gets the Position anchor.
  211. *
  212. * @return the anchor
  213. */
  214. public PositionAnchor getAnchor(){
  215. return this.currentAnchor;
  216. }
  217. /**
  218. * Sets the anchor. The Anchor determines which reference point
  219. * is used at set/getPosition(). The default anchor point is the rectangle's
  220. * center.
  221. *
  222. * @param anchor the new anchor
  223. */
  224. public void setAnchor(PositionAnchor anchor){
  225. this.currentAnchor = anchor;
  226. }
  227. /* (non-Javadoc)
  228. * @see org.mt4j.components.visibleComponents.shapes.AbstractShape#setPositionGlobal(org.mt4j.util.math.Vector3D)
  229. */
  230. @Override
  231. public void setPositionGlobal(Vector3D position) {
  232. switch (this.getAnchor()) {
  233. case CENTER:
  234. super.setPositionGlobal(position);
  235. break;
  236. case LOWER_LEFT:{
  237. Vertex[] vertices = this.getVerticesGlobal();
  238. Vertex lowerLeft = new Vertex(vertices[3]);
  239. this.translateGlobal(position.getSubtracted(lowerLeft));
  240. }break;
  241. case LOWER_RIGHT:{
  242. Vertex[] vertices = this.getVerticesGlobal();
  243. Vertex v = new Vertex(vertices[2]);
  244. this.translateGlobal(position.getSubtracted(v));
  245. }break;
  246. case UPPER_LEFT:{
  247. Vertex[] vertices = this.getVerticesGlobal();
  248. Vertex upperLeft = new Vertex(vertices[0]);
  249. this.translateGlobal(position.getSubtracted(upperLeft));
  250. }break;
  251. default:
  252. break;
  253. }
  254. }
  255. /* (non-Javadoc)
  256. * @see org.mt4j.components.visibleComponents.shapes.AbstractShape#setPositionRelativeToParent(org.mt4j.util.math.Vector3D)
  257. */
  258. @Override
  259. public void setPositionRelativeToParent(Vector3D position) {
  260. switch (this.getAnchor()) {
  261. case CENTER:
  262. super.setPositionRelativeToParent(position);
  263. break;
  264. case LOWER_LEFT:{
  265. Vertex[] vertices = this.getVerticesLocal();
  266. Vertex lowerLeft = new Vertex(vertices[3]);
  267. lowerLeft.transform(this.getLocalMatrix());
  268. this.translate(position.getSubtracted(lowerLeft), TransformSpace.RELATIVE_TO_PARENT);
  269. }break;
  270. case LOWER_RIGHT:{
  271. Vertex[] vertices = this.getVerticesLocal();
  272. Vertex v = new Vertex(vertices[2]);
  273. v.transform(this.getLocalMatrix());
  274. this.translate(position.getSubtracted(v), TransformSpace.RELATIVE_TO_PARENT);
  275. }break;
  276. case UPPER_LEFT:{
  277. Vertex[] vertices = this.getVerticesLocal();
  278. Vertex v = new Vertex(vertices[0]);
  279. v.transform(this.getLocalMatrix());
  280. this.translate(position.getSubtracted(v), TransformSpace.RELATIVE_TO_PARENT);
  281. }break;
  282. default:
  283. break;
  284. }
  285. }
  286. /**
  287. * Gets the position. The position is dependant on the
  288. * set PositionAnchor. The default is the PositionAnchor.CENTER.
  289. *
  290. * @param transformSpace the transform space
  291. * @return the position
  292. */
  293. public Vector3D getPosition(TransformSpace transformSpace){
  294. Vector3D v;
  295. switch (transformSpace) {
  296. case LOCAL:
  297. switch (this.getAnchor()) {
  298. case CENTER:
  299. return this.getCenterPointLocal();
  300. case LOWER_LEFT:
  301. return new Vector3D(this.getVerticesLocal()[3]);
  302. case LOWER_RIGHT:
  303. return new Vector3D(this.getVerticesLocal()[2]);
  304. case UPPER_LEFT:
  305. return new Vector3D(this.getVerticesLocal()[0]);
  306. default:
  307. break;
  308. }
  309. break;
  310. case RELATIVE_TO_PARENT:
  311. switch (this.getAnchor()) {
  312. case CENTER:
  313. return this.getCenterPointRelativeToParent();
  314. case LOWER_LEFT:
  315. v = new Vector3D(this.getVerticesLocal()[3]);
  316. v.transform(this.getLocalMatrix());
  317. return v;
  318. case LOWER_RIGHT:
  319. v = new Vector3D(this.getVerticesLocal()[2]);
  320. v.transform(this.getLocalMatrix());
  321. return v;
  322. case UPPER_LEFT:
  323. v = new Vector3D(this.getVerticesLocal()[0]);
  324. v.transform(this.getLocalMatrix());
  325. return v;
  326. default:
  327. break;
  328. }
  329. break;
  330. case GLOBAL:
  331. switch (this.getAnchor()) {
  332. case CENTER:
  333. return this.getCenterPointGlobal();
  334. case LOWER_LEFT:
  335. v = new Vector3D(this.getVerticesLocal()[3]);
  336. v.transform(this.getGlobalMatrix());
  337. return v;
  338. case LOWER_RIGHT:
  339. v = new Vector3D(this.getVerticesLocal()[2]);
  340. v.transform(this.getGlobalMatrix());
  341. return v;
  342. case UPPER_LEFT:
  343. v = new Vector3D(this.getVerticesLocal()[0]);
  344. v.transform(this.getGlobalMatrix());
  345. return v;
  346. default:
  347. break;
  348. }
  349. break;
  350. default:
  351. break;
  352. }
  353. return null;
  354. }
  355. /* (non-Javadoc)
  356. * @see org.mt4j.components.visibleComponents.shapes.MTPolygon#get2DPolygonArea()
  357. */
  358. @Override
  359. public double get2DPolygonArea() {
  360. return (getHeightXY(TransformSpace.RELATIVE_TO_PARENT)*getWidthXY(TransformSpace.RELATIVE_TO_PARENT));
  361. }
  362. /* (non-Javadoc)
  363. * @see org.mt4j.components.visibleComponents.shapes.MTPolygon#getCenterOfMass2DLocal()
  364. */
  365. @Override
  366. public Vector3D getCenterOfMass2DLocal() {
  367. Vertex[] v = this.getVerticesLocal();
  368. return new Vector3D(
  369. v[0].getX() + ((v[1].getX() - v[0].getX())/2),
  370. v[1].getY() + ((v[2].getY() - v[1].getY())/2),
  371. v[0].getZ());
  372. }
  373. /* (non-Javadoc)
  374. * @see org.mt4j.components.visibleComponents.shapes.MTPolygon#getCenterPointLocal()
  375. */
  376. @Override
  377. public Vector3D getCenterPointLocal(){
  378. return this.getCenterOfMass2DLocal();
  379. }
  380. /**
  381. * Sets the size locally, meaning that not the transformation of the rectangle is changed, (as setSize/setWidth, scale etc. would do) but the vertices
  382. * of the rectangle themselves. This is useful if we dont want the rectangles children to be scaled as well, for example.
  383. * <br>Note: The scaling is done from the rectangles upper left corner - not the center!
  384. *
  385. * @param width the width
  386. * @param height the height
  387. */
  388. public void setSizeLocal(float width, float height){
  389. if (width > 0 && height > 0){
  390. Vertex[] v = this.getVerticesLocal();
  391. this.setVertices(new Vertex[]{
  392. new Vertex(v[0].x, v[0].y, v[0].z, v[0].getTexCoordU(), v[0].getTexCoordV(), v[0].getR(), v[0].getG(), v[0].getB(), v[0].getA()),
  393. new Vertex(v[0].x+width, v[1].y, v[1].z, v[1].getTexCoordU(), v[1].getTexCoordV(), v[1].getR(), v[1].getG(), v[1].getB(), v[1].getA()),
  394. new Vertex(v[0].x+width, v[1].y+height, v[2].z, v[2].getTexCoordU(), v[2].getTexCoordV(), v[2].getR(), v[2].getG(), v[2].getB(), v[2].getA()),
  395. new Vertex(v[3].x, v[0].y+height, v[3].z, v[3].getTexCoordU(), v[3].getTexCoordV(), v[3].getR(), v[3].getG(), v[3].getB(), v[3].getA()),
  396. new Vertex(v[4].x, v[4].y, v[4].z, v[4].getTexCoordU(), v[4].getTexCoordV(), v[4].getR(), v[4].getG(), v[4].getB(), v[4].getA()),
  397. });
  398. }
  399. }
  400. /**
  401. * Sets the height locally, meaning that not the transformation of the rectangle is changed, (as setSize/setWidth, scale etc. would do) but the vertices
  402. * of the rectangle themselves. This is useful if we dont want the rectangles children to be scaled as well, for example.
  403. * <br>Note: The scaling is done from the rectangles upper left corner - not the center!
  404. *
  405. * @param height the new height local
  406. */
  407. public void setHeightLocal(float height){
  408. Vertex[] v = this.getVerticesLocal();
  409. this.setVertices(new Vertex[]{
  410. new Vertex(v[0].x, v[0].y, v[0].z, v[0].getTexCoordU(), v[0].getTexCoordV(), v[0].getR(), v[0].getG(), v[0].getB(), v[0].getA()),
  411. new Vertex(v[1].x, v[1].y, v[1].z, v[1].getTexCoordU(), v[1].getTexCoordV(), v[1].getR(), v[1].getG(), v[1].getB(), v[1].getA()),
  412. new Vertex(v[2].x, v[1].y+height, v[2].z, v[2].getTexCoordU(), v[2].getTexCoordV(), v[2].getR(), v[2].getG(), v[2].getB(), v[2].getA()),
  413. new Vertex(v[3].x, v[1].y+height, v[3].z, v[3].getTexCoordU(), v[3].getTexCoordV(), v[3].getR(), v[3].getG(), v[3].getB(), v[3].getA()),
  414. new Vertex(v[4].x, v[4].y, v[4].z, v[4].getTexCoordU(), v[4].getTexCoordV(), v[4].getR(), v[4].getG(), v[4].getB(), v[4].getA()),
  415. });
  416. }
  417. /**
  418. * Sets the width locally, meaning that not the transformation of the rectangle is changed, (as setSize/setWidth, scale etc. would do) but the vertices
  419. * of the rectangle themselves. This is useful if we dont want the rectangles children to be scaled as well, for example.
  420. * <br>Note: The scaling is done from the rectangles upper left corner - not the center!
  421. * @param width the new width local
  422. */
  423. public void setWidthLocal(float width){
  424. if (width > 0){
  425. Vertex[] v = this.getVerticesLocal();
  426. this.setVertices(new Vertex[]{
  427. new Vertex(v[0].x, v[0].y, v[0].z, v[0].getTexCoordU(), v[0].getTexCoordV(), v[0].getR(), v[0].getG(), v[0].getB(), v[0].getA()),
  428. new Vertex(v[0].x+width, v[1].y, v[1].z, v[1].getTexCoordU(), v[1].getTexCoordV(), v[1].getR(), v[1].getG(), v[1].getB(), v[1].getA()),
  429. new Vertex(v[0].x+width, v[2].y, v[2].z, v[2].getTexCoordU(), v[2].getTexCoordV(), v[2].getR(), v[2].getG(), v[2].getB(), v[2].getA()),
  430. new Vertex(v[3].x, v[3].y, v[3].z, v[3].getTexCoordU(), v[3].getTexCoordV(), v[3].getR(), v[3].getG(), v[3].getB(), v[3].getA()),
  431. new Vertex(v[4].x, v[4].y, v[4].z, v[4].getTexCoordU(), v[4].getTexCoordV(), v[4].getR(), v[4].getG(), v[4].getB(), v[4].getA()),
  432. });
  433. }
  434. }
  435. @Override
  436. protected void applyStyleSheetCustom(CSSStyle virtualStyleSheet) {
  437. super.applyStyleSheetCustom(virtualStyleSheet);
  438. if (virtualStyleSheet.isWidthPercentage()
  439. && virtualStyleSheet.isHeightPercentage()) {
  440. if (this.getParent() != null) {
  441. if (virtualStyleSheet.getWidth() > 0)
  442. this.setWidthLocal(virtualStyleSheet.getWidth() / 100f
  443. * this.getParent().getBounds()
  444. .getWidthXY(TransformSpace.RELATIVE_TO_PARENT));
  445. if (virtualStyleSheet.getHeight() > 0)
  446. this.setHeightLocal(virtualStyleSheet.getHeight()/ 100f
  447. * this.getParent().getBounds()
  448. .getHeightXY(TransformSpace.RELATIVE_TO_PARENT));
  449. }
  450. } else if (virtualStyleSheet.isWidthPercentage()) {
  451. if (virtualStyleSheet.getWidth() > 0)
  452. this.setWidthLocal(virtualStyleSheet.getWidth() / 100f
  453. * this.getParent().getBounds()
  454. .getWidthXY(TransformSpace.RELATIVE_TO_PARENT));
  455. if (virtualStyleSheet.getHeight() > 0)
  456. this.setHeightLocal(virtualStyleSheet.getHeight());
  457. } else if (virtualStyleSheet.isHeightPercentage()) {
  458. if (virtualStyleSheet.getWidth() > 0)
  459. this.setWidthLocal(virtualStyleSheet.getWidth());
  460. if (virtualStyleSheet.getHeight() > 0)
  461. this.setHeightLocal(virtualStyleSheet.getHeight() / 100f
  462. * this.getParent().getBounds()
  463. .getHeightXY(TransformSpace.RELATIVE_TO_PARENT));
  464. } else {
  465. if (virtualStyleSheet.getWidth() > 0)
  466. this.setWidthLocal(virtualStyleSheet.getWidth());
  467. if (virtualStyleSheet.getHeight() > 0)
  468. this.setHeightLocal(virtualStyleSheet.getHeight());
  469. }
  470. }
  471. }