1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.tests; 18 19 import com.badlogic.gdx.Gdx; 20 import com.badlogic.gdx.graphics.GL20; 21 import com.badlogic.gdx.graphics.OrthographicCamera; 22 import com.badlogic.gdx.graphics.Texture; 23 import com.badlogic.gdx.graphics.g2d.Batch; 24 import com.badlogic.gdx.graphics.g2d.BitmapFont; 25 import com.badlogic.gdx.graphics.g2d.SpriteBatch; 26 import com.badlogic.gdx.graphics.g2d.TextureRegion; 27 import com.badlogic.gdx.math.Rectangle; 28 import com.badlogic.gdx.scenes.scene2d.Actor; 29 import com.badlogic.gdx.scenes.scene2d.Stage; 30 import com.badlogic.gdx.scenes.scene2d.ui.Image; 31 import com.badlogic.gdx.scenes.scene2d.utils.Cullable; 32 import com.badlogic.gdx.tests.utils.GdxTest; 33 import com.badlogic.gdx.tests.utils.OrthoCamController; 34 import com.badlogic.gdx.utils.Align; 35 import com.badlogic.gdx.utils.Array; 36 import com.badlogic.gdx.utils.Scaling; 37 38 /** This is a simple demonstration of how to perform VERY basic culling on hierarchies of stage actors that do not scale or rotate. 39 * It is not a general solution as it assumes that actors and groups are only translated (moved, change their x/y coordinates). 40 * NOTE: This has been obsoleted by {@link Cullable}. 41 * 42 * @author mzechner */ 43 public class SimpleStageCullingTest extends GdxTest { 44 45 /** We need to extend a base actor class so we can add the culling in the render method. We also add a method to get the stage 46 * coordinates of the actor so we can cull it against the camera's view volume. 47 * 48 * @author mzechner */ 49 private class CullableActor extends Image { 50 /** the camera to test against **/ 51 final OrthographicCamera camera; 52 /** whether we are visible or not, used for counting visible actors **/ 53 boolean visible = false; 54 CullableActor(String name, Texture texture, OrthographicCamera camera)55 public CullableActor (String name, Texture texture, OrthographicCamera camera) { 56 super(new TextureRegion(texture)); 57 setAlign(Align.center); 58 setScaling(Scaling.none); 59 this.camera = camera; 60 } 61 draw(Batch batch, float parentAlpha)62 public void draw (Batch batch, float parentAlpha) { 63 // if this actor is not within the view of the camera we don't draw it. 64 if (isCulled()) return; 65 66 // otherwise we draw via the super class method 67 super.draw(batch, parentAlpha); 68 } 69 70 /** static helper Rectangles **/ 71 Rectangle actorRect = new Rectangle(); 72 Rectangle camRect = new Rectangle(); 73 isCulled()74 private boolean isCulled () { 75 // we start by setting the stage coordinates to this 76 // actors coordinates which are relative to its parent 77 // Group. 78 float stageX = getX(); 79 float stageY = getY(); 80 81 // now we go up the hierarchy and add all the parents' 82 // coordinates to this actors coordinates. Note that 83 // this assumes that neither this actor nor any of its 84 // parents are rotated or scaled! 85 Actor parent = this.getParent(); 86 while (parent != null) { 87 stageX += parent.getX(); 88 stageY += parent.getY(); 89 parent = parent.getParent(); 90 } 91 92 // now we check if the rectangle of this actor in screen 93 // coordinates is in the rectangle spanned by the camera's 94 // view. This assumes that the camera has no zoom and is 95 // not rotated! 96 actorRect.set(stageX, stageY, getWidth(), getHeight()); 97 camRect.set(camera.position.x - camera.viewportWidth / 2.0f, camera.position.y - camera.viewportHeight / 2.0f, 98 camera.viewportWidth, camera.viewportHeight); 99 visible = camRect.overlaps(actorRect); 100 return !visible; 101 } 102 } 103 104 OrthoCamController camController; 105 Stage stage; 106 Texture texture; 107 SpriteBatch batch; 108 BitmapFont font; 109 110 @Override create()111 public void create () { 112 // create a stage and a camera controller so we can pan the view. 113 stage = new Stage();; 114 camController = new OrthoCamController((OrthographicCamera)stage.getCamera()); // we know it's an ortho cam at this point! 115 Gdx.input.setInputProcessor(camController); 116 117 // load a dummy texture 118 texture = new Texture(Gdx.files.internal("data/badlogicsmall.jpg")); 119 120 // populate the stage with some actors and groups. 121 for (int i = 0; i < 5000; i++) { 122 Actor img = new CullableActor("img" + i, texture, (OrthographicCamera)stage.getCamera()); 123 img.setX((float)Math.random() * 480 * 10); 124 img.setY((float)Math.random() * 320 * 10); 125 stage.addActor(img); 126 } 127 128 // we also want to output the number of visible actors, so we need a SpriteBatch and a BitmapFont 129 batch = new SpriteBatch(); 130 font = new BitmapFont(Gdx.files.internal("data/arial-15.fnt"), false); 131 } 132 render()133 public void render () { 134 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 135 stage.draw(); 136 137 // check how many actors are visible. 138 Array<Actor> actors = stage.getActors(); 139 int numVisible = 0; 140 for (int i = 0; i < actors.size; i++) { 141 numVisible += ((CullableActor)actors.get(i)).visible ? 1 : 0; 142 } 143 144 batch.begin(); 145 font.draw(batch, "Visible: " + numVisible + ", fps: " + Gdx.graphics.getFramesPerSecond(), 20, 30); 146 batch.end(); 147 } 148 149 @Override dispose()150 public void dispose () { 151 stage.dispose(); 152 texture.dispose(); 153 batch.dispose(); 154 font.dispose(); 155 } 156 } 157