OSDN Git Service

[fixed] SpriteSheet/SpriteSheetPacker bugs.
authornathan.sweet <nathan.sweet@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Sun, 21 Nov 2010 06:27:17 +0000 (06:27 +0000)
committernathan.sweet <nathan.sweet@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Sun, 21 Nov 2010 06:27:17 +0000 (06:27 +0000)
[changed] ParticleEmitter to take Sprite rather than Texture.
[added] Sprite copy constructor.
[fixed] Sprite scale bug.

extensions/image-packer/src/com/badlogic/gdx/imagepacker/SpriteSheetPacker.java
extensions/particle-editor/src/com/badlogic/gdx/graphics/particles/EffectPanel.java
extensions/particle-editor/src/com/badlogic/gdx/graphics/particles/ImagePanel.java
extensions/particle-editor/src/com/badlogic/gdx/graphics/particles/ParticleEditor.java
gdx/src/com/badlogic/gdx/graphics/Sprite.java
gdx/src/com/badlogic/gdx/graphics/SpriteSheet.java
gdx/src/com/badlogic/gdx/graphics/particles/ParticleEffect.java
gdx/src/com/badlogic/gdx/graphics/particles/ParticleEmitter.java

index 3bd59f1..a598e44 100644 (file)
@@ -43,13 +43,6 @@ public class SpriteSheetPacker {
                this.inputDir = inputDir;\r
                this.filter = filter;\r
 \r
-               minWidth = filter.width != -1 ? filter.width : settings.minWidth;\r
-               minHeight = filter.height != -1 ? filter.height : settings.minHeight;\r
-               maxWidth = filter.width != -1 ? filter.width : settings.maxWidth;\r
-               maxHeight = filter.height != -1 ? filter.height : settings.maxHeight;\r
-               xPadding = images.size() > 1 && filter.direction != Direction.x && filter.direction != Direction.xy ? settings.padding : 0;\r
-               yPadding = images.size() > 1 && filter.direction != Direction.y && filter.direction != Direction.xy ? settings.padding : 0;\r
-\r
                // Collect and squeeze images.\r
                File[] files = inputDir.listFiles(filter);\r
                if (files == null) return;\r
@@ -60,6 +53,13 @@ public class SpriteSheetPacker {
                }\r
                if (images.isEmpty()) return;\r
 \r
+               minWidth = filter.width != -1 ? filter.width : settings.minWidth;\r
+               minHeight = filter.height != -1 ? filter.height : settings.minHeight;\r
+               maxWidth = filter.width != -1 ? filter.width : settings.maxWidth;\r
+               maxHeight = filter.height != -1 ? filter.height : settings.maxHeight;\r
+               xPadding = images.size() > 1 && !filter.direction.isX() ? settings.padding : 0;\r
+               yPadding = images.size() > 1 && !filter.direction.isY() ? settings.padding : 0;\r
+\r
                System.out.println(inputDir);\r
                if (filter.format != null)\r
                        System.out.println("Format: " + filter.format);\r
@@ -87,27 +87,6 @@ public class SpriteSheetPacker {
        }\r
 \r
        private void writePage (String prefix, File outputDir) throws IOException {\r
-               // Remove existing image pages in output dir.\r
-               int imageNumber = 1;\r
-               File outputFile = new File(outputDir, prefix + imageNumber + ".png");\r
-               while (outputFile.exists())\r
-                       outputFile = new File(outputDir, prefix + ++imageNumber + ".png");\r
-\r
-               writer.write("\n" + prefix + imageNumber + ".png\n");\r
-               Format format;\r
-               if (filter.format != null) {\r
-                       writer.write("format: " + filter.format + "\n");\r
-                       format = filter.format;\r
-               } else {\r
-                       writer.write("format: " + settings.defaultFormat + "\n");\r
-                       format = settings.defaultFormat;\r
-               }\r
-               if (filter.minFilter == null || filter.magFilter == null)\r
-                       writer.write("filter: " + settings.defaultFilterMin + "," + settings.defaultFilterMag + "\n");\r
-               else\r
-                       writer.write("filter: " + filter.minFilter + "," + filter.magFilter + "\n");\r
-               writer.write("repeat: " + filter.direction + "\n");\r
-\r
                // Try reasonably hard to pack images into the smallest POT size.\r
                Comparator bestComparator = null;\r
                Comparator secondBestComparator = imageComparators.get(0);\r
@@ -118,7 +97,6 @@ public class SpriteSheetPacker {
                int grownPixels = 0, grownPixels2 = 0;\r
                int i = 0, ii = 0;\r
                while (true) {\r
-                       if (width > maxWidth && height > maxHeight) break;\r
                        for (Comparator comparator : imageComparators) {\r
                                // Pack as many images as possible, sorting the images different ways.\r
                                Collections.sort(images, comparator);\r
@@ -138,19 +116,17 @@ public class SpriteSheetPacker {
                                        }\r
                                }\r
                        }\r
+                       if (width == maxWidth && height == maxHeight) break;\r
                        if (bestComparator != null) break;\r
                        if (settings.pot) {\r
-                               // 64,64 then 64,128 then 128,64 then 128,128 then 128,256 etc.\r
-                               if (i % 3 == 0) {\r
-                                       width *= 2;\r
-                                       i++;\r
-                               } else if (i % 3 == 1) {\r
-                                       width /= 2;\r
+                               // 64,64 then 64,128 then 64,256 etc then 128,64 then 128,128 then 128,256 etc.\r
+                               grownPixels += width;\r
+                               width *= 2;\r
+                               if (width > maxWidth) {\r
+                                       width -= grownPixels;\r
+                                       grownPixels = 0;\r
                                        height *= 2;\r
-                                       i++;\r
-                               } else {\r
                                        width *= 2;\r
-                                       i++;\r
                                }\r
                        } else {\r
                                // 64-127,64 then 64,64-127 then 128-255,128 then 128,128-255 etc.\r
@@ -179,6 +155,8 @@ public class SpriteSheetPacker {
                                        i++;\r
                                }\r
                        }\r
+                       width = Math.min(maxWidth, width);\r
+                       height = Math.min(maxHeight, height);\r
                }\r
                if (bestComparator != null) {\r
                        Collections.sort(images, bestComparator);\r
@@ -195,7 +173,7 @@ public class SpriteSheetPacker {
                }\r
 \r
                int type;\r
-               switch (format) {\r
+               switch (filter.format != null ? filter.format : settings.defaultFormat) {\r
                case RGBA8888:\r
                case RGBA4444:\r
                        type = BufferedImage.TYPE_INT_ARGB;\r
@@ -209,6 +187,27 @@ public class SpriteSheetPacker {
                default:\r
                        throw new RuntimeException();\r
                }\r
+\r
+               int imageNumber = 1;\r
+               File outputFile = new File(outputDir, prefix + imageNumber + ".png");\r
+               while (outputFile.exists())\r
+                       outputFile = new File(outputDir, prefix + ++imageNumber + ".png");\r
+\r
+               writer.write("\n" + outputFile.getName() + "\n");\r
+               Format format;\r
+               if (filter.format != null) {\r
+                       writer.write("format: " + filter.format + "\n");\r
+                       format = filter.format;\r
+               } else {\r
+                       writer.write("format: " + settings.defaultFormat + "\n");\r
+                       format = settings.defaultFormat;\r
+               }\r
+               if (filter.minFilter == null || filter.magFilter == null)\r
+                       writer.write("filter: " + settings.defaultFilterMin + "," + settings.defaultFilterMag + "\n");\r
+               else\r
+                       writer.write("filter: " + filter.minFilter + "," + filter.magFilter + "\n");\r
+               writer.write("repeat: " + filter.direction + "\n");\r
+\r
                BufferedImage canvas = new BufferedImage(width, height, type);\r
                insert(canvas, images, bestWidth, bestHeight);\r
                System.out.println("Writing " + canvas.getWidth() + "x" + canvas.getHeight() + ": " + outputFile);\r
@@ -223,8 +222,8 @@ public class SpriteSheetPacker {
                        g.drawRect(0, 0, width - 1, height - 1);\r
                }\r
                // Pretend image is larger so padding on right and bottom edges is ignored.\r
-               if (filter.direction != Direction.x && filter.direction != Direction.xy) width += xPadding;\r
-               if (filter.direction != Direction.y && filter.direction != Direction.xy) height += yPadding;\r
+               if (!filter.direction.isX()) width += xPadding;\r
+               if (!filter.direction.isY()) height += yPadding;\r
                Node root = new Node(0, 0, width, height);\r
                int usedPixels = 0;\r
                for (int i = images.size() - 1; i >= 0; i--) {\r
@@ -276,7 +275,7 @@ public class SpriteSheetPacker {
                final byte[] a = new byte[1];\r
                int top = 0;\r
                int bottom = source.getHeight();\r
-               if (filter.direction != Direction.y && filter.direction != Direction.xy) {\r
+               if (!filter.direction.isY()) {\r
                        outer:\r
                        for (int y = 0; y < source.getHeight(); y++) {\r
                                for (int x = 0; x < source.getWidth(); x++) {\r
@@ -300,10 +299,10 @@ public class SpriteSheetPacker {
                }\r
                int left = 0;\r
                int right = source.getWidth();\r
-               if (filter.direction != Direction.x && filter.direction != Direction.xy) {\r
+               if (!filter.direction.isX()) {\r
                        outer:\r
                        for (int x = 0; x < source.getWidth(); x++) {\r
-                               for (int y = top; y <= bottom; y++) {\r
+                               for (int y = top; y < bottom; y++) {\r
                                        alphaRaster.getDataElements(x, y, a);\r
                                        int alpha = a[0];\r
                                        if (alpha < 0) alpha += 256;\r
@@ -313,7 +312,7 @@ public class SpriteSheetPacker {
                        }\r
                        outer:\r
                        for (int x = source.getWidth(); --x >= left;) {\r
-                               for (int y = top; y <= bottom; y++) {\r
+                               for (int y = top; y < bottom; y++) {\r
                                        alphaRaster.getDataElements(x, y, a);\r
                                        int alpha = a[0];\r
                                        if (alpha < 0) alpha += 256;\r
@@ -388,7 +387,7 @@ public class SpriteSheetPacker {
                        if (imageName.startsWith("/") || imageName.startsWith("\\")) imageName = imageName.substring(1);\r
                        int dotIndex = imageName.lastIndexOf('.');\r
                        if (dotIndex != -1) imageName = imageName.substring(0, dotIndex);\r
-                       imageName = imageName.replace("_" + filter.format, "");\r
+                       imageName = imageName.replace("_" + formatToAbbrev.get(filter.format), "");\r
                        imageName = imageName.replace("_" + filter.direction, "");\r
                        imageName = imageName.replace("_" + filterToAbbrev.get(filter.minFilter) + "," + filterToAbbrev.get(filter.magFilter),\r
                                "");\r
@@ -461,9 +460,7 @@ public class SpriteSheetPacker {
                int height = -1;\r
                Settings settings;\r
 \r
-               public Filter (Settings settings, Direction direction, Format format, int width, int height, TextureFilter minFilter,\r
-                       TextureFilter magFilter) {\r
-                       this.settings = settings;\r
+               public Filter (Direction direction, Format format, int width, int height, TextureFilter minFilter, TextureFilter magFilter) {\r
                        this.direction = direction;\r
                        this.format = format;\r
                        this.width = width;\r
@@ -523,7 +520,15 @@ public class SpriteSheetPacker {
        }\r
 \r
        static private enum Direction {\r
-               x, y, xy, none\r
+               x, y, xy, none;\r
+\r
+               public boolean isX () {\r
+                       return this == x || this == xy;\r
+               }\r
+\r
+               public boolean isY () {\r
+                       return this == y || this == xy;\r
+               }\r
        }\r
 \r
        static final HashMap<TextureFilter, String> filterToAbbrev = new HashMap();\r
@@ -561,6 +566,8 @@ public class SpriteSheetPacker {
        }\r
 \r
        static private void process (Settings settings, File inputDir, File outputDir, File packFile) throws Exception {\r
+               if (inputDir.getName().startsWith(".")) return;\r
+\r
                // Clean existing page images.\r
                if (outputDir.exists()) {\r
                        String prefix = inputDir.getName();\r
@@ -583,22 +590,22 @@ public class SpriteSheetPacker {
                                        TextureFilter mag = filters.get(iii);\r
                                        if ((min == null && mag != null) || (min != null && mag == null)) continue;\r
 \r
-                                       Filter filter = new Filter(settings, Direction.none, format, -1, -1, min, mag);\r
+                                       Filter filter = new Filter(Direction.none, format, -1, -1, min, mag);\r
                                        new SpriteSheetPacker(settings, inputDir, filter, outputDir, packFile);\r
 \r
                                        for (int width = settings.minWidth; width <= settings.maxWidth; width <<= 1) {\r
-                                               filter = new Filter(settings, Direction.x, format, width, -1, min, mag);\r
+                                               filter = new Filter(Direction.x, format, width, -1, min, mag);\r
                                                new SpriteSheetPacker(settings, inputDir, filter, outputDir, packFile);\r
                                        }\r
 \r
                                        for (int height = settings.minHeight; height <= settings.maxHeight; height <<= 1) {\r
-                                               filter = new Filter(settings, Direction.y, format, -1, height, min, mag);\r
+                                               filter = new Filter(Direction.y, format, -1, height, min, mag);\r
                                                new SpriteSheetPacker(settings, inputDir, filter, outputDir, packFile);\r
                                        }\r
 \r
                                        for (int width = settings.minWidth; width <= settings.maxWidth; width <<= 1) {\r
                                                for (int height = settings.minHeight; height <= settings.maxHeight; height <<= 1) {\r
-                                                       filter = new Filter(settings, Direction.xy, format, width, height, min, mag);\r
+                                                       filter = new Filter(Direction.xy, format, width, height, min, mag);\r
                                                        new SpriteSheetPacker(settings, inputDir, filter, outputDir, packFile);\r
                                                }\r
                                        }\r
@@ -610,7 +617,7 @@ public class SpriteSheetPacker {
                File[] files = inputDir.listFiles();\r
                if (files == null) return;\r
                for (File file : files)\r
-                       if (file.isDirectory()) process(settings, file, new File(outputDir, file.getName()), packFile);\r
+                       if (file.isDirectory()) process(settings, file, outputDir, packFile);\r
        }\r
 \r
        static public void process (Settings settings, String input, String output) throws Exception {\r
@@ -637,8 +644,7 @@ public class SpriteSheetPacker {
                }\r
                input = args[0];\r
                output = args[1];\r
-               // input = "c:/temp/pack-in";\r
-               // output = "c:/temp/pack-out";\r
-               process(new Settings(), input, output);\r
+               Settings settings = new Settings();\r
+               process(settings, input, output);\r
        }\r
 }\r
index 6189dfa..a6b8051 100644 (file)
@@ -108,7 +108,7 @@ class EffectPanel extends JPanel {
                lastDir = dir;\r
                ParticleEffect effect = new ParticleEffect();\r
                try {\r
-                       effect.loadEmitters(Gdx.files.getFileHandle(new File(dir, file).getAbsolutePath(), FileType.Absolute));\r
+                       effect.loadEmitters(Gdx.files.absolute(new File(dir, file).getAbsolutePath()));\r
                        editor.effect = effect;\r
                        emitterTableModel.getDataVector().removeAllElements();\r
                        editor.particleData.clear();\r
index c1e46c0..3a9962c 100644 (file)
@@ -44,7 +44,7 @@ class ImagePanel extends EditorPanel {
                                                heightLabel.setText("Height: " + icon.getIconHeight());\r
                                                revalidate();\r
                                                emitter.setImagePath(new File(dir, file).getAbsolutePath());\r
-                                               emitter.setTexture(null);\r
+                                               emitter.setSprite(null);\r
                                        } catch (Exception ex) {\r
                                                ex.printStackTrace();\r
                                        }\r
index 364ba03..16c1339 100644 (file)
@@ -33,6 +33,7 @@ import com.badlogic.gdx.Files.FileType;
 import com.badlogic.gdx.Gdx;\r
 import com.badlogic.gdx.InputProcessor;\r
 import com.badlogic.gdx.backends.lwjgl.LwjglCanvas;\r
+import com.badlogic.gdx.files.FileHandle;\r
 import com.badlogic.gdx.graphics.BitmapFont;\r
 import com.badlogic.gdx.graphics.Color;\r
 import com.badlogic.gdx.graphics.GL10;\r
@@ -150,6 +151,7 @@ public class ParticleEditor extends JFrame {
                ParticleData data = particleData.get(emitter);\r
                if (data == null) particleData.put(emitter, data = new ParticleData());\r
                data.enabled = enabled;\r
+               emitter.reset();\r
        }\r
 \r
        public boolean isEnabled (ParticleEmitter emitter) {\r
@@ -265,15 +267,18 @@ public class ParticleEditor extends JFrame {
                        }\r
 \r
                        activeCount = 0;\r
+                       boolean complete = true;\r
                        for (ParticleEmitter emitter : effect.getEmitters()) {\r
-                               if (emitter.getTexture() == null && emitter.getImagePath() != null) loadImage(emitter);\r
+                               if (emitter.getSprite() == null && emitter.getImagePath() != null) loadImage(emitter);\r
                                boolean enabled = isEnabled(emitter);\r
                                if (enabled) {\r
-                                       if (emitter.getTexture() != null) emitter.draw(spriteBatch, delta);\r
+                                       if (emitter.getSprite() != null) emitter.draw(spriteBatch, delta);\r
                                        activeCount += emitter.getActiveCount();\r
+                                       if (emitter.isContinuous()) complete = false;\r
+                                       if (!emitter.isComplete()) complete = false;\r
                                }\r
                        }\r
-                       if (effect.isComplete()) effect.start();\r
+                       if (complete) effect.start();\r
 \r
                        maxActive = Math.max(maxActive, activeCount);\r
                        maxActiveTimer += delta;\r
@@ -296,15 +301,22 @@ public class ParticleEditor extends JFrame {
                        spriteBatch.end();\r
 \r
                        // gl.drawLine((int)(viewWidth * getCurrentParticles().getPercentComplete()), viewHeight - 1, viewWidth, viewHeight -\r
-// 1);\r
+                       // 1);\r
                }\r
 \r
                private void loadImage (ParticleEmitter emitter) {\r
                        final String imagePath = emitter.getImagePath();\r
+                       String imageName = new File(imagePath.replace('\\', '/')).getName();\r
                        try {\r
-                               emitter.setTexture(Gdx.graphics.newTexture(Gdx.files.getFileHandle(imagePath, FileType.Absolute),\r
-                                       TextureFilter.Linear, TextureFilter.Linear, TextureWrap.ClampToEdge, TextureWrap.ClampToEdge));\r
+                               FileHandle file;\r
+                               if (imagePath.equals("particle.png"))\r
+                                       file = Gdx.files.classpath(imagePath);\r
+                               else\r
+                                       file = Gdx.files.absolute(imagePath);\r
+                               emitter.setSprite(new Sprite(Gdx.graphics.newTexture(file, TextureFilter.Linear, TextureFilter.Linear,\r
+                                       TextureWrap.ClampToEdge, TextureWrap.ClampToEdge)));\r
                        } catch (GdxRuntimeException ex) {\r
+                               ex.printStackTrace();\r
                                EventQueue.invokeLater(new Runnable() {\r
                                        public void run () {\r
                                                JOptionPane.showMessageDialog(ParticleEditor.this, "Error loading image:\n" + imagePath);\r
index 245658a..65493d8 100644 (file)
@@ -21,14 +21,14 @@ public class Sprite {
        static final int VERTEX_SIZE = 2 + 1 + 2;\r
        static final int SPRITE_SIZE = 4 * VERTEX_SIZE;\r
 \r
-       Texture texture;\r
-       private float[] vertices = new float[20];\r
+       private Texture texture;\r
+       private final float[] vertices = new float[20];\r
        private float x, y;\r
        private float width, height;\r
        private float originX, originY;\r
        private float rotation;\r
        private float scaleX = 1, scaleY = 1;\r
-       private Color color = new Color(1, 1, 1, 1);\r
+       private final Color color = new Color(1, 1, 1, 1);\r
        private boolean dirty;\r
 \r
        /**\r
@@ -101,6 +101,26 @@ public class Sprite {
        }\r
 \r
        /**\r
+        * Creates a sprite that is a copy in every way of the specified sprite.\r
+        */\r
+       public Sprite (Sprite sprite) {\r
+               if (sprite == null) throw new IllegalArgumentException("sprite cannot be null.");\r
+               texture = sprite.texture;\r
+               System.arraycopy(sprite.vertices, 0, vertices, 0, 20);\r
+               x = sprite.x;\r
+               y = sprite.y;\r
+               width = sprite.width;\r
+               height = sprite.height;\r
+               originX = sprite.originX;\r
+               originY = sprite.originY;\r
+               rotation = sprite.rotation;\r
+               scaleX = sprite.scaleX;\r
+               scaleY = sprite.scaleY;\r
+               color.set(sprite.color);\r
+               dirty = sprite.dirty;\r
+       }\r
+\r
+       /**\r
         * Sets the position and size of the sprite when drawn, before scaling and\r
         * rotation are applied. If origin, rotation, or scale are changed, it is\r
         * slightly more efficient to set the bounds after those operations.\r
@@ -415,18 +435,18 @@ public class Sprite {
                        dirty = false;\r
 \r
                        float[] vertices = this.vertices;\r
-                       float localX = -originX * scaleX;\r
-                       float localY = -originY * scaleY;\r
-                       float localX2 = (-originX + width) * scaleX;\r
-                       float localY2 = (-originY + height) * scaleY;\r
+                       float localX = -originX;\r
+                       float localY = -originY;\r
+                       float localX2 = localX + width;\r
+                       float localY2 = localY + height;\r
+                       float worldOriginX = this.x - localX;\r
+                       float worldOriginY = this.y - localY;\r
                        if (scaleX != 1 || scaleY != 1) {\r
                                localX *= scaleX;\r
                                localY *= scaleY;\r
                                localX2 *= scaleX;\r
                                localY2 *= scaleY;\r
                        }\r
-                       float worldOriginX = this.x + originX;\r
-                       float worldOriginY = this.y + originY;\r
                        if (rotation != 0) {\r
                                float cos = MathUtils.cosDeg(rotation);\r
                                float sin = MathUtils.sinDeg(rotation);\r
index 5b2175f..f45ed3b 100644 (file)
@@ -31,6 +31,10 @@ public class SpriteSheet {
        private final PackedSprite[] images;\r
 \r
        public SpriteSheet (FileHandle packFile, FileHandle imagesDir) {\r
+               this(packFile, imagesDir, false);\r
+       }\r
+\r
+       public SpriteSheet (FileHandle packFile, FileHandle imagesDir, boolean flip) {\r
                PriorityQueue<PackedSprite> sortedSprites = new PriorityQueue(16, indexComparator);\r
 \r
                BufferedReader reader = new BufferedReader(new InputStreamReader(packFile.read()), 64);\r
@@ -78,27 +82,28 @@ public class SpriteSheet {
                                        int width = Integer.parseInt(tuple[0]);\r
                                        int height = Integer.parseInt(tuple[1]);\r
 \r
-                                       PackedSprite image;\r
+                                       PackedSprite sprite;\r
                                        if (rotate) {\r
-                                               image = new PackedSprite(pageImage, left, top, height, width);\r
-                                               image.rotate90(true);\r
+                                               sprite = new PackedSprite(pageImage, left, top, height, width);\r
+                                               sprite.rotate90(true);\r
                                        } else\r
-                                               image = new PackedSprite(pageImage, left, top, width, height);\r
-                                       image.name = line;\r
+                                               sprite = new PackedSprite(pageImage, left, top, width, height);\r
+                                       sprite.name = line;\r
 \r
                                        readTuple(reader);\r
-                                       image.originalWidth = Integer.parseInt(tuple[0]);\r
-                                       image.originalHeight = Integer.parseInt(tuple[1]);\r
+                                       sprite.originalWidth = Integer.parseInt(tuple[0]);\r
+                                       sprite.originalHeight = Integer.parseInt(tuple[1]);\r
 \r
                                        readTuple(reader);\r
-                                       image.offsetX = Integer.parseInt(tuple[0]);\r
-                                       image.offsetY = Integer.parseInt(tuple[1]);\r
-                                       image.setPosition(image.offsetX, image.offsetY);\r
+                                       sprite.offsetX = Integer.parseInt(tuple[0]);\r
+                                       sprite.offsetY = Integer.parseInt(tuple[1]);\r
+                                       sprite.setPosition(sprite.offsetX, sprite.offsetY);\r
 \r
-                                       image.index = Integer.parseInt(readValue(reader));\r
-                                       if (image.index == -1) image.index = Integer.MAX_VALUE;\r
+                                       sprite.index = Integer.parseInt(readValue(reader));\r
+                                       if (sprite.index == -1) sprite.index = Integer.MAX_VALUE;\r
 \r
-                                       sortedSprites.add(image);\r
+                                       if (flip) sprite.flip(false, true);\r
+                                       sortedSprites.add(sprite);\r
                                }\r
                        }\r
                } catch (IOException ex) {\r
@@ -195,6 +200,10 @@ public class SpriteSheet {
                        super.setBounds(x + offsetX, y + offsetY, width, height);\r
                }\r
 \r
+               public void setOrigin (float originX, float originY) {\r
+                       super.setOrigin(originX + offsetX, originY + offsetY);\r
+               }\r
+\r
                /**\r
                 * The name of the original image file, with any trailing numbers or special flags removed.\r
                 */\r
index dc4bc18..19532bb 100644 (file)
@@ -10,10 +10,12 @@ import java.io.InputStreamReader;
 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.files.FileHandle;\r
+import com.badlogic.gdx.graphics.Sprite;\r
 import com.badlogic.gdx.graphics.SpriteBatch;\r
+import com.badlogic.gdx.graphics.SpriteSheet;\r
+import com.badlogic.gdx.graphics.SpriteSheet.PackedSprite;\r
 import com.badlogic.gdx.graphics.Texture;\r
 import com.badlogic.gdx.graphics.Texture.TextureFilter;\r
 import com.badlogic.gdx.graphics.Texture.TextureWrap;\r
@@ -94,8 +96,13 @@ public class ParticleEffect {
                loadEmitterImages(imagesDir);\r
        }\r
 \r
-       void loadEmitters (FileHandle file) {\r
-               InputStream input = file.read();\r
+       public void load (FileHandle effectFile, SpriteSheet spriteSheet) {\r
+               loadEmitters(effectFile);\r
+               loadEmitterImages(spriteSheet);\r
+       }\r
+\r
+       public void loadEmitters (FileHandle effectFile) {\r
+               InputStream input = effectFile.read();\r
                emitters.clear();\r
                BufferedReader reader = null;\r
                try {\r
@@ -103,13 +110,13 @@ public class ParticleEffect {
                        while (true) {\r
                                ParticleEmitter emitter = new ParticleEmitter(reader);\r
                                reader.readLine();\r
-                               emitter.setImagePath(ParticleEmitter.readString(reader, "Image Path"));\r
+                               emitter.setImagePath(reader.readLine());\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
+                       throw new GdxRuntimeException("Error loading effect: " + effectFile, ex);\r
                } finally {\r
                        try {\r
                                if (reader != null) reader.close();\r
@@ -118,13 +125,27 @@ public class ParticleEffect {
                }\r
        }\r
 \r
-       private void loadEmitterImages (FileHandle imagesDir) {\r
+       public void loadEmitterImages (SpriteSheet spriteSheet) {\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
+                       String imageName = new File(imagePath.replace('\\', '/')).getName();\r
+                       int lastDotIndex = imageName.lastIndexOf('.');\r
+                       if (lastDotIndex != -1) imageName = imageName.substring(0, lastDotIndex);\r
+                       Sprite sprite = spriteSheet.get(imageName);\r
+                       if (sprite == null) throw new IllegalArgumentException("SpriteSheet missing image: " + imageName);\r
+                       emitter.setSprite(sprite);\r
+               }\r
+       }\r
+\r
+       public void loadEmitterImages (FileHandle 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
                        String imageName = new File(imagePath.replace('\\', '/')).getName();\r
-                       emitter.setTexture(loadTexture(imagesDir.child(imageName)));\r
+                       emitter.setSprite(new Sprite(loadTexture(imagesDir.child(imageName))));\r
                }\r
        }\r
 \r
index 97273b8..893341b 100644 (file)
@@ -43,10 +43,9 @@ public class ParticleEmitter {
        private ScaledNumericValue spawnHeightValue = new ScaledNumericValue();\r
        private SpawnShapeValue spawnShapeValue = new SpawnShapeValue();\r
 \r
-       private Texture texture;\r
+       private Sprite sprite;\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
@@ -80,8 +79,7 @@ public class ParticleEmitter {
        }\r
 \r
        public ParticleEmitter (ParticleEmitter emitter) {\r
-               texture = emitter.texture;\r
-               imageAspectRatio = emitter.imageAspectRatio;\r
+               sprite = emitter.sprite;\r
                setMaxParticleCount(emitter.maxParticleCount);\r
                minParticleCount = emitter.minParticleCount;\r
                delayValue.load(emitter.delayValue);\r
@@ -210,6 +208,12 @@ public class ParticleEmitter {
                restart();\r
        }\r
 \r
+       public void reset () {\r
+               emissionDelta = 0;\r
+               durationTimer = 0;\r
+               start();\r
+       }\r
+\r
        private void restart () {\r
                delay = delayValue.active ? delayValue.newLowValue() : 0;\r
                delayTimer = 0;\r
@@ -242,15 +246,15 @@ public class ParticleEmitter {
                if (velocityValue.active && velocityValue.active) updateFlags |= UPDATE_VELOCITY;\r
                if (scaleValue.timeline.length > 1) updateFlags |= UPDATE_SCALE;\r
                if (rotationValue.active && rotationValue.timeline.length > 1) updateFlags |= UPDATE_ROTATION;\r
-               if (windValue.active && windValue.timeline.length > 1) updateFlags |= UPDATE_WIND;\r
-               if (gravityValue.active && gravityValue.timeline.length > 1) updateFlags |= UPDATE_GRAVITY;\r
+               if (windValue.active) updateFlags |= UPDATE_WIND;\r
+               if (gravityValue.active) updateFlags |= UPDATE_GRAVITY;\r
                if (tintValue.timeline.length > 1) updateFlags |= UPDATE_TINT;\r
        }\r
 \r
        private void activateParticle (int index) {\r
                Particle particle = particles[index];\r
                if (particle == null) {\r
-                       particles[index] = particle = new Particle(texture);\r
+                       particles[index] = particle = new Particle(sprite);\r
                        particle.flip(flipX, flipY);\r
                }\r
 \r
@@ -269,15 +273,16 @@ public class ParticleEmitter {
                particle.angle = angleValue.newLowValue();\r
                particle.angleDiff = angleValue.newHighValue();\r
                if (!angleValue.isRelative()) particle.angleDiff -= particle.angle;\r
+               float angle = 0;\r
                if ((updateFlags & UPDATE_ANGLE) == 0) {\r
-                       float angle = particle.angle + particle.angleDiff * angleValue.getScale(0);\r
+                       angle = particle.angle + particle.angleDiff * angleValue.getScale(0);\r
                        particle.angle = angle;\r
                        particle.angleCos = MathUtils.cosDeg(angle);\r
                        particle.angleSin = MathUtils.sinDeg(angle);\r
                }\r
 \r
-               particle.scale = scaleValue.newLowValue() / texture.getWidth();\r
-               particle.scaleDiff = scaleValue.newHighValue() / texture.getWidth();\r
+               particle.scale = scaleValue.newLowValue() / sprite.getWidth();\r
+               particle.scaleDiff = scaleValue.newHighValue() / sprite.getWidth();\r
                if (!scaleValue.isRelative()) particle.scaleDiff -= particle.scale;\r
                if ((updateFlags & UPDATE_SCALE) == 0) particle.setScale(particle.scale + particle.scaleDiff * scaleValue.getScale(0));\r
 \r
@@ -285,8 +290,11 @@ public class ParticleEmitter {
                        particle.rotation = rotationValue.newLowValue();\r
                        particle.rotationDiff = rotationValue.newHighValue();\r
                        if (!rotationValue.isRelative()) particle.rotationDiff -= particle.rotation;\r
-                       if ((updateFlags & UPDATE_ROTATION) == 0)\r
-                               particle.setRotation(particle.rotation + particle.rotationDiff * rotationValue.getScale(0));\r
+                       if ((updateFlags & UPDATE_ROTATION) == 0) {\r
+                               float rotation = particle.rotation + particle.rotationDiff * rotationValue.getScale(0);\r
+                               if (aligned) rotation += angle;\r
+                               particle.setRotation(rotation);\r
+                       }\r
                }\r
 \r
                if (windValue.active) {\r
@@ -334,20 +342,20 @@ public class ParticleEmitter {
                        if (radiusX == 0 || radiusY == 0) break;\r
                        float scaleY = radiusX / (float)radiusY;\r
                        if (spawnShapeValue.edges) {\r
-                               float angle;\r
+                               float spawnAngle;\r
                                switch (spawnShapeValue.side) {\r
                                case top:\r
-                                       angle = -MathUtils.random(179f);\r
+                                       spawnAngle = -MathUtils.random(179f);\r
                                        break;\r
                                case bottom:\r
-                                       angle = MathUtils.random(179f);\r
+                                       spawnAngle = MathUtils.random(179f);\r
                                        break;\r
                                default:\r
-                                       angle = MathUtils.random(360f);\r
+                                       spawnAngle = MathUtils.random(360f);\r
                                        break;\r
                                }\r
-                               x += MathUtils.cosDeg(angle) * radiusX;\r
-                               y += MathUtils.sinDeg(angle) * radiusX / scaleY;\r
+                               x += MathUtils.cosDeg(spawnAngle) * radiusX;\r
+                               y += MathUtils.sinDeg(spawnAngle) * radiusX / scaleY;\r
                        } else {\r
                                int radius2 = radiusX * radiusX;\r
                                while (true) {\r
@@ -374,9 +382,9 @@ public class ParticleEmitter {
                }\r
                }\r
 \r
-               int texWidth = texture.getWidth();\r
-               int texHeight = texture.getHeight();\r
-               particle.setBounds(x - texWidth / 2, y - texHeight / 2, texWidth, texHeight);\r
+               float spriteWidth = sprite.getWidth();\r
+               float spriteHeight = sprite.getHeight();\r
+               particle.setBounds(x - spriteWidth / 2, y - spriteHeight / 2, spriteWidth, spriteHeight);\r
        }\r
 \r
        private boolean updateParticle (int index, float delta, int deltaMillis) {\r
@@ -407,7 +415,7 @@ public class ParticleEmitter {
                        } else {\r
                                velocityX = velocity * particle.angleCos;\r
                                velocityY = velocity * particle.angleSin;\r
-                               if ((updateFlags & UPDATE_ROTATION) != 0) {\r
+                               if (aligned || (updateFlags & UPDATE_ROTATION) != 0) {\r
                                        float rotation = particle.rotation + particle.rotationDiff * rotationValue.getScale(percent);\r
                                        if (aligned) rotation += particle.angle;\r
                                        particle.setRotation(rotation);\r
@@ -455,13 +463,12 @@ public class ParticleEmitter {
                this.y = y;\r
        }\r
 \r
-       // BOZO - Should be setSprite.\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
+       public void setSprite (Sprite sprite) {\r
+               this.sprite = sprite;\r
+               if (sprite == null) return;\r
+               float originX = sprite.getOriginX();\r
+               float originY = sprite.getOriginY();\r
+               Texture texture = sprite.getTexture();\r
                for (int i = 0, n = particles.length; i < n; i++) {\r
                        Particle particle = particles[i];\r
                        if (particle == null) break;\r
@@ -470,8 +477,8 @@ public class ParticleEmitter {
                }\r
        }\r
 \r
-       public Texture getTexture () {\r
-               return texture;\r
+       public Sprite getSprite () {\r
+               return sprite;\r
        }\r
 \r
        public String getName () {\r
@@ -778,8 +785,8 @@ public class ParticleEmitter {
                float gravity, gravityDiff;\r
                float[] tint;\r
 \r
-               public Particle (Texture texture) {\r
-                       super(texture);\r
+               public Particle (Sprite sprite) {\r
+                       super(sprite);\r
                }\r
        }\r
 \r