PageRenderTime 81ms CodeModel.GetById 14ms app.highlight 62ms RepoModel.GetById 1ms app.codeStats 0ms

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