• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Input.Keys;
21 import com.badlogic.gdx.InputAdapter;
22 import com.badlogic.gdx.InputMultiplexer;
23 import com.badlogic.gdx.graphics.Color;
24 import com.badlogic.gdx.graphics.GL20;
25 import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
26 import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
27 import com.badlogic.gdx.math.Interpolation;
28 import com.badlogic.gdx.math.MathUtils;
29 import com.badlogic.gdx.math.Vector2;
30 import com.badlogic.gdx.scenes.scene2d.Actor;
31 import com.badlogic.gdx.scenes.scene2d.Stage;
32 import com.badlogic.gdx.scenes.scene2d.ui.List;
33 import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
34 import com.badlogic.gdx.scenes.scene2d.ui.Skin;
35 import com.badlogic.gdx.scenes.scene2d.ui.Table;
36 import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
37 import com.badlogic.gdx.tests.utils.GdxTest;
38 import com.badlogic.gdx.utils.Align;
39 import com.badlogic.gdx.utils.reflect.ClassReflection;
40 import com.badlogic.gdx.utils.reflect.Field;
41 import com.badlogic.gdx.utils.viewport.ScreenViewport;
42 
43 public class InterpolationTest extends GdxTest {
44 	Stage stage;
45 	private Skin skin;
46 	private Table table;
47 	List<String> list;
48 	String interpolationNames[], selectedInterpolation;
49 	private ShapeRenderer renderer;
50 	float graphSize, steps, time = 0, duration = 2.5f;
51 	Vector2 startPosition = new Vector2(), targetPosition = new Vector2(), position = new Vector2();
52 
53 	/** resets {@link #startPosition} and {@link #targetPosition} */
resetPositions()54 	void resetPositions () {
55 		startPosition.set(stage.getWidth() - stage.getWidth() / 5f, stage.getHeight() - stage.getHeight() / 5f);
56 		targetPosition.set(startPosition.x, stage.getHeight() / 5f);
57 	}
58 
59 	/** @return the {@link #position} with the {@link #selectedInterpolation interpolation} applied */
getPosition(float time)60 	Vector2 getPosition (float time) {
61 		position.set(targetPosition);
62 		position.sub(startPosition);
63 		position.scl(getInterpolation(selectedInterpolation).apply(time / duration));
64 		position.add(startPosition);
65 		return position;
66 	}
67 
68 	/** @return the {@link #selectedInterpolation selected} interpolation */
getInterpolation(String name)69 	private Interpolation getInterpolation (String name) {
70 		try {
71 			return (Interpolation)ClassReflection.getField(Interpolation.class, name).get(null);
72 		} catch (Exception e) {
73 			throw new RuntimeException(e);
74 		}
75 	}
76 
77 	@Override
create()78 	public void create () {
79 		Gdx.gl.glClearColor(.3f, .3f, .3f, 1);
80 		renderer = new ShapeRenderer();
81 
82 		skin = new Skin(Gdx.files.internal("data/uiskin.json"));
83 
84 		stage = new Stage(new ScreenViewport());
85 		resetPositions();
86 
87 		Field[] interpolationFields = ClassReflection.getFields(Interpolation.class);
88 
89 		// see how many fields are actually interpolations (for safety; other fields may be added with future)
90 		int interpolationMembers = 0;
91 		for (int i = 0; i < interpolationFields.length; i++)
92 			if (ClassReflection.isAssignableFrom(Interpolation.class, interpolationFields[i].getDeclaringClass()))
93 				interpolationMembers++;
94 
95 		// get interpolation names
96 		interpolationNames = new String[interpolationMembers];
97 		for (int i = 0; i < interpolationFields.length; i++)
98 			if (ClassReflection.isAssignableFrom(Interpolation.class, interpolationFields[i].getDeclaringClass()))
99 				interpolationNames[i] = interpolationFields[i].getName();
100 		selectedInterpolation = interpolationNames[0];
101 
102 		list = new List(skin);
103 		list.setItems(interpolationNames);
104 		list.addListener(new ChangeListener() {
105 			public void changed (ChangeEvent event, Actor actor) {
106 				selectedInterpolation = list.getSelected();
107 				time = 0;
108 				resetPositions();
109 			}
110 		});
111 
112 		ScrollPane scroll = new ScrollPane(list, skin);
113 		scroll.setFadeScrollBars(false);
114 		scroll.setScrollingDisabled(true, false);
115 
116 		table = new Table();
117 		table.setFillParent(true);
118 		table.add(scroll).expandX().left().width(100);
119 		stage.addActor(table);
120 
121 		Gdx.input.setInputProcessor(new InputMultiplexer(new InputAdapter() {
122 			public boolean scrolled (int amount) {
123 				if (!Gdx.input.isKeyPressed(Keys.CONTROL_LEFT)) return false;
124 				duration -= amount / 15f;
125 				duration = MathUtils.clamp(duration, 0, Float.POSITIVE_INFINITY);
126 				return true;
127 			}
128 
129 		}, stage, new InputAdapter() {
130 			public boolean touchDown (int screenX, int screenY, int pointer, int button) {
131 				if (!Float.isNaN(time)) // if "walking" was interrupted by this touch down event
132 					startPosition.set(getPosition(time)); // set startPosition to the current position
133 				targetPosition.set(stage.screenToStageCoordinates(targetPosition.set(screenX, screenY)));
134 				time = 0;
135 				return true;
136 			}
137 
138 		}));
139 	}
140 
render()141 	public void render () {
142 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
143 
144 		float bottomLeftX = Gdx.graphics.getWidth() / 2 - graphSize / 2, bottomLeftY = Gdx.graphics.getHeight() / 2 - graphSize / 2;
145 
146 		// only show up to two decimals
147 		String text = String.valueOf(duration);
148 		if (text.length() > 4) text = text.substring(0, text.lastIndexOf('.') + 3);
149 		text = "duration: " + text + " s (ctrl + scroll to change)";
150 		stage.getBatch().begin();
151 		list.getStyle().font.draw(stage.getBatch(), text, bottomLeftX + graphSize / 2, bottomLeftY + graphSize
152 			+ list.getStyle().font.getLineHeight(), 0, Align.center, false);
153 		stage.getBatch().end();
154 
155 		renderer.begin(ShapeType.Line);
156 		renderer.rect(bottomLeftX, bottomLeftY, graphSize, graphSize); // graph bounds
157 		float lastX = bottomLeftX, lastY = bottomLeftY;
158 		for (float step = 0; step <= steps; step++) {
159 			Interpolation interpolation = getInterpolation(selectedInterpolation);
160 			float percent = step / steps;
161 			float x = bottomLeftX + graphSize * percent, y = bottomLeftY + graphSize * interpolation.apply(percent);
162 			renderer.line(lastX, lastY, x, y);
163 			lastX = x;
164 			lastY = y;
165 		}
166 		time += Gdx.graphics.getDeltaTime();
167 		if (time > duration) {
168 			time = Float.NaN; // stop "walking"
169 			startPosition.set(targetPosition); // set startPosition to targetPosition for next click
170 		}
171 		// draw time marker
172 		renderer.line(bottomLeftX + graphSize * time / duration, bottomLeftY, bottomLeftX + graphSize * time / duration,
173 			bottomLeftY + graphSize);
174 		// draw path
175 		renderer.setColor(Color.GRAY);
176 		renderer.line(startPosition, targetPosition);
177 		renderer.setColor(Color.WHITE);
178 		renderer.end();
179 
180 		// draw the position
181 		renderer.begin(ShapeType.Filled);
182 		if (!Float.isNaN(time)) // don't mess up position if time is NaN
183 			getPosition(time);
184 		renderer.circle(position.x, position.y, 7);
185 		renderer.end();
186 
187 		stage.act();
188 		stage.draw();
189 	}
190 
resize(int width, int height)191 	public void resize (int width, int height) {
192 		stage.getViewport().update(width, height, true);
193 		table.invalidateHierarchy();
194 
195 		renderer.setProjectionMatrix(stage.getViewport().getCamera().combined);
196 
197 		graphSize = 0.75f * Math.min(stage.getViewport().getWorldWidth(), stage.getViewport().getWorldHeight());
198 		steps = graphSize * 0.5f;
199 	}
200 
dispose()201 	public void dispose () {
202 		stage.dispose();
203 		skin.dispose();
204 	}
205 }
206