diff --git a/assets/plugins/plugin-tiled-0.0.7.jar b/assets/plugins/plugin-tiled-0.0.7.jar index 23403c92..82eaf069 100644 Binary files a/assets/plugins/plugin-tiled-0.0.7.jar and b/assets/plugins/plugin-tiled-0.0.7.jar differ diff --git a/h2d-libgdx-spine-extension b/h2d-libgdx-spine-extension index b9090afb..8e09aab5 160000 --- a/h2d-libgdx-spine-extension +++ b/h2d-libgdx-spine-extension @@ -1 +1 @@ -Subproject commit b9090afb410851d07e157eb92cadeb4d12c954a5 +Subproject commit 8e09aab5639fd95152e66291b70f8c7a3e942c65 diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/manager/ResourcesManager.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/manager/ResourcesManager.java index 5371fd4d..2eb06a0a 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/manager/ResourcesManager.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/manager/ResourcesManager.java @@ -14,6 +14,7 @@ import com.google.common.io.ByteStreams; import games.rednblack.editor.plugin.tiled.TiledPlugin; import games.rednblack.editor.plugin.tiled.view.SpineDrawable; import games.rednblack.editor.renderer.factory.EntityFactory; +import games.rednblack.h2d.extention.spine.PrefixAtlasAttachmentLoader; import java.io.File; import java.io.FileOutputStream; @@ -95,7 +96,8 @@ public class ResourcesManager { public SpineDrawable getSpineDrawable(String name) { if (spineDrawableCache.get(name) == null) { - SkeletonJson skeletonJson = new SkeletonJson(tiledPlugin.getAPI().getSceneLoader().getRm().getMainPack()); + PrefixAtlasAttachmentLoader atlasAttachmentLoader = new PrefixAtlasAttachmentLoader(name, tiledPlugin.getAPI().getSceneLoader().getRm().getMainPack()); + SkeletonJson skeletonJson = new SkeletonJson(atlasAttachmentLoader); SkeletonData skeletonData = skeletonJson.readSkeletonData(tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonJSON(name)); Skeleton skeleton = new Skeleton(skeletonData); diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpineDrawStrategy.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpineDrawStrategy.java index 2821c21e..927a615e 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpineDrawStrategy.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpineDrawStrategy.java @@ -6,12 +6,10 @@ import com.esotericsoftware.spine.SkeletonData; import com.esotericsoftware.spine.SkeletonJson; import games.rednblack.editor.plugin.tiled.TiledPlugin; import games.rednblack.editor.renderer.components.SpineDataComponent; -import games.rednblack.editor.renderer.components.sprite.SpriteAnimationComponent; -import games.rednblack.editor.renderer.components.sprite.SpriteAnimationStateComponent; import games.rednblack.editor.renderer.utils.ComponentRetriever; import games.rednblack.h2d.common.command.ReplaceSpineCommandBuilder; import games.rednblack.h2d.common.factory.IFactory; -import games.rednblack.h2d.extention.spine.SpineObjectComponent; +import games.rednblack.h2d.extention.spine.PrefixAtlasAttachmentLoader; public class SpineDrawStrategy extends BasicDrawStrategy { @@ -47,7 +45,8 @@ public class SpineDrawStrategy extends BasicDrawStrategy { replaceSpineCommandBuilder.begin(entity); String animName = tiledPlugin.getSelectedTileName(); replaceSpineCommandBuilder.setAnimationName(animName); - SkeletonJson skeletonJson = new SkeletonJson(tiledPlugin.getAPI().getSceneLoader().getRm().getMainPack()); + PrefixAtlasAttachmentLoader atlasAttachmentLoader = new PrefixAtlasAttachmentLoader(animName, tiledPlugin.getAPI().getSceneLoader().getRm().getMainPack()); + SkeletonJson skeletonJson = new SkeletonJson(atlasAttachmentLoader); replaceSpineCommandBuilder.setSkeletonJson(skeletonJson); SkeletonData skeletonData = skeletonJson.readSkeletonData((tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonJSON(animName))); replaceSpineCommandBuilder.setSkeleton(new Skeleton(skeletonData)); diff --git a/src/main/java/games/rednblack/editor/data/migrations/IVersionMigrator.java b/src/main/java/games/rednblack/editor/data/migrations/IVersionMigrator.java index 4bc57dd9..2bce91ac 100644 --- a/src/main/java/games/rednblack/editor/data/migrations/IVersionMigrator.java +++ b/src/main/java/games/rednblack/editor/data/migrations/IVersionMigrator.java @@ -1,29 +1,8 @@ -/* - * ****************************************************************************** - * * Copyright 2015 See AUTHORS file. - * * - * * Licensed under the Apache License, Version 2.0 (the "License"); - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * - * * http://www.apache.org/licenses/LICENSE-2.0 - * * - * * Unless required by applicable law or agreed to in writing, software - * * distributed under the License is distributed on an "AS IS" BASIS, - * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * * See the License for the specific language governing permissions and - * * limitations under the License. - * ***************************************************************************** - */ - package games.rednblack.editor.data.migrations; -/** - * Created by azakhary on 9/28/2014. - */ +import games.rednblack.h2d.common.vo.ProjectVO; + public interface IVersionMigrator { - - void setProject(String path); - + void setProject(String path, ProjectVO vo); boolean doMigration(); } diff --git a/src/main/java/games/rednblack/editor/data/migrations/ProjectVersionMigrator.java b/src/main/java/games/rednblack/editor/data/migrations/ProjectVersionMigrator.java index 1b45e9b6..8e2c1360 100644 --- a/src/main/java/games/rednblack/editor/data/migrations/ProjectVersionMigrator.java +++ b/src/main/java/games/rednblack/editor/data/migrations/ProjectVersionMigrator.java @@ -20,15 +20,12 @@ package games.rednblack.editor.data.migrations; import java.io.IOException; -import games.rednblack.editor.data.migrations.migrators.VersionMigTo009; -import games.rednblack.editor.data.migrations.migrators.VersionMigTo011; +import games.rednblack.editor.data.migrations.migrators.*; import games.rednblack.h2d.common.vo.ProjectVO; import org.apache.commons.io.FileUtils; import com.badlogic.gdx.utils.Json; import com.badlogic.gdx.utils.JsonWriter; -import games.rednblack.editor.data.migrations.migrators.DummyMig; -import games.rednblack.editor.data.migrations.migrators.VersionMigTo005; /** * Created by azakhary on 9/28/2014. @@ -91,10 +88,14 @@ public class ProjectVersionMigrator { IVersionMigrator vmt = new VersionMigTo011(); doMigration(vmt, "0.1.1"); } + if (projectVo.projectVersion.equals("0.1.1")) { + IVersionMigrator vmt = new VersionMigTo020(); + doMigration(vmt, "0.2.0"); + } } private void doMigration (IVersionMigrator vmt, String nextVersion) { - vmt.setProject(projectPath); + vmt.setProject(projectPath, projectVo); if (vmt.doMigration()) { setVersion(nextVersion); diff --git a/src/main/java/games/rednblack/editor/data/migrations/migrators/DummyMig.java b/src/main/java/games/rednblack/editor/data/migrations/migrators/DummyMig.java index 55d10132..6e05610c 100644 --- a/src/main/java/games/rednblack/editor/data/migrations/migrators/DummyMig.java +++ b/src/main/java/games/rednblack/editor/data/migrations/migrators/DummyMig.java @@ -19,13 +19,14 @@ package games.rednblack.editor.data.migrations.migrators; import games.rednblack.editor.data.migrations.IVersionMigrator; +import games.rednblack.h2d.common.vo.ProjectVO; /** * Created by azakhary on 1/29/2015. */ public class DummyMig implements IVersionMigrator { @Override - public void setProject(String path) { + public void setProject(String path, ProjectVO vo) { } diff --git a/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo005.java b/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo005.java index c0e8f17f..4f8f73b9 100644 --- a/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo005.java +++ b/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo005.java @@ -21,6 +21,7 @@ package games.rednblack.editor.data.migrations.migrators; import java.io.File; import java.io.IOException; +import games.rednblack.h2d.common.vo.ProjectVO; import org.apache.commons.io.FileUtils; import com.badlogic.gdx.Gdx; @@ -31,9 +32,7 @@ import com.badlogic.gdx.utils.JsonWriter; import games.rednblack.editor.data.migrations.IVersionMigrator; import games.rednblack.editor.HyperLap2DFacade; import games.rednblack.editor.proxy.ProjectManager; -import games.rednblack.editor.proxy.ResolutionManager; import games.rednblack.editor.renderer.data.ProjectInfoVO; -import games.rednblack.editor.renderer.data.ResolutionEntryVO; /** * Created by azakhary on 9/28/2014. @@ -48,7 +47,7 @@ public class VersionMigTo005 implements IVersionMigrator { private ProjectManager projectManager; @Override - public void setProject(String path) { + public void setProject(String path, ProjectVO vo) { facade = HyperLap2DFacade.getInstance(); projectManager = facade.retrieveProxy(ProjectManager.NAME); projectPath = path; diff --git a/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo009.java b/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo009.java index 31c48216..1ed51c57 100644 --- a/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo009.java +++ b/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo009.java @@ -27,6 +27,7 @@ import com.badlogic.gdx.utils.JsonWriter; import games.rednblack.editor.HyperLap2DFacade; import games.rednblack.editor.data.migrations.IVersionMigrator; import games.rednblack.editor.proxy.ProjectManager; +import games.rednblack.h2d.common.vo.ProjectVO; import org.apache.commons.io.FileUtils; import java.io.File; @@ -46,7 +47,7 @@ public class VersionMigTo009 implements IVersionMigrator { private ProjectManager projectManager; @Override - public void setProject(String path) { + public void setProject(String path, ProjectVO vo) { facade = HyperLap2DFacade.getInstance(); projectManager = facade.retrieveProxy(ProjectManager.NAME); projectPath = path; diff --git a/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo011.java b/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo011.java index 7534dccb..72ca3094 100644 --- a/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo011.java +++ b/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo011.java @@ -6,10 +6,10 @@ import com.badlogic.gdx.utils.JsonValue; import com.badlogic.gdx.utils.JsonWriter; import games.rednblack.editor.data.migrations.IVersionMigrator; import games.rednblack.editor.renderer.data.GraphVO; +import games.rednblack.h2d.common.vo.ProjectVO; import org.apache.commons.io.FileUtils; import java.io.File; -import java.io.IOException; public class VersionMigTo011 implements IVersionMigrator { @@ -19,7 +19,7 @@ public class VersionMigTo011 implements IVersionMigrator { private String projectPath; @Override - public void setProject(String path) { + public void setProject(String path, ProjectVO vo) { projectPath = path; json.setOutputType(JsonWriter.OutputType.json); } diff --git a/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo020.java b/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo020.java new file mode 100644 index 00000000..5cf45092 --- /dev/null +++ b/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo020.java @@ -0,0 +1,107 @@ +package games.rednblack.editor.data.migrations.migrators; + +import com.badlogic.gdx.files.FileHandle; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.PixmapIO; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.Json; +import com.badlogic.gdx.utils.JsonWriter; +import games.rednblack.editor.data.migrations.IVersionMigrator; +import games.rednblack.editor.proxy.ProjectManager; +import games.rednblack.editor.utils.ImportUtils; +import games.rednblack.h2d.common.vo.ProjectVO; +import games.rednblack.h2d.common.vo.TexturePackVO; +import org.apache.commons.io.FilenameUtils; + +import java.io.File; + +public class VersionMigTo020 implements IVersionMigrator { + private final Json json = new Json(); + + private String projectPath; + private ProjectVO projectVO; + + @Override + public void setProject(String path, ProjectVO vo) { + projectPath = path; + projectVO = vo; + json.setOutputType(JsonWriter.OutputType.json); + } + + @Override + public boolean doMigration() { + TexturePackVO mainPack = new TexturePackVO(); + mainPack.name = "main"; + projectVO.imagesPacks.put("main", mainPack); + + TexturePackVO mainAnimPack = new TexturePackVO(); + mainAnimPack.name = "main"; + projectVO.animationsPacks.put("main", mainAnimPack); + + String spriteAnimationsPath = projectPath + File.separator + "assets/orig" + File.separator + "sprite-animations"; + FileHandle sourceDir = new FileHandle(spriteAnimationsPath); + for (FileHandle entry : sourceDir.list()) { + if (entry.file().isDirectory()) { + String animName = FilenameUtils.removeExtension(entry.file().getName()); + + FileHandle atlasTargetPath = new FileHandle(new File(spriteAnimationsPath + File.separator + animName + File.separator + animName + ".atlas")); + TextureAtlas.TextureAtlasData atlas = new TextureAtlas.TextureAtlasData(atlasTargetPath, atlasTargetPath.parent(), false); + + for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(atlas.getRegions())) { + projectVO.animationsPacks.get("main").regions.add(region.name); + } + + try { + ImportUtils.unpackAtlasIntoTmpFolder(atlasTargetPath.file(), null,projectPath + File.separator + ProjectManager.IMAGE_DIR_PATH); + } catch (Exception ignore) { + } + + for (TextureAtlas.TextureAtlasData.Page page : new Array.ArrayIterator<>(atlas.getPages())) { + if (page.textureFile != null) + page.textureFile.delete(); + } + } + } + + String spineAnimationsPath = projectPath + File.separator + "assets/orig" + File.separator + "spine-animations"; + FileHandle spineDir = new FileHandle(spineAnimationsPath); + for (FileHandle entry : spineDir.list()) { + if (entry.file().isDirectory()) { + String animName = FilenameUtils.removeExtension(entry.file().getName()); + + FileHandle atlasTargetPath = new FileHandle(new File(spineAnimationsPath + File.separator + animName + File.separator + animName + ".atlas")); + TextureAtlas.TextureAtlasData atlas = new TextureAtlas.TextureAtlasData(atlasTargetPath, atlasTargetPath.parent(), false); + + for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(atlas.getRegions())) { + projectVO.animationsPacks.get("main").regions.add(animName+region.name); + } + + try { + ImportUtils.unpackAtlasIntoTmpFolder(atlasTargetPath.file(), animName, projectPath + File.separator + ProjectManager.IMAGE_DIR_PATH); + } catch (Exception ignore) { + } + + for (TextureAtlas.TextureAtlasData.Page page : new Array.ArrayIterator<>(atlas.getPages())) { + if (page.textureFile != null) + page.textureFile.delete(); + } + } + } + + Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888); + pixmap.setColor(Color.WHITE); + pixmap.fill(); + FileHandle whitePixel = new FileHandle(projectPath + File.separator + "assets/orig/images" + File.separator + "white-pixel.png"); + PixmapIO.writePNG(whitePixel, pixmap); + + projectVO.imagesPacks.get("main").regions.add("white-pixel"); + + String res = projectVO.lastOpenResolution.isEmpty() ? "orig" : projectVO.lastOpenResolution; + File pack = new File(projectPath + "/assets/" + res + "/pack/pack.atlas"); + pack.delete(); + + return true; + } +} diff --git a/src/main/java/games/rednblack/editor/proxy/ProjectManager.java b/src/main/java/games/rednblack/editor/proxy/ProjectManager.java index 9a52fb9e..aeb9b4cd 100755 --- a/src/main/java/games/rednblack/editor/proxy/ProjectManager.java +++ b/src/main/java/games/rednblack/editor/proxy/ProjectManager.java @@ -218,9 +218,8 @@ public class ProjectManager extends Proxy { } else { resolutionManager.currentResolutionName = resolution; currentProjectVO.lastOpenResolution = resolutionManager.currentResolutionName; - saveCurrentProject(); - } + saveCurrentProject(); currentProjectPath = projectPath; checkForConsistency(projectPath); loadProjectData(projectPath); diff --git a/src/main/java/games/rednblack/editor/proxy/ResolutionManager.java b/src/main/java/games/rednblack/editor/proxy/ResolutionManager.java index 40476da0..cd2fd2f1 100644 --- a/src/main/java/games/rednblack/editor/proxy/ResolutionManager.java +++ b/src/main/java/games/rednblack/editor/proxy/ResolutionManager.java @@ -35,9 +35,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.tools.texturepacker.TexturePacker; -import com.badlogic.gdx.tools.texturepacker.TextureUnpacker; import com.badlogic.gdx.utils.Array; import com.mortennobel.imagescaling.ResampleOp; import games.rednblack.editor.view.stage.Sandbox; diff --git a/src/main/java/games/rednblack/editor/utils/ImportUtils.java b/src/main/java/games/rednblack/editor/utils/ImportUtils.java index fce6ce7b..5b72b072 100644 --- a/src/main/java/games/rednblack/editor/utils/ImportUtils.java +++ b/src/main/java/games/rednblack/editor/utils/ImportUtils.java @@ -20,7 +20,6 @@ package games.rednblack.editor.utils; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.tools.texturepacker.TextureUnpacker; import com.badlogic.gdx.utils.Array; import com.kotcrab.vis.ui.widget.file.FileTypeFilter; @@ -138,11 +137,11 @@ public class ImportUtils { return regions.get(regions.size - 1).index == regions.size - 1; } - public static void unpackAtlasIntoTmpFolder(File atlasFile, String tmpDir) { + public static void unpackAtlasIntoTmpFolder(File atlasFile, String prefix, String tmpDir) { FileHandle atlasFileHandle = new FileHandle(atlasFile); TextureAtlas.TextureAtlasData atlasData = new TextureAtlas.TextureAtlasData(atlasFileHandle, atlasFileHandle.parent(), false); TextureUnpacker unpacker = new TextureUnpacker(); - unpacker.splitAtlas(atlasData, tmpDir); + unpacker.splitAtlas(atlasData, prefix, tmpDir); } public static String getAtlasName(FileHandle fileHandle) { diff --git a/src/main/java/games/rednblack/editor/utils/TextureUnpacker.java b/src/main/java/games/rednblack/editor/utils/TextureUnpacker.java new file mode 100644 index 00000000..6ef24f64 --- /dev/null +++ b/src/main/java/games/rednblack/editor/utils/TextureUnpacker.java @@ -0,0 +1,202 @@ +package games.rednblack.editor.utils; + +import com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData; +import com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData.Page; +import com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData.Region; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +/** Unpacks a texture atlas into individual image files. + * @author Geert Konijnendijk + * @author Nathan Sweet + * @author Michael Bazos */ +public class TextureUnpacker { + private static final String DEFAULT_OUTPUT_PATH = "output"; + private static final int NINEPATCH_PADDING = 1; + private static final String OUTPUT_TYPE = "png"; + private static final String HELP = "Usage: atlasFile [imageDir] [outputDir]"; + private static final String ATLAS_FILE_EXTENSION = ".atlas"; + + private boolean quiet; + + /** Checks the command line arguments for correctness. + * @return 0 If arguments are invalid, Number of arguments otherwise. */ + private int parseArguments (String[] args) { + int numArgs = args.length; + // check if number of args is right + if (numArgs < 1) return 0; + // check if the input file's extension is right + boolean extension = args[0].substring(args[0].length() - ATLAS_FILE_EXTENSION.length()).equals(ATLAS_FILE_EXTENSION); + // check if the directory names are valid + boolean directory = true; + if (numArgs >= 2) directory &= checkDirectoryValidity(args[1]); + if (numArgs == 3) directory &= checkDirectoryValidity(args[2]); + return extension && directory ? numArgs : 0; + } + + private boolean checkDirectoryValidity (String directory) { + File checkFile = new File(directory); + boolean path = true; + // try to get the canonical path, if this fails the path is not valid + try { + checkFile.getCanonicalPath(); + } catch (Exception e) { + path = false; + } + return path; + } + + /** Splits an atlas into seperate image and ninepatch files. */ + public void splitAtlas (TextureAtlasData atlas, String prefix, String outputDir) { + // create the output directory if it did not exist yet + File outputDirFile = new File(outputDir); + if (!outputDirFile.exists()) { + outputDirFile.mkdirs(); + if (!quiet) System.out.println(String.format("Creating directory: %s", outputDirFile.getPath())); + } + + for (Page page : atlas.getPages()) { + // load the image file belonging to this page as a Buffered Image + File file = page.textureFile.file(); + if (!file.exists()) throw new RuntimeException("Unable to find atlas image: " + file.getAbsolutePath()); + BufferedImage img = null; + try { + img = ImageIO.read(file); + } catch (IOException e) { + printExceptionAndExit(e); + } + for (Region region : atlas.getRegions()) { + if (!quiet) System.out.println(String.format("Processing image for %s: x[%s] y[%s] w[%s] h[%s], rotate[%s]", + region.name, region.left, region.top, region.width, region.height, region.rotate)); + + // check if the page this region is in is currently loaded in a Buffered Image + if (region.page == page) { + BufferedImage splitImage = null; + String extension = null; + + // check if the region is a ninepatch or a normal image and delegate accordingly + if (region.findValue("split") == null) { + splitImage = extractImage(img, region, outputDirFile, 0); + if (region.width != region.originalWidth || region.height != region.originalHeight) { + BufferedImage originalImg = new BufferedImage(region.originalWidth, region.originalHeight, img.getType()); + Graphics2D g2 = originalImg.createGraphics(); + g2.drawImage(splitImage, (int) region.offsetX, (int) (region.originalHeight - region.height - region.offsetY), null); + g2.dispose(); + splitImage = originalImg; + } + extension = OUTPUT_TYPE; + } else { + splitImage = extractNinePatch(img, region, outputDirFile); + extension = String.format("9.%s", OUTPUT_TYPE); + } + + // check if the parent directories of this image file exist and create them if not + File imgOutput; + if (prefix != null) { + imgOutput = new File(outputDirFile, + String.format("%s%s.%s", prefix, region.index == -1 ? region.name : region.name + "_" + region.index, extension)); + } else { + imgOutput = new File(outputDirFile, + String.format("%s.%s", region.index == -1 ? region.name : region.name + "_" + region.index, extension)); + } + File imgDir = imgOutput.getParentFile(); + if (!imgDir.exists()) { + if (!quiet) System.out.printf("Creating directory: %s%n", imgDir.getPath()); + imgDir.mkdirs(); + } + + // save the image + try { + ImageIO.write(splitImage, OUTPUT_TYPE, imgOutput); + } catch (Exception e) { + printExceptionAndExit(e); + } + } + } + } + } + + /** Extract an image from a texture atlas. + * @param page The image file related to the page the region is in + * @param region The region to extract + * @param outputDirFile The output directory + * @param padding padding (in pixels) to apply to the image + * @return The extracted image */ + private BufferedImage extractImage (BufferedImage page, Region region, File outputDirFile, int padding) { + BufferedImage splitImage = null; + + // get the needed part of the page and rotate if needed + if (region.rotate) { + BufferedImage srcImage = page.getSubimage(region.left, region.top, region.height, region.width); + splitImage = new BufferedImage(region.width, region.height, page.getType()); + + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90.0)); + transform.translate(0, -region.width); + AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR); + op.filter(srcImage, splitImage); + } else { + splitImage = page.getSubimage(region.left, region.top, region.width, region.height); + } + + // draw the image to a bigger one if padding is needed + if (padding > 0) { + BufferedImage paddedImage = new BufferedImage(splitImage.getWidth() + padding * 2, splitImage.getHeight() + padding * 2, + page.getType()); + Graphics2D g2 = paddedImage.createGraphics(); + g2.drawImage(splitImage, padding, padding, null); + g2.dispose(); + return paddedImage; + } else { + return splitImage; + } + } + + /** Extract a ninepatch from a texture atlas, according to the android specification. + * @see ninepatch specification + * @param page The image file related to the page the region is in + * @param region The region to extract */ + private BufferedImage extractNinePatch (BufferedImage page, Region region, File outputDirFile) { + BufferedImage splitImage = extractImage(page, region, outputDirFile, NINEPATCH_PADDING); + Graphics2D g2 = splitImage.createGraphics(); + g2.setColor(Color.BLACK); + + // Draw the four lines to save the ninepatch's padding and splits + int[] splits = region.findValue("split"); + int startX = splits[0] + NINEPATCH_PADDING; + int endX = region.width - splits[1] + NINEPATCH_PADDING - 1; + int startY = splits[2] + NINEPATCH_PADDING; + int endY = region.height - splits[3] + NINEPATCH_PADDING - 1; + if (endX >= startX) g2.drawLine(startX, 0, endX, 0); + if (endY >= startY) g2.drawLine(0, startY, 0, endY); + int[] pads = region.findValue("pad"); + if (pads != null) { + int padStartX = pads[0] + NINEPATCH_PADDING; + int padEndX = region.width - pads[1] + NINEPATCH_PADDING - 1; + int padStartY = pads[2] + NINEPATCH_PADDING; + int padEndY = region.height - pads[3] + NINEPATCH_PADDING - 1; + g2.drawLine(padStartX, splitImage.getHeight() - 1, padEndX, splitImage.getHeight() - 1); + g2.drawLine(splitImage.getWidth() - 1, padStartY, splitImage.getWidth() - 1, padEndY); + } + g2.dispose(); + + return splitImage; + } + + private void printExceptionAndExit (Exception e) { + e.printStackTrace(); + System.exit(1); + } + + public void setQuiet (boolean quiet) { + this.quiet = quiet; + } +} diff --git a/src/main/java/games/rednblack/editor/utils/asset/impl/SpineAsset.java b/src/main/java/games/rednblack/editor/utils/asset/impl/SpineAsset.java index 03a15ec8..b8517340 100644 --- a/src/main/java/games/rednblack/editor/utils/asset/impl/SpineAsset.java +++ b/src/main/java/games/rednblack/editor/utils/asset/impl/SpineAsset.java @@ -107,11 +107,11 @@ public class SpineAsset extends Asset { File jsonFileTarget = new File(targetPath + File.separator + fileNameWithOutExt + ".json"); FileUtils.copyFile(animationFileSource.file(), jsonFileTarget); - ImportUtils.unpackAtlasIntoTmpFolder(atlasFileSource.file(), projectManager.getCurrentProjectPath() + File.separator + ImportUtils.unpackAtlasIntoTmpFolder(atlasFileSource.file(), fileNameWithOutExt,projectManager.getCurrentProjectPath() + File.separator + ProjectManager.IMAGE_DIR_PATH); for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(atlas.getRegions())) { - projectManager.getCurrentProjectVO().animationsPacks.get("main").regions.add(region.name); + projectManager.getCurrentProjectVO().animationsPacks.get("main").regions.add(fileNameWithOutExt+region.name); } return jsonFileTarget; diff --git a/src/main/java/games/rednblack/editor/utils/asset/impl/SpriteAnimationAtlasAsset.java b/src/main/java/games/rednblack/editor/utils/asset/impl/SpriteAnimationAtlasAsset.java index b1ed4d95..ce4d1037 100644 --- a/src/main/java/games/rednblack/editor/utils/asset/impl/SpriteAnimationAtlasAsset.java +++ b/src/main/java/games/rednblack/editor/utils/asset/impl/SpriteAnimationAtlasAsset.java @@ -55,7 +55,7 @@ public class SpriteAnimationAtlasAsset extends Asset { FileUtils.deleteDirectory(targetDir); } - ImportUtils.unpackAtlasIntoTmpFolder(fileHandle.file(), projectManager.getCurrentProjectPath() + File.separator + ImportUtils.unpackAtlasIntoTmpFolder(fileHandle.file(), null, projectManager.getCurrentProjectPath() + File.separator + ProjectManager.IMAGE_DIR_PATH); File atlasTargetPath = new File(targetPath + File.separator + fileNameWithoutExt + ".atlas"); diff --git a/src/main/java/games/rednblack/editor/view/ui/widget/actors/SpineActor.java b/src/main/java/games/rednblack/editor/view/ui/widget/actors/SpineActor.java index 54bd0438..6f5dcdfd 100644 --- a/src/main/java/games/rednblack/editor/view/ui/widget/actors/SpineActor.java +++ b/src/main/java/games/rednblack/editor/view/ui/widget/actors/SpineActor.java @@ -19,6 +19,7 @@ import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.MeshAttachment; import com.esotericsoftware.spine.attachments.RegionAttachment; import games.rednblack.editor.renderer.resources.IResourceRetriever; +import games.rednblack.h2d.extention.spine.PrefixAtlasAttachmentLoader; public class SpineActor extends Actor { @@ -80,7 +81,7 @@ public class SpineActor extends Actor { } private void initSkeletonData() { - skeletonJson = new SkeletonJson(irr.getMainPack()); + skeletonJson = new SkeletonJson(new PrefixAtlasAttachmentLoader(animationName, irr.getMainPack())); skeletonData = skeletonJson.readSkeletonData((irr.getSkeletonJSON(animationName))); }