package org.andengine.entity.clip; import org.andengine.engine.camera.Camera; import org.andengine.entity.Entity; import org.andengine.opengl.util.GLState; import org.andengine.util.Constants; import org.andengine.util.math.MathUtils; /** * A {@link ClipEntity} clips drawing of all its children in a rectangle, which is defined as the axis aligned bounding box around itself. * It can be attached anywhere in the scene graph, which means that it inherits transformations from its parents, which have a direct effect on the clipping area. * * (c) 2012 Zynga Inc. * * @author Nicolas Gramlich <ngramlich@zynga.com> * @since 13:53:29 - 10.05.2012 */ public class ClipEntity extends Entity { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== private boolean mClippingEnabled = true; // =========================================================== // Constructors // =========================================================== public ClipEntity() { super(); } public ClipEntity(final float pX, final float pY) { super(pX, pY); } public ClipEntity(final float pX, final float pY, final float pWidth, final float pHeight) { super(pX, pY, pWidth, pHeight); } // =========================================================== // Getter & Setter // =========================================================== public boolean isClippingEnabled() { return this.mClippingEnabled; } public void setClippingEnabled(final boolean pClippingEnabled) { this.mClippingEnabled = pClippingEnabled; } // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== @Override protected void onManagedDraw(final GLState pGLState, final Camera pCamera) { if (this.mClippingEnabled) { /* Enable scissor test, while remembering previous state. */ final boolean wasScissorTestEnabled = pGLState.enableScissorTest(); final int surfaceHeight = pCamera.getSurfaceHeight(); /* In order to apply clipping, we need to determine the the axis aligned bounds in OpenGL coordinates. */ /* Determine clipping coordinates of each corner in surface coordinates. */ final float[] lowerLeftSurfaceCoordinates = pCamera.getSurfaceCoordinatesFromSceneCoordinates(this.convertLocalCoordinatesToSceneCoordinates(0, 0)); final int lowerLeftX = (int) Math.round(lowerLeftSurfaceCoordinates[Constants.VERTEX_INDEX_X]); final int lowerLeftY = surfaceHeight - (int) Math.round(lowerLeftSurfaceCoordinates[Constants.VERTEX_INDEX_Y]); final float[] upperLeftSurfaceCoordinates = pCamera.getSurfaceCoordinatesFromSceneCoordinates(this.convertLocalCoordinatesToSceneCoordinates(0, this.mHeight)); final int upperLeftX = (int) Math.round(upperLeftSurfaceCoordinates[Constants.VERTEX_INDEX_X]); final int upperLeftY = surfaceHeight - (int) Math.round(upperLeftSurfaceCoordinates[Constants.VERTEX_INDEX_Y]); final float[] upperRightSurfaceCoordinates = pCamera.getSurfaceCoordinatesFromSceneCoordinates(this.convertLocalCoordinatesToSceneCoordinates(this.mWidth, this.mHeight)); final int upperRightX = (int) Math.round(upperRightSurfaceCoordinates[Constants.VERTEX_INDEX_X]); final int upperRightY = surfaceHeight - (int) Math.round(upperRightSurfaceCoordinates[Constants.VERTEX_INDEX_Y]); final float[] lowerRightSurfaceCoordinates = pCamera.getSurfaceCoordinatesFromSceneCoordinates(this.convertLocalCoordinatesToSceneCoordinates(this.mWidth, 0)); final int lowerRightX = (int) Math.round(lowerRightSurfaceCoordinates[Constants.VERTEX_INDEX_X]); final int lowerRightY = surfaceHeight - (int) Math.round(lowerRightSurfaceCoordinates[Constants.VERTEX_INDEX_Y]); /* Determine minimum and maximum x clipping coordinates. */ final int minClippingX = MathUtils.min(lowerLeftX, upperLeftX, upperRightX, lowerRightX); final int maxClippingX = MathUtils.max(lowerLeftX, upperLeftX, upperRightX, lowerRightX); /* Determine minimum and maximum y clipping coordinates. */ final int minClippingY = MathUtils.min(lowerLeftY, upperLeftY, upperRightY, lowerRightY); final int maxClippingY = MathUtils.max(lowerLeftY, upperLeftY, upperRightY, lowerRightY); /* Determine clipping width and height. */ final int clippingWidth = maxClippingX - minClippingX; final int clippingHeight = maxClippingY - minClippingY; /* Finally apply the clipping. */ pGLState.glPushScissor(minClippingX, minClippingY, clippingWidth, clippingHeight); /* Draw children, etc... */ super.onManagedDraw(pGLState, pCamera); /* Revert scissor test to previous state. */ pGLState.glPopScissor(); pGLState.setScissorTestEnabled(wasScissorTestEnabled); } else { super.onManagedDraw(pGLState, pCamera); } } // =========================================================== // Methods // =========================================================== // =========================================================== // Inner and Anonymous Classes // =========================================================== }