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.g3d; 18 19 import com.badlogic.gdx.Gdx; 20 import com.badlogic.gdx.InputMultiplexer; 21 import com.badlogic.gdx.math.MathUtils; 22 import com.badlogic.gdx.math.Matrix4; 23 import com.badlogic.gdx.math.Vector3; 24 import com.badlogic.gdx.scenes.scene2d.Actor; 25 import com.badlogic.gdx.scenes.scene2d.InputEvent; 26 import com.badlogic.gdx.scenes.scene2d.Stage; 27 import com.badlogic.gdx.scenes.scene2d.ui.CheckBox; 28 import com.badlogic.gdx.scenes.scene2d.ui.Label; 29 import com.badlogic.gdx.scenes.scene2d.ui.List; 30 import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; 31 import com.badlogic.gdx.scenes.scene2d.ui.Skin; 32 import com.badlogic.gdx.scenes.scene2d.ui.Window; 33 import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; 34 import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; 35 import com.badlogic.gdx.utils.Scaling; 36 import com.badlogic.gdx.utils.StringBuilder; 37 import com.badlogic.gdx.utils.viewport.ScalingViewport; 38 39 public abstract class BaseG3dHudTest extends BaseG3dTest { 40 public final static int PREF_HUDWIDTH = 640; 41 public final static int PREF_HUDHEIGHT = 480; 42 public final static float rotationSpeed = 0.02f * 360f; // degrees per second 43 public final static float moveSpeed = 0.25f; // cycles per second 44 45 protected Stage hud; 46 protected float hudWidth, hudHeight; 47 protected Skin skin; 48 protected Label fpsLabel; 49 protected CollapsableWindow modelsWindow; 50 protected CheckBox gridCheckBox, rotateCheckBox, moveCheckBox; 51 protected final StringBuilder stringBuilder = new StringBuilder(); 52 protected final Matrix4 transform = new Matrix4(); 53 protected float moveRadius = 2f; 54 55 protected String models[] = new String[] {"car.obj", "cube.obj", "scene.obj", "scene2.obj", "wheel.obj", "g3d/invaders.g3dj", 56 "g3d/head.g3db", "g3d/knight.g3dj", "g3d/knight.g3db", "g3d/monkey.g3db", "g3d/ship.obj", "g3d/shapes/cube_1.0x1.0.g3dj", 57 "g3d/shapes/cube_1.5x1.5.g3dj", "g3d/shapes/sphere.g3dj", "g3d/shapes/teapot.g3dj", "g3d/shapes/torus.g3dj"}; 58 59 @Override create()60 public void create () { 61 super.create(); 62 63 createHUD(); 64 65 Gdx.input.setInputProcessor(new InputMultiplexer(hud, this, inputController)); 66 } 67 createHUD()68 protected void createHUD () { 69 hud = new Stage(new ScalingViewport(Scaling.fit, PREF_HUDWIDTH, PREF_HUDHEIGHT)); 70 hudWidth = hud.getWidth(); 71 hudHeight = hud.getHeight(); 72 skin = new Skin(Gdx.files.internal("data/uiskin.json")); 73 74 final List<String> modelsList = new List(skin); 75 modelsList.setItems(models); 76 modelsList.addListener(new ClickListener() { 77 @Override 78 public void clicked (InputEvent event, float x, float y) { 79 if (!modelsWindow.isCollapsed() && getTapCount() == 2) { 80 onModelClicked(modelsList.getSelected()); 81 modelsWindow.collapse(); 82 } 83 } 84 }); 85 modelsWindow = addListWindow("Models", modelsList, 0, -1); 86 87 fpsLabel = new Label("FPS: 999", skin); 88 hud.addActor(fpsLabel); 89 gridCheckBox = new CheckBox("Show grid", skin); 90 gridCheckBox.setChecked(showAxes); 91 gridCheckBox.addListener(new ChangeListener() { 92 @Override 93 public void changed (ChangeEvent event, Actor actor) { 94 showAxes = gridCheckBox.isChecked(); 95 } 96 }); 97 gridCheckBox.setPosition(hudWidth - gridCheckBox.getWidth(), 0); 98 hud.addActor(gridCheckBox); 99 100 rotateCheckBox = new CheckBox("Rotate", skin); 101 rotateCheckBox.setChecked(true); 102 rotateCheckBox.setPosition(hudWidth - rotateCheckBox.getWidth(), gridCheckBox.getHeight()); 103 hud.addActor(rotateCheckBox); 104 105 moveCheckBox = new CheckBox("Move", skin); 106 moveCheckBox.setChecked(false); 107 moveCheckBox.setPosition(hudWidth - moveCheckBox.getWidth(), rotateCheckBox.getTop()); 108 hud.addActor(moveCheckBox); 109 } 110 addListWindow(String title, List list, float x, float y)111 protected CollapsableWindow addListWindow (String title, List list, float x, float y) { 112 CollapsableWindow window = new CollapsableWindow(title, skin); 113 window.row(); 114 ScrollPane pane = new ScrollPane(list, skin); 115 pane.setFadeScrollBars(false); 116 window.add(pane); 117 window.pack(); 118 window.pack(); 119 if (window.getHeight() > hudHeight) { 120 window.setHeight(hudHeight); 121 } 122 window.setX(x < 0 ? hudWidth - (window.getWidth() - (x + 1)) : x); 123 window.setY(y < 0 ? hudHeight - (window.getHeight() - (y + 1)) : y); 124 window.layout(); 125 window.collapse(); 126 hud.addActor(window); 127 pane.setScrollX(0); 128 pane.setScrollY(0); 129 return window; 130 } 131 132 protected abstract void onModelClicked (final String name); 133 134 protected void getStatus (final StringBuilder stringBuilder) { 135 stringBuilder.append("FPS: ").append(Gdx.graphics.getFramesPerSecond()); 136 if (loading) stringBuilder.append(" loading..."); 137 } 138 139 protected float rotation, movement; 140 141 @Override 142 public void render () { 143 transform.idt(); 144 if (rotateCheckBox.isChecked()) 145 transform.rotate(Vector3.Y, rotation = (rotation + rotationSpeed * Gdx.graphics.getRawDeltaTime()) % 360); 146 if (moveCheckBox.isChecked()) { 147 movement = (movement + moveSpeed * Gdx.graphics.getRawDeltaTime()) % 1f; 148 final float sm = MathUtils.sin(movement * MathUtils.PI2); 149 final float cm = MathUtils.cos(movement * MathUtils.PI2); 150 transform.trn(0, moveRadius * cm, moveRadius * sm); 151 } 152 153 super.render(); 154 155 stringBuilder.setLength(0); 156 getStatus(stringBuilder); 157 fpsLabel.setText(stringBuilder); 158 hud.act(Gdx.graphics.getDeltaTime()); 159 hud.draw(); 160 } 161 162 @Override 163 public void resize (int width, int height) { 164 super.resize(width, height); 165 hud.getViewport().update(width, height, true); 166 hudWidth = hud.getWidth(); 167 hudHeight = hud.getHeight(); 168 } 169 170 @Override 171 public void dispose () { 172 super.dispose(); 173 skin.dispose(); 174 skin = null; 175 } 176 177 /** Double click title to expand/collapse */ 178 public static class CollapsableWindow extends Window { 179 private boolean collapsed; 180 private float collapseHeight = 20f; 181 private float expandHeight; 182 183 public CollapsableWindow (String title, Skin skin) { 184 super(title, skin); 185 addListener(new ClickListener() { 186 @Override 187 public void clicked (InputEvent event, float x, float y) { 188 if (getTapCount() == 2 && getHeight() - y <= getPadTop() && y < getHeight() && x > 0 && x < getWidth()) 189 toggleCollapsed(); 190 } 191 }); 192 } 193 194 public void expand () { 195 if (!collapsed) return; 196 setHeight(expandHeight); 197 setY(getY() - expandHeight + collapseHeight); 198 collapsed = false; 199 } 200 201 public void collapse () { 202 if (collapsed) return; 203 expandHeight = getHeight(); 204 setHeight(collapseHeight); 205 setY(getY() + expandHeight - collapseHeight); 206 collapsed = true; 207 if (getStage() != null) getStage().setScrollFocus(null); 208 } 209 210 public void toggleCollapsed () { 211 if (collapsed) 212 expand(); 213 else 214 collapse(); 215 } 216 217 public boolean isCollapsed () { 218 return collapsed; 219 } 220 } 221 } 222