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.Color; 21 import com.badlogic.gdx.graphics.GL20; 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.graphics.glutils.ShapeRenderer; 28 import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; 29 import com.badlogic.gdx.math.MathUtils; 30 import com.badlogic.gdx.math.Vector2; 31 import com.badlogic.gdx.scenes.scene2d.Actor; 32 import com.badlogic.gdx.scenes.scene2d.Group; 33 import com.badlogic.gdx.scenes.scene2d.InputEvent; 34 import com.badlogic.gdx.scenes.scene2d.InputListener; 35 import com.badlogic.gdx.scenes.scene2d.Stage; 36 import com.badlogic.gdx.tests.utils.GdxTest; 37 38 /** This tests both {@link Actor#parentToLocalCoordinates(Vector2)} and {@link Actor#localToParentCoordinates(Vector2)}. */ 39 public class GroupTest extends GdxTest { 40 Stage stage; 41 SpriteBatch batch; 42 BitmapFont font; 43 ShapeRenderer renderer; 44 TextureRegion region; 45 TestGroup group1; 46 TestGroup group2; 47 create()48 public void create () { 49 batch = new SpriteBatch(); 50 font = new BitmapFont(); 51 renderer = new ShapeRenderer(); 52 53 stage = new Stage(); 54 Gdx.input.setInputProcessor(stage); 55 56 region = new TextureRegion(new Texture(Gdx.files.internal("data/group-debug.png"))); 57 58 group2 = new TestGroup("group2"); 59 group2.setTransform(true); 60 stage.addActor(group2); 61 62 group1 = new TestGroup("group1"); 63 group1.setTransform(true); 64 group2.addActor(group1); 65 } 66 render()67 public void render () { 68 // Vary the transforms to exercise the different code paths. 69 group2.setBounds(150, 150, 150, 150); 70 group2.setRotation(45); 71 group2.setOrigin(150, 150); 72 group2.setScale(1.25f); 73 74 group1.setBounds(150, 150, 50, 50); 75 group1.setRotation(45); 76 group1.setOrigin(25, 25); 77 group1.setScale(1.3f); 78 79 Gdx.gl.glClearColor(0, 0, 0, 1); 80 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 81 stage.draw(); 82 83 renderer.setProjectionMatrix(batch.getProjectionMatrix()); 84 renderer.begin(ShapeType.Filled); 85 if (MathUtils.randomBoolean()) { // So we see when they are drawn on top of each other (which should be always). 86 renderer.setColor(Color.GREEN); 87 renderer.circle(group1.toScreenCoordinates.x, Gdx.graphics.getHeight() - group1.toScreenCoordinates.y, 5); 88 renderer.setColor(Color.RED); 89 renderer.circle(group1.localToParentCoordinates.x, Gdx.graphics.getHeight() - group1.localToParentCoordinates.y, 5); 90 } else { 91 renderer.setColor(Color.RED); 92 renderer.circle(group1.localToParentCoordinates.x, Gdx.graphics.getHeight() - group1.localToParentCoordinates.y, 5); 93 renderer.setColor(Color.GREEN); 94 renderer.circle(group1.toScreenCoordinates.x, Gdx.graphics.getHeight() - group1.toScreenCoordinates.y, 5); 95 } 96 renderer.end(); 97 } 98 resize(int width, int height)99 public void resize (int width, int height) { 100 stage.getViewport().update(width, height, true); 101 } 102 needsGL20()103 public boolean needsGL20 () { 104 return false; 105 } 106 107 class TestGroup extends Group { 108 private String name; 109 Vector2 toScreenCoordinates = new Vector2(); 110 Vector2 localToParentCoordinates = new Vector2(); 111 float testX = 25; 112 float testY = 25; 113 TestGroup(String name)114 public TestGroup (String name) { 115 this.name = name; 116 117 addListener(new InputListener() { 118 public boolean mouseMoved (InputEvent event, float x, float y) { 119 // These come from Actor#parentToLocalCoordinates. 120 testX = x; 121 testY = y; 122 return true; 123 } 124 }); 125 } 126 draw(Batch batch, float parentAlpha)127 public void draw (Batch batch, float parentAlpha) { 128 // Use Stage#toScreenCoordinates, which we know is correct. 129 toScreenCoordinates.set(testX, testY).sub(getOriginX(), getOriginY()).scl(getScaleX(), getScaleY()) 130 .rotate(getRotation()).add(getOriginX(), getOriginY()).add(getX(), getY()); 131 getStage().toScreenCoordinates(toScreenCoordinates, batch.getTransformMatrix()); 132 133 // Do the same as toScreenCoordinates via Actor#localToParentCoordinates. 134 localToAscendantCoordinates(null, localToParentCoordinates.set(testX, testY)); 135 getStage().stageToScreenCoordinates(localToParentCoordinates); 136 137 // System.out.println(name + " " + toScreenCoordinates + " " + localToParentCoordinates); 138 139 batch.setColor(getColor()); 140 batch.draw(region, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(), getScaleX(), getScaleY(), 141 getRotation()); 142 super.draw(batch, parentAlpha); 143 } 144 } 145 } 146