gdx-studio

#libgdx#java#desktop

git clone https://git.pyrossh.dev/gdx-studio

An IDE for creating Games using libgdx and Java supported on all platforms Android, iOS, Desktop


src_libs/com/badlogic/gdx/tools/particleeditor/Chart.java
a62d533 1
/*******************************************************************************
a62d533 2
 * Copyright 2011 See AUTHORS file.
a62d533 3
 * 
a62d533 4
 * Licensed under the Apache License, Version 2.0 (the "License");
a62d533 5
 * you may not use this file except in compliance with the License.
a62d533 6
 * You may obtain a copy of the License at
a62d533 7
 * 
a62d533 8
 *   http://www.apache.org/licenses/LICENSE-2.0
a62d533 9
 * 
a62d533 10
 * Unless required by applicable law or agreed to in writing, software
a62d533 11
 * distributed under the License is distributed on an "AS IS" BASIS,
a62d533 12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
a62d533 13
 * See the License for the specific language governing permissions and
a62d533 14
 * limitations under the License.
a62d533 15
 ******************************************************************************/
a62d533 16
a62d533 17
package com.badlogic.gdx.tools.particleeditor;
a62d533 18
a62d533 19
import java.awt.BasicStroke;
a62d533 20
import java.awt.Color;
a62d533 21
import java.awt.Font;
a62d533 22
import java.awt.FontMetrics;
a62d533 23
import java.awt.Graphics;
a62d533 24
import java.awt.Graphics2D;
a62d533 25
import java.awt.GridBagLayout;
a62d533 26
import java.awt.event.MouseAdapter;
a62d533 27
import java.awt.event.MouseEvent;
a62d533 28
import java.awt.event.MouseMotionListener;
a62d533 29
import java.util.ArrayList;
a62d533 30
a62d533 31
import javax.swing.JPanel;
a62d533 32
a62d533 33
class Chart extends JPanel {
a62d533 34
	static private final int POINT_SIZE = 6;
a62d533 35
	static private final int POINT_SIZE_EXPANDED = 10;
a62d533 36
a62d533 37
	ArrayList<Point> points = new ArrayList();
a62d533 38
	private int numberHeight;
a62d533 39
	int chartX, chartY;
a62d533 40
	int chartWidth, chartHeight;
a62d533 41
	int maxX, maxY;
a62d533 42
	int overIndex = -1;
a62d533 43
	int movingIndex = -1;
a62d533 44
	boolean isExpanded;
a62d533 45
	String title;
a62d533 46
a62d533 47
	public Chart (String title) {
a62d533 48
		this.title = title;
a62d533 49
a62d533 50
		setLayout(new GridBagLayout());
a62d533 51
a62d533 52
		addMouseListener(new MouseAdapter() {
a62d533 53
			public void mousePressed (MouseEvent event) {
a62d533 54
				movingIndex = overIndex;
a62d533 55
			}
a62d533 56
a62d533 57
			public void mouseReleased (MouseEvent event) {
a62d533 58
				movingIndex = -1;
a62d533 59
			}
a62d533 60
a62d533 61
			public void mouseClicked (MouseEvent event) {
a62d533 62
				if (event.getClickCount() == 2) {
a62d533 63
					if (overIndex <= 0) return;
a62d533 64
					points.remove(overIndex);
a62d533 65
					pointsChanged();
a62d533 66
					repaint();
a62d533 67
					return;
a62d533 68
				}
a62d533 69
				if (movingIndex != -1) return;
a62d533 70
				if (overIndex != -1) return;
a62d533 71
				int mouseX = event.getX();
a62d533 72
				int mouseY = event.getY();
a62d533 73
				if (mouseX < chartX || mouseX > chartX + chartWidth) return;
a62d533 74
				if (mouseY < chartY || mouseY > chartY + chartHeight) return;
a62d533 75
				Point newPoint = pixelToPoint(mouseX, mouseY);
a62d533 76
				int i = 0;
a62d533 77
				Point lastPoint = null;
a62d533 78
				for (Point point : points) {
a62d533 79
					if (point.x > newPoint.x) {
a62d533 80
						if (Math.abs(point.x - newPoint.x) < 0.001f) return;
a62d533 81
						if (lastPoint != null && Math.abs(lastPoint.x - newPoint.x) < 0.001f) return;
a62d533 82
						points.add(i, newPoint);
a62d533 83
						overIndex = i;
a62d533 84
						pointsChanged();
a62d533 85
						repaint();
a62d533 86
						return;
a62d533 87
					}
a62d533 88
					lastPoint = point;
a62d533 89
					i++;
a62d533 90
				}
a62d533 91
				overIndex = points.size();
a62d533 92
				points.add(newPoint);
a62d533 93
				pointsChanged();
a62d533 94
				repaint();
a62d533 95
			}
a62d533 96
		});
a62d533 97
		addMouseMotionListener(new MouseMotionListener() {
a62d533 98
			public void mouseDragged (MouseEvent event) {
a62d533 99
				if (movingIndex == -1) return;
a62d533 100
				float nextX = movingIndex == points.size() - 1 ? maxX : points.get(movingIndex + 1).x - 0.001f;
a62d533 101
				if (movingIndex == 0) nextX = 0;
a62d533 102
				float prevX = movingIndex == 0 ? 0 : points.get(movingIndex - 1).x + 0.001f;
a62d533 103
				Point point = points.get(movingIndex);
a62d533 104
				point.x = Math.min(nextX, Math.max(prevX, (event.getX() - chartX) / (float)chartWidth * maxX));
a62d533 105
				point.y = Math.min(maxY, Math.max(0, chartHeight - (event.getY() - chartY)) / (float)chartHeight * maxY);
a62d533 106
				pointsChanged();
a62d533 107
				repaint();
a62d533 108
			}
a62d533 109
a62d533 110
			public void mouseMoved (MouseEvent event) {
a62d533 111
				int mouseX = event.getX();
a62d533 112
				int mouseY = event.getY();
a62d533 113
				int oldIndex = overIndex;
a62d533 114
				overIndex = -1;
a62d533 115
				int pointSize = isExpanded ? POINT_SIZE_EXPANDED : POINT_SIZE;
a62d533 116
				int i = 0;
a62d533 117
				for (Point point : points) {
a62d533 118
					int x = chartX + (int)(chartWidth * (point.x / (float)maxX));
a62d533 119
					int y = chartY + chartHeight - (int)(chartHeight * (point.y / (float)maxY));
a62d533 120
					if (Math.abs(x - mouseX) <= pointSize && Math.abs(y - mouseY) <= pointSize) {
a62d533 121
						overIndex = i;
a62d533 122
						break;
a62d533 123
					}
a62d533 124
					i++;
a62d533 125
				}
a62d533 126
				if (overIndex != oldIndex) repaint();
a62d533 127
			}
a62d533 128
		});
a62d533 129
	}
a62d533 130
a62d533 131
	public void addPoint (float x, float y) {
a62d533 132
		points.add(new Point(x, y));
a62d533 133
	}
a62d533 134
a62d533 135
	public void pointsChanged () {
a62d533 136
	}
a62d533 137
a62d533 138
	public float[] getValuesX () {
a62d533 139
		float[] values = new float[points.size()];
a62d533 140
		int i = 0;
a62d533 141
		for (Point point : points)
a62d533 142
			values[i++] = point.x;
a62d533 143
		return values;
a62d533 144
	}
a62d533 145
a62d533 146
	public float[] getValuesY () {
a62d533 147
		float[] values = new float[points.size()];
a62d533 148
		int i = 0;
a62d533 149
		for (Point point : points)
a62d533 150
			values[i++] = point.y;
a62d533 151
		return values;
a62d533 152
	}
a62d533 153
a62d533 154
	public void setValues (float[] x, float[] y) {
a62d533 155
		points.clear();
a62d533 156
		for (int i = 0; i < x.length; i++)
a62d533 157
			points.add(new Point(x[i], y[i]));
a62d533 158
	}
a62d533 159
a62d533 160
	Point pixelToPoint (float x, float y) {
a62d533 161
		Point point = new Point();
a62d533 162
		point.x = Math.min(maxX, Math.max(0, x - chartX) / (float)chartWidth * maxX);
a62d533 163
		point.y = Math.min(maxY, Math.max(0, chartHeight - (y - chartY)) / (float)chartHeight * maxY);
a62d533 164
		return point;
a62d533 165
	}
a62d533 166
a62d533 167
	Point pointToPixel (Point point) {
a62d533 168
		Point pixel = new Point();
a62d533 169
		pixel.x = chartX + (int)(chartWidth * (point.x / (float)maxX));
a62d533 170
		pixel.y = chartY + chartHeight - (int)(chartHeight * (point.y / (float)maxY));
a62d533 171
		return pixel;
a62d533 172
	}
a62d533 173
a62d533 174
	protected void paintComponent (Graphics graphics) {
a62d533 175
		// setOpaque(true);
a62d533 176
		// setBackground(Color.red);
a62d533 177
		super.paintComponent(graphics);
a62d533 178
a62d533 179
		Graphics2D g = (Graphics2D)graphics;
a62d533 180
		FontMetrics metrics = g.getFontMetrics();
a62d533 181
		if (numberHeight == 0) {
a62d533 182
			numberHeight = getFont().layoutGlyphVector(g.getFontRenderContext(), new char[] {'0'}, 0, 1, Font.LAYOUT_LEFT_TO_RIGHT)
a62d533 183
				.getGlyphPixelBounds(0, g.getFontRenderContext(), 0, 0).height;
a62d533 184
		}
a62d533 185
a62d533 186
		int width = getWidth();
a62d533 187
		if (!isExpanded) width = Math.min(150, width);
a62d533 188
		width = Math.max(100, width);
a62d533 189
		int height = getHeight();
a62d533 190
		int maxAxisLabelWidth;
a62d533 191
		int yAxisWidth;
a62d533 192
		if (isExpanded) {
a62d533 193
			maxAxisLabelWidth = metrics.stringWidth("100%");
a62d533 194
			yAxisWidth = maxAxisLabelWidth + 8;
a62d533 195
			chartX = yAxisWidth;
a62d533 196
			chartY = numberHeight / 2 + 1;
a62d533 197
			chartWidth = width - yAxisWidth - 2;
a62d533 198
			chartHeight = height - chartY - numberHeight - 8;
a62d533 199
		} else {
a62d533 200
			maxAxisLabelWidth = 0;
a62d533 201
			yAxisWidth = 2;
a62d533 202
			chartX = yAxisWidth;
a62d533 203
			chartY = 2;
a62d533 204
			chartWidth = width - yAxisWidth - 2;
a62d533 205
			chartHeight = height - chartY - 3;
a62d533 206
		}
a62d533 207
a62d533 208
		g.setColor(Color.white);
a62d533 209
		g.fillRect(chartX, chartY, chartWidth, chartHeight);
a62d533 210
		g.setColor(Color.black);
a62d533 211
		g.drawRect(chartX, chartY, chartWidth, chartHeight);
a62d533 212
a62d533 213
		maxX = 1;
a62d533 214
		{
a62d533 215
			int y = height;
a62d533 216
			if (isExpanded)
a62d533 217
				y -= numberHeight;
a62d533 218
			else
a62d533 219
				y += 5;
a62d533 220
			int xSplit = (int)Math.min(10, chartWidth / (maxAxisLabelWidth * 1.5f));
a62d533 221
			for (int i = 0; i <= xSplit; i++) {
a62d533 222
				float percent = i / (float)xSplit;
a62d533 223
				String label = axisLabel(maxX * percent);
a62d533 224
				int labelWidth = metrics.stringWidth(label);
a62d533 225
				int x = (int)(yAxisWidth + chartWidth * percent);
a62d533 226
				if (i != 0 && i != xSplit) {
a62d533 227
					g.setColor(Color.lightGray);
a62d533 228
					g.drawLine(x, chartY + 1, x, chartY + chartHeight);
a62d533 229
					g.setColor(Color.black);
a62d533 230
				}
a62d533 231
				g.drawLine(x, y - 4, x, y - 8);
a62d533 232
				if (isExpanded) {
a62d533 233
					x -= labelWidth / 2;
a62d533 234
					if (i == xSplit) x = Math.min(x, width - labelWidth);
a62d533 235
					g.drawString(label, x, y + numberHeight);
a62d533 236
				}
a62d533 237
			}
a62d533 238
		}
a62d533 239
a62d533 240
		maxY = 1;
a62d533 241
		{
a62d533 242
			int ySplit = isExpanded ? Math.min(10, chartHeight / (numberHeight * 3)) : 4;
a62d533 243
			for (int i = 0; i <= ySplit; i++) {
a62d533 244
				float percent = i / (float)ySplit;
a62d533 245
				String label = axisLabel(maxY * percent);
a62d533 246
				int labelWidth = metrics.stringWidth(label);
a62d533 247
				int y = (int)(chartY + chartHeight - chartHeight * percent);
a62d533 248
				if (isExpanded) g.drawString(label, yAxisWidth - 6 - labelWidth, y + numberHeight / 2);
a62d533 249
				if (i != 0 && i != ySplit) {
a62d533 250
					g.setColor(Color.lightGray);
a62d533 251
					g.drawLine(chartX, y, chartX + chartWidth - 1, y);
a62d533 252
					g.setColor(Color.black);
a62d533 253
				}
a62d533 254
				g.drawLine(yAxisWidth - 4, y, yAxisWidth, y);
a62d533 255
			}
a62d533 256
		}
a62d533 257
a62d533 258
		{
a62d533 259
			int titleWidth = metrics.stringWidth(title);
a62d533 260
			int x = yAxisWidth + chartWidth / 2 - titleWidth / 2;
a62d533 261
			int y = chartY + chartHeight / 2 - numberHeight / 2;
a62d533 262
			g.setColor(Color.white);
a62d533 263
			g.fillRect(x - 2, y - 2, titleWidth + 4, numberHeight + 4);
a62d533 264
			g.setColor(Color.lightGray);
a62d533 265
			g.drawString(title, x, y + numberHeight);
a62d533 266
		}
a62d533 267
a62d533 268
		g.setColor(Color.blue);
a62d533 269
		g.setStroke(new BasicStroke(isExpanded ? 3 : 2));
a62d533 270
		int lastX = -1, lastY = -1;
a62d533 271
		for (Point point : points) {
a62d533 272
			Point pixel = pointToPixel(point);
a62d533 273
			if (lastX != -1) g.drawLine(lastX, lastY, (int)pixel.x, (int)pixel.y);
a62d533 274
			lastX = (int)pixel.x;
a62d533 275
			lastY = (int)pixel.y;
a62d533 276
		}
a62d533 277
		g.drawLine(lastX, lastY, chartX + chartWidth - 1, lastY);
a62d533 278
		for (int i = 0, n = points.size(); i < n; i++) {
a62d533 279
			Point point = points.get(i);
a62d533 280
			Point pixel = pointToPixel(point);
a62d533 281
			if (overIndex == i)
a62d533 282
				g.setColor(Color.red);
a62d533 283
			else
a62d533 284
				g.setColor(Color.black);
a62d533 285
			String label = valueLabel(point.y);
a62d533 286
			int labelWidth = metrics.stringWidth(label);
a62d533 287
			int pointSize = isExpanded ? POINT_SIZE_EXPANDED : POINT_SIZE;
a62d533 288
			int x = (int)pixel.x - pointSize / 2;
a62d533 289
			int y = (int)pixel.y - pointSize / 2;
a62d533 290
			g.fillOval(x, y, pointSize, pointSize);
a62d533 291
			if (isExpanded) {
a62d533 292
				g.setColor(Color.black);
a62d533 293
				x = Math.max(chartX + 2, Math.min(chartX + chartWidth - labelWidth, x));
a62d533 294
				y -= 3;
a62d533 295
				if (y < chartY + numberHeight + 3)
a62d533 296
					y += 27;
a62d533 297
				else if (n > 1) {
a62d533 298
					Point comparePoint = i == n - 1 ? points.get(i - 1) : points.get(i + 1);
a62d533 299
					if (y < chartY + chartHeight - 27 && comparePoint.y > point.y) y += 27;
a62d533 300
				}
a62d533 301
				g.drawString(label, x, y);
a62d533 302
			}
a62d533 303
		}
a62d533 304
	}
a62d533 305
a62d533 306
	private String valueLabel (float value) {
a62d533 307
		value = (int)(value * 1000) / 10f;
a62d533 308
		if (value % 1 == 0)
a62d533 309
			return String.valueOf((int)value) + '%';
a62d533 310
		else
a62d533 311
			return String.valueOf(value) + '%';
a62d533 312
	}
a62d533 313
a62d533 314
	private String axisLabel (float value) {
a62d533 315
		value = (int)(value * 100);
a62d533 316
		if (value % 1 == 0)
a62d533 317
			return String.valueOf((int)value) + '%';
a62d533 318
		else
a62d533 319
			return String.valueOf(value) + '%';
a62d533 320
	}
a62d533 321
a62d533 322
	static public class Point {
a62d533 323
		public float x;
a62d533 324
		public float y;
a62d533 325
a62d533 326
		public Point () {
a62d533 327
		}
a62d533 328
a62d533 329
		public Point (float x, float y) {
a62d533 330
			this.x = x;
a62d533 331
			this.y = y;
a62d533 332
		}
a62d533 333
	}
a62d533 334
a62d533 335
	public boolean isExpanded () {
a62d533 336
		return isExpanded;
a62d533 337
	}
a62d533 338
a62d533 339
	public void setExpanded (boolean isExpanded) {
a62d533 340
		this.isExpanded = isExpanded;
a62d533 341
	}
a62d533 342
}