[added] LwjglApplication#setSize.
[changed] Named LWJGL audio and music threads.
[changed] SpriteBatch#renderMesh made private.
[added] SpriteBatch#flush (public).
[added] Sprite#setTexture.
[added] Particle classes and particle editor tool (in extensions). 99,999 particles on the desktop at 44fps (default 32x32 image). Haven't tried performance on a device yet, that will get me motivated to work on it again.
* {@inheritDoc}\r
*/\r
@Override public FileHandle getFileHandle (String filename, FileType type) {\r
- if (type == FileType.Absolut || type == FileType.External)\r
+ if (type == FileType.Absolute || type == FileType.External)\r
return null;\r
else\r
return new AppletFileHandle(filename);\r
* {@inheritDoc}\r
*/\r
@Override public InputStream readFile (String fileName, FileType type) {\r
- if (type == FileType.Absolut || type == FileType.External)\r
+ if (type == FileType.Absolute || type == FileType.External)\r
return null;\r
else\r
return new AppletFileHandle(fileName).getInputStream();\r
*/\r
@Override public FileHandle getFileHandle (String filename, FileType type) {\r
File file = null;\r
- if (type == FileType.Absolut || type == FileType.Internal)\r
+ if (type == FileType.Absolute || type == FileType.Internal)\r
file = new File(filename);\r
else\r
file = new File(this.externalPath + filename);\r
*/\r
@Override public String[] listDirectory (String directory, FileType type) {\r
File file = null;\r
- if (type == FileType.Absolut || type == FileType.Internal)\r
+ if (type == FileType.Absolute || type == FileType.Internal)\r
file = new File(directory);\r
else\r
file = new File(this.externalPath + directory);\r
\r
if (type == FileType.Internal) return false;\r
\r
- if (type == FileType.Absolut)\r
+ if (type == FileType.Absolute)\r
file = new File(directory);\r
else\r
file = new File(this.externalPath + directory);\r
@Override public InputStream readFile (String fileName, FileType type) {\r
File file = null;\r
InputStream in = null;\r
- if (type == FileType.Absolut || type == FileType.Internal)\r
+ if (type == FileType.Absolute || type == FileType.Internal)\r
file = new File(fileName);\r
else\r
file = new File(this.externalPath + fileName);\r
\r
if (type == FileType.Internal) return null;\r
\r
- if (type == FileType.Absolut)\r
+ if (type == FileType.Absolute)\r
file = new File(filename);\r
else\r
file = new File(this.externalPath + filename);\r
\r
package com.badlogic.gdx.backends.desktop;\r
\r
+import java.awt.Canvas;\r
import java.io.BufferedOutputStream;\r
import java.io.File;\r
import java.io.FileOutputStream;\r
Gdx.audio = this.getAudio();\r
Gdx.files = this.getFiles();\r
\r
- new Thread("LWJGL") {\r
+ new Thread("LWJGL Application") {\r
public void run () {\r
try {\r
LwjglApplication.this.start();\r
}\r
}\r
\r
+ public void setSize (int width, int height) {\r
+ this.width = width;\r
+ this.height = height;\r
+ for (RenderListener listener : listeners)\r
+ listener.surfaceChanged(getWidth(), getHeight());\r
+ }\r
+\r
void start () throws LWJGLException {\r
gameThread = Thread.currentThread();\r
\r
setupDisplay();\r
\r
- for (RenderListener listener : listeners) {\r
+ for (RenderListener listener : listeners)\r
listener.surfaceCreated();\r
- listener.surfaceChanged(getWidth(), getHeight());\r
- }\r
+ setSize(width, height);\r
for (RenderListener listener : listeners)\r
listener.render();\r
\r
line = AudioSystem.getSourceDataLine(format);\r
line.open(format, 4410);\r
line.start();\r
- thread = new Thread(this);\r
+ thread = new Thread(this, "LWJGL Audio");\r
thread.setDaemon(true);\r
thread.start();\r
} catch (Exception e) {\r
\r
public FileHandle getFileHandle (String filename, FileType type) {\r
File file = null;\r
- if (type == FileType.Absolut || type == FileType.Internal)\r
+ if (type == FileType.Absolute || type == FileType.Internal)\r
file = new File(filename);\r
else\r
file = new File(this.externalPath + filename);\r
\r
public String[] listDirectory (String directory, FileType type) {\r
File file = null;\r
- if (type == FileType.Absolut || type == FileType.Internal)\r
+ if (type == FileType.Absolute || type == FileType.Internal)\r
file = new File(directory);\r
else\r
file = new File(this.externalPath + directory);\r
\r
if (type == FileType.Internal) return false;\r
\r
- if (type == FileType.Absolut)\r
+ if (type == FileType.Absolute)\r
file = new File(directory);\r
else\r
file = new File(this.externalPath + directory);\r
public InputStream readFile (String fileName, FileType type) {\r
File file = null;\r
InputStream in = null;\r
- if (type == FileType.Absolut || type == FileType.Internal)\r
+ if (type == FileType.Absolute || type == FileType.Internal)\r
file = new File(fileName);\r
else\r
file = new File(this.externalPath + fileName);\r
\r
if (type == FileType.Internal) return null;\r
\r
- if (type == FileType.Absolut)\r
+ if (type == FileType.Absolute)\r
file = new File(filename);\r
else\r
file = new File(this.externalPath + filename);\r
ain.close();\r
ain = null;\r
\r
- thread = new Thread(this);\r
+ thread = new Thread(this, "LWJGL Music");\r
thread.setDaemon(true);\r
thread.start();\r
}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry excluding="**/.svn/*" kind="src" path="src"/>\r
+ <classpathentry excluding="**/.svn/*" kind="src" path="data"/>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
+ <classpathentry combineaccessrules="false" kind="src" path="/gdx"/>\r
+ <classpathentry combineaccessrules="false" kind="src" path="/gdx-backend-lwjgl"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>particle-editor</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+info face="Droid Sans" size=17 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1\r
+common lineHeight=20 base=26 scaleW=256 scaleH=128 pages=1 packed=0\r
+page id=0 file="default.png"\r
+chars count=95\r
+char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=16 xadvance=4 page=0 chnl=0 \r
+char id=124 x=0 y=0 width=6 height=20 xoffset=1 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=106 x=6 y=0 width=9 height=20 xoffset=-4 yoffset=3 xadvance=4 page=0 chnl=0 \r
+char id=81 x=15 y=0 width=15 height=19 xoffset=-2 yoffset=3 xadvance=12 page=0 chnl=0 \r
+char id=74 x=30 y=0 width=11 height=19 xoffset=-5 yoffset=3 xadvance=4 page=0 chnl=0 \r
+char id=125 x=41 y=0 width=10 height=18 xoffset=-3 yoffset=3 xadvance=6 page=0 chnl=0 \r
+char id=123 x=51 y=0 width=10 height=18 xoffset=-3 yoffset=3 xadvance=6 page=0 chnl=0 \r
+char id=93 x=61 y=0 width=8 height=18 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0 \r
+char id=91 x=69 y=0 width=8 height=18 xoffset=-2 yoffset=3 xadvance=5 page=0 chnl=0 \r
+char id=41 x=77 y=0 width=9 height=18 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0 \r
+char id=40 x=86 y=0 width=9 height=18 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0 \r
+char id=64 x=95 y=0 width=18 height=17 xoffset=-3 yoffset=3 xadvance=14 page=0 chnl=0 \r
+char id=121 x=113 y=0 width=13 height=17 xoffset=-3 yoffset=6 xadvance=8 page=0 chnl=0 \r
+char id=113 x=126 y=0 width=13 height=17 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0 \r
+char id=112 x=139 y=0 width=13 height=17 xoffset=-2 yoffset=6 xadvance=9 page=0 chnl=0 \r
+char id=103 x=152 y=0 width=13 height=17 xoffset=-3 yoffset=6 xadvance=8 page=0 chnl=0 \r
+char id=38 x=165 y=0 width=16 height=16 xoffset=-3 yoffset=3 xadvance=11 page=0 chnl=0 \r
+char id=37 x=181 y=0 width=18 height=16 xoffset=-3 yoffset=3 xadvance=14 page=0 chnl=0 \r
+char id=36 x=199 y=0 width=12 height=16 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=63 x=211 y=0 width=11 height=16 xoffset=-3 yoffset=3 xadvance=7 page=0 chnl=0 \r
+char id=33 x=222 y=0 width=7 height=16 xoffset=-2 yoffset=3 xadvance=4 page=0 chnl=0 \r
+char id=48 x=229 y=0 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=57 x=242 y=0 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=56 x=0 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=54 x=13 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=53 x=26 y=20 width=12 height=16 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=51 x=38 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=100 x=51 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=98 x=64 y=20 width=13 height=16 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=85 x=77 y=20 width=14 height=16 xoffset=-2 yoffset=3 xadvance=11 page=0 chnl=0 \r
+char id=83 x=91 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=8 page=0 chnl=0 \r
+char id=79 x=104 y=20 width=15 height=16 xoffset=-2 yoffset=3 xadvance=12 page=0 chnl=0 \r
+char id=71 x=119 y=20 width=14 height=16 xoffset=-2 yoffset=3 xadvance=11 page=0 chnl=0 \r
+char id=67 x=133 y=20 width=13 height=16 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0 \r
+char id=127 x=146 y=20 width=12 height=15 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0 \r
+char id=35 x=158 y=20 width=15 height=15 xoffset=-3 yoffset=3 xadvance=10 page=0 chnl=0 \r
+char id=92 x=173 y=20 width=11 height=15 xoffset=-3 yoffset=3 xadvance=6 page=0 chnl=0 \r
+char id=47 x=184 y=20 width=11 height=15 xoffset=-3 yoffset=3 xadvance=6 page=0 chnl=0 \r
+char id=59 x=195 y=20 width=8 height=15 xoffset=-3 yoffset=6 xadvance=4 page=0 chnl=0 \r
+char id=55 x=203 y=20 width=13 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=52 x=216 y=20 width=14 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=50 x=230 y=20 width=13 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=49 x=243 y=20 width=9 height=15 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=116 x=0 y=36 width=10 height=15 xoffset=-3 yoffset=4 xadvance=5 page=0 chnl=0 \r
+char id=108 x=10 y=36 width=6 height=15 xoffset=-2 yoffset=3 xadvance=4 page=0 chnl=0 \r
+char id=107 x=16 y=36 width=12 height=15 xoffset=-2 yoffset=3 xadvance=8 page=0 chnl=0 \r
+char id=105 x=28 y=36 width=7 height=15 xoffset=-2 yoffset=3 xadvance=4 page=0 chnl=0 \r
+char id=104 x=35 y=36 width=12 height=15 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0 \r
+char id=102 x=47 y=36 width=11 height=15 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0 \r
+char id=90 x=58 y=36 width=13 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=89 x=71 y=36 width=13 height=15 xoffset=-3 yoffset=3 xadvance=8 page=0 chnl=0 \r
+char id=88 x=84 y=36 width=14 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=87 x=98 y=36 width=19 height=15 xoffset=-3 yoffset=3 xadvance=15 page=0 chnl=0 \r
+char id=86 x=117 y=36 width=14 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=84 x=131 y=36 width=13 height=15 xoffset=-3 yoffset=3 xadvance=8 page=0 chnl=0 \r
+char id=82 x=144 y=36 width=13 height=15 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0 \r
+char id=80 x=157 y=36 width=12 height=15 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=78 x=169 y=36 width=14 height=15 xoffset=-2 yoffset=3 xadvance=12 page=0 chnl=0 \r
+char id=77 x=183 y=36 width=17 height=15 xoffset=-2 yoffset=3 xadvance=14 page=0 chnl=0 \r
+char id=76 x=200 y=36 width=11 height=15 xoffset=-2 yoffset=3 xadvance=8 page=0 chnl=0 \r
+char id=75 x=211 y=36 width=13 height=15 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=73 x=224 y=36 width=10 height=15 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0 \r
+char id=72 x=234 y=36 width=14 height=15 xoffset=-2 yoffset=3 xadvance=11 page=0 chnl=0 \r
+char id=70 x=0 y=51 width=11 height=15 xoffset=-2 yoffset=3 xadvance=8 page=0 chnl=0 \r
+char id=69 x=11 y=51 width=11 height=15 xoffset=-2 yoffset=3 xadvance=8 page=0 chnl=0 \r
+char id=68 x=22 y=51 width=14 height=15 xoffset=-2 yoffset=3 xadvance=11 page=0 chnl=0 \r
+char id=66 x=36 y=51 width=13 height=15 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0 \r
+char id=65 x=49 y=51 width=15 height=15 xoffset=-3 yoffset=3 xadvance=10 page=0 chnl=0 \r
+char id=58 x=64 y=51 width=7 height=13 xoffset=-2 yoffset=6 xadvance=4 page=0 chnl=0 \r
+char id=117 x=71 y=51 width=12 height=13 xoffset=-2 yoffset=6 xadvance=10 page=0 chnl=0 \r
+char id=115 x=83 y=51 width=11 height=13 xoffset=-3 yoffset=6 xadvance=7 page=0 chnl=0 \r
+char id=111 x=94 y=51 width=13 height=13 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0 \r
+char id=101 x=107 y=51 width=13 height=13 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0 \r
+char id=99 x=120 y=51 width=12 height=13 xoffset=-3 yoffset=6 xadvance=7 page=0 chnl=0 \r
+char id=97 x=132 y=51 width=12 height=13 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0 \r
+char id=60 x=144 y=51 width=13 height=12 xoffset=-3 yoffset=5 xadvance=9 page=0 chnl=0 \r
+char id=122 x=157 y=51 width=11 height=12 xoffset=-3 yoffset=6 xadvance=7 page=0 chnl=0 \r
+char id=120 x=168 y=51 width=13 height=12 xoffset=-3 yoffset=6 xadvance=8 page=0 chnl=0 \r
+char id=119 x=181 y=51 width=17 height=12 xoffset=-3 yoffset=6 xadvance=12 page=0 chnl=0 \r
+char id=118 x=198 y=51 width=13 height=12 xoffset=-3 yoffset=6 xadvance=8 page=0 chnl=0 \r
+char id=114 x=211 y=51 width=10 height=12 xoffset=-2 yoffset=6 xadvance=6 page=0 chnl=0 \r
+char id=110 x=221 y=51 width=12 height=12 xoffset=-2 yoffset=6 xadvance=10 page=0 chnl=0 \r
+char id=109 x=233 y=51 width=17 height=12 xoffset=-2 yoffset=6 xadvance=15 page=0 chnl=0 \r
+char id=94 x=0 y=66 width=13 height=11 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=62 x=13 y=66 width=13 height=11 xoffset=-3 yoffset=5 xadvance=9 page=0 chnl=0 \r
+char id=42 x=26 y=66 width=13 height=10 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0 \r
+char id=43 x=39 y=66 width=13 height=10 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0 \r
+char id=61 x=52 y=66 width=13 height=8 xoffset=-3 yoffset=7 xadvance=9 page=0 chnl=0 \r
+char id=39 x=65 y=66 width=6 height=8 xoffset=-2 yoffset=3 xadvance=3 page=0 chnl=0 \r
+char id=34 x=71 y=66 width=9 height=8 xoffset=-2 yoffset=3 xadvance=6 page=0 chnl=0 \r
+char id=44 x=80 y=66 width=8 height=7 xoffset=-3 yoffset=14 xadvance=4 page=0 chnl=0 \r
+char id=126 x=88 y=66 width=13 height=6 xoffset=-3 yoffset=8 xadvance=9 page=0 chnl=0 \r
+char id=46 x=101 y=66 width=7 height=6 xoffset=-2 yoffset=13 xadvance=4 page=0 chnl=0 \r
+char id=96 x=108 y=66 width=8 height=6 xoffset=0 yoffset=2 xadvance=9 page=0 chnl=0 \r
+char id=45 x=116 y=66 width=9 height=5 xoffset=-3 yoffset=10 xadvance=5 page=0 chnl=0 \r
+char id=95 x=125 y=66 width=13 height=4 xoffset=-4 yoffset=17 xadvance=6 page=0 chnl=0 \r
+kernings count=-1\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Font;\r
+import java.awt.FontMetrics;\r
+import java.awt.Graphics;\r
+import java.awt.Graphics2D;\r
+import java.awt.GridBagLayout;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.event.MouseMotionListener;\r
+import java.util.ArrayList;\r
+\r
+import javax.swing.JPanel;\r
+\r
+class Chart extends JPanel {\r
+ static private final int POINT_SIZE = 6;\r
+ static private final int POINT_SIZE_EXPANDED = 10;\r
+\r
+ ArrayList<Point> points = new ArrayList();\r
+ private int numberHeight;\r
+ int chartX, chartY;\r
+ int chartWidth, chartHeight;\r
+ int maxX, maxY;\r
+ int overIndex = -1;\r
+ int movingIndex = -1;\r
+ boolean isExpanded;\r
+ String title;\r
+\r
+ public Chart (String title) {\r
+ this.title = title;\r
+\r
+ setLayout(new GridBagLayout());\r
+\r
+ addMouseListener(new MouseAdapter() {\r
+ public void mousePressed (MouseEvent event) {\r
+ movingIndex = overIndex;\r
+ }\r
+\r
+ public void mouseReleased (MouseEvent event) {\r
+ movingIndex = -1;\r
+ }\r
+\r
+ public void mouseClicked (MouseEvent event) {\r
+ if (event.getClickCount() == 2) {\r
+ if (overIndex <= 0) return;\r
+ points.remove(overIndex);\r
+ pointsChanged();\r
+ repaint();\r
+ return;\r
+ }\r
+ if (movingIndex != -1) return;\r
+ if (overIndex != -1) return;\r
+ int mouseX = event.getX();\r
+ int mouseY = event.getY();\r
+ if (mouseX < chartX || mouseX > chartX + chartWidth) return;\r
+ if (mouseY < chartY || mouseY > chartY + chartHeight) return;\r
+ Point newPoint = pixelToPoint(mouseX, mouseY);\r
+ int i = 0;\r
+ Point lastPoint = null;\r
+ for (Point point : points) {\r
+ if (point.x > newPoint.x) {\r
+ if (Math.abs(point.x - newPoint.x) < 0.001f) return;\r
+ if (lastPoint != null && Math.abs(lastPoint.x - newPoint.x) < 0.001f) return;\r
+ points.add(i, newPoint);\r
+ overIndex = i;\r
+ pointsChanged();\r
+ repaint();\r
+ return;\r
+ }\r
+ lastPoint = point;\r
+ i++;\r
+ }\r
+ overIndex = points.size();\r
+ points.add(newPoint);\r
+ pointsChanged();\r
+ repaint();\r
+ }\r
+ });\r
+ addMouseMotionListener(new MouseMotionListener() {\r
+ public void mouseDragged (MouseEvent event) {\r
+ if (movingIndex == -1) return;\r
+ float nextX = movingIndex == points.size() - 1 ? maxX : points.get(movingIndex + 1).x - 0.001f;\r
+ if (movingIndex == 0) nextX = 0;\r
+ float prevX = movingIndex == 0 ? 0 : points.get(movingIndex - 1).x + 0.001f;\r
+ Point point = points.get(movingIndex);\r
+ point.x = Math.min(nextX, Math.max(prevX, (event.getX() - chartX) / (float)chartWidth * maxX));\r
+ point.y = Math.min(maxY, Math.max(0, chartHeight - (event.getY() - chartY)) / (float)chartHeight * maxY);\r
+ pointsChanged();\r
+ repaint();\r
+ }\r
+\r
+ public void mouseMoved (MouseEvent event) {\r
+ int mouseX = event.getX();\r
+ int mouseY = event.getY();\r
+ int oldIndex = overIndex;\r
+ overIndex = -1;\r
+ int pointSize = isExpanded ? POINT_SIZE_EXPANDED : POINT_SIZE;\r
+ int i = 0;\r
+ for (Point point : points) {\r
+ int x = chartX + (int)(chartWidth * (point.x / (float)maxX));\r
+ int y = chartY + chartHeight - (int)(chartHeight * (point.y / (float)maxY));\r
+ if (Math.abs(x - mouseX) <= pointSize && Math.abs(y - mouseY) <= pointSize) {\r
+ overIndex = i;\r
+ break;\r
+ }\r
+ i++;\r
+ }\r
+ if (overIndex != oldIndex) repaint();\r
+ }\r
+ });\r
+ }\r
+\r
+ public void addPoint (float x, float y) {\r
+ points.add(new Point(x, y));\r
+ }\r
+\r
+ public void pointsChanged () {\r
+ }\r
+\r
+ public float[] getValuesX () {\r
+ float[] values = new float[points.size()];\r
+ int i = 0;\r
+ for (Point point : points)\r
+ values[i++] = point.x;\r
+ return values;\r
+ }\r
+\r
+ public float[] getValuesY () {\r
+ float[] values = new float[points.size()];\r
+ int i = 0;\r
+ for (Point point : points)\r
+ values[i++] = point.y;\r
+ return values;\r
+ }\r
+\r
+ public void setValues (float[] x, float[] y) {\r
+ points.clear();\r
+ for (int i = 0; i < x.length; i++)\r
+ points.add(new Point(x[i], y[i]));\r
+ }\r
+\r
+ Point pixelToPoint (float x, float y) {\r
+ Point point = new Point();\r
+ point.x = Math.min(maxX, Math.max(0, x - chartX) / (float)chartWidth * maxX);\r
+ point.y = Math.min(maxY, Math.max(0, chartHeight - (y - chartY)) / (float)chartHeight * maxY);\r
+ return point;\r
+ }\r
+\r
+ Point pointToPixel (Point point) {\r
+ Point pixel = new Point();\r
+ pixel.x = chartX + (int)(chartWidth * (point.x / (float)maxX));\r
+ pixel.y = chartY + chartHeight - (int)(chartHeight * (point.y / (float)maxY));\r
+ return pixel;\r
+ }\r
+\r
+ protected void paintComponent (Graphics graphics) {\r
+ // setOpaque(true);\r
+ // setBackground(Color.red);\r
+ super.paintComponent(graphics);\r
+\r
+ Graphics2D g = (Graphics2D)graphics;\r
+ FontMetrics metrics = g.getFontMetrics();\r
+ if (numberHeight == 0) {\r
+ numberHeight = getFont().layoutGlyphVector(g.getFontRenderContext(), new char[] {'0'}, 0, 1, Font.LAYOUT_LEFT_TO_RIGHT)\r
+ .getGlyphPixelBounds(0, g.getFontRenderContext(), 0, 0).height;\r
+ }\r
+\r
+ int width = getWidth();\r
+ if (!isExpanded) width = Math.min(150, width);\r
+ width = Math.max(100, width);\r
+ int height = getHeight();\r
+ int maxAxisLabelWidth;\r
+ int yAxisWidth;\r
+ if (isExpanded) {\r
+ maxAxisLabelWidth = metrics.stringWidth("100%");\r
+ yAxisWidth = maxAxisLabelWidth + 8;\r
+ chartX = yAxisWidth;\r
+ chartY = numberHeight / 2 + 1;\r
+ chartWidth = width - yAxisWidth - 2;\r
+ chartHeight = height - chartY - numberHeight - 8;\r
+ } else {\r
+ maxAxisLabelWidth = 0;\r
+ yAxisWidth = 2;\r
+ chartX = yAxisWidth;\r
+ chartY = 2;\r
+ chartWidth = width - yAxisWidth - 2;\r
+ chartHeight = height - chartY - 3;\r
+ }\r
+\r
+ g.setColor(Color.white);\r
+ g.fillRect(chartX, chartY, chartWidth, chartHeight);\r
+ g.setColor(Color.black);\r
+ g.drawRect(chartX, chartY, chartWidth, chartHeight);\r
+\r
+ maxX = 1;\r
+ {\r
+ int y = height;\r
+ if (isExpanded)\r
+ y -= numberHeight;\r
+ else\r
+ y += 5;\r
+ int xSplit = (int)Math.min(10, chartWidth / (maxAxisLabelWidth * 1.5f));\r
+ for (int i = 0; i <= xSplit; i++) {\r
+ float percent = i / (float)xSplit;\r
+ String label = axisLabel(maxX * percent);\r
+ int labelWidth = metrics.stringWidth(label);\r
+ int x = (int)(yAxisWidth + chartWidth * percent);\r
+ if (i != 0 && i != xSplit) {\r
+ g.setColor(Color.lightGray);\r
+ g.drawLine(x, chartY + 1, x, chartY + chartHeight);\r
+ g.setColor(Color.black);\r
+ }\r
+ g.drawLine(x, y - 4, x, y - 8);\r
+ if (isExpanded) {\r
+ x -= labelWidth / 2;\r
+ if (i == xSplit) x = Math.min(x, width - labelWidth);\r
+ g.drawString(label, x, y + numberHeight);\r
+ }\r
+ }\r
+ }\r
+\r
+ maxY = 1;\r
+ {\r
+ int ySplit = isExpanded ? Math.min(10, chartHeight / (numberHeight * 3)) : 4;\r
+ for (int i = 0; i <= ySplit; i++) {\r
+ float percent = i / (float)ySplit;\r
+ String label = axisLabel(maxY * percent);\r
+ int labelWidth = metrics.stringWidth(label);\r
+ int y = (int)(chartY + chartHeight - chartHeight * percent);\r
+ if (isExpanded) g.drawString(label, yAxisWidth - 6 - labelWidth, y + numberHeight / 2);\r
+ if (i != 0 && i != ySplit) {\r
+ g.setColor(Color.lightGray);\r
+ g.drawLine(chartX, y, chartX + chartWidth - 1, y);\r
+ g.setColor(Color.black);\r
+ }\r
+ g.drawLine(yAxisWidth - 4, y, yAxisWidth, y);\r
+ }\r
+ }\r
+\r
+ {\r
+ int titleWidth = metrics.stringWidth(title);\r
+ int x = yAxisWidth + chartWidth / 2 - titleWidth / 2;\r
+ int y = chartY + chartHeight / 2 - numberHeight / 2;\r
+ g.setColor(Color.white);\r
+ g.fillRect(x - 2, y - 2, titleWidth + 4, numberHeight + 4);\r
+ g.setColor(Color.lightGray);\r
+ g.drawString(title, x, y + numberHeight);\r
+ }\r
+\r
+ g.setColor(Color.blue);\r
+ g.setStroke(new BasicStroke(isExpanded ? 3 : 2));\r
+ int lastX = -1, lastY = -1;\r
+ for (Point point : points) {\r
+ Point pixel = pointToPixel(point);\r
+ if (lastX != -1) g.drawLine(lastX, lastY, (int)pixel.x, (int)pixel.y);\r
+ lastX = (int)pixel.x;\r
+ lastY = (int)pixel.y;\r
+ }\r
+ g.drawLine(lastX, lastY, chartX + chartWidth - 1, lastY);\r
+ for (int i = 0, n = points.size(); i < n; i++) {\r
+ Point point = points.get(i);\r
+ Point pixel = pointToPixel(point);\r
+ if (overIndex == i)\r
+ g.setColor(Color.red);\r
+ else\r
+ g.setColor(Color.black);\r
+ String label = valueLabel(point.y);\r
+ int labelWidth = metrics.stringWidth(label);\r
+ int pointSize = isExpanded ? POINT_SIZE_EXPANDED : POINT_SIZE;\r
+ int x = (int)pixel.x - pointSize / 2;\r
+ int y = (int)pixel.y - pointSize / 2;\r
+ g.fillOval(x, y, pointSize, pointSize);\r
+ if (isExpanded) {\r
+ g.setColor(Color.black);\r
+ x = Math.max(chartX + 2, Math.min(chartX + chartWidth - labelWidth, x));\r
+ y -= 3;\r
+ if (y < chartY + numberHeight + 3)\r
+ y += 27;\r
+ else if (n > 1) {\r
+ Point comparePoint = i == n - 1 ? points.get(i - 1) : points.get(i + 1);\r
+ if (y < chartY + chartHeight - 27 && comparePoint.y > point.y) y += 27;\r
+ }\r
+ g.drawString(label, x, y);\r
+ }\r
+ }\r
+ }\r
+\r
+ private String valueLabel (float value) {\r
+ value = (int)(value * 1000) / 10f;\r
+ if (value % 1 == 0)\r
+ return String.valueOf((int)value) + '%';\r
+ else\r
+ return String.valueOf(value) + '%';\r
+ }\r
+\r
+ private String axisLabel (float value) {\r
+ value = (int)(value * 100);\r
+ if (value % 1 == 0)\r
+ return String.valueOf((int)value) + '%';\r
+ else\r
+ return String.valueOf(value) + '%';\r
+ }\r
+\r
+ static public class Point {\r
+ public float x;\r
+ public float y;\r
+\r
+ public Point () {\r
+ }\r
+\r
+ public Point (float x, float y) {\r
+ this.x = x;\r
+ this.y = y;\r
+ }\r
+ }\r
+\r
+ public boolean isExpanded () {\r
+ return isExpanded;\r
+ }\r
+\r
+ public void setExpanded (boolean isExpanded) {\r
+ this.isExpanded = isExpanded;\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.GridBagConstraints;\r
+import java.awt.Insets;\r
+\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.JSpinner;\r
+import javax.swing.SpinnerNumberModel;\r
+import javax.swing.event.ChangeEvent;\r
+import javax.swing.event.ChangeListener;\r
+\r
+class CountPanel extends EditorPanel {\r
+ JSpinner maxSpinner, minSpinner;\r
+\r
+ public CountPanel (final ParticleEditor editor) {\r
+ super("Count", null);\r
+\r
+ initializeComponents();\r
+\r
+ maxSpinner.setValue(editor.getEmitter().getMaxParticleCount());\r
+ maxSpinner.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ synchronized (editor.effect) {\r
+ editor.getEmitter().setMaxParticleCount((Integer)maxSpinner.getValue());\r
+ }\r
+ }\r
+ });\r
+\r
+ minSpinner.setValue(editor.getEmitter().getMinParticleCount());\r
+ minSpinner.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ synchronized (editor.effect) {\r
+ editor.getEmitter().setMinParticleCount((Integer)minSpinner.getValue());\r
+ }\r
+ }\r
+ });\r
+ }\r
+\r
+ private void initializeComponents () {\r
+ JPanel contentPanel = getContentPanel();\r
+ {\r
+ JLabel label = new JLabel("Min:");\r
+ contentPanel.add(label, new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ minSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 99999, 1));\r
+ contentPanel.add(minSpinner, new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ JLabel label = new JLabel("Max:");\r
+ contentPanel.add(label, new GridBagConstraints(2, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 12, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ maxSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 99999, 1));\r
+ contentPanel.add(maxSpinner, new GridBagConstraints(3, 1, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.Cursor;\r
+import java.awt.Font;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.GridBagLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.JToggleButton;\r
+\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter.ParticleValue;\r
+\r
+class EditorPanel extends JPanel {\r
+ private final String name;\r
+ private final ParticleValue value;\r
+ private JPanel titlePanel;\r
+ JToggleButton activeButton;\r
+ private JPanel contentPanel;\r
+ JToggleButton advancedButton;\r
+ JPanel advancedPanel;\r
+ private boolean hasAdvanced;\r
+\r
+ public EditorPanel (String name, ParticleValue value) {\r
+ this.name = name;\r
+ this.value = value;\r
+\r
+ initializeComponents();\r
+\r
+ titlePanel.addMouseListener(new MouseAdapter() {\r
+ public void mouseClicked (MouseEvent event) {\r
+ if (!activeButton.isVisible()) return;\r
+ activeButton.setSelected(!activeButton.isSelected());\r
+ updateActive();\r
+ }\r
+ });\r
+ activeButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ updateActive();\r
+ }\r
+ });\r
+ advancedButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ advancedPanel.setVisible(advancedButton.isSelected());\r
+ }\r
+ });\r
+\r
+ if (value != null) {\r
+ activeButton.setSelected(value.isActive());\r
+ updateActive();\r
+ }\r
+\r
+ boolean alwaysActive = value == null ? true : value.isAlwaysActive();\r
+ activeButton.setVisible(!alwaysActive);\r
+ if (alwaysActive) contentPanel.setVisible(true);\r
+ if (alwaysActive) titlePanel.setCursor(null);\r
+ }\r
+\r
+ void updateActive () {\r
+ contentPanel.setVisible(activeButton.isSelected());\r
+ advancedPanel.setVisible(activeButton.isSelected() && advancedButton.isSelected());\r
+ advancedButton.setVisible(activeButton.isSelected() && hasAdvanced);\r
+ if (value != null) value.setActive(activeButton.isSelected());\r
+ }\r
+\r
+ public void update (ParticleEditor editor) {\r
+ }\r
+\r
+ public void setHasAdvanced (boolean hasAdvanced) {\r
+ this.hasAdvanced = hasAdvanced;\r
+ advancedButton.setVisible(hasAdvanced && (value.isActive() || value.isAlwaysActive()));\r
+ }\r
+\r
+ public JPanel getContentPanel () {\r
+ return contentPanel;\r
+ }\r
+\r
+ public JPanel getAdvancedPanel () {\r
+ return advancedPanel;\r
+ }\r
+\r
+ public String getName () {\r
+ return name;\r
+ }\r
+\r
+ public void setEmbedded () {\r
+ GridBagLayout layout = (GridBagLayout)getLayout();\r
+ GridBagConstraints constraints = layout.getConstraints(contentPanel);\r
+ constraints.insets = new Insets(0, 0, 0, 0);\r
+ layout.setConstraints(contentPanel, constraints);\r
+\r
+ titlePanel.setVisible(false);\r
+ }\r
+\r
+ private void initializeComponents () {\r
+ setLayout(new GridBagLayout());\r
+ {\r
+ titlePanel = new JPanel(new GridBagLayout());\r
+ add(titlePanel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,\r
+ new Insets(3, 0, 3, 0), 0, 0));\r
+ titlePanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));\r
+ {\r
+ JLabel label = new JLabel(name);\r
+ titlePanel.add(label, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,\r
+ new Insets(3, 6, 3, 6), 0, 0));\r
+ label.setFont(label.getFont().deriveFont(Font.BOLD));\r
+ }\r
+ {\r
+ advancedButton = new JToggleButton("Advanced");\r
+ titlePanel.add(advancedButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.NONE, new Insets(0, 0, 0, 6), 0, 0));\r
+ advancedButton.setVisible(false);\r
+ }\r
+ {\r
+ activeButton = new JToggleButton("Active");\r
+ titlePanel.add(activeButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.NONE, new Insets(0, 0, 0, 6), 0, 0));\r
+ }\r
+ }\r
+ {\r
+ contentPanel = new JPanel(new GridBagLayout());\r
+ add(contentPanel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,\r
+ new Insets(0, 6, 6, 6), 0, 0));\r
+ contentPanel.setVisible(false);\r
+ }\r
+ {\r
+ advancedPanel = new JPanel(new GridBagLayout());\r
+ add(advancedPanel, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,\r
+ new Insets(0, 6, 6, 6), 0, 0));\r
+ advancedPanel.setVisible(false);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.FileDialog;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.GridBagLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+\r
+import javax.swing.JButton;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JSeparator;\r
+import javax.swing.JTable;\r
+import javax.swing.ListSelectionModel;\r
+import javax.swing.event.ListSelectionEvent;\r
+import javax.swing.event.ListSelectionListener;\r
+import javax.swing.event.TableModelEvent;\r
+import javax.swing.event.TableModelListener;\r
+import javax.swing.table.DefaultTableModel;\r
+\r
+import com.badlogic.gdx.Files.FileType;\r
+import com.badlogic.gdx.Gdx;\r
+\r
+class EffectPanel extends JPanel {\r
+ ParticleEditor editor;\r
+ JTable emitterTable;\r
+ DefaultTableModel emitterTableModel;\r
+ int editIndex;\r
+ String lastDir;\r
+\r
+ public EffectPanel (ParticleEditor editor) {\r
+ this.editor = editor;\r
+ initializeComponents();\r
+ }\r
+\r
+ public ParticleEmitter newEmitter (String name, boolean select) {\r
+ final ParticleEmitter emitter = new ParticleEmitter();\r
+ emitter.setFlip(false, true);\r
+ emitter.setMaxParticleCount(15);\r
+ emitter.setImagePath("data/particle.png");\r
+ synchronized (editor.effect) {\r
+ ArrayList<ParticleEmitter> emitters = editor.effect.getEmitters();\r
+ if (emitters.isEmpty())\r
+ emitter.setPosition(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);\r
+ else {\r
+ ParticleEmitter p = emitters.get(0);\r
+ emitter.setPosition(p.getX(), p.getY());\r
+ }\r
+ emitters.add(emitter);\r
+ }\r
+ emitterTableModel.addRow(new Object[] {name, true});\r
+ if (select) {\r
+ editor.reloadRows();\r
+ int row = emitterTableModel.getRowCount() - 1;\r
+ emitterTable.getSelectionModel().setSelectionInterval(row, row);\r
+ }\r
+ return emitter;\r
+ }\r
+\r
+ void emitterSelected () {\r
+ int row = emitterTable.getSelectedRow();\r
+ if (row == -1) {\r
+ row = editIndex;\r
+ emitterTable.getSelectionModel().setSelectionInterval(row, row);\r
+ }\r
+ if (row == editIndex) return;\r
+ editIndex = row;\r
+ editor.reloadRows();\r
+ }\r
+\r
+ void openEffect () {\r
+ FileDialog dialog = new FileDialog(editor, "Open Effect", FileDialog.LOAD);\r
+ if (lastDir != null) dialog.setDirectory(lastDir);\r
+ dialog.setVisible(true);\r
+ final String file = dialog.getFile();\r
+ final String dir = dialog.getDirectory();\r
+ if (dir == null || file == null || file.trim().length() == 0) return;\r
+ lastDir = dir;\r
+ synchronized (editor.effect) {\r
+ ParticleEffect effect = new ParticleEffect();\r
+ try {\r
+ effect.loadEmitters(Gdx.files.getFileHandle(new File(dir, file).getAbsolutePath(), FileType.Absolute));\r
+ editor.effect = effect;\r
+ emitterTableModel.getDataVector().removeAllElements();\r
+ editor.particleData.clear();\r
+ } catch (Exception ex) {\r
+ System.out.println("Error loading effect: " + new File(dir, file).getAbsolutePath());\r
+ ex.printStackTrace();\r
+ JOptionPane.showMessageDialog(editor, "Error opening effect.");\r
+ return;\r
+ }\r
+ for (ParticleEmitter emitter : effect.getEmitters()) {\r
+ emitter.setPosition(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);\r
+ emitterTableModel.addRow(new Object[] {emitter.getName(), true});\r
+ }\r
+ }\r
+ editIndex = 0;\r
+ emitterTable.getSelectionModel().setSelectionInterval(editIndex, editIndex);\r
+ editor.reloadRows();\r
+ }\r
+\r
+ void saveEffect () {\r
+ FileDialog dialog = new FileDialog(editor, "Save Effect", FileDialog.SAVE);\r
+ if (lastDir != null) dialog.setDirectory(lastDir);\r
+ dialog.setVisible(true);\r
+ String file = dialog.getFile();\r
+ String dir = dialog.getDirectory();\r
+ if (dir == null || file == null || file.trim().length() == 0) return;\r
+ lastDir = dir;\r
+ synchronized (editor.effect) {\r
+ int index = 0;\r
+ for (ParticleEmitter particles : editor.effect.getEmitters())\r
+ particles.setName((String)emitterTableModel.getValueAt(index++, 0));\r
+ try {\r
+ editor.effect.save(new File(dir, file));\r
+ } catch (Exception ex) {\r
+ System.out.println("Error saving effect: " + new File(dir, file).getAbsolutePath());\r
+ ex.printStackTrace();\r
+ JOptionPane.showMessageDialog(editor, "Error saving effect.");\r
+ }\r
+ }\r
+ }\r
+\r
+ void deleteEmitter () {\r
+ synchronized (editor.effect) {\r
+ if (editor.effect.getEmitters().size() == 1) return;\r
+ int row = emitterTable.getSelectedRow();\r
+ if (row == -1) return;\r
+ if (row <= editIndex) {\r
+ int oldEditIndex = editIndex;\r
+ editIndex = Math.max(0, editIndex - 1);\r
+ if (oldEditIndex == row) editor.reloadRows();\r
+ }\r
+ editor.effect.getEmitters().remove(row);\r
+ emitterTableModel.removeRow(row);\r
+ }\r
+ emitterTable.getSelectionModel().setSelectionInterval(editIndex, editIndex);\r
+ }\r
+\r
+ void move (int direction) {\r
+ if (direction < 0 && editIndex == 0) return;\r
+ synchronized (editor.effect) {\r
+ ArrayList<ParticleEmitter> emitters = editor.effect.getEmitters();\r
+ if (direction > 0 && editIndex == emitters.size() - 1) return;\r
+ int insertIndex = editIndex + direction;\r
+ Object name = emitterTableModel.getValueAt(editIndex, 0);\r
+ emitterTableModel.removeRow(editIndex);\r
+ ParticleEmitter particles = emitters.remove(editIndex);\r
+ emitterTableModel.insertRow(insertIndex, new Object[] {name});\r
+ emitters.add(insertIndex, particles);\r
+ editIndex = insertIndex;\r
+ }\r
+ emitterTable.getSelectionModel().setSelectionInterval(editIndex, editIndex);\r
+ }\r
+\r
+ void emitterChecked (int index, boolean checked) {\r
+ synchronized (editor.effect) {\r
+ editor.setEnabled(editor.effect.getEmitters().get(index), checked);\r
+ editor.effect.start();\r
+ }\r
+ }\r
+\r
+ private void initializeComponents () {\r
+ setLayout(new GridBagLayout());\r
+ {\r
+ JPanel sideButtons = new JPanel(new GridBagLayout());\r
+ add(sideButtons, new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ {\r
+ JButton newButton = new JButton("New");\r
+ sideButtons.add(newButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));\r
+ newButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ newEmitter("Untitled", true);\r
+ }\r
+ });\r
+ }\r
+ {\r
+ JButton deleteButton = new JButton("Delete");\r
+ sideButtons.add(deleteButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));\r
+ deleteButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ deleteEmitter();\r
+ }\r
+ });\r
+ }\r
+ {\r
+ sideButtons.add(new JSeparator(JSeparator.HORIZONTAL), new GridBagConstraints(0, -1, 1, 1, 0, 0,\r
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));\r
+ }\r
+ {\r
+ JButton saveButton = new JButton("Save");\r
+ sideButtons.add(saveButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));\r
+ saveButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ saveEffect();\r
+ }\r
+ });\r
+ }\r
+ {\r
+ JButton openButton = new JButton("Open");\r
+ sideButtons.add(openButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));\r
+ openButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ openEffect();\r
+ }\r
+ });\r
+ }\r
+ {\r
+ JButton upButton = new JButton("Up");\r
+ sideButtons.add(upButton, new GridBagConstraints(0, -1, 1, 1, 0, 1, GridBagConstraints.SOUTH,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));\r
+ upButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ move(-1);\r
+ }\r
+ });\r
+ }\r
+ {\r
+ JButton downButton = new JButton("Down");\r
+ sideButtons.add(downButton, new GridBagConstraints(0, -1, 1, 1, 0, 0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));\r
+ downButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ move(1);\r
+ }\r
+ });\r
+ }\r
+ }\r
+ {\r
+ JScrollPane scroll = new JScrollPane();\r
+ add(scroll, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,\r
+ 0, 0, 6), 0, 0));\r
+ {\r
+ emitterTable = new JTable() {\r
+ public Class getColumnClass (int column) {\r
+ return column == 1 ? Boolean.class : super.getColumnClass(column);\r
+ }\r
+ };\r
+ emitterTable.getTableHeader().setReorderingAllowed(false);\r
+ emitterTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);\r
+ scroll.setViewportView(emitterTable);\r
+ emitterTableModel = new DefaultTableModel(new String[0][0], new String[] {"Emitter", ""});\r
+ emitterTable.setModel(emitterTableModel);\r
+ emitterTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
+ public void valueChanged (ListSelectionEvent event) {\r
+ if (event.getValueIsAdjusting()) return;\r
+ emitterSelected();\r
+ }\r
+ });\r
+ emitterTableModel.addTableModelListener(new TableModelListener() {\r
+ public void tableChanged (TableModelEvent event) {\r
+ if (event.getColumn() != 1) return;\r
+ emitterChecked(event.getFirstRow(), (Boolean)emitterTable.getValueAt(event.getFirstRow(), 1));\r
+ }\r
+ });\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.Color;\r
+import java.awt.Dimension;\r
+import java.awt.GradientPaint;\r
+import java.awt.Graphics;\r
+import java.awt.Graphics2D;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.GridBagLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.event.MouseMotionAdapter;\r
+import java.util.ArrayList;\r
+\r
+import javax.swing.BorderFactory;\r
+import javax.swing.JColorChooser;\r
+import javax.swing.JPanel;\r
+import javax.swing.JSlider;\r
+import javax.swing.event.ChangeEvent;\r
+import javax.swing.event.ChangeListener;\r
+\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter.GradientColorValue;\r
+\r
+class GradientPanel extends EditorPanel {\r
+ private final GradientColorValue value;\r
+ private GradientEditor gradientEditor;\r
+ ColorSlider saturationSlider, lightnessSlider;\r
+ JPanel colorPanel;\r
+ private ColorSlider hueSlider;\r
+\r
+ public GradientPanel (String name, GradientColorValue value) {\r
+ super(name, value);\r
+ this.value = value;\r
+\r
+ initializeComponents();\r
+\r
+ gradientEditor.percentages.clear();\r
+ for (float percent : value.getTimeline())\r
+ gradientEditor.percentages.add(percent);\r
+\r
+ gradientEditor.colors.clear();\r
+ float[] colors = value.getColors();\r
+ for (int i = 0; i < colors.length;) {\r
+ float r = colors[i++];\r
+ float g = colors[i++];\r
+ float b = colors[i++];\r
+ gradientEditor.colors.add(new Color(r, g, b));\r
+ }\r
+ if (gradientEditor.colors.isEmpty() || gradientEditor.percentages.isEmpty()) {\r
+ gradientEditor.percentages.clear();\r
+ gradientEditor.percentages.add(0f);\r
+ gradientEditor.percentages.add(1f);\r
+ gradientEditor.colors.clear();\r
+ gradientEditor.colors.add(Color.white);\r
+ }\r
+ setColor(gradientEditor.colors.get(0));\r
+ }\r
+\r
+ public Dimension getPreferredSize () {\r
+ Dimension size = super.getPreferredSize();\r
+ size.width = 10;\r
+ return size;\r
+ }\r
+\r
+ private void initializeComponents () {\r
+ JPanel contentPanel = getContentPanel();\r
+ {\r
+ gradientEditor = new GradientEditor() {\r
+ public void handleSelected (Color color) {\r
+ GradientPanel.this.setColor(color);\r
+ }\r
+ };\r
+ contentPanel.add(gradientEditor, new GridBagConstraints(0, 1, 3, 1, 1.0, 0.0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 10));\r
+ }\r
+ {\r
+ hueSlider = new ColorSlider(new Color[] {Color.red, Color.yellow, Color.green, Color.cyan, Color.blue, Color.magenta,\r
+ Color.red}) {\r
+ protected void colorPicked () {\r
+ saturationSlider.setColors(new Color[] {new Color(Color.HSBtoRGB(getPercentage(), 1, 1)), Color.white});\r
+ updateColor();\r
+ }\r
+ };\r
+ contentPanel.add(hueSlider, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 6, 0), 0, 0));\r
+ }\r
+ {\r
+ saturationSlider = new ColorSlider(new Color[] {Color.red, Color.white}) {\r
+ protected void colorPicked () {\r
+ updateColor();\r
+ }\r
+ };\r
+ contentPanel.add(saturationSlider, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ lightnessSlider = new ColorSlider(new Color[0]) {\r
+ protected void colorPicked () {\r
+ updateColor();\r
+ }\r
+ };\r
+ contentPanel.add(lightnessSlider, new GridBagConstraints(2, 3, 1, 1, 1, 0.0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ colorPanel = new JPanel() {\r
+ public Dimension getPreferredSize () {\r
+ Dimension size = super.getPreferredSize();\r
+ size.width = 52;\r
+ return size;\r
+ }\r
+ };\r
+ contentPanel.add(colorPanel, new GridBagConstraints(0, 2, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.BOTH, new Insets(3, 0, 0, 6), 0, 0));\r
+ }\r
+\r
+ colorPanel.addMouseListener(new MouseAdapter() {\r
+ public void mouseClicked (MouseEvent e) {\r
+ Color color = JColorChooser.showDialog(colorPanel, "Set Color", colorPanel.getBackground());\r
+ if (color != null) setColor(color);\r
+ }\r
+ });\r
+ colorPanel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.black));\r
+ }\r
+\r
+ public void setColor (Color color) {\r
+ float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null);\r
+ hueSlider.setPercentage(hsb[0]);\r
+ saturationSlider.setPercentage(1 - hsb[1]);\r
+ lightnessSlider.setPercentage(1 - hsb[2]);\r
+ colorPanel.setBackground(color);\r
+ }\r
+\r
+ void updateColor () {\r
+ Color color = new Color(Color.HSBtoRGB(hueSlider.getPercentage(), 1 - saturationSlider.getPercentage(), 1));\r
+ lightnessSlider.setColors(new Color[] {color, Color.black});\r
+ color = new Color(Color.HSBtoRGB(hueSlider.getPercentage(), 1 - saturationSlider.getPercentage(), 1 - lightnessSlider\r
+ .getPercentage()));\r
+ colorPanel.setBackground(color);\r
+ gradientEditor.setColor(color);\r
+\r
+ float[] colors = new float[gradientEditor.colors.size() * 3];\r
+ int i = 0;\r
+ for (Color c : gradientEditor.colors) {\r
+ colors[i++] = c.getRed() / 255f;\r
+ colors[i++] = c.getGreen() / 255f;\r
+ colors[i++] = c.getBlue() / 255f;\r
+ }\r
+ float[] percentages = new float[gradientEditor.percentages.size()];\r
+ i = 0;\r
+ for (Float percent : gradientEditor.percentages)\r
+ percentages[i++] = percent;\r
+ value.setColors(colors);\r
+ value.setTimeline(percentages);\r
+ }\r
+\r
+ public class GradientEditor extends JPanel {\r
+ ArrayList<Color> colors = new ArrayList();\r
+ ArrayList<Float> percentages = new ArrayList();\r
+\r
+ int handleWidth = 12;\r
+ int handleHeight = 12;\r
+ int gradientX = handleWidth / 2;\r
+ int gradientY = 0;\r
+ int gradientWidth;\r
+ int gradientHeight;\r
+ int dragIndex = -1;\r
+ int selectedIndex;\r
+\r
+ public GradientEditor () {\r
+ setPreferredSize(new Dimension(100, 30));\r
+\r
+ addMouseListener(new MouseAdapter() {\r
+ public void mousePressed (MouseEvent event) {\r
+ dragIndex = -1;\r
+ int mouseX = event.getX();\r
+ int mouseY = event.getY();\r
+ int y = gradientY + gradientHeight;\r
+ for (int i = 0, n = colors.size(); i < n; i++) {\r
+ int x = gradientX + (int)(percentages.get(i) * gradientWidth) - handleWidth / 2;\r
+ if (mouseX >= x && mouseX <= x + handleWidth && mouseY >= gradientY && mouseY <= y + handleHeight) {\r
+ dragIndex = selectedIndex = i;\r
+ handleSelected(colors.get(selectedIndex));\r
+ repaint();\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ public void mouseReleased (MouseEvent event) {\r
+ if (dragIndex != -1) {\r
+ dragIndex = -1;\r
+ repaint();\r
+ }\r
+ }\r
+\r
+ public void mouseClicked (MouseEvent event) {\r
+ int mouseX = event.getX();\r
+ int mouseY = event.getY();\r
+ if (event.getClickCount() == 2) {\r
+ if (percentages.size() <= 1) return;\r
+ if (selectedIndex == -1 || selectedIndex == 0) return;\r
+ int y = gradientY + gradientHeight;\r
+ int x = gradientX + (int)(percentages.get(selectedIndex) * gradientWidth) - handleWidth / 2;\r
+ if (mouseX >= x && mouseX <= x + handleWidth && mouseY >= gradientY && mouseY <= y + handleHeight) {\r
+ percentages.remove(selectedIndex);\r
+ colors.remove(selectedIndex);\r
+ selectedIndex--;\r
+ dragIndex = selectedIndex;\r
+ if (percentages.size() == 2) percentages.set(1, 1f);\r
+ handleSelected(colors.get(selectedIndex));\r
+ repaint();\r
+ }\r
+ return;\r
+ }\r
+ if (mouseX < gradientX || mouseX > gradientX + gradientWidth) return;\r
+ if (mouseY < gradientY || mouseY > gradientY + gradientHeight) return;\r
+ float percent = (event.getX() - gradientX) / (float)gradientWidth;\r
+ if (percentages.size() == 1) percent = 1f;\r
+ for (int i = 0, n = percentages.size(); i <= n; i++) {\r
+ if (i == n || percent < percentages.get(i)) {\r
+ percentages.add(i, percent);\r
+ colors.add(i, colors.get(i - 1));\r
+ dragIndex = selectedIndex = i;\r
+ handleSelected(colors.get(selectedIndex));\r
+ repaint();\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ });\r
+ addMouseMotionListener(new MouseMotionAdapter() {\r
+ public void mouseDragged (MouseEvent event) {\r
+ if (dragIndex == -1 || dragIndex == 0 || dragIndex == percentages.size() - 1) return;\r
+ float percent = (event.getX() - gradientX) / (float)gradientWidth;\r
+ percent = Math.max(percent, percentages.get(dragIndex - 1) + 0.01f);\r
+ percent = Math.min(percent, percentages.get(dragIndex + 1) - 0.01f);\r
+ percentages.set(dragIndex, percent);\r
+ repaint();\r
+ }\r
+ });\r
+ }\r
+\r
+ public void setColor (Color color) {\r
+ if (selectedIndex == -1) return;\r
+ colors.set(selectedIndex, color);\r
+ repaint();\r
+ }\r
+\r
+ public void handleSelected (Color color) {\r
+ }\r
+\r
+ protected void paintComponent (Graphics graphics) {\r
+ super.paintComponent(graphics);\r
+ Graphics2D g = (Graphics2D)graphics;\r
+ int width = getWidth() - 1;\r
+ int height = getHeight();\r
+\r
+ gradientWidth = width - handleWidth;\r
+ gradientHeight = height - 16;\r
+\r
+ g.translate(gradientX, gradientY);\r
+ for (int i = 0, n = colors.size() == 1 ? 1 : colors.size() - 1; i < n; i++) {\r
+ Color color1 = colors.get(i);\r
+ Color color2 = colors.size() == 1 ? color1 : colors.get(i + 1);\r
+ float percent1 = percentages.get(i);\r
+ float percent2 = colors.size() == 1 ? 1 : percentages.get(i + 1);\r
+ int point1 = (int)(percent1 * gradientWidth);\r
+ int point2 = (int)Math.ceil(percent2 * gradientWidth);\r
+ g.setPaint(new GradientPaint(point1, 0, color1, point2, 0, color2, false));\r
+ g.fillRect(point1, 0, point2 - point1, gradientHeight);\r
+ }\r
+ g.setPaint(null);\r
+ g.setColor(Color.black);\r
+ g.drawRect(0, 0, gradientWidth, gradientHeight);\r
+\r
+ int y = gradientHeight;\r
+ int[] yPoints = new int[3];\r
+ yPoints[0] = y;\r
+ yPoints[1] = y + handleHeight;\r
+ yPoints[2] = y + handleHeight;\r
+ int[] xPoints = new int[3];\r
+ for (int i = 0, n = colors.size(); i < n; i++) {\r
+ int x = (int)(percentages.get(i) * gradientWidth);\r
+ xPoints[0] = x;\r
+ xPoints[1] = x - handleWidth / 2;\r
+ xPoints[2] = x + handleWidth / 2;\r
+ if (i == selectedIndex) {\r
+ g.setColor(colors.get(i));\r
+ g.fillPolygon(xPoints, yPoints, 3);\r
+ g.fillRect(xPoints[1], yPoints[1] + 2, handleWidth + 1, 2);\r
+ g.setColor(Color.black);\r
+ }\r
+ g.drawPolygon(xPoints, yPoints, 3);\r
+ }\r
+ g.translate(-gradientX, -gradientY);\r
+ }\r
+ }\r
+\r
+ static public class ColorSlider extends JPanel {\r
+ Color[] paletteColors;\r
+ JSlider slider;\r
+ private ColorPicker colorPicker;\r
+\r
+ public ColorSlider (Color[] paletteColors) {\r
+ this.paletteColors = paletteColors;\r
+ setLayout(new GridBagLayout());\r
+ {\r
+ slider = new JSlider(0, 1000, 0);\r
+ slider.setPaintTrack(false);\r
+ add(slider, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,\r
+ new Insets(0, 6, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ colorPicker = new ColorPicker();\r
+ add(colorPicker, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,\r
+ GridBagConstraints.HORIZONTAL, new Insets(0, 6, 0, 6), 0, 0));\r
+ }\r
+\r
+ slider.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ colorPicked();\r
+ }\r
+ });\r
+ }\r
+\r
+ public Dimension getPreferredSize () {\r
+ Dimension size = super.getPreferredSize();\r
+ size.width = 10;\r
+ return size;\r
+ }\r
+\r
+ public void setPercentage (float percent) {\r
+ slider.setValue((int)(1000 * percent));\r
+ }\r
+\r
+ public float getPercentage () {\r
+ return slider.getValue() / 1000f;\r
+ }\r
+\r
+ protected void colorPicked () {\r
+ }\r
+\r
+ public void setColors (Color[] colors) {\r
+ paletteColors = colors;\r
+ repaint();\r
+ }\r
+\r
+ public class ColorPicker extends JPanel {\r
+ public ColorPicker () {\r
+ addMouseListener(new MouseAdapter() {\r
+ public void mouseClicked (MouseEvent event) {\r
+ slider.setValue((int)(event.getX() / (float)getWidth() * 1000));\r
+ }\r
+ });\r
+ }\r
+\r
+ protected void paintComponent (Graphics graphics) {\r
+ Graphics2D g = (Graphics2D)graphics;\r
+ int width = getWidth() - 1;\r
+ int height = getHeight() - 1;\r
+ for (int i = 0, n = paletteColors.length - 1; i < n; i++) {\r
+ Color color1 = paletteColors[i];\r
+ Color color2 = paletteColors[i + 1];\r
+ float point1 = i / (float)n * width;\r
+ float point2 = (i + 1) / (float)n * width;\r
+ g.setPaint(new GradientPaint(point1, 0, color1, point2, 0, color2, false));\r
+ g.fillRect((int)point1, 0, (int)Math.ceil(point2 - point1), height);\r
+ }\r
+ g.setPaint(null);\r
+ g.setColor(Color.black);\r
+ g.drawRect(0, 0, width, height);\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.FileDialog;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.io.File;\r
+\r
+import javax.swing.ImageIcon;\r
+import javax.swing.JButton;\r
+import javax.swing.JLabel;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter;\r
+\r
+class ImagePanel extends EditorPanel {\r
+ JLabel imageLabel;\r
+ JLabel widthLabel;\r
+ JLabel heightLabel;\r
+ String lastDir;\r
+\r
+ public ImagePanel (final ParticleEditor editor) {\r
+ super("Image", null);\r
+ JPanel contentPanel = getContentPanel();\r
+ {\r
+ JButton openButton = new JButton("Open");\r
+ contentPanel.add(openButton, new GridBagConstraints(2, 1, 1, 1, 0, 0, GridBagConstraints.NORTHWEST,\r
+ GridBagConstraints.NONE, new Insets(0, 0, 6, 6), 0, 0));\r
+ openButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ FileDialog dialog = new FileDialog(editor, "Open Image", FileDialog.LOAD);\r
+ if (lastDir != null) dialog.setDirectory(lastDir);\r
+ dialog.setVisible(true);\r
+ final String file = dialog.getFile();\r
+ final String dir = dialog.getDirectory();\r
+ if (dir == null || file == null || file.trim().length() == 0) return;\r
+ lastDir = dir;\r
+ try {\r
+ ImageIcon icon = new ImageIcon(new File(dir, file).toURI().toURL());\r
+ synchronized (editor.effect) {\r
+ final ParticleEmitter emitter = editor.getEmitter();\r
+ editor.setIcon(emitter, icon);\r
+ imageLabel.setIcon(icon);\r
+ widthLabel.setText("Width: " + icon.getIconWidth());\r
+ heightLabel.setText("Height: " + icon.getIconHeight());\r
+ revalidate();\r
+ emitter.setImagePath(new File(dir, file).getAbsolutePath());\r
+ emitter.setTexture(null);\r
+ }\r
+ } catch (Exception ex) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+ });\r
+ }\r
+ {\r
+ widthLabel = new JLabel();\r
+ contentPanel.add(widthLabel, new GridBagConstraints(2, 2, 1, 1, 0, 0, GridBagConstraints.NORTHWEST,\r
+ GridBagConstraints.NONE, new Insets(0, 0, 6, 6), 0, 0));\r
+ }\r
+ {\r
+ heightLabel = new JLabel();\r
+ contentPanel.add(heightLabel, new GridBagConstraints(2, 3, 1, 1, 0, 1, GridBagConstraints.NORTHWEST,\r
+ GridBagConstraints.NONE, new Insets(0, 0, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ imageLabel = new JLabel();\r
+ contentPanel.add(imageLabel, new GridBagConstraints(3, 1, 1, 3, 1, 0, GridBagConstraints.NORTHWEST,\r
+ GridBagConstraints.NONE, new Insets(0, 6, 0, 0), 0, 0));\r
+ }\r
+ ImageIcon icon = editor.getIcon(editor.getEmitter());\r
+ if (icon != null) {\r
+ imageLabel.setIcon(icon);\r
+ widthLabel.setText("Width: " + icon.getIconWidth());\r
+ heightLabel.setText("Height: " + icon.getIconHeight());\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.GridBagConstraints;\r
+import java.awt.Insets;\r
+\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.JSpinner;\r
+import javax.swing.SpinnerNumberModel;\r
+import javax.swing.event.ChangeEvent;\r
+import javax.swing.event.ChangeListener;\r
+\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter.NumericValue;\r
+\r
+class NumericPanel extends EditorPanel {\r
+ private final NumericValue value;\r
+ JSpinner valueSpinner;\r
+\r
+ public NumericPanel (String name, final NumericValue value) {\r
+ super(name, value);\r
+ this.value = value;\r
+\r
+ initializeComponents();\r
+\r
+ valueSpinner.setValue(value.getValue());\r
+\r
+ valueSpinner.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ value.setValue((Float)valueSpinner.getValue());\r
+ }\r
+ });\r
+ }\r
+\r
+ private void initializeComponents () {\r
+ JPanel contentPanel = getContentPanel();\r
+ {\r
+ JLabel label = new JLabel("Value:");\r
+ contentPanel.add(label, new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ valueSpinner = new JSpinner(new SpinnerNumberModel(new Float(0), new Float(-99999), new Float(99999), new Float(0.1f)));\r
+ contentPanel.add(valueSpinner, new GridBagConstraints(1, 1, 1, 1, 1, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.GridBagConstraints;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+\r
+import javax.swing.JCheckBox;\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.event.ChangeEvent;\r
+import javax.swing.event.ChangeListener;\r
+\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter;\r
+\r
+class OptionsPanel extends EditorPanel {\r
+ JCheckBox attachedCheckBox;\r
+ JCheckBox continuousCheckbox;\r
+ JCheckBox alignedCheckbox;\r
+ JCheckBox additiveCheckbox;\r
+ JCheckBox behindCheckbox;\r
+\r
+ public OptionsPanel (final ParticleEditor editor) {\r
+ super("Options", null);\r
+\r
+ initializeComponents();\r
+\r
+ attachedCheckBox.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ synchronized (editor.effect) {\r
+ editor.getEmitter().setAttached(attachedCheckBox.isSelected());\r
+ }\r
+ }\r
+ });\r
+\r
+ continuousCheckbox.setSelected(editor.getEmitter().isContinuous());\r
+ continuousCheckbox.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ synchronized (editor.effect) {\r
+ editor.getEmitter().setContinuous(continuousCheckbox.isSelected());\r
+ }\r
+ }\r
+ });\r
+\r
+ alignedCheckbox.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ synchronized (editor.effect) {\r
+ editor.getEmitter().setAligned(alignedCheckbox.isSelected());\r
+ }\r
+ }\r
+ });\r
+\r
+ additiveCheckbox.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ synchronized (editor.effect) {\r
+ editor.getEmitter().setAdditive(additiveCheckbox.isSelected());\r
+ }\r
+ }\r
+ });\r
+\r
+ behindCheckbox.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ synchronized (editor.effect) {\r
+ editor.getEmitter().setBehind(behindCheckbox.isSelected());\r
+ }\r
+ }\r
+ });\r
+\r
+ ParticleEmitter particles = editor.getEmitter();\r
+ attachedCheckBox.setSelected(particles.isAttached());\r
+ continuousCheckbox.setSelected(particles.isContinuous());\r
+ alignedCheckbox.setSelected(particles.isAligned());\r
+ additiveCheckbox.setSelected(particles.isAdditive());\r
+ behindCheckbox.setSelected(particles.isBehind());\r
+ }\r
+\r
+ private void initializeComponents () {\r
+ JPanel contentPanel = getContentPanel();\r
+ {\r
+ JLabel label = new JLabel("Additive:");\r
+ contentPanel.add(label, new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(6, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ additiveCheckbox = new JCheckBox();\r
+ contentPanel.add(additiveCheckbox, new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(6, 6, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ JLabel label = new JLabel("Attached:");\r
+ contentPanel.add(label, new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(6, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ attachedCheckBox = new JCheckBox();\r
+ contentPanel.add(attachedCheckBox, new GridBagConstraints(1, 2, 1, 1, 1, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(6, 6, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ JLabel label = new JLabel("Continuous:");\r
+ contentPanel.add(label, new GridBagConstraints(0, 3, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(6, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ continuousCheckbox = new JCheckBox();\r
+ contentPanel.add(continuousCheckbox, new GridBagConstraints(1, 3, 1, 1, 0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(6, 6, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ JLabel label = new JLabel("Aligned:");\r
+ contentPanel.add(label, new GridBagConstraints(0, 4, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(6, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ alignedCheckbox = new JCheckBox();\r
+ contentPanel.add(alignedCheckbox, new GridBagConstraints(1, 4, 1, 1, 0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(6, 6, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ JLabel label = new JLabel("Behind:");\r
+ contentPanel.add(label, new GridBagConstraints(0, 5, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(6, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ behindCheckbox = new JCheckBox();\r
+ contentPanel.add(behindCheckbox, new GridBagConstraints(1, 5, 1, 1, 0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(6, 6, 0, 0), 0, 0));\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Canvas;\r
+import java.awt.Component;\r
+import java.awt.Dimension;\r
+import java.awt.EventQueue;\r
+import java.awt.Graphics;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.GridBagLayout;\r
+import java.awt.Insets;\r
+import java.io.File;\r
+import java.net.MalformedURLException;\r
+import java.net.URL;\r
+import java.util.HashMap;\r
+\r
+import javax.swing.BorderFactory;\r
+import javax.swing.ImageIcon;\r
+import javax.swing.JComponent;\r
+import javax.swing.JFrame;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JSplitPane;\r
+import javax.swing.UIManager;\r
+import javax.swing.UIManager.LookAndFeelInfo;\r
+import javax.swing.border.CompoundBorder;\r
+import javax.swing.plaf.basic.BasicSplitPaneUI;\r
+\r
+import org.lwjgl.LWJGLException;\r
+import org.lwjgl.opengl.Display;\r
+\r
+import com.badlogic.gdx.Files.FileType;\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.GdxRuntimeException;\r
+import com.badlogic.gdx.InputListener;\r
+import com.badlogic.gdx.RenderListener;\r
+import com.badlogic.gdx.backends.desktop.LwjglApplication;\r
+import com.badlogic.gdx.graphics.BitmapFont;\r
+import com.badlogic.gdx.graphics.Color;\r
+import com.badlogic.gdx.graphics.GL10;\r
+import com.badlogic.gdx.graphics.Sprite;\r
+import com.badlogic.gdx.graphics.SpriteBatch;\r
+import com.badlogic.gdx.graphics.Texture.TextureFilter;\r
+import com.badlogic.gdx.graphics.Texture.TextureWrap;\r
+import com.badlogic.gdx.math.Matrix4;\r
+\r
+public class ParticleEditor extends JFrame implements RenderListener, InputListener {\r
+ LwjglApplication app;\r
+ Canvas glCanvas;\r
+ JPanel rowsPanel;\r
+ EffectPanel effectPanel;\r
+ private JSplitPane splitPane;\r
+\r
+ ParticleEffect effect = new ParticleEffect();\r
+ final HashMap<ParticleEmitter, ParticleData> particleData = new HashMap();\r
+ private float maxActiveTimer;\r
+ private int maxActive, lastMaxActive;\r
+ private boolean mouseDown;\r
+ private int activeCount;\r
+ private BitmapFont font;\r
+ private SpriteBatch spriteBatch;\r
+ private Sprite bgImage; // BOZO - Add setting background image to UI.\r
+ private int mouseX, mouseY;\r
+\r
+ public ParticleEditor () {\r
+ super("GDX Particle Editor");\r
+\r
+ glCanvas = new Canvas() {\r
+ private final Dimension minSize = new Dimension();\r
+\r
+ public final void addNotify () {\r
+ super.addNotify();\r
+ app = new LwjglApplication("ParticleEditor", 200, 200, false) {\r
+ protected void setupDisplay () throws LWJGLException {\r
+ try {\r
+ Display.setParent(glCanvas);\r
+ } catch (LWJGLException ex) {\r
+ throw new GdxRuntimeException("Error setting display parent.", ex);\r
+ }\r
+ super.setupDisplay();\r
+ }\r
+ };\r
+ app.getGraphics().setRenderListener(ParticleEditor.this);\r
+ }\r
+\r
+ public Dimension getMinimumSize () {\r
+ return minSize;\r
+ }\r
+ };\r
+\r
+ initializeComponents();\r
+\r
+ setSize(950, 950);\r
+ setLocationRelativeTo(null);\r
+ setDefaultCloseOperation(DISPOSE_ON_CLOSE);\r
+ setVisible(true);\r
+ }\r
+\r
+ void reloadRows () {\r
+ EventQueue.invokeLater(new Runnable() {\r
+ public void run () {\r
+ rowsPanel.removeAll();\r
+ synchronized (effect) {\r
+ ParticleEmitter emitter = getEmitter();\r
+ addRow(new ImagePanel(ParticleEditor.this));\r
+ addRow(new RangedNumericPanel("Delay", emitter.getDelay()));\r
+ addRow(new RangedNumericPanel("Duration", emitter.getDuration()));\r
+ addRow(new CountPanel(ParticleEditor.this));\r
+ addRow(new ScaledNumericPanel("Emission", "Duration", emitter.getEmission()));\r
+ addRow(new ScaledNumericPanel("Life", "Duration", emitter.getLife()));\r
+ addRow(new ScaledNumericPanel("Life Offset", "Duration", emitter.getLifeOffset()));\r
+ addRow(new RangedNumericPanel("X Offset", emitter.getXOffsetValue()));\r
+ addRow(new RangedNumericPanel("Y Offset", emitter.getYOffsetValue()));\r
+ addRow(new SpawnPanel(emitter.getSpawnShape(), ParticleEditor.this));\r
+ addRow(new ScaledNumericPanel("Spawn Width", "Duration", emitter.getSpawnWidth()));\r
+ addRow(new ScaledNumericPanel("Spawn Height", "Duration", emitter.getSpawnHeight()));\r
+ addRow(new ScaledNumericPanel("Size", "Life", emitter.getSize()));\r
+ addRow(new ScaledNumericPanel("Velocity", "Life", emitter.getVelocity()));\r
+ addRow(new ScaledNumericPanel("Angle", "Life", emitter.getAngle()));\r
+ addRow(new ScaledNumericPanel("Rotation", "Life", emitter.getRotation()));\r
+ addRow(new ScaledNumericPanel("Wind", "Life", emitter.getWind()));\r
+ addRow(new ScaledNumericPanel("Gravity", "Life", emitter.getGravity()));\r
+ addRow(new GradientPanel("Tint", emitter.getTint()));\r
+ addRow(new PercentagePanel("Transparency", "Life", emitter.getTransparency()));\r
+ addRow(new OptionsPanel(ParticleEditor.this));\r
+ for (Component component : rowsPanel.getComponents())\r
+ if (component instanceof EditorPanel) ((EditorPanel)component).update(ParticleEditor.this);\r
+ }\r
+ rowsPanel.repaint();\r
+ }\r
+ });\r
+ }\r
+\r
+ void addRow (JPanel row) {\r
+ row.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, java.awt.Color.black));\r
+ rowsPanel.add(row, new GridBagConstraints(0, -1, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+\r
+ public void setVisible (String name, boolean visible) {\r
+ for (Component component : rowsPanel.getComponents())\r
+ if (component instanceof EditorPanel && ((EditorPanel)component).getName().equals(name)) component.setVisible(visible);\r
+ }\r
+\r
+ public ParticleEmitter getEmitter () {\r
+ return effect.getEmitters().get(effectPanel.editIndex);\r
+ }\r
+\r
+ public ImageIcon getIcon (ParticleEmitter emitter) {\r
+ ParticleData data = particleData.get(emitter);\r
+ if (data == null) particleData.put(emitter, data = new ParticleData());\r
+ String imagePath = emitter.getImagePath();\r
+ if (data.icon == null && imagePath != null) {\r
+ try {\r
+ URL url;\r
+ File file = new File(imagePath);\r
+ if (file.exists())\r
+ url = file.toURI().toURL();\r
+ else {\r
+ url = ParticleEditor.class.getResource(imagePath);\r
+ if (url == null) return null;\r
+ }\r
+ data.icon = new ImageIcon(url);\r
+ } catch (MalformedURLException ex) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+ return data.icon;\r
+ }\r
+\r
+ public void setIcon (ParticleEmitter emitters, ImageIcon icon) {\r
+ ParticleData data = particleData.get(emitters);\r
+ if (data == null) particleData.put(emitters, data = new ParticleData());\r
+ data.icon = icon;\r
+ }\r
+\r
+ public void setEnabled (ParticleEmitter emitter, boolean enabled) {\r
+ ParticleData data = particleData.get(emitter);\r
+ if (data == null) particleData.put(emitter, data = new ParticleData());\r
+ data.enabled = enabled;\r
+ }\r
+\r
+ public boolean isEnabled (ParticleEmitter emitter) {\r
+ ParticleData data = particleData.get(emitter);\r
+ if (data == null) return true;\r
+ return data.enabled;\r
+ }\r
+\r
+ private void initializeComponents () {\r
+ // {\r
+ // JMenuBar menuBar = new JMenuBar();\r
+ // setJMenuBar(menuBar);\r
+ // JPopupMenu.setDefaultLightWeightPopupEnabled(false);\r
+ // JMenu fileMenu = new JMenu("File");\r
+ // menuBar.add(fileMenu);\r
+ // }\r
+ splitPane = new JSplitPane();\r
+ splitPane.setUI(new BasicSplitPaneUI() {\r
+ public void paint (Graphics g, JComponent jc) {\r
+ }\r
+ });\r
+ splitPane.setDividerSize(4);\r
+ getContentPane().add(splitPane, BorderLayout.CENTER);\r
+ {\r
+ JPanel propertiesPanel = new JPanel(new GridBagLayout());\r
+ splitPane.add(propertiesPanel, JSplitPane.RIGHT);\r
+ propertiesPanel.setBorder(new CompoundBorder(BorderFactory.createEmptyBorder(3, 0, 6, 6), BorderFactory\r
+ .createTitledBorder("Emitter Properties")));\r
+ {\r
+ JScrollPane scroll = new JScrollPane();\r
+ propertiesPanel.add(scroll, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTH,\r
+ GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));\r
+ scroll.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));\r
+ {\r
+ rowsPanel = new JPanel(new GridBagLayout());\r
+ scroll.setViewportView(rowsPanel);\r
+ scroll.getVerticalScrollBar().setUnitIncrement(70);\r
+ }\r
+ }\r
+ }\r
+ {\r
+ JSplitPane leftSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT);\r
+ leftSplit.setUI(new BasicSplitPaneUI() {\r
+ public void paint (Graphics g, JComponent jc) {\r
+ }\r
+ });\r
+ leftSplit.setDividerSize(4);\r
+ splitPane.add(leftSplit, JSplitPane.LEFT);\r
+ {\r
+ JPanel spacer = new JPanel(new BorderLayout());\r
+ leftSplit.add(spacer, JSplitPane.TOP);\r
+ spacer.add(glCanvas);\r
+ spacer.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 4));\r
+ }\r
+ {\r
+ JPanel emittersPanel = new JPanel(new BorderLayout());\r
+ leftSplit.add(emittersPanel, JSplitPane.BOTTOM);\r
+ emittersPanel.setBorder(new CompoundBorder(BorderFactory.createEmptyBorder(0, 6, 6, 0), BorderFactory\r
+ .createTitledBorder("Effect Emitters")));\r
+ {\r
+ effectPanel = new EffectPanel(this);\r
+ emittersPanel.add(effectPanel);\r
+ }\r
+ }\r
+ leftSplit.setDividerLocation(625);\r
+ }\r
+ splitPane.setDividerLocation(325);\r
+ }\r
+\r
+ public void surfaceCreated () {\r
+ if (spriteBatch != null) return;\r
+ spriteBatch = new SpriteBatch();\r
+\r
+ font = new BitmapFont(Gdx.files.getFileHandle("data/default.fnt", FileType.Internal), Gdx.files.getFileHandle(\r
+ "data/default.png", FileType.Internal), true);\r
+ effectPanel.newEmitter("Untitled", true);\r
+ // if (resources.openFile("/editor-bg.png") != null) bgImage = new Image(gl, "/editor-bg.png");\r
+\r
+ Gdx.input.addInputListener(this);\r
+ }\r
+\r
+ public void surfaceChanged (int width, int height) {\r
+ int viewWidth = Gdx.graphics.getWidth();\r
+ int viewHeight = Gdx.graphics.getHeight();\r
+\r
+ spriteBatch.setProjectionMatrix(new Matrix4().setToOrtho(0, viewWidth, viewHeight, 0, 0, 1));\r
+\r
+ synchronized (effect) {\r
+ effect.setPosition(viewWidth / 2, viewHeight / 2);\r
+ }\r
+ }\r
+\r
+ public void render () {\r
+ synchronized (effect) {\r
+ int viewWidth = Gdx.graphics.getWidth();\r
+ int viewHeight = Gdx.graphics.getHeight();\r
+ if (viewWidth != glCanvas.getWidth() || viewHeight != glCanvas.getHeight()) {\r
+ viewWidth = Math.max(1, glCanvas.getWidth());\r
+ viewHeight = Math.max(1, glCanvas.getHeight());\r
+ app.setSize(viewWidth, viewHeight);\r
+ }\r
+\r
+ float delta = Gdx.graphics.getDeltaTime();\r
+\r
+ Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);\r
+\r
+ spriteBatch.begin();\r
+ spriteBatch.enableBlending();\r
+ spriteBatch.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);\r
+\r
+ if (bgImage != null) {\r
+ bgImage.setPosition(viewWidth / 2 - bgImage.getWidth() / 2, viewHeight / 2 - bgImage.getHeight() / 2);\r
+ bgImage.draw(spriteBatch);\r
+ }\r
+\r
+ activeCount = 0;\r
+ for (ParticleEmitter emitter : effect.getEmitters()) {\r
+ if (emitter.getTexture() == null && emitter.getImagePath() != null) loadImage(emitter);\r
+ boolean enabled = isEnabled(emitter);\r
+ if (enabled) {\r
+ if (emitter.getTexture() != null) emitter.draw(spriteBatch, delta);\r
+ activeCount += emitter.getActiveCount();\r
+ }\r
+ }\r
+ if (effect.isComplete()) effect.start();\r
+\r
+ maxActive = Math.max(maxActive, activeCount);\r
+ maxActiveTimer += delta;\r
+ if (maxActiveTimer > 3) {\r
+ maxActiveTimer = 0;\r
+ lastMaxActive = maxActive;\r
+ maxActive = 0;\r
+ }\r
+\r
+ if (mouseDown) {\r
+ // gl.drawLine(mouseX - 6, mouseY, mouseX + 5, mouseY);\r
+ // gl.drawLine(mouseX, mouseY - 5, mouseX, mouseY + 6);\r
+ }\r
+\r
+ font.draw(spriteBatch, "FPS: " + Gdx.graphics.getFramesPerSecond(), 10, 10, Color.WHITE);\r
+ font.draw(spriteBatch, "Count: " + activeCount, 10, 30, Color.WHITE);\r
+ font.draw(spriteBatch, "Max: " + lastMaxActive, 10, 50, Color.WHITE);\r
+ font.draw(spriteBatch, (int)(getEmitter().getPercentComplete() * 100) + "%", 10, 70, Color.WHITE);\r
+\r
+ spriteBatch.end();\r
+\r
+ // gl.drawLine((int)(viewWidth * getCurrentParticles().getPercentComplete()), viewHeight - 1, viewWidth, viewHeight - 1);\r
+ }\r
+ }\r
+\r
+ private void loadImage (ParticleEmitter emitter) {\r
+ final String imagePath = emitter.getImagePath();\r
+ try {\r
+ emitter.setTexture(Gdx.graphics.newTexture(Gdx.files.getFileHandle(imagePath, FileType.Absolute), TextureFilter.Linear,\r
+ TextureFilter.Linear, TextureWrap.ClampToEdge, TextureWrap.ClampToEdge));\r
+ } catch (GdxRuntimeException ex) {\r
+ EventQueue.invokeLater(new Runnable() {\r
+ public void run () {\r
+ JOptionPane.showMessageDialog(ParticleEditor.this, "Error loading image:\n" + imagePath);\r
+ }\r
+ });\r
+ emitter.setImagePath(null);\r
+ }\r
+ }\r
+\r
+ public boolean keyDown (int keycode) {\r
+ return false;\r
+ }\r
+\r
+ public boolean keyUp (int keycode) {\r
+ return false;\r
+ }\r
+\r
+ public boolean keyTyped (char character) {\r
+ return false;\r
+ }\r
+\r
+ public boolean touchDown (int x, int y, int pointer) {\r
+ synchronized (effect) {\r
+ effect.setPosition(x, y);\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public boolean touchUp (int x, int y, int pointer) {\r
+ return false;\r
+ }\r
+\r
+ public boolean touchDragged (int x, int y, int pointer) {\r
+ synchronized (effect) {\r
+ effect.setPosition(x, y);\r
+ }\r
+ return false;\r
+ }\r
+\r
+ static class ParticleData {\r
+ public ImageIcon icon;\r
+ public String imagePath;\r
+ public boolean enabled = true;\r
+ }\r
+\r
+ public static void main (String[] args) {\r
+ for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {\r
+ if ("Nimbus".equals(info.getName())) {\r
+ try {\r
+ UIManager.setLookAndFeel(info.getClassName());\r
+ } catch (Throwable ignored) {\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ new ParticleEditor();\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.Dimension;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.GridBagLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+\r
+import javax.swing.BorderFactory;\r
+import javax.swing.JButton;\r
+import javax.swing.JPanel;\r
+\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter.ScaledNumericValue;\r
+\r
+class PercentagePanel extends EditorPanel {\r
+ final ScaledNumericValue value;\r
+ JButton expandButton;\r
+ Chart chart;\r
+\r
+ public PercentagePanel (String name, String chartTitle, final ScaledNumericValue value) {\r
+ super(name, value);\r
+ this.value = value;\r
+\r
+ initializeComponents(chartTitle);\r
+\r
+ chart.setValues(value.getTimeline(), value.getScaling());\r
+\r
+ expandButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ chart.setExpanded(!chart.isExpanded());\r
+ boolean expanded = chart.isExpanded();\r
+ GridBagLayout layout = (GridBagLayout)getContentPanel().getLayout();\r
+ GridBagConstraints chartConstraints = layout.getConstraints(chart);\r
+ GridBagConstraints expandButtonConstraints = layout.getConstraints(expandButton);\r
+ if (expanded) {\r
+ chart.setPreferredSize(new Dimension(150, 200));\r
+ expandButton.setText("-");\r
+ chartConstraints.weightx = 1;\r
+ expandButtonConstraints.weightx = 0;\r
+ } else {\r
+ chart.setPreferredSize(new Dimension(150, 62));\r
+ expandButton.setText("+");\r
+ chartConstraints.weightx = 0;\r
+ expandButtonConstraints.weightx = 1;\r
+ }\r
+ layout.setConstraints(chart, chartConstraints);\r
+ layout.setConstraints(expandButton, expandButtonConstraints);\r
+ chart.revalidate();\r
+ }\r
+ });\r
+ }\r
+\r
+ private void initializeComponents (String chartTitle) {\r
+ JPanel contentPanel = getContentPanel();\r
+ {\r
+ chart = new Chart(chartTitle) {\r
+ public void pointsChanged () {\r
+ value.setTimeline(chart.getValuesX());\r
+ value.setScaling(chart.getValuesY());\r
+ }\r
+ };\r
+ chart.setPreferredSize(new Dimension(150, 62));\r
+ contentPanel.add(chart, new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.BOTH,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ expandButton = new JButton("+");\r
+ expandButton.setBorder(BorderFactory.createEmptyBorder(4, 10, 4, 10));\r
+ contentPanel.add(expandButton, new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,\r
+ GridBagConstraints.NONE, new Insets(0, 6, 0, 0), 0, 0));\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.GridBagConstraints;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+\r
+import javax.swing.BorderFactory;\r
+import javax.swing.JButton;\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.JSpinner;\r
+import javax.swing.SpinnerNumberModel;\r
+import javax.swing.event.ChangeEvent;\r
+import javax.swing.event.ChangeListener;\r
+\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter.RangedNumericValue;\r
+\r
+class RangedNumericPanel extends EditorPanel {\r
+ private final RangedNumericValue value;\r
+ JSpinner minSpinner, maxSpinner;\r
+ JButton rangeButton;\r
+ JLabel label;\r
+\r
+ public RangedNumericPanel (String name, final RangedNumericValue value) {\r
+ super(name, value);\r
+ this.value = value;\r
+\r
+ initializeComponents();\r
+\r
+ minSpinner.setValue(value.getLowMin());\r
+ maxSpinner.setValue(value.getLowMax());\r
+\r
+ minSpinner.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ value.setLowMin((Float)minSpinner.getValue());\r
+ if (!maxSpinner.isVisible()) value.setLowMax((Float)minSpinner.getValue());\r
+ }\r
+ });\r
+\r
+ maxSpinner.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ value.setLowMax((Float)maxSpinner.getValue());\r
+ }\r
+ });\r
+\r
+ rangeButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ boolean visible = !maxSpinner.isVisible();\r
+ maxSpinner.setVisible(visible);\r
+ rangeButton.setText(visible ? "<" : ">");\r
+ JSpinner spinner = visible ? maxSpinner : minSpinner;\r
+ value.setLowMax((Float)spinner.getValue());\r
+ }\r
+ });\r
+\r
+ if (value.getLowMin() == value.getLowMax()) rangeButton.doClick(0);\r
+ }\r
+\r
+ private void initializeComponents () {\r
+ JPanel contentPanel = getContentPanel();\r
+ {\r
+ label = new JLabel("Value:");\r
+ contentPanel.add(label, new GridBagConstraints(2, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ minSpinner = new JSpinner(new SpinnerNumberModel(new Float(0), new Float(-99999), new Float(99999), new Float(1f)));\r
+ contentPanel.add(minSpinner, new GridBagConstraints(3, 2, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ maxSpinner = new JSpinner(new SpinnerNumberModel(new Float(0), new Float(-99999), new Float(99999), new Float(1f)));\r
+ contentPanel.add(maxSpinner, new GridBagConstraints(4, 2, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,\r
+ new Insets(0, 6, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ rangeButton = new JButton("<");\r
+ rangeButton.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));\r
+ contentPanel.add(rangeButton, new GridBagConstraints(5, 2, 1, 1, 1.0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(0, 1, 0, 0), 0, 0));\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.Dimension;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.GridBagLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+\r
+import javax.swing.BorderFactory;\r
+import javax.swing.JButton;\r
+import javax.swing.JCheckBox;\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.JSpinner;\r
+import javax.swing.SpinnerNumberModel;\r
+import javax.swing.event.ChangeEvent;\r
+import javax.swing.event.ChangeListener;\r
+\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter.ScaledNumericValue;\r
+\r
+class ScaledNumericPanel extends EditorPanel {\r
+ final ScaledNumericValue value;\r
+ JSpinner lowMinSpinner, lowMaxSpinner;\r
+ JSpinner highMinSpinner, highMaxSpinner;\r
+ JCheckBox relativeCheckBox;\r
+ Chart chart;\r
+ JPanel formPanel;\r
+ JButton expandButton;\r
+ JButton lowRangeButton;\r
+ JButton highRangeButton;\r
+\r
+ public ScaledNumericPanel (String name, String chartTitle, final ScaledNumericValue value) {\r
+ super(name, value);\r
+ this.value = value;\r
+\r
+ initializeComponents(chartTitle);\r
+\r
+ lowMinSpinner.setValue(value.getLowMin());\r
+ lowMaxSpinner.setValue(value.getLowMax());\r
+ highMinSpinner.setValue(value.getHighMin());\r
+ highMaxSpinner.setValue(value.getHighMax());\r
+ chart.setValues(value.getTimeline(), value.getScaling());\r
+ relativeCheckBox.setSelected(value.isRelative());\r
+\r
+ lowMinSpinner.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ value.setLowMin((Float)lowMinSpinner.getValue());\r
+ if (!lowMaxSpinner.isVisible()) value.setLowMax((Float)lowMinSpinner.getValue());\r
+ }\r
+ });\r
+ lowMaxSpinner.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ value.setLowMax((Float)lowMaxSpinner.getValue());\r
+ }\r
+ });\r
+ highMinSpinner.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ value.setHighMin((Float)highMinSpinner.getValue());\r
+ if (!highMaxSpinner.isVisible()) value.setHighMax((Float)highMinSpinner.getValue());\r
+ }\r
+ });\r
+ highMaxSpinner.addChangeListener(new ChangeListener() {\r
+ public void stateChanged (ChangeEvent event) {\r
+ value.setHighMax((Float)highMaxSpinner.getValue());\r
+ }\r
+ });\r
+\r
+ relativeCheckBox.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ value.setRelative(relativeCheckBox.isSelected());\r
+ }\r
+ });\r
+\r
+ lowRangeButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ boolean visible = !lowMaxSpinner.isVisible();\r
+ lowMaxSpinner.setVisible(visible);\r
+ lowRangeButton.setText(visible ? "<" : ">");\r
+ GridBagLayout layout = (GridBagLayout)formPanel.getLayout();\r
+ GridBagConstraints constraints = layout.getConstraints(lowRangeButton);\r
+ constraints.gridx = visible ? 5 : 4;\r
+ layout.setConstraints(lowRangeButton, constraints);\r
+ JSpinner spinner = visible ? lowMaxSpinner : lowMinSpinner;\r
+ value.setLowMax((Float)spinner.getValue());\r
+ }\r
+ });\r
+\r
+ highRangeButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ boolean visible = !highMaxSpinner.isVisible();\r
+ highMaxSpinner.setVisible(visible);\r
+ highRangeButton.setText(visible ? "<" : ">");\r
+ GridBagLayout layout = (GridBagLayout)formPanel.getLayout();\r
+ GridBagConstraints constraints = layout.getConstraints(highRangeButton);\r
+ constraints.gridx = visible ? 5 : 4;\r
+ layout.setConstraints(highRangeButton, constraints);\r
+ JSpinner spinner = visible ? highMaxSpinner : highMinSpinner;\r
+ value.setHighMax((Float)spinner.getValue());\r
+ }\r
+ });\r
+\r
+ expandButton.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ chart.setExpanded(!chart.isExpanded());\r
+ boolean expanded = chart.isExpanded();\r
+ GridBagLayout layout = (GridBagLayout)getContentPanel().getLayout();\r
+ GridBagConstraints chartConstraints = layout.getConstraints(chart);\r
+ GridBagConstraints expandButtonConstraints = layout.getConstraints(expandButton);\r
+ if (expanded) {\r
+ chart.setPreferredSize(new Dimension(150, 200));\r
+ expandButton.setText("\96");\r
+ chartConstraints.weightx = 1;\r
+ expandButtonConstraints.weightx = 0;\r
+ } else {\r
+ chart.setPreferredSize(new Dimension(150, 30));\r
+ expandButton.setText("+");\r
+ chartConstraints.weightx = 0;\r
+ expandButtonConstraints.weightx = 1;\r
+ }\r
+ layout.setConstraints(chart, chartConstraints);\r
+ layout.setConstraints(expandButton, expandButtonConstraints);\r
+ relativeCheckBox.setVisible(!expanded);\r
+ formPanel.setVisible(!expanded);\r
+ chart.revalidate();\r
+ }\r
+ });\r
+\r
+ if (value.getLowMin() == value.getLowMax()) lowRangeButton.doClick(0);\r
+ if (value.getHighMin() == value.getHighMax()) highRangeButton.doClick(0);\r
+ }\r
+\r
+ public JPanel getFormPanel () {\r
+ return formPanel;\r
+ }\r
+\r
+ private void initializeComponents (String chartTitle) {\r
+ JPanel contentPanel = getContentPanel();\r
+ {\r
+ formPanel = new JPanel(new GridBagLayout());\r
+ contentPanel.add(formPanel, new GridBagConstraints(5, 5, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 6), 0, 0));\r
+ {\r
+ JLabel label = new JLabel("High:");\r
+ formPanel.add(label, new GridBagConstraints(2, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ highMinSpinner = new JSpinner(\r
+ new SpinnerNumberModel(new Float(0), new Float(-99999), new Float(99999), new Float(1f)));\r
+ formPanel.add(highMinSpinner, new GridBagConstraints(3, 1, 1, 1, 0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ highMaxSpinner = new JSpinner(\r
+ new SpinnerNumberModel(new Float(0), new Float(-99999), new Float(99999), new Float(1f)));\r
+ formPanel.add(highMaxSpinner, new GridBagConstraints(4, 1, 1, 1, 0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(0, 6, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ highRangeButton = new JButton("<");\r
+ highRangeButton.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));\r
+ formPanel.add(highRangeButton, new GridBagConstraints(5, 1, 1, 1, 0.0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(0, 1, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ JLabel label = new JLabel("Low:");\r
+ formPanel.add(label, new GridBagConstraints(2, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ lowMinSpinner = new JSpinner(new SpinnerNumberModel(new Float(0), new Float(-99999), new Float(99999), new Float(1f)));\r
+ formPanel.add(lowMinSpinner, new GridBagConstraints(3, 2, 1, 1, 0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ lowMaxSpinner = new JSpinner(new SpinnerNumberModel(new Float(0), new Float(-99999), new Float(99999), new Float(1f)));\r
+ formPanel.add(lowMaxSpinner, new GridBagConstraints(4, 2, 1, 1, 0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(0, 6, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ lowRangeButton = new JButton("<");\r
+ lowRangeButton.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));\r
+ formPanel.add(lowRangeButton, new GridBagConstraints(5, 2, 1, 1, 0.0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(0, 1, 0, 0), 0, 0));\r
+ }\r
+ }\r
+ {\r
+ chart = new Chart(chartTitle) {\r
+ public void pointsChanged () {\r
+ value.setTimeline(chart.getValuesX());\r
+ value.setScaling(chart.getValuesY());\r
+ }\r
+ };\r
+ contentPanel.add(chart, new GridBagConstraints(6, 5, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ chart.setPreferredSize(new Dimension(150, 30));\r
+ }\r
+ {\r
+ expandButton = new JButton("+");\r
+ contentPanel.add(expandButton, new GridBagConstraints(7, 5, 1, 1, 1, 0, GridBagConstraints.SOUTHWEST,\r
+ GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0));\r
+ expandButton.setBorder(BorderFactory.createEmptyBorder(4, 8, 4, 8));\r
+ }\r
+ {\r
+ relativeCheckBox = new JCheckBox("Relative");\r
+ contentPanel.add(relativeCheckBox, new GridBagConstraints(7, 5, 1, 1, 0, 0, GridBagConstraints.NORTHWEST,\r
+ GridBagConstraints.NONE, new Insets(0, 6, 0, 0), 0, 0));\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.awt.Dimension;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+\r
+import javax.swing.DefaultComboBoxModel;\r
+import javax.swing.JCheckBox;\r
+import javax.swing.JComboBox;\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter.SpawnEllipseSide;\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter.SpawnShape;\r
+import com.badlogic.gdx.graphics.particles.ParticleEmitter.SpawnShapeValue;\r
+\r
+class SpawnPanel extends EditorPanel {\r
+ JComboBox shapeCombo;\r
+ JCheckBox edgesCheckbox;\r
+ JLabel edgesLabel;\r
+ JComboBox sideCombo;\r
+ JLabel sideLabel;\r
+\r
+ public SpawnPanel (final SpawnShapeValue spawnShapeValue, final ParticleEditor editor) {\r
+ super("Spawn", null);\r
+\r
+ initializeComponents();\r
+\r
+ edgesCheckbox.setSelected(spawnShapeValue.isEdges());\r
+ sideCombo.setSelectedItem(spawnShapeValue.getShape());\r
+\r
+ shapeCombo.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ SpawnShape shape = (SpawnShape)shapeCombo.getSelectedItem();\r
+ spawnShapeValue.setShape(shape);\r
+ switch (shape) {\r
+ case line:\r
+ case square:\r
+ setEdgesVisible(false);\r
+ editor.setVisible("Spawn Width", true);\r
+ editor.setVisible("Spawn Height", true);\r
+ break;\r
+ case ellipse:\r
+ setEdgesVisible(true);\r
+ editor.setVisible("Spawn Width", true);\r
+ editor.setVisible("Spawn Height", true);\r
+ break;\r
+ case point:\r
+ setEdgesVisible(false);\r
+ editor.setVisible("Spawn Width", false);\r
+ editor.setVisible("Spawn Height", false);\r
+ break;\r
+ }\r
+ }\r
+ });\r
+\r
+ edgesCheckbox.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ spawnShapeValue.setEdges(edgesCheckbox.isSelected());\r
+ setEdgesVisible(true);\r
+ }\r
+ });\r
+\r
+ sideCombo.addActionListener(new ActionListener() {\r
+ public void actionPerformed (ActionEvent event) {\r
+ SpawnEllipseSide side = (SpawnEllipseSide)sideCombo.getSelectedItem();\r
+ spawnShapeValue.setSide(side);\r
+ }\r
+ });\r
+\r
+ shapeCombo.setSelectedItem(spawnShapeValue.getShape());\r
+ }\r
+\r
+ public void update (ParticleEditor editor) {\r
+ shapeCombo.setSelectedItem(editor.getEmitter().getSpawnShape().getShape());\r
+ }\r
+\r
+ void setEdgesVisible (boolean visible) {\r
+ edgesCheckbox.setVisible(visible);\r
+ edgesLabel.setVisible(visible);\r
+ visible = visible && edgesCheckbox.isSelected();\r
+ sideCombo.setVisible(visible);\r
+ sideLabel.setVisible(visible);\r
+ }\r
+\r
+ private void initializeComponents () {\r
+ JPanel contentPanel = getContentPanel();\r
+ {\r
+ JLabel label = new JLabel("Shape:");\r
+ contentPanel.add(label, new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ shapeCombo = new JComboBox();\r
+ shapeCombo.setModel(new DefaultComboBoxModel(SpawnShape.values()));\r
+ contentPanel.add(shapeCombo, new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ edgesLabel = new JLabel("Edges:");\r
+ contentPanel.add(edgesLabel, new GridBagConstraints(2, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 12, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ edgesCheckbox = new JCheckBox();\r
+ contentPanel.add(edgesCheckbox, new GridBagConstraints(3, 1, 1, 1, 0, 0, GridBagConstraints.WEST,\r
+ GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ sideLabel = new JLabel("Side:");\r
+ contentPanel.add(sideLabel, new GridBagConstraints(4, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE,\r
+ new Insets(0, 12, 0, 6), 0, 0));\r
+ }\r
+ {\r
+ sideCombo = new JComboBox();\r
+ sideCombo.setModel(new DefaultComboBoxModel(SpawnEllipseSide.values()));\r
+ contentPanel.add(sideCombo, new GridBagConstraints(5, 1, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ {\r
+ JPanel spacer = new JPanel();\r
+ spacer.setPreferredSize(new Dimension());\r
+ contentPanel.add(spacer, new GridBagConstraints(6, 0, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,\r
+ new Insets(0, 0, 0, 0), 0, 0));\r
+ }\r
+ }\r
+}\r
}\r
\r
public void setClipRect (Rect rect) {\r
- if (rendering) spriteBatch.renderMesh();\r
+ if (rendering) spriteBatch.flush();\r
if (rect == null) {\r
Gdx.gl.glDisable(GL10.GL_SCISSOR_TEST);\r
hasScissor = false;\r
* \r
*/\r
public enum FileType {\r
- Internal, External, Absolut\r
+ Internal, External, Absolute\r
}\r
\r
/**\r
spriteBatch.draw(texture, vertices, 0, 20);\r
}\r
\r
+ public void setTexture (Texture texture) {\r
+ this.texture = texture;\r
+ }\r
+\r
public Texture getTexture () {\r
return texture;\r
}\r
idx += length;\r
}\r
\r
- public void renderMesh () {\r
+ /**\r
+ * Causes any pending sprites to be rendered, without ending the SpriteBatch.\r
+ */\r
+ public void flush () {\r
+ renderMesh();\r
+ }\r
+ \r
+ private void renderMesh () {\r
if (idx == 0) return;\r
\r
renderCalls++;\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.File;\r
+import java.io.FileWriter;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.InputStreamReader;\r
+import java.io.Writer;\r
+import java.util.ArrayList;\r
+\r
+import com.badlogic.gdx.Files.FileType;\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.GdxRuntimeException;\r
+import com.badlogic.gdx.files.FileHandle;\r
+import com.badlogic.gdx.graphics.SpriteBatch;\r
+import com.badlogic.gdx.graphics.Texture.TextureFilter;\r
+import com.badlogic.gdx.graphics.Texture.TextureWrap;\r
+\r
+// BOZO - Cache particle images? Or add hook to customize loading of particle images?\r
+\r
+public class ParticleEffect {\r
+ private ArrayList<ParticleEmitter> emitters = new ArrayList();\r
+\r
+ public void start () {\r
+ for (ParticleEmitter particles : emitters)\r
+ particles.start();\r
+ }\r
+\r
+ public void draw (SpriteBatch spriteBatch, float delta) {\r
+ for (int i = 0, n = emitters.size(); i < n; i++)\r
+ emitters.get(i).draw(spriteBatch, delta);\r
+ }\r
+\r
+ public void allowCompletion () {\r
+ for (int i = 0, n = emitters.size(); i < n; i++) {\r
+ ParticleEmitter emitter = emitters.get(i);\r
+ emitter.setContinuous(false);\r
+ emitter.durationTimer = emitter.duration;\r
+ }\r
+ }\r
+\r
+ public boolean isComplete () {\r
+ for (int i = 0, n = emitters.size(); i < n; i++) {\r
+ ParticleEmitter emitter = emitters.get(i);\r
+ if (emitter.isContinuous()) return false;\r
+ if (!emitter.isComplete()) return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ public void setDuration (int duration) {\r
+ for (int i = 0, n = emitters.size(); i < n; i++) {\r
+ ParticleEmitter emitter = emitters.get(i);\r
+ emitter.setContinuous(false);\r
+ emitter.duration = duration;\r
+ emitter.durationTimer = 0;\r
+ }\r
+ }\r
+\r
+ public void setPosition (int x, int y) {\r
+ for (int i = 0, n = emitters.size(); i < n; i++)\r
+ emitters.get(i).setPosition(x, y);\r
+ }\r
+\r
+ public ArrayList<ParticleEmitter> getEmitters () {\r
+ return emitters;\r
+ }\r
+\r
+ public void save (File file) {\r
+ Writer output = null;\r
+ try {\r
+ output = new FileWriter(file);\r
+ int index = 0;\r
+ for (int i = 0, n = emitters.size(); i < n; i++) {\r
+ ParticleEmitter emitter = emitters.get(i);\r
+ if (index++ > 0) output.write("\n\n");\r
+ emitter.save(output);\r
+ output.write("- Image Path -\n");\r
+ output.write(emitter.getImagePath() + "\n");\r
+ }\r
+ } catch (IOException ex) {\r
+ throw new GdxRuntimeException("Error saving effect: " + file, ex);\r
+ } finally {\r
+ try {\r
+ if (output != null) output.close();\r
+ } catch (IOException ex) {\r
+ }\r
+ }\r
+ }\r
+\r
+ public void load (FileHandle effectFile, String imagesDir, FileType fileType) {\r
+ loadEmitters(effectFile);\r
+ loadEmitterImages(imagesDir, fileType);\r
+ }\r
+\r
+ void loadEmitters (FileHandle file) {\r
+ InputStream input = file.getInputStream();\r
+ if (input == null) throw new GdxRuntimeException("Effect file not found: " + file);\r
+ emitters.clear();\r
+ BufferedReader reader = null;\r
+ try {\r
+ reader = new BufferedReader(new InputStreamReader(input), 512);\r
+ while (true) {\r
+ ParticleEmitter emitter = new ParticleEmitter(reader);\r
+ reader.readLine();\r
+ emitter.setImagePath(ParticleEmitter.readString(reader, "Image Path"));\r
+ emitters.add(emitter);\r
+ if (reader.readLine() == null) break;\r
+ if (reader.readLine() == null) break;\r
+ }\r
+ } catch (IOException ex) {\r
+ throw new GdxRuntimeException("Error loading effect: " + file, ex);\r
+ } finally {\r
+ try {\r
+ if (reader != null) reader.close();\r
+ } catch (IOException ex) {\r
+ }\r
+ }\r
+ }\r
+\r
+ private void loadEmitterImages (String imagesDir, FileType fileType) {\r
+ imagesDir = imagesDir.replace('\\', '/');\r
+ if (!imagesDir.endsWith("/")) imagesDir += '/';\r
+ for (int i = 0, n = emitters.size(); i < n; i++) {\r
+ ParticleEmitter emitter = emitters.get(i);\r
+ String imagePath = emitter.getImagePath();\r
+ if (imagePath == null) continue;\r
+ imagePath = imagesDir + new File(imagePath).getName();\r
+ emitter.setTexture(Gdx.graphics.newTexture(Gdx.files.getFileHandle(imagePath, fileType), TextureFilter.Linear,\r
+ TextureFilter.Linear, TextureWrap.ClampToEdge, TextureWrap.ClampToEdge));\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+package com.badlogic.gdx.graphics.particles;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.IOException;\r
+import java.io.Writer;\r
+import java.util.BitSet;\r
+\r
+import com.badlogic.gdx.Files.FileType;\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.graphics.GL10;\r
+import com.badlogic.gdx.graphics.Sprite;\r
+import com.badlogic.gdx.graphics.SpriteBatch;\r
+import com.badlogic.gdx.graphics.Texture;\r
+import com.badlogic.gdx.graphics.Texture.TextureFilter;\r
+import com.badlogic.gdx.graphics.Texture.TextureWrap;\r
+import com.badlogic.gdx.utils.MathUtils;\r
+\r
+// BOZO - Support point particles?\r
+// BOZO - Add a duplicate emitter button.\r
+\r
+public class ParticleEmitter {\r
+ private RangedNumericValue delayValue = new RangedNumericValue();\r
+ private ScaledNumericValue lifeOffsetValue = new ScaledNumericValue();\r
+ private RangedNumericValue durationValue = new RangedNumericValue();\r
+ private ScaledNumericValue lifeValue = new ScaledNumericValue();\r
+ private ScaledNumericValue emissionValue = new ScaledNumericValue();\r
+ private ScaledNumericValue sizeValue = new ScaledNumericValue();\r
+ private ScaledNumericValue rotationValue = new ScaledNumericValue();\r
+ private ScaledNumericValue velocityValue = new ScaledNumericValue();\r
+ private ScaledNumericValue angleValue = new ScaledNumericValue();\r
+ private ScaledNumericValue windValue = new ScaledNumericValue();\r
+ private ScaledNumericValue gravityValue = new ScaledNumericValue();\r
+ private ScaledNumericValue transparencyValue = new ScaledNumericValue();\r
+ private GradientColorValue tintValue = new GradientColorValue();\r
+ private RangedNumericValue xOffsetValue = new ScaledNumericValue();\r
+ private RangedNumericValue yOffsetValue = new ScaledNumericValue();\r
+ private ScaledNumericValue spawnWidthValue = new ScaledNumericValue();\r
+ private ScaledNumericValue spawnHeightValue = new ScaledNumericValue();\r
+ private SpawnShapeValue spawnShapeValue = new SpawnShapeValue();\r
+\r
+ private Texture texture;\r
+ private Particle[] particles;\r
+ private int minParticleCount, maxParticleCount = 4;\r
+ private float imageAspectRatio;\r
+ private int x, y;\r
+ private String name;\r
+ private String imagePath;\r
+ private int activeCount;\r
+ private BitSet active;\r
+ private boolean firstUpdate;\r
+ private boolean flipX, flipY;\r
+\r
+ private float emission, emissionDiff, emissionDelta;\r
+ private float lifeOffset, lifeOffsetDiff;\r
+ private float life, lifeDiff;\r
+ private int spawnWidth, spawnWidthDiff;\r
+ private int spawnHeight, spawnHeightDiff;\r
+ public float duration = 1, durationTimer;\r
+ private float delay, delayTimer;\r
+\r
+ private boolean attached;\r
+ private boolean continuous;\r
+ private boolean aligned;\r
+ private boolean behind;\r
+ private boolean additive = true;\r
+\r
+ public ParticleEmitter () {\r
+ this((Texture)null);\r
+ }\r
+\r
+ public ParticleEmitter (Texture texture) {\r
+ this.texture = texture;\r
+\r
+ initialize();\r
+\r
+ durationValue.setLow(3, 3);\r
+\r
+ emissionValue.setHigh(10, 10);\r
+\r
+ lifeValue.setHigh(1, 1);\r
+\r
+ sizeValue.setHigh(32, 32);\r
+\r
+ rotationValue.setLow(1, 360);\r
+ rotationValue.setHigh(180, 180);\r
+ rotationValue.setTimeline(new float[] {0, 1});\r
+ rotationValue.setScaling(new float[] {0, 1});\r
+ rotationValue.setRelative(true);\r
+\r
+ angleValue.setHigh(1, 360);\r
+ angleValue.setActive(true);\r
+\r
+ velocityValue.setHigh(80, 80);\r
+ velocityValue.setActive(true);\r
+\r
+ transparencyValue.setHigh(1, 1);\r
+ transparencyValue.setTimeline(new float[] {0, 0.2f, 0.8f, 1});\r
+ transparencyValue.setScaling(new float[] {0, 1, 1, 0});\r
+ }\r
+\r
+ public ParticleEmitter (BufferedReader reader) throws IOException {\r
+ initialize();\r
+ load(reader);\r
+ }\r
+\r
+ public ParticleEmitter (ParticleEmitter emitter) {\r
+ texture = emitter.texture;\r
+ imageAspectRatio = emitter.imageAspectRatio;\r
+ setMaxParticleCount(emitter.maxParticleCount);\r
+ minParticleCount = emitter.minParticleCount;\r
+ delayValue.load(emitter.delayValue);\r
+ durationValue.load(emitter.durationValue);\r
+ emissionValue.load(emitter.emissionValue);\r
+ lifeValue.load(emitter.lifeValue);\r
+ lifeOffsetValue.load(emitter.lifeOffsetValue);\r
+ sizeValue.load(emitter.sizeValue);\r
+ rotationValue.load(emitter.rotationValue);\r
+ velocityValue.load(emitter.velocityValue);\r
+ angleValue.load(emitter.angleValue);\r
+ windValue.load(emitter.windValue);\r
+ gravityValue.load(emitter.gravityValue);\r
+ transparencyValue.load(emitter.transparencyValue);\r
+ tintValue.load(emitter.tintValue);\r
+ xOffsetValue.load(emitter.xOffsetValue);\r
+ yOffsetValue.load(emitter.yOffsetValue);\r
+ spawnWidthValue.load(emitter.spawnWidthValue);\r
+ spawnHeightValue.load(emitter.spawnHeightValue);\r
+ spawnShapeValue.load(emitter.spawnShapeValue);\r
+ attached = emitter.attached;\r
+ continuous = emitter.continuous;\r
+ aligned = emitter.aligned;\r
+ behind = emitter.behind;\r
+ additive = emitter.additive;\r
+ }\r
+\r
+ private void initialize () {\r
+ durationValue.setAlwaysActive(true);\r
+ emissionValue.setAlwaysActive(true);\r
+ lifeValue.setAlwaysActive(true);\r
+ sizeValue.setAlwaysActive(true);\r
+ transparencyValue.setAlwaysActive(true);\r
+ spawnShapeValue.setAlwaysActive(true);\r
+ spawnWidthValue.setAlwaysActive(true);\r
+ spawnHeightValue.setAlwaysActive(true);\r
+ }\r
+\r
+ public void setMaxParticleCount (int maxParticleCount) {\r
+ this.maxParticleCount = maxParticleCount;\r
+ active = new BitSet(maxParticleCount);\r
+ activeCount = 0;\r
+ particles = new Particle[maxParticleCount];\r
+ }\r
+\r
+ public void addParticle () {\r
+ int activeCount = this.activeCount;\r
+ if (activeCount == maxParticleCount) return;\r
+ BitSet active = this.active;\r
+ int index = active.nextClearBit(0);\r
+ activateParticle(index);\r
+ active.set(index);\r
+ this.activeCount = activeCount + 1;\r
+ }\r
+\r
+ public void addParticles (int count) {\r
+ count = Math.min(count, maxParticleCount - activeCount);\r
+ if (count == 0) return;\r
+ BitSet active = this.active;\r
+ for (int i = 0; i < count; i++) {\r
+ int index = active.nextClearBit(0);\r
+ activateParticle(index);\r
+ active.set(index);\r
+ }\r
+ this.activeCount += count;\r
+ }\r
+\r
+ public void draw (SpriteBatch spriteBatch, float delta) {\r
+ delta = Math.min(delta, 0.250f);\r
+\r
+ if (additive) spriteBatch.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);\r
+\r
+ BitSet active = this.active;\r
+ int activeCount = this.activeCount;\r
+ int index = 0;\r
+ while (true) {\r
+ index = active.nextSetBit(index);\r
+ if (index == -1) break;\r
+ if (updateParticle(index, delta))\r
+ particles[index].draw(spriteBatch);\r
+ else {\r
+ active.clear(index);\r
+ activeCount--;\r
+ }\r
+ index++;\r
+ }\r
+ this.activeCount = activeCount;\r
+\r
+ if (additive) spriteBatch.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);\r
+\r
+ if (delayTimer < delay) {\r
+ delayTimer += delta;\r
+ return;\r
+ }\r
+\r
+ if (firstUpdate) {\r
+ firstUpdate = false;\r
+ addParticle();\r
+ }\r
+\r
+ if (durationTimer < duration)\r
+ durationTimer += delta;\r
+ else {\r
+ if (!continuous) return;\r
+ restart();\r
+ }\r
+\r
+ emissionDelta += delta;\r
+ float emissionTime = emission + emissionDiff * emissionValue.getScale(durationTimer / (float)duration);\r
+ if (emissionTime > 0) {\r
+ emissionTime = 1 / emissionTime;\r
+ if (emissionDelta >= emissionTime) {\r
+ int emitCount = (int)(emissionDelta / emissionTime);\r
+ emitCount = Math.min(emitCount, maxParticleCount - activeCount);\r
+ emissionDelta -= emitCount * emissionTime;\r
+ emissionDelta %= emissionTime;\r
+ addParticles(emitCount);\r
+ }\r
+ }\r
+ if (activeCount < minParticleCount) addParticles(minParticleCount - activeCount);\r
+ }\r
+\r
+ public void start () {\r
+ firstUpdate = true;\r
+ restart();\r
+ }\r
+\r
+ private void restart () {\r
+ delay = delayValue.active ? delayValue.newLowValue() : 0;\r
+ delayTimer = 0;\r
+\r
+ durationTimer -= duration;\r
+ duration = durationValue.newLowValue();\r
+\r
+ emission = emissionValue.newLowValue();\r
+ emissionDiff = emissionValue.newHighValue();\r
+ if (!emissionValue.isRelative()) emissionDiff -= emission;\r
+\r
+ life = lifeValue.newLowValue();\r
+ lifeDiff = lifeValue.newHighValue();\r
+ if (!lifeValue.isRelative()) lifeDiff -= life;\r
+\r
+ lifeOffset = lifeOffsetValue.active ? lifeOffsetValue.newLowValue() : 0;\r
+ lifeOffsetDiff = lifeOffsetValue.newHighValue();\r
+ if (!lifeOffsetValue.isRelative()) lifeOffsetDiff -= lifeOffset;\r
+\r
+ spawnWidth = (int)spawnWidthValue.newLowValue();\r
+ spawnWidthDiff = (int)spawnWidthValue.newHighValue();\r
+ if (!spawnWidthValue.isRelative()) spawnWidthDiff -= spawnWidth;\r
+\r
+ spawnHeight = (int)spawnHeightValue.newLowValue();\r
+ spawnHeightDiff = (int)spawnHeightValue.newHighValue();\r
+ if (!spawnHeightValue.isRelative()) spawnHeightDiff -= spawnHeight;\r
+ }\r
+\r
+ public void activateParticle (int index) {\r
+ Particle particle = particles[index];\r
+ if (particle == null) {\r
+ particles[index] = particle = new Particle(texture);\r
+ particle.flip(flipX, flipY);\r
+ }\r
+\r
+ float percent = durationTimer / (float)duration;\r
+\r
+ float offsetTime = lifeOffset + lifeOffsetDiff * lifeOffsetValue.getScale(percent);\r
+ particle.life = particle.currentLife = life + lifeDiff * lifeValue.getScale(percent);\r
+\r
+ if (velocityValue.active) {\r
+ particle.velocity = velocityValue.newLowValue();\r
+ particle.velocityDiff = velocityValue.newHighValue();\r
+ if (!velocityValue.isRelative()) particle.velocityDiff -= particle.velocity;\r
+ }\r
+\r
+ particle.angle = angleValue.newLowValue();\r
+ particle.angleDiff = angleValue.newHighValue();\r
+ if (!angleValue.isRelative()) particle.angleDiff -= particle.angle;\r
+\r
+ particle.size = sizeValue.newLowValue() / texture.getWidth();\r
+ particle.sizeDiff = sizeValue.newHighValue() / texture.getWidth();\r
+ if (!sizeValue.isRelative()) particle.sizeDiff -= particle.size;\r
+\r
+ if (rotationValue.active) {\r
+ particle.rotation = particle.currentRotation = rotationValue.newLowValue();\r
+ particle.rotationDiff = rotationValue.newHighValue();\r
+ if (!rotationValue.isRelative()) particle.rotationDiff -= particle.rotation;\r
+ }\r
+\r
+ if (windValue.active) {\r
+ particle.wind = windValue.newLowValue();\r
+ particle.windDiff = windValue.newHighValue();\r
+ if (!windValue.isRelative()) particle.windDiff -= particle.wind;\r
+ }\r
+\r
+ if (gravityValue.active) {\r
+ particle.gravity = gravityValue.newLowValue();\r
+ particle.gravityDiff = gravityValue.newHighValue();\r
+ if (!gravityValue.isRelative()) particle.gravityDiff -= particle.gravity;\r
+ }\r
+\r
+ particle.transparency = transparencyValue.newLowValue();\r
+ particle.transparencyDiff = transparencyValue.newHighValue() - particle.transparency;\r
+\r
+ // Spawn.\r
+ int x = this.x;\r
+ if (xOffsetValue.active) x += (int)xOffsetValue.newLowValue();\r
+ int y = this.y;\r
+ if (yOffsetValue.active) y += (int)yOffsetValue.newLowValue();\r
+ switch (spawnShapeValue.shape) {\r
+ case square: {\r
+ int width = spawnWidth + (int)(spawnWidthDiff * spawnWidthValue.getScale(percent));\r
+ int height = spawnHeight + (int)(spawnHeightDiff * spawnHeightValue.getScale(percent));\r
+ x += MathUtils.random(width) - width / 2;\r
+ y += MathUtils.random(height) - height / 2;\r
+ break;\r
+ }\r
+ case ellipse: {\r
+ int width = spawnWidth + (int)(spawnWidthDiff * spawnWidthValue.getScale(percent));\r
+ int height = spawnHeight + (int)(spawnHeightDiff * spawnHeightValue.getScale(percent));\r
+ int radiusX = width / 2;\r
+ int radiusY = height / 2;\r
+ if (radiusX == 0 || radiusY == 0) break;\r
+ float scaleY = radiusX / (float)radiusY;\r
+ if (spawnShapeValue.edges) {\r
+ float angle;\r
+ switch (spawnShapeValue.side) {\r
+ case top:\r
+ angle = -MathUtils.random(179f);\r
+ break;\r
+ case bottom:\r
+ angle = MathUtils.random(179f);\r
+ break;\r
+ default:\r
+ angle = MathUtils.random(360f);\r
+ break;\r
+ }\r
+ x += MathUtils.cosDeg(angle) * radiusX;\r
+ y += MathUtils.sinDeg(angle) * radiusX / scaleY;\r
+ } else {\r
+ int radius2 = radiusX * radiusX;\r
+ while (true) {\r
+ int px = MathUtils.random(width) - radiusX;\r
+ int py = MathUtils.random(width) - radiusX;\r
+ if (px * px + py * py <= radius2) {\r
+ x += px;\r
+ y += py / scaleY;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ case line: {\r
+ int width = spawnWidth + (int)(spawnWidthDiff * spawnWidthValue.getScale(percent));\r
+ int height = spawnHeight + (int)(spawnHeightDiff * spawnHeightValue.getScale(percent));\r
+ if (width != 0) {\r
+ float lineX = width * MathUtils.random();\r
+ x += lineX;\r
+ y += lineX * (height / (float)width);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ particle.setRotation(particle.currentRotation);\r
+ particle.setBounds(x - texture.getWidth() / 2, y - texture.getHeight() / 2, texture.getWidth(), texture.getHeight());\r
+\r
+ updateParticle(index, offsetTime);\r
+ }\r
+\r
+ public boolean updateParticle (int index, float delta) {\r
+ Particle particle = particles[index];\r
+ float life = particle.currentLife - delta;\r
+ if (life <= 0) return false;\r
+ particle.currentLife = life;\r
+\r
+ float percent = 1 - particle.currentLife / particle.life;\r
+\r
+ particle.setScale(particle.size + particle.sizeDiff * sizeValue.getScale(percent));\r
+\r
+ float angle = particle.angle + particle.angleDiff * angleValue.getScale(percent);\r
+\r
+ if (rotationValue.active) {\r
+ float rotation = particle.rotation + particle.rotationDiff * rotationValue.getScale(percent);\r
+ if (aligned) rotation += angle;\r
+ rotation -= particle.currentRotation;\r
+ if (rotation != 0) {\r
+ particle.currentRotation += rotation;\r
+ particle.rotate(rotation);\r
+ }\r
+ }\r
+\r
+ if (velocityValue.active) {\r
+ float velocity = (particle.velocity + particle.velocityDiff * velocityValue.getScale(percent)) * delta;\r
+ float velocityX = velocity;\r
+ float velocityY = velocity;\r
+ if (angleValue.active) {\r
+ velocityX *= MathUtils.cosDeg(angle);\r
+ velocityY *= MathUtils.sinDeg(angle);\r
+ }\r
+ if (windValue.active) velocityX += (particle.wind + particle.windDiff * windValue.getScale(percent)) * delta;\r
+ if (gravityValue.active)\r
+ velocityY += (particle.gravity + particle.gravityDiff * gravityValue.getScale(percent)) * delta;\r
+ particle.translate(velocityX, velocityY);\r
+ }\r
+\r
+ float[] color = tintValue.getColor(percent);\r
+ particle.setColor(color[0], color[1], color[2],\r
+ particle.transparency + particle.transparencyDiff * transparencyValue.getScale(percent));\r
+\r
+ return true;\r
+ }\r
+\r
+ public void setPosition (int x, int y) {\r
+ if (attached) {\r
+ int xAmount = x - this.x;\r
+ int yAmount = y - this.y;\r
+ BitSet active = this.active;\r
+ int index = 0;\r
+ while (true) {\r
+ index = active.nextSetBit(index);\r
+ if (index == -1) break;\r
+ Particle particle = particles[index];\r
+ particle.translate(xAmount, yAmount);\r
+ index++;\r
+ }\r
+ }\r
+ this.x = x;\r
+ this.y = y;\r
+ }\r
+\r
+ public void setTexture (Texture texture) {\r
+ this.texture = texture;\r
+ if (texture == null) return;\r
+ imageAspectRatio = texture.getHeight() / (float)texture.getWidth();\r
+ float originX = texture.getWidth() / 2;\r
+ float originY = texture.getHeight() / 2;\r
+ for (int i = 0, n = particles.length; i < n; i++) {\r
+ Particle particle = particles[i];\r
+ if (particle == null) break;\r
+ particle.setTexture(texture);\r
+ particle.setOrigin(originX, originY);\r
+ }\r
+ }\r
+\r
+ public Texture getTexture () {\r
+ return texture;\r
+ }\r
+\r
+ public String getName () {\r
+ return name;\r
+ }\r
+\r
+ public void setName (String name) {\r
+ this.name = name;\r
+ }\r
+\r
+ public ScaledNumericValue getLife () {\r
+ return lifeValue;\r
+ }\r
+\r
+ public ScaledNumericValue getSize () {\r
+ return sizeValue;\r
+ }\r
+\r
+ public ScaledNumericValue getRotation () {\r
+ return rotationValue;\r
+ }\r
+\r
+ public GradientColorValue getTint () {\r
+ return tintValue;\r
+ }\r
+\r
+ public ScaledNumericValue getVelocity () {\r
+ return velocityValue;\r
+ }\r
+\r
+ public ScaledNumericValue getWind () {\r
+ return windValue;\r
+ }\r
+\r
+ public ScaledNumericValue getGravity () {\r
+ return gravityValue;\r
+ }\r
+\r
+ public ScaledNumericValue getAngle () {\r
+ return angleValue;\r
+ }\r
+\r
+ public ScaledNumericValue getEmission () {\r
+ return emissionValue;\r
+ }\r
+\r
+ public ScaledNumericValue getTransparency () {\r
+ return transparencyValue;\r
+ }\r
+\r
+ public RangedNumericValue getDuration () {\r
+ return durationValue;\r
+ }\r
+\r
+ public RangedNumericValue getDelay () {\r
+ return delayValue;\r
+ }\r
+\r
+ public ScaledNumericValue getLifeOffset () {\r
+ return lifeOffsetValue;\r
+ }\r
+\r
+ public RangedNumericValue getXOffsetValue () {\r
+ return xOffsetValue;\r
+ }\r
+\r
+ public RangedNumericValue getYOffsetValue () {\r
+ return yOffsetValue;\r
+ }\r
+\r
+ public ScaledNumericValue getSpawnWidth () {\r
+ return spawnWidthValue;\r
+ }\r
+\r
+ public ScaledNumericValue getSpawnHeight () {\r
+ return spawnHeightValue;\r
+ }\r
+\r
+ public SpawnShapeValue getSpawnShape () {\r
+ return spawnShapeValue;\r
+ }\r
+\r
+ public boolean isAttached () {\r
+ return attached;\r
+ }\r
+\r
+ public void setAttached (boolean attached) {\r
+ this.attached = attached;\r
+ }\r
+\r
+ public boolean isContinuous () {\r
+ return continuous;\r
+ }\r
+\r
+ public void setContinuous (boolean continuous) {\r
+ this.continuous = continuous;\r
+ }\r
+\r
+ public boolean isAligned () {\r
+ return aligned;\r
+ }\r
+\r
+ public void setAligned (boolean aligned) {\r
+ this.aligned = aligned;\r
+ }\r
+\r
+ public boolean isAdditive () {\r
+ return additive;\r
+ }\r
+\r
+ public void setAdditive (boolean additive) {\r
+ this.additive = additive;\r
+ }\r
+\r
+ public boolean isBehind () {\r
+ return behind;\r
+ }\r
+\r
+ public void setBehind (boolean behind) {\r
+ this.behind = behind;\r
+ }\r
+\r
+ public int getMinParticleCount () {\r
+ return minParticleCount;\r
+ }\r
+\r
+ public void setMinParticleCount (int minParticleCount) {\r
+ this.minParticleCount = minParticleCount;\r
+ }\r
+\r
+ public int getMaxParticleCount () {\r
+ return maxParticleCount;\r
+ }\r
+\r
+ public boolean isComplete () {\r
+ if (delayTimer < delay) return false;\r
+ return durationTimer >= duration && activeCount == 0;\r
+ }\r
+\r
+ public float getPercentComplete () {\r
+ if (delayTimer < delay) return 0;\r
+ return Math.min(1, durationTimer / (float)duration);\r
+ }\r
+\r
+ public int getX () {\r
+ return x;\r
+ }\r
+\r
+ public int getY () {\r
+ return y;\r
+ }\r
+\r
+ public int getActiveCount () {\r
+ return activeCount;\r
+ }\r
+\r
+ public int getDrawCount () {\r
+ return active.length();\r
+ }\r
+\r
+ public String getImagePath () {\r
+ return imagePath;\r
+ }\r
+\r
+ public void setImagePath (String imagePath) {\r
+ this.imagePath = imagePath;\r
+ }\r
+\r
+ public void setFlip (boolean flipX, boolean flipY) {\r
+ this.flipX = flipX;\r
+ this.flipY = flipY;\r
+ }\r
+\r
+ public void save (Writer output) throws IOException {\r
+ output.write(name + "\n");\r
+ output.write("- Delay -\n");\r
+ delayValue.save(output);\r
+ output.write("- Duration - \n");\r
+ durationValue.save(output);\r
+ output.write("- Count - \n");\r
+ output.write("min: " + minParticleCount + "\n");\r
+ output.write("max: " + maxParticleCount + "\n");\r
+ output.write("- Emission - \n");\r
+ emissionValue.save(output);\r
+ output.write("- Life - \n");\r
+ lifeValue.save(output);\r
+ output.write("- Life Offset - \n");\r
+ lifeOffsetValue.save(output);\r
+ output.write("- X Offset - \n");\r
+ xOffsetValue.save(output);\r
+ output.write("- Y Offset - \n");\r
+ yOffsetValue.save(output);\r
+ output.write("- Spawn Shape - \n");\r
+ spawnShapeValue.save(output);\r
+ output.write("- Spawn Width - \n");\r
+ spawnWidthValue.save(output);\r
+ output.write("- Spawn Height - \n");\r
+ spawnHeightValue.save(output);\r
+ output.write("- Size - \n");\r
+ sizeValue.save(output);\r
+ output.write("- Velocity - \n");\r
+ velocityValue.save(output);\r
+ output.write("- Angle - \n");\r
+ angleValue.save(output);\r
+ output.write("- Rotation - \n");\r
+ rotationValue.save(output);\r
+ output.write("- Wind - \n");\r
+ windValue.save(output);\r
+ output.write("- Gravity - \n");\r
+ gravityValue.save(output);\r
+ output.write("- Tint - \n");\r
+ tintValue.save(output);\r
+ output.write("- Transparency - \n");\r
+ transparencyValue.save(output);\r
+ output.write("- Options - \n");\r
+ output.write("attached: " + attached + "\n");\r
+ output.write("continuous: " + continuous + "\n");\r
+ output.write("aligned: " + aligned + "\n");\r
+ output.write("additive: " + additive + "\n");\r
+ output.write("behind: " + behind + "\n");\r
+ }\r
+\r
+ public void load (BufferedReader reader) throws IOException {\r
+ name = readString(reader, "name");\r
+ reader.readLine();\r
+ delayValue.load(reader);\r
+ reader.readLine();\r
+ durationValue.load(reader);\r
+ reader.readLine();\r
+ setMinParticleCount(readInt(reader, "minParticleCount"));\r
+ setMaxParticleCount(readInt(reader, "maxParticleCount"));\r
+ reader.readLine();\r
+ emissionValue.load(reader);\r
+ reader.readLine();\r
+ lifeValue.load(reader);\r
+ reader.readLine();\r
+ lifeOffsetValue.load(reader);\r
+ reader.readLine();\r
+ xOffsetValue.load(reader);\r
+ reader.readLine();\r
+ yOffsetValue.load(reader);\r
+ reader.readLine();\r
+ spawnShapeValue.load(reader);\r
+ reader.readLine();\r
+ spawnWidthValue.load(reader);\r
+ reader.readLine();\r
+ spawnHeightValue.load(reader);\r
+ reader.readLine();\r
+ sizeValue.load(reader);\r
+ reader.readLine();\r
+ velocityValue.load(reader);\r
+ reader.readLine();\r
+ angleValue.load(reader);\r
+ reader.readLine();\r
+ rotationValue.load(reader);\r
+ reader.readLine();\r
+ windValue.load(reader);\r
+ reader.readLine();\r
+ gravityValue.load(reader);\r
+ reader.readLine();\r
+ tintValue.load(reader);\r
+ reader.readLine();\r
+ transparencyValue.load(reader);\r
+ reader.readLine();\r
+ attached = readBoolean(reader, "attached");\r
+ continuous = readBoolean(reader, "continuous");\r
+ aligned = readBoolean(reader, "aligned");\r
+ additive = readBoolean(reader, "additive");\r
+ behind = readBoolean(reader, "behind");\r
+ }\r
+\r
+ static String readString (BufferedReader reader, String name) throws IOException {\r
+ String line = reader.readLine();\r
+ if (line == null) throw new IOException("Missing value: " + name);\r
+ return line.substring(line.indexOf(":") + 1).trim();\r
+ }\r
+\r
+ static boolean readBoolean (BufferedReader reader, String name) throws IOException {\r
+ return Boolean.parseBoolean(readString(reader, name));\r
+ }\r
+\r
+ static int readInt (BufferedReader reader, String name) throws IOException {\r
+ return Integer.parseInt(readString(reader, name));\r
+ }\r
+\r
+ static float readFloat (BufferedReader reader, String name) throws IOException {\r
+ return Float.parseFloat(readString(reader, name));\r
+ }\r
+\r
+ static class Particle extends Sprite {\r
+ float life, currentLife;\r
+ float size, sizeDiff;\r
+ float rotation, currentRotation, rotationDiff;\r
+ float velocity, velocityDiff;\r
+ float angle, angleDiff;\r
+ float transparency, transparencyDiff;\r
+ float wind, windDiff;\r
+ float gravity, gravityDiff;\r
+\r
+ public Particle (Texture texture) {\r
+ super(texture);\r
+ }\r
+ }\r
+\r
+ static public class ParticleValue {\r
+ boolean active;\r
+ boolean alwaysActive;\r
+\r
+ public void setAlwaysActive (boolean alwaysActive) {\r
+ this.alwaysActive = alwaysActive;\r
+ }\r
+\r
+ public boolean isAlwaysActive () {\r
+ return alwaysActive;\r
+ }\r
+\r
+ public boolean isActive () {\r
+ return active;\r
+ }\r
+\r
+ public void setActive (boolean active) {\r
+ this.active = active;\r
+ }\r
+\r
+ public void save (Writer output) throws IOException {\r
+ if (!alwaysActive)\r
+ output.write("active: " + active + "\n");\r
+ else\r
+ active = true;\r
+ }\r
+\r
+ public void load (BufferedReader reader) throws IOException {\r
+ if (!alwaysActive)\r
+ active = readBoolean(reader, "active");\r
+ else\r
+ active = true;\r
+ }\r
+\r
+ public void load (ParticleValue value) {\r
+ active = value.active;\r
+ alwaysActive = value.alwaysActive;\r
+ }\r
+ }\r
+\r
+ static public class NumericValue extends ParticleValue {\r
+ private float value;\r
+\r
+ public float getValue () {\r
+ return value;\r
+ }\r
+\r
+ public void setValue (float value) {\r
+ this.value = value;\r
+ }\r
+\r
+ public void save (Writer output) throws IOException {\r
+ super.save(output);\r
+ if (!active) return;\r
+ output.write("value: " + value + "\n");\r
+ }\r
+\r
+ public void load (BufferedReader reader) throws IOException {\r
+ super.load(reader);\r
+ if (!active) return;\r
+ value = readFloat(reader, "value");\r
+ }\r
+\r
+ public void load (NumericValue value) {\r
+ super.load(value);\r
+ this.value = value.value;\r
+ }\r
+ }\r
+\r
+ static public class RangedNumericValue extends ParticleValue {\r
+ private float lowMin, lowMax;\r
+\r
+ public float newLowValue () {\r
+ return lowMin + (lowMax - lowMin) * MathUtils.random();\r
+ }\r
+\r
+ public void setLow (int value) {\r
+ lowMin = value;\r
+ lowMax = value;\r
+ }\r
+\r
+ public void setLow (int min, int max) {\r
+ lowMin = min;\r
+ lowMax = max;\r
+ }\r
+\r
+ public float getLowMin () {\r
+ return lowMin;\r
+ }\r
+\r
+ public void setLowMin (float lowMin) {\r
+ this.lowMin = lowMin;\r
+ }\r
+\r
+ public float getLowMax () {\r
+ return lowMax;\r
+ }\r
+\r
+ public void setLowMax (float lowMax) {\r
+ this.lowMax = lowMax;\r
+ }\r
+\r
+ public void save (Writer output) throws IOException {\r
+ super.save(output);\r
+ if (!active) return;\r
+ output.write("lowMin: " + lowMin + "\n");\r
+ output.write("lowMax: " + lowMax + "\n");\r
+ }\r
+\r
+ public void load (BufferedReader reader) throws IOException {\r
+ super.load(reader);\r
+ if (!active) return;\r
+ lowMin = readFloat(reader, "lowMin");\r
+ lowMax = readFloat(reader, "lowMax");\r
+ }\r
+\r
+ public void load (RangedNumericValue value) {\r
+ super.load(value);\r
+ lowMax = value.lowMax;\r
+ lowMin = value.lowMin;\r
+ }\r
+ }\r
+\r
+ static public class ScaledNumericValue extends RangedNumericValue {\r
+ private float[] scaling = {1};\r
+ private float[] timeline = {0};\r
+ private float highMin, highMax;\r
+ private boolean relative;\r
+\r
+ public float newHighValue () {\r
+ return highMin + (highMax - highMin) * MathUtils.random();\r
+ }\r
+\r
+ public void setHigh (int value) {\r
+ highMin = value;\r
+ highMax = value;\r
+ }\r
+\r
+ public void setHigh (int min, int max) {\r
+ highMin = min;\r
+ highMax = max;\r
+ }\r
+\r
+ public float getHighMin () {\r
+ return highMin;\r
+ }\r
+\r
+ public void setHighMin (float highMin) {\r
+ this.highMin = highMin;\r
+ }\r
+\r
+ public float getHighMax () {\r
+ return highMax;\r
+ }\r
+\r
+ public void setHighMax (float highMax) {\r
+ this.highMax = highMax;\r
+ }\r
+\r
+ public float[] getScaling () {\r
+ return scaling;\r
+ }\r
+\r
+ public void setScaling (float[] values) {\r
+ this.scaling = values;\r
+ }\r
+\r
+ public float[] getTimeline () {\r
+ return timeline;\r
+ }\r
+\r
+ public void setTimeline (float[] timeline) {\r
+ this.timeline = timeline;\r
+ }\r
+\r
+ public boolean isRelative () {\r
+ return relative;\r
+ }\r
+\r
+ public void setRelative (boolean relative) {\r
+ this.relative = relative;\r
+ }\r
+\r
+ public float getScale (float percent) {\r
+ int endIndex = -1;\r
+ float[] timeline = this.timeline;\r
+ int n = timeline.length;\r
+ for (int i = 1; i < n; i++) {\r
+ float t = timeline[i];\r
+ if (t > percent) {\r
+ endIndex = i;\r
+ break;\r
+ }\r
+ }\r
+ if (endIndex == -1) return scaling[n - 1];\r
+ float[] scaling = this.scaling;\r
+ int startIndex = endIndex - 1;\r
+ float startValue = scaling[startIndex];\r
+ float startTime = timeline[startIndex];\r
+ return startValue + (scaling[endIndex] - startValue) * ((percent - startTime) / (timeline[endIndex] - startTime));\r
+ }\r
+\r
+ public void save (Writer output) throws IOException {\r
+ super.save(output);\r
+ if (!active) return;\r
+ output.write("highMin: " + highMin + "\n");\r
+ output.write("highMax: " + highMax + "\n");\r
+ output.write("relative: " + relative + "\n");\r
+ output.write("scalingCount: " + scaling.length + "\n");\r
+ for (int i = 0; i < scaling.length; i++)\r
+ output.write("scaling" + i + ": " + scaling[i] + "\n");\r
+ output.write("timelineCount: " + timeline.length + "\n");\r
+ for (int i = 0; i < timeline.length; i++)\r
+ output.write("timeline" + i + ": " + timeline[i] + "\n");\r
+ }\r
+\r
+ public void load (BufferedReader reader) throws IOException {\r
+ super.load(reader);\r
+ if (!active) return;\r
+ highMin = readFloat(reader, "highMin");\r
+ highMax = readFloat(reader, "highMax");\r
+ relative = readBoolean(reader, "relative");\r
+ scaling = new float[readInt(reader, "scalingCount")];\r
+ for (int i = 0; i < scaling.length; i++)\r
+ scaling[i] = readFloat(reader, "scaling" + i);\r
+ timeline = new float[readInt(reader, "timelineCount")];\r
+ for (int i = 0; i < timeline.length; i++)\r
+ timeline[i] = readFloat(reader, "timeline" + i);\r
+ }\r
+\r
+ public void load (ScaledNumericValue value) {\r
+ super.load(value);\r
+ highMax = value.highMax;\r
+ highMin = value.highMin;\r
+ scaling = new float[value.scaling.length];\r
+ System.arraycopy(value.scaling, 0, scaling, 0, scaling.length);\r
+ timeline = new float[value.timeline.length];\r
+ System.arraycopy(value.timeline, 0, timeline, 0, timeline.length);\r
+ relative = value.relative;\r
+ }\r
+ }\r
+\r
+ static public class GradientColorValue extends ParticleValue {\r
+ static private float[] temp = new float[4];\r
+\r
+ private float[] colors = {1, 1, 1};\r
+ private float[] timeline = {0};\r
+\r
+ public GradientColorValue () {\r
+ alwaysActive = true;\r
+ }\r
+\r
+ public float[] getTimeline () {\r
+ return timeline;\r
+ }\r
+\r
+ public void setTimeline (float[] timeline) {\r
+ this.timeline = timeline;\r
+ }\r
+\r
+ public float[] getColors () {\r
+ return colors;\r
+ }\r
+\r
+ public void setColors (float[] colors) {\r
+ this.colors = colors;\r
+ }\r
+\r
+ public float[] getColor (float percent) {\r
+ int startIndex = 0, endIndex = -1;\r
+ float[] timeline = this.timeline;\r
+ int n = timeline.length;\r
+ for (int i = 1; i < n; i++) {\r
+ float t = timeline[i];\r
+ if (t > percent) {\r
+ endIndex = i;\r
+ break;\r
+ }\r
+ startIndex = i;\r
+ }\r
+ float startTime = timeline[startIndex];\r
+ startIndex *= 3;\r
+ float r1 = colors[startIndex];\r
+ float g1 = colors[startIndex + 1];\r
+ float b1 = colors[startIndex + 2];\r
+ if (endIndex == -1) {\r
+ temp[0] = r1;\r
+ temp[1] = g1;\r
+ temp[2] = b1;\r
+ return temp;\r
+ }\r
+ float factor = (percent - startTime) / (timeline[endIndex] - startTime);\r
+ endIndex *= 3;\r
+ temp[0] = r1 + (colors[endIndex] - r1) * factor;\r
+ temp[1] = g1 + (colors[endIndex + 1] - g1) * factor;\r
+ temp[2] = b1 + (colors[endIndex + 2] - b1) * factor;\r
+ return temp;\r
+ }\r
+\r
+ public void save (Writer output) throws IOException {\r
+ super.save(output);\r
+ if (!active) return;\r
+ output.write("colorsCount: " + colors.length + "\n");\r
+ for (int i = 0; i < colors.length; i++)\r
+ output.write("colors" + i + ": " + colors[i] + "\n");\r
+ output.write("timelineCount: " + timeline.length + "\n");\r
+ for (int i = 0; i < timeline.length; i++)\r
+ output.write("timeline" + i + ": " + timeline[i] + "\n");\r
+ }\r
+\r
+ public void load (BufferedReader reader) throws IOException {\r
+ super.load(reader);\r
+ if (!active) return;\r
+ colors = new float[readInt(reader, "colorsCount")];\r
+ for (int i = 0; i < colors.length; i++)\r
+ colors[i] = readFloat(reader, "colors" + i);\r
+ timeline = new float[readInt(reader, "timelineCount")];\r
+ for (int i = 0; i < timeline.length; i++)\r
+ timeline[i] = readFloat(reader, "timeline" + i);\r
+ }\r
+\r
+ public void load (GradientColorValue value) {\r
+ super.load(value);\r
+ colors = new float[3];\r
+ System.arraycopy(value.colors, 0, colors, 0, colors.length);\r
+ timeline = new float[value.timeline.length];\r
+ System.arraycopy(value.timeline, 0, timeline, 0, timeline.length);\r
+ }\r
+ }\r
+\r
+ static public class SpawnShapeValue extends ParticleValue {\r
+ SpawnShape shape = SpawnShape.point;\r
+ boolean edges;\r
+ SpawnEllipseSide side = SpawnEllipseSide.both;\r
+\r
+ public SpawnShape getShape () {\r
+ return shape;\r
+ }\r
+\r
+ public void setShape (SpawnShape shape) {\r
+ this.shape = shape;\r
+ }\r
+\r
+ public boolean isEdges () {\r
+ return edges;\r
+ }\r
+\r
+ public void setEdges (boolean edges) {\r
+ this.edges = edges;\r
+ }\r
+\r
+ public SpawnEllipseSide getSide () {\r
+ return side;\r
+ }\r
+\r
+ public void setSide (SpawnEllipseSide side) {\r
+ this.side = side;\r
+ }\r
+\r
+ public void save (Writer output) throws IOException {\r
+ super.save(output);\r
+ if (!active) return;\r
+ output.write("shape: " + shape + "\n");\r
+ if (shape == SpawnShape.ellipse) {\r
+ output.write("edges: " + edges + "\n");\r
+ output.write("side: " + side + "\n");\r
+ }\r
+ }\r
+\r
+ public void load (BufferedReader reader) throws IOException {\r
+ super.load(reader);\r
+ if (!active) return;\r
+ shape = SpawnShape.valueOf(readString(reader, "shape"));\r
+ if (shape == SpawnShape.ellipse) {\r
+ edges = readBoolean(reader, "edges");\r
+ side = SpawnEllipseSide.valueOf(readString(reader, "side"));\r
+ }\r
+ }\r
+\r
+ public void load (SpawnShapeValue value) {\r
+ super.load(value);\r
+ shape = value.shape;\r
+ edges = value.edges;\r
+ side = value.side;\r
+ }\r
+ }\r
+\r
+ static public enum SpawnShape {\r
+ point, line, square, ellipse\r
+ }\r
+\r
+ static public enum SpawnEllipseSide {\r
+ both, top, bottom\r
+ }\r
+}\r
* Roquen on JavaGaming.org for random numbers.<br>\r
*/\r
public class MathUtils {\r
- static public final float PI = 3.1415926535897932384626433832795028841971f;\r
+ static public final float PI = 3.1415927f;\r
\r
- static private final int SIN_BITS = 14; // Adjust for accuracy.\r
+ static private final int SIN_BITS = 13; // Adjust for accuracy.\r
static private final int SIN_MASK = ~(-1 << SIN_BITS);\r
static private final int SIN_COUNT = SIN_MASK + 1;\r
\r
mul = 1;\r
add = 0;\r
}\r
- float invDiv = 1 / (((x < y) ? y : x) * INV_ATAN2_DIM_MINUS_1);\r
+ float invDiv = 1 / ((x < y ? y : x) * INV_ATAN2_DIM_MINUS_1);\r
int xi = (int)(x * invDiv);\r
int yi = (int)(y * invDiv);\r
return (atan2[yi * ATAN2_DIM + xi] + add) * mul;\r
\r
// ---\r
\r
- static public final float sqrt (float value) {\r
- // BOZO - Want to call android.util.FloatMath.sqrt, but then what to do for desktop?\r
- return (float)Math.sqrt(value);\r
- }\r
-\r
- // ---\r
-\r
static private int randomSeed = (int)System.currentTimeMillis();\r
\r
/**\r
static public final int random (int range) {\r
int seed = randomSeed * 1103515245 + 12345;\r
randomSeed = seed;\r
- return ((seed >>> 15) * (range + 1)) >>> 17;\r
+ return (seed >>> 15) * (range + 1) >>> 17;\r
}\r
\r
static public final int random (int start, int end) {\r
int seed = randomSeed * 1103515245 + 12345;\r
randomSeed = seed;\r
- return (((seed >>> 15) * ((end - start) + 1)) >>> 17) + start;\r
+ return ((seed >>> 15) * (end - start + 1) >>> 17) + start;\r
}\r
\r
static public final boolean randomBoolean () {\r
static public final float random () {\r
int seed = randomSeed * 1103515245 + 12345;\r
randomSeed = seed;\r
- return (seed >>> 8) * (1f / (1 << 24));\r
+ return (seed >>> 8) * 1f / (1 << 24);\r
}\r
\r
static public final float random (float range) {\r
int seed = randomSeed * 1103515245 + 12345;\r
randomSeed = seed;\r
- return (seed >>> 8) * (1f / (1 << 24)) * range;\r
+ return (seed >>> 8) * 1f / (1 << 24) * range;\r
}\r
\r
static public final float random (float start, float end) {\r
int seed = randomSeed * 1103515245 + 12345;\r
randomSeed = seed;\r
- return start + (seed >>> 8) * (1f / (1 << 24)) * (end - start);\r
+ return start + (seed >>> 8) * 1f / (1 << 24) * (end - start);\r
}\r
\r
// ---\r
\r
static public int nextPowerOfTwo (int value) {\r
- return 1 << (32 - Integer.numberOfLeadingZeros(value - 1));\r
+ return 1 << 32 - Integer.numberOfLeadingZeros(value - 1);\r
}\r
\r
// ---\r