diff --git a/AUTHORS b/AUTHORS index 28f27cfd..c7c4c56f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -9,4 +9,6 @@ Francesco Marongiu (@fgnm) - https://github.com/fgnm damios (@crykn) - https://github.com/crykn Raymond Buckley (@raeleus) - https://github.com/raeleus -alyrow (@alyrow) - https://github.com/alyrow \ No newline at end of file +alyrow (@alyrow) - https://github.com/alyrow +6money (@6money) - https://github.com/6money +jantwegener (@jantwegener) - https://github.com/jantwegener \ No newline at end of file diff --git a/CHANGES b/CHANGES index 4797b451..56428b31 100644 --- a/CHANGES +++ b/CHANGES @@ -1,10 +1,16 @@ [0.0.7] +- [BREAK CHANGE] Spine and Sprite animations are now packed into same main atlas pack +- [BREAK CHANGE] Update Project version to `0.2.0` - Experimental support to Normal Mapping in lights: * Simple Images - Add light `intensity` +- Add Box2D Body Sensors = Editor = - Use Distance Field fonts for GUI +- Add Editor performance settings (MSAA, OpenGL 3) +- Add multiple atlas packing settings +- Add Import libGDX atlas format - Huge improvements to Tiled Plugin: * Sprite and Spine animated Tiles * UI improvements and general refactoring diff --git a/assets/plugins/plugin-9patch-0.0.7.jar b/assets/plugins/plugin-9patch-0.0.7.jar index f3541ac6..39dee0e6 100644 Binary files a/assets/plugins/plugin-9patch-0.0.7.jar and b/assets/plugins/plugin-9patch-0.0.7.jar differ diff --git a/assets/plugins/plugin-tiled-0.0.7.jar b/assets/plugins/plugin-tiled-0.0.7.jar index af8113e1..40d852cd 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/assets/style/uiskin.json b/assets/style/uiskin.json index a30adcd0..d8ad3efe 100644 --- a/assets/style/uiskin.json +++ b/assets/style/uiskin.json @@ -135,6 +135,9 @@ hScrollKnob: scroll-knob-horizontal } }, + com.kotcrab.vis.ui.util.adapter.SimpleListAdapter$SimpleListAdapterStyle: { + default: {selection: list-selection } + } com.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: { default: { font: default-font, diff --git a/h2d-libgdx-spine-extension b/h2d-libgdx-spine-extension index 04189a68..f9de1d70 160000 --- a/h2d-libgdx-spine-extension +++ b/h2d-libgdx-spine-extension @@ -1 +1 @@ -Subproject commit 04189a68fc2cdf62ae9aa4d53dfa11b6b8aea031 +Subproject commit f9de1d70029721df5c7526158c86fba2b24c018c diff --git a/h2d-libgdx-talos-extension b/h2d-libgdx-talos-extension index 2b43d7b7..94b1d7dc 160000 --- a/h2d-libgdx-talos-extension +++ b/h2d-libgdx-talos-extension @@ -1 +1 @@ -Subproject commit 2b43d7b7cb9eb84d1322782cee692712f9f0f797 +Subproject commit 94b1d7dce75962ee60a38fb405548fe168f21b3b diff --git a/hyperlap2d-common-api b/hyperlap2d-common-api index 9c72233c..06009aa7 160000 --- a/hyperlap2d-common-api +++ b/hyperlap2d-common-api @@ -1 +1 @@ -Subproject commit 9c72233c08a6e573b59bfd3951291ff9c897c4ce +Subproject commit 06009aa76abb57a83692033d5e97f67d5282200d diff --git a/hyperlap2d-runtime-libgdx b/hyperlap2d-runtime-libgdx index f284ffcf..b1b5e944 160000 --- a/hyperlap2d-runtime-libgdx +++ b/hyperlap2d-runtime-libgdx @@ -1 +1 @@ -Subproject commit f284ffcfbb128f89dd1b5ce67073f42923668df2 +Subproject commit b1b5e9445c33e1474d46b9d805394076f1a1cfb2 diff --git a/plugin-9patch/src/main/java/games/rednblack/editor/plugin/ninepatch/MainPanelMediator.java b/plugin-9patch/src/main/java/games/rednblack/editor/plugin/ninepatch/MainPanelMediator.java index 9860a572..696912d8 100644 --- a/plugin-9patch/src/main/java/games/rednblack/editor/plugin/ninepatch/MainPanelMediator.java +++ b/plugin-9patch/src/main/java/games/rednblack/editor/plugin/ninepatch/MainPanelMediator.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import games.rednblack.editor.renderer.components.MainItemComponent; import games.rednblack.editor.renderer.components.NinePatchComponent; import games.rednblack.editor.renderer.components.TextureRegionComponent; @@ -148,9 +149,9 @@ public class MainPanelMediator extends Mediator { } private void loadRegion(String name) { - TextureAtlas atlas = plugin.getAPI().getProjectTextureAtlas(); - validateNinePatchTextureRegion(atlas.findRegion(name)); - viewComponent.setTexture(atlas.findRegion(name)); + TextureAtlas.AtlasRegion region = plugin.getAPI().getProjectTextureRegion(name); + validateNinePatchTextureRegion(region); + viewComponent.setTexture(region); viewComponent.setListeners(plugin.getAPI().getUIStage()); } 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 20b62c18..bf5d7aa6 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.ResourceRetrieverAttachmentLoader; import java.io.File; import java.io.FileOutputStream; @@ -86,7 +87,7 @@ public class ResourcesManager { region = tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(name); break; case EntityFactory.SPRITE_TYPE: - region = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(name).getRegions().get(0); + region = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(name).get(0); break; } } @@ -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().getSkeletonAtlas(name)); + ResourceRetrieverAttachmentLoader atlasAttachmentLoader = new ResourceRetrieverAttachmentLoader(name, tiledPlugin.getAPI().getSceneLoader().getRm()); + 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 514cbeca..22f51459 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.ResourceRetrieverAttachmentLoader; 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().getSkeletonAtlas(animName)); + ResourceRetrieverAttachmentLoader atlasAttachmentLoader = new ResourceRetrieverAttachmentLoader(animName, tiledPlugin.getAPI().getSceneLoader().getRm()); + 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/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpriteDrawStrategy.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpriteDrawStrategy.java index 46b2e0c0..f7719b00 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpriteDrawStrategy.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpriteDrawStrategy.java @@ -51,7 +51,7 @@ public class SpriteDrawStrategy extends BasicDrawStrategy { private Array getRegions(String filter) { // filtering regions by name - Array allRegions = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(filter).getRegions(); + Array allRegions = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(filter); Array regions = new Array<>(); for(TextureAtlas.AtlasRegion region: allRegions) { if(region.name.contains(filter)) { diff --git a/src/main/java/games/rednblack/editor/controller/BootstrapViewCommand.java b/src/main/java/games/rednblack/editor/controller/BootstrapViewCommand.java index 08db49d5..edef14b2 100644 --- a/src/main/java/games/rednblack/editor/controller/BootstrapViewCommand.java +++ b/src/main/java/games/rednblack/editor/controller/BootstrapViewCommand.java @@ -47,12 +47,14 @@ import games.rednblack.editor.view.ui.box.bottom.UIResolutionBoxMediator; import games.rednblack.editor.view.ui.box.bottom.UISceneBoxMediator; import games.rednblack.editor.view.ui.box.bottom.UIZoomBoxMediator; import games.rednblack.editor.view.ui.dialog.AboutDialogMediator; +import games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator; import games.rednblack.editor.view.ui.dialog.AutoTraceDialogMediator; import games.rednblack.editor.view.ui.dialog.CodeEditorDialogMediator; import games.rednblack.editor.view.ui.dialog.ConsoleDialogMediator; import games.rednblack.editor.view.ui.dialog.CreateNewResolutionDialogMediator; import games.rednblack.editor.view.ui.dialog.CreateNoiseDialogMediator; import games.rednblack.editor.view.ui.dialog.CreatePlaceholderDialogMediator; +import games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator; import games.rednblack.editor.view.ui.dialog.LoadingBarDialogMediator; import games.rednblack.editor.view.ui.dialog.NewProjectDialogMediator; import games.rednblack.editor.view.ui.dialog.NodeEditorDialogMediator; @@ -122,6 +124,8 @@ public class BootstrapViewCommand extends SimpleCommand { facade.registerMediator(new CreatePlaceholderDialogMediator()); facade.registerMediator(new CreateNoiseDialogMediator()); facade.registerMediator(new ConsoleDialogMediator()); + facade.registerMediator(new ImagesPackDialogMediator()); + facade.registerMediator(new AnimationsPackDialogMediator()); facade.registerMediator(new SaveProjectDialogMediator()); } diff --git a/src/main/java/games/rednblack/editor/controller/commands/resource/DeleteSpineAnimation.java b/src/main/java/games/rednblack/editor/controller/commands/resource/DeleteSpineAnimation.java index 6a849ca1..e48197d0 100644 --- a/src/main/java/games/rednblack/editor/controller/commands/resource/DeleteSpineAnimation.java +++ b/src/main/java/games/rednblack/editor/controller/commands/resource/DeleteSpineAnimation.java @@ -1,6 +1,7 @@ package games.rednblack.editor.controller.commands.resource; import com.badlogic.ashley.core.Entity; +import games.rednblack.editor.proxy.ResolutionManager; import games.rednblack.editor.renderer.components.SpineDataComponent; import games.rednblack.editor.renderer.data.CompositeItemVO; import games.rednblack.editor.renderer.data.SceneVO; @@ -34,7 +35,8 @@ public class DeleteSpineAnimation extends DeleteResourceCommand { if (projectManager.deleteSpineForAllResolutions(spineItemName)) { deleteEntitiesWithParticleEffects(sandbox.getRootEntity(), spineItemName); deleteAllItemsSpineAnimations(spineItemName); - projectManager.loadProjectData(projectManager.getCurrentProjectPath()); + ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); + resolutionManager.rePackProjectImagesForAllResolutions(true); sendNotification(DONE, spineItemName); SceneVO vo = sandbox.sceneVoFromItems(); projectManager.saveCurrentProject(vo); diff --git a/src/main/java/games/rednblack/editor/controller/commands/resource/DeleteSpriteAnimation.java b/src/main/java/games/rednblack/editor/controller/commands/resource/DeleteSpriteAnimation.java index f337fbae..7a320daf 100644 --- a/src/main/java/games/rednblack/editor/controller/commands/resource/DeleteSpriteAnimation.java +++ b/src/main/java/games/rednblack/editor/controller/commands/resource/DeleteSpriteAnimation.java @@ -1,6 +1,7 @@ package games.rednblack.editor.controller.commands.resource; import com.badlogic.ashley.core.Entity; +import games.rednblack.editor.proxy.ResolutionManager; import games.rednblack.editor.renderer.components.sprite.SpriteAnimationComponent; import games.rednblack.editor.renderer.data.CompositeItemVO; import games.rednblack.editor.renderer.data.SceneVO; @@ -34,7 +35,8 @@ public class DeleteSpriteAnimation extends DeleteResourceCommand { if (projectManager.deleteSpriteAnimationForAllResolutions(spriteAnimationName)) { deleteEntitiesWithSpriteAnimation(sandbox.getRootEntity(), spriteAnimationName); deleteAllItemsSpriteAnimations(spriteAnimationName); - projectManager.loadProjectData(projectManager.getCurrentProjectPath()); + ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); + resolutionManager.rePackProjectImagesForAllResolutions(true); facade.sendNotification(DONE, spriteAnimationName); SceneVO vo = sandbox.sceneVoFromItems(); projectManager.saveCurrentProject(vo); diff --git a/src/main/java/games/rednblack/editor/data/SpineAnimData.java b/src/main/java/games/rednblack/editor/data/SpineAnimData.java index d7299f18..f3f2f965 100644 --- a/src/main/java/games/rednblack/editor/data/SpineAnimData.java +++ b/src/main/java/games/rednblack/editor/data/SpineAnimData.java @@ -25,7 +25,6 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas; * Created by azakhary on 7/3/2014. */ public class SpineAnimData { - public TextureAtlas atlas; public FileHandle jsonFile; public String animName; } 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..a93923dc 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,9 @@ -/* - * ****************************************************************************** - * * 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.editor.renderer.data.ProjectInfoVO; +import games.rednblack.h2d.common.vo.ProjectVO; + public interface IVersionMigrator { - - void setProject(String path); - + void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO); 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 4f3e4840..f908f5eb 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,15 @@ 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 com.badlogic.gdx.Gdx; +import com.badlogic.gdx.files.FileHandle; +import games.rednblack.editor.data.migrations.migrators.*; +import games.rednblack.editor.renderer.data.ProjectInfoVO; 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. @@ -37,19 +37,29 @@ public class ProjectVersionMigrator { private String projectPath; private ProjectVO projectVo; + private ProjectInfoVO projectInfoVO; private int safetyIterator = 0; /** * this is the current supported version, change when data format is changed, and add migration script */ - public static String dataFormatVersion = "0.1.1"; + public static String dataFormatVersion = "0.2.0"; - private Json json = new Json(); + private final Json json = new Json(); public ProjectVersionMigrator (String projectPath, ProjectVO projectVo) { this.projectPath = projectPath; this.projectVo = projectVo; + String prjInfoFilePath = projectPath + "/project.dt"; + FileHandle projectInfoFile = Gdx.files.internal(prjInfoFilePath); + String projectInfoContents = "{}"; + try { + projectInfoContents = FileUtils.readFileToString(projectInfoFile.file(), "utf-8"); + } catch (IOException e) { + e.printStackTrace(); + } + projectInfoVO = json.fromJson(ProjectInfoVO.class, projectInfoContents); json.setOutputType(JsonWriter.OutputType.json); } @@ -91,10 +101,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, projectInfoVO); 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..bae676f5 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,15 @@ package games.rednblack.editor.data.migrations.migrators; import games.rednblack.editor.data.migrations.IVersionMigrator; +import games.rednblack.editor.renderer.data.ProjectInfoVO; +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, ProjectInfoVO projectInfoVO) { } 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 52c7ea19..ba5d39fe 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, ProjectInfoVO projectInfoVO) { facade = HyperLap2DFacade.getInstance(); projectManager = facade.retrieveProxy(ProjectManager.NAME); projectPath = path; @@ -57,7 +56,6 @@ public class VersionMigTo005 implements IVersionMigrator { @Override public boolean doMigration() { - // Rename folder animations to spine-animations in orig (if exist); File animationsDir = new File(projectPath + File.separator + "assets" + File.separator + "orig" + File.separator + "animations"); if (animationsDir.exists() && animationsDir.isDirectory()) { @@ -73,12 +71,6 @@ public class VersionMigTo005 implements IVersionMigrator { projectInfoContents = FileUtils.readFileToString(projectInfoFile.file(), "utf-8"); ProjectInfoVO currentProjectInfoVO = json.fromJson(ProjectInfoVO.class, projectInfoContents); projectManager.currentProjectInfoVO = currentProjectInfoVO; - - // run through all resolutions and remake animations for all - for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) { - ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); - resolutionManager.createResizedAnimations(resolutionEntryVO); - } } catch (IOException e) { e.printStackTrace(); } 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..8883c46c 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,8 @@ 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.editor.renderer.data.ProjectInfoVO; +import games.rednblack.h2d.common.vo.ProjectVO; import org.apache.commons.io.FileUtils; import java.io.File; @@ -46,7 +48,7 @@ public class VersionMigTo009 implements IVersionMigrator { private ProjectManager projectManager; @Override - public void setProject(String path) { + public void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO) { 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..802a7bec 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,11 @@ 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.editor.renderer.data.ProjectInfoVO; +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 +20,7 @@ public class VersionMigTo011 implements IVersionMigrator { private String projectPath; @Override - public void setProject(String path) { + public void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO) { 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..6a70c463 --- /dev/null +++ b/src/main/java/games/rednblack/editor/data/migrations/migrators/VersionMigTo020.java @@ -0,0 +1,124 @@ +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.renderer.data.ProjectInfoVO; +import games.rednblack.editor.utils.ImportUtils; +import games.rednblack.h2d.common.vo.ProjectVO; +import games.rednblack.editor.renderer.data.TexturePackVO; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; + +import java.io.File; +import java.io.IOException; + +public class VersionMigTo020 implements IVersionMigrator { + private final Json json = new Json(); + + private String projectPath; + private ProjectVO projectVO; + private ProjectInfoVO projectInfoVO; + + @Override + public void setProject(String path, ProjectVO vo, ProjectInfoVO projectInfoVO) { + projectPath = path; + projectVO = vo; + this.projectInfoVO = projectInfoVO; + json.setOutputType(JsonWriter.OutputType.json); + } + + @Override + public boolean doMigration() { + TexturePackVO mainPack = new TexturePackVO(); + mainPack.name = "main"; + projectInfoVO.imagesPacks.put("main", mainPack); + + String res = projectVO.lastOpenResolution.isEmpty() ? "orig" : projectVO.lastOpenResolution; + FileHandle pack = new FileHandle(projectPath + "/assets/" + res + "/pack/pack.atlas"); + TextureAtlas.TextureAtlasData mainAtlas = new TextureAtlas.TextureAtlasData(pack, pack.parent(), false); + + for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(mainAtlas.getRegions())) { + projectInfoVO.imagesPacks.get("main").regions.add(region.name); + } + + TexturePackVO mainAnimPack = new TexturePackVO(); + mainAnimPack.name = "main"; + projectInfoVO.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())) { + projectInfoVO.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())) { + projectInfoVO.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(); + } + atlasTargetPath.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); + + projectInfoVO.imagesPacks.get("main").regions.add("white-pixel"); + try { + FileUtils.writeStringToFile(new File(projectPath + "/project.dt"), projectInfoVO.constructJsonString(), "utf-8"); + } catch (IOException e) { + return false; + } + + pack.delete(); + + return true; + } +} diff --git a/src/main/java/games/rednblack/editor/proxy/PluginManager.java b/src/main/java/games/rednblack/editor/proxy/PluginManager.java index 521c9563..4210a176 100644 --- a/src/main/java/games/rednblack/editor/proxy/PluginManager.java +++ b/src/main/java/games/rednblack/editor/proxy/PluginManager.java @@ -109,9 +109,9 @@ public class PluginManager extends Proxy implements PluginAPI { } @Override - public TextureAtlas getProjectTextureAtlas() { + public TextureAtlas.AtlasRegion getProjectTextureRegion(String regionName) { ResourceManager resourceManager = facade.retrieveProxy(ResourceManager.NAME); - return resourceManager.getTextureAtlas(); + return (TextureAtlas.AtlasRegion) resourceManager.getTextureRegion(regionName); } @Override diff --git a/src/main/java/games/rednblack/editor/proxy/ProjectManager.java b/src/main/java/games/rednblack/editor/proxy/ProjectManager.java index 12ee4d94..c5ba39de 100755 --- a/src/main/java/games/rednblack/editor/proxy/ProjectManager.java +++ b/src/main/java/games/rednblack/editor/proxy/ProjectManager.java @@ -20,9 +20,14 @@ package games.rednblack.editor.proxy; import com.badlogic.gdx.Gdx; 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.tools.texturepacker.TexturePacker.Settings; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Json; +import com.badlogic.gdx.utils.JsonReader; +import com.badlogic.gdx.utils.JsonValue; import com.kotcrab.vis.ui.util.dialog.Dialogs; import games.rednblack.editor.HyperLap2DFacade; import games.rednblack.editor.data.manager.PreferencesManager; @@ -105,14 +110,6 @@ public class ProjectManager extends Proxy { } public void createEmptyProject(String projectPath, int width, int height, int pixelPerWorldUnit) throws IOException { - - /* - if (workspacePath.endsWith(File.separator)) { - workspacePath = workspacePath.substring(0, workspacePath.length() - 1); - } - - String projPath = workspacePath + File.separator + projectName; - */ String projectName = new File(projectPath).getName(); String projPath = FilenameUtils.normalize(projectPath); @@ -123,9 +120,13 @@ public class ProjectManager extends Proxy { FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig")); FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig/images")); FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig/particles")); - FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig/animations")); FileUtils.forceMkdir(new File(projPath + File.separator + "assets/orig/pack")); + Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888); + pixmap.setColor(Color.WHITE); + pixmap.fill(); + FileHandle whitePixel = new FileHandle(projPath + File.separator + "assets/orig/images" + File.separator + "white-pixel.png"); + PixmapIO.writePNG(whitePixel, pixmap); // create project file ProjectVO projVo = new ProjectVO(); @@ -138,6 +139,13 @@ public class ProjectManager extends Proxy { projInfoVo.originalResolution.width = width; projInfoVo.originalResolution.height = height; projInfoVo.pixelToWorld = pixelPerWorldUnit; + TexturePackVO mainPack = new TexturePackVO(); + mainPack.name = "main"; + mainPack.regions.add("white-pixel"); + projInfoVo.imagesPacks.put("main", mainPack); + TexturePackVO mainAnimPack = new TexturePackVO(); + mainAnimPack.name = "main"; + projInfoVo.animationsPacks.put("main", mainAnimPack); //TODO: add project orig resolution setting currentProjectVO = projVo; @@ -187,19 +195,6 @@ public class ProjectManager extends Proxy { File prjFile = new File(prjFilePath); if (!prjFile.isDirectory()) { - if (!prjFile.exists()) { - - ProjectVO projVoEmpty = new ProjectVO(); - projVoEmpty.projectName = prjFile.getName(); - projVoEmpty.projectVersion = ProjectVersionMigrator.dataFormatVersion; - - try { - FileUtils.writeStringToFile(prjFile, projVoEmpty.constructJsonString(), "utf-8"); - } catch (IOException e) { - e.printStackTrace(); - } - } - String projectContents = null; try { projectContents = FileUtils.readFileToString(projectFile.file(), "utf-8"); @@ -225,10 +220,10 @@ public class ProjectManager extends Proxy { } else { resolutionManager.currentResolutionName = resolution; currentProjectVO.lastOpenResolution = resolutionManager.currentResolutionName; - saveCurrentProject(); - } currentProjectPath = projectPath; + saveCurrentProject(); + checkForConsistency(projectPath); loadProjectData(projectPath); @@ -304,12 +299,6 @@ public class ProjectManager extends Proxy { } } - public void reLoadProjectAssets() { - ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); - ResourceManager resourceManager = facade.retrieveProxy(ResourceManager.NAME); - resourceManager.loadCurrentProjectAssets(currentProjectPath + "/assets/" + resolutionManager.currentResolutionName + "/pack/pack.atlas"); - } - public void loadProjectData(String projectPath) { // All legit loading assets ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); @@ -410,12 +399,7 @@ public class ProjectManager extends Proxy { newFile.mkdir(); } - // The filename should not be changed because the particle effects contain the name in their - // configuration. Unfortunately though, the texture packer does not support the underscore because - // any underscore in the texture packer is considered an image index. More info here: - // https://github.com/libgdx/libgdx/wiki/Texture-packer#image-indexes - // So, long story short, we MUST remove the underscore. - ImageIO.write(bufferedImage, "png", new File(targetPath + "/" + handle.name().replace("_", ""))); + ImageIO.write(bufferedImage, "png", new File(targetPath + "/" + handle.name())); } catch (IOException e) { e.printStackTrace(); } @@ -455,7 +439,6 @@ public class ProjectManager extends Proxy { if (!currentProjectVO.projectMainExportPath.isEmpty()) { exportFonts(currentProjectVO.projectMainExportPath); } - exportStyles(defaultBuildPath); SceneDataManager sceneDataManager = facade.retrieveProxy(SceneDataManager.NAME); sceneDataManager.buildScenes(defaultBuildPath); if (!currentProjectVO.projectMainExportPath.isEmpty()) { @@ -463,18 +446,6 @@ public class ProjectManager extends Proxy { } } - private void exportStyles(String targetPath) { - String srcPath = currentProjectPath + "/assets/orig"; - FileHandle origDirectoryHandle = Gdx.files.absolute(srcPath); - FileHandle stylesDirectory = origDirectoryHandle.child("styles"); - File fileTarget = new File(targetPath + "/" + stylesDirectory.name()); - try { - FileUtils.copyDirectory(stylesDirectory.file(), fileTarget); - } catch (IOException e) { - e.printStackTrace(); - } - } - private void exportShaders(String targetPath) { String srcPath = currentProjectPath + "/assets"; FileHandle origDirectoryHandle = Gdx.files.absolute(srcPath); @@ -482,8 +453,7 @@ public class ProjectManager extends Proxy { File fileTarget = new File(targetPath + "/" + shadersDirectory.name()); try { FileUtils.copyDirectory(shadersDirectory.file(), fileTarget); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ignore) { } } @@ -494,8 +464,7 @@ public class ProjectManager extends Proxy { File fileTarget = new File(targetPath + "/" + particlesDirectory.name()); try { FileUtils.copyDirectory(particlesDirectory.file(), fileTarget); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ignore) { } } @@ -506,8 +475,7 @@ public class ProjectManager extends Proxy { File fileTarget = new File(targetPath + "/" + particlesDirectory.name()); try { FileUtils.copyDirectory(particlesDirectory.file(), fileTarget); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ignore) { } } @@ -518,18 +486,15 @@ public class ProjectManager extends Proxy { File fileTarget = new File(targetPath + "/" + fontsDirectory.name()); try { FileUtils.copyDirectory(fontsDirectory.file(), fileTarget); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ignore) { } } private void exportAnimations(String targetPath) { exportSpineAnimationForResolution("orig", targetPath); - exportSpriteAnimationForResolution("orig", targetPath); for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) { exportSpineAnimationForResolution(resolutionEntryVO.name, targetPath); - exportSpriteAnimationForResolution(resolutionEntryVO.name, targetPath); } } @@ -548,21 +513,6 @@ public class ProjectManager extends Proxy { } } - private void exportSpriteAnimationForResolution(String res, String targetPath) { - String spineSrcPath = currentProjectPath + "/assets/" + res + File.separator + "sprite-animations"; - try { - FileUtils.forceMkdir(new File(targetPath + File.separator + res + File.separator + "sprite_animations")); - File fileSrc = new File(spineSrcPath); - String finalTarget = targetPath + File.separator + res + File.separator + "sprite_animations"; - - File fileTargetSprite = new File(finalTarget); - - FileUtils.copyDirectory(fileSrc, fileTargetSprite); - } catch (IOException e) { - e.printStackTrace(); - } - } - private void exportPacks(String targetPath) { String srcPath = currentProjectPath + "/assets"; FileHandle assetDirectoryHandle = Gdx.files.absolute(srcPath); @@ -681,6 +631,7 @@ public class ProjectManager extends Proxy { private boolean deleteSingleImage(String resolutionName, String imageName) { String imagesPath = currentProjectPath + "/assets/" + resolutionName + "/images" + File.separator; String filePath = imagesPath + imageName + ".png"; + deleteRegionFromPack(currentProjectInfoVO.imagesPacks, imageName); if (!(new File(filePath)).delete()) { filePath = imagesPath + imageName + ".9.png"; return (new File(filePath)).delete(); @@ -711,6 +662,18 @@ public class ProjectManager extends Proxy { private boolean deleteSpineAnimation(String resolutionName, String spineName) { String spinePath = currentProjectPath + "/assets/" + resolutionName + "/spine-animations" + File.separator; String filePath = spinePath + spineName; + FileHandle jsonPath = new FileHandle(filePath + File.separator + spineName + ".json"); + + JsonValue root = new JsonReader().parse(jsonPath); + for (JsonValue skinMap = root.getChild("skins"); skinMap != null; skinMap = skinMap.next) { + for (JsonValue slotEntry = skinMap.getChild("attachments"); slotEntry != null; slotEntry = slotEntry.next) { + for (JsonValue entry = slotEntry.child; entry != null; entry = entry.next) { + String name = spineName + entry.getString("name", entry.name); + deleteSingleImage(resolutionName, name); + deleteRegionFromPack(currentProjectInfoVO.animationsPacks, name); + } + } + } return deleteDirectory(filePath); } @@ -722,12 +685,25 @@ public class ProjectManager extends Proxy { return deleteSpineAnimation("orig", spineName); } - private boolean deleteSpriteAnimation(String resolutionName, String spineName) { + private boolean deleteSpriteAnimation(String resolutionName, String spriteName) { String spritePath = currentProjectPath + "/assets/" + resolutionName + "/sprite-animations" + File.separator; - String filePath = spritePath + spineName; + String filePath = spritePath + spriteName; + FileHandle imagesPath = new FileHandle(currentProjectPath + "/assets/" + resolutionName + "/images" + File.separator); + String prefix = spriteName + "_"; + for (FileHandle f : imagesPath.list()) { + if (f.nameWithoutExtension().startsWith(prefix)) { + f.delete(); + } + } + deleteRegionFromPack(currentProjectInfoVO.animationsPacks, spriteName); return deleteDirectory(filePath); } + public void deleteRegionFromPack(HashMap map, String region) { + for (TexturePackVO vo : map.values()) + vo.regions.remove(region); + } + public boolean deleteSpriteAnimationForAllResolutions(String spineName) { for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) { if(!deleteSpriteAnimation(resolutionEntryVO.name, spineName)) diff --git a/src/main/java/games/rednblack/editor/proxy/ResolutionManager.java b/src/main/java/games/rednblack/editor/proxy/ResolutionManager.java index ad710263..449904f4 100644 --- a/src/main/java/games/rednblack/editor/proxy/ResolutionManager.java +++ b/src/main/java/games/rednblack/editor/proxy/ResolutionManager.java @@ -29,15 +29,15 @@ import java.util.concurrent.Executors; import javax.imageio.ImageIO; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.utils.ObjectMap; import com.kotcrab.vis.ui.util.dialog.Dialogs; +import games.rednblack.editor.renderer.data.TexturePackVO; import games.rednblack.h2d.common.MsgAPI; 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; @@ -152,7 +152,6 @@ public class ResolutionManager extends Proxy { copyTexturesFromTo(sourcePath, targetPath); int resizeWarnings = resizeTextures(targetPath, resolutionEntryVO); rePackProjectImages(resolutionEntryVO); - createResizedAnimations(resolutionEntryVO); changePercentBy(5); if (resizeWarnings > 0) { Dialogs.showOKDialog(Sandbox.getInstance().getUIStage(), "Warning", resizeWarnings + " images were not resized for smaller resolutions due to already small size ( < 3px )"); @@ -177,144 +176,10 @@ public class ResolutionManager extends Proxy { //handler.progressChanged(currentPercent); } - public void createResizedAnimations(ResolutionEntryVO resolution) { - ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME); - String currProjectPath = projectManager.getCurrentProjectPath(); - - // Unpack spine orig - File spineSourceDir = new File(currProjectPath + File.separator + "assets/orig/spine-animations"); - if (spineSourceDir.exists()) { - for (File entry : spineSourceDir.listFiles()) { - if (entry.isDirectory()) { - String animName = FilenameUtils.removeExtension(entry.getName()); - createResizedSpineAnimation(animName, resolution); - } - } - } - - //Unpack sprite orig - File spriteSourceDir = new File(currProjectPath + File.separator + "assets/orig/sprite-animations"); - if (spriteSourceDir.exists()) { - for (File entry : spriteSourceDir.listFiles()) { - if (entry.isDirectory()) { - String animName = FilenameUtils.removeExtension(entry.getName()); - createResizedSpriteAnimation(animName, resolution); - } - } - } - } - - public void createResizedSpriteAnimation(String animName, ResolutionEntryVO resolution) { - ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME); - String currProjectPath = projectManager.getCurrentProjectPath(); - File animAtlasFile = new File(currProjectPath + File.separator + "assets/orig/sprite-animations/" + animName + "/" + animName + ".atlas"); - - String tmpPath = currProjectPath + File.separator + "assets/orig/sprite-animations/" + animName + "/tmp"; - File tmpFolder = new File(tmpPath); - try { - FileUtils.forceMkdir(new File(currProjectPath + File.separator + "assets/" + resolution.name + "/sprite-animations/")); - FileUtils.forceMkdir(new File(currProjectPath + File.separator + "assets/" + resolution.name + "/spine-animations/" + animName)); - - String targetPath = currProjectPath + File.separator + "assets/" + resolution.name + "/sprite-animations/" + animName; - File targetFolder = new File(targetPath); - - unpackAtlasIntoTmpFolder(animAtlasFile, tmpPath); - resizeImagesTmpDirToResolution(animName, tmpFolder, resolution, targetFolder); - - - FileUtils.deleteDirectory(tmpFolder); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void unpackAtlasIntoTmpFolder(File atlasFile, 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); - } - - public void createResizedSpineAnimation(String animName, ResolutionEntryVO resolution) { - ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME); - String currProjectPath = projectManager.getCurrentProjectPath(); - - File animAtlasFile = new File(currProjectPath + File.separator + "assets/orig/spine-animations/" + animName + "/" + animName + ".atlas"); - - String tmpPath = currProjectPath + File.separator + "assets/orig/spine-animations/" + animName + "/tmp"; - File tmpFolder = new File(tmpPath); - try { - FileUtils.forceMkdir(new File(currProjectPath + File.separator + "assets/" + resolution.name + "/spine-animations/")); - FileUtils.forceMkdir(new File(currProjectPath + File.separator + "assets/" + resolution.name + "/spine-animations/" + animName)); - - String targetPath = currProjectPath + File.separator + "assets/" + resolution.name + "/spine-animations/" + animName; - File targetFolder = new File(targetPath); - - unpackAtlasIntoTmpFolder(animAtlasFile, tmpPath); - resizeImagesTmpDirToResolution(animName, tmpFolder, resolution, targetFolder); - - FileUtils.deleteDirectory(tmpFolder); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void resizeSpriteAnimationForAllResolutions(String animName, ProjectInfoVO currentProjectInfoVO) { - ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME); - String currProjectPath = projectManager.getCurrentProjectPath(); - - File atlasFile = new File(currProjectPath + File.separator + "assets" + File.separator + "orig" + File.separator + "sprite-animations" + File.separator + animName + File.separator + animName + ".atlas"); - - String tmpDir = currProjectPath + File.separator + "assets" + File.separator + "orig" + File.separator + "sprite-animations" + File.separator + animName + File.separator + "tmp"; - File sourceFolder = new File(tmpDir); - - unpackAtlasIntoTmpFolder(atlasFile, tmpDir); - try { - for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) { - String spriteAnimationsRoot = currProjectPath + File.separator + "assets" + File.separator + resolutionEntryVO.name + File.separator + "sprite-animations"; - FileUtils.forceMkdir(new File(spriteAnimationsRoot)); - String targetPath = spriteAnimationsRoot + File.separator + animName; - File targetFolder = new File(targetPath); - - resizeImagesTmpDirToResolution(animName, sourceFolder, resolutionEntryVO, targetFolder); - } - - FileUtils.deleteDirectory(sourceFolder); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void resizeSpineAnimationForAllResolutions(File atlasFile, ProjectInfoVO currentProjectInfoVO) { - - String fileNameWithOutExt = FilenameUtils.removeExtension(atlasFile.getName()); - ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME); - String tmpDir = projectManager.getCurrentProjectPath() + "/assets/orig/spine-animations" + File.separator + fileNameWithOutExt + File.separator + "tmp"; - File sourceFolder = new File(tmpDir); - - unpackAtlasIntoTmpFolder(atlasFile, tmpDir); - try { - for (ResolutionEntryVO resolutionEntryVO : currentProjectInfoVO.resolutions) { - FileUtils.forceMkdir(new File(projectManager.getCurrentProjectPath() + File.separator + - "assets" + File.separator + resolutionEntryVO.name + File.separator + "spine-animations")); - String targetPath = projectManager.getCurrentProjectPath() + File.separator + "assets" + - File.separator + resolutionEntryVO.name + File.separator + "spine-animations" + File.separator + fileNameWithOutExt; - FileUtils.forceMkdir(new File(targetPath)); - File targetFolder = new File(targetPath); - resizeImagesTmpDirToResolution(atlasFile.getName(), sourceFolder, resolutionEntryVO, targetFolder); - } - FileUtils.deleteDirectory(sourceFolder); - } catch (IOException e) { - e.printStackTrace(); - } - } - public void rePackProjectImages(ResolutionEntryVO resEntry) { ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME); TexturePacker.Settings settings = projectManager.getTexturePackerSettings(); - TexturePacker tp = new TexturePacker(settings); - String sourcePath = projectManager.getCurrentProjectPath() + "/assets/" + resEntry.name + "/images"; String outputPath = projectManager.getCurrentProjectPath() + "/assets/" + resEntry.name + "/pack"; @@ -328,15 +193,36 @@ public class ResolutionManager extends Proxy { e.printStackTrace(); } + ObjectMap packerMap = new ObjectMap<>(); + ObjectMap regionsReverse = new ObjectMap<>(); + for (TexturePackVO packVO : projectManager.currentProjectInfoVO.imagesPacks.values()) { + String name = packVO.name.equals("main") ? "pack" : packVO.name; + packerMap.put(name, new TexturePacker(settings)); + for (String region : packVO.regions) + regionsReverse.put(region, name); + } + for (TexturePackVO packVO : projectManager.currentProjectInfoVO.animationsPacks.values()) { + String name = packVO.name.equals("main") ? "pack" : packVO.name; + if (packerMap.get(name) == null) + packerMap.put(name, new TexturePacker(settings)); + for (String region : packVO.regions) + regionsReverse.put(region, name); + } + + for (FileHandle entry : sourceDir.list()) { - String filename = entry.file().getName(); - String extension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase(); - if (extension.equals("png")) { + if (entry.extension().equals("png")) { + String name = regionsReverse.get(entry.nameWithoutExtension().replace(".9", "").replaceAll("_[0-9]+", "")); + name = name == null ? "pack" : name; + TexturePacker tp = packerMap.get(name); tp.addImage(entry.file()); } } - tp.pack(outputDir, "pack"); + for (String name : packerMap.keys()) { + TexturePacker tp = packerMap.get(name); + tp.pack(outputDir, name); + } } private int resizeTextures(String path, ResolutionEntryVO resolution) { diff --git a/src/main/java/games/rednblack/editor/proxy/ResourceManager.java b/src/main/java/games/rednblack/editor/proxy/ResourceManager.java index 06b6c3cb..ec985eb4 100644 --- a/src/main/java/games/rednblack/editor/proxy/ResourceManager.java +++ b/src/main/java/games/rednblack/editor/proxy/ResourceManager.java @@ -18,6 +18,7 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.*; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.utils.Align; +import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; import com.kotcrab.vis.ui.VisUI; import com.talosvfx.talos.runtime.ParticleEffectDescriptor; @@ -29,6 +30,7 @@ import games.rednblack.editor.renderer.data.*; import games.rednblack.editor.renderer.utils.H2DSkinLoader; import games.rednblack.editor.renderer.utils.ShadedDistanceFieldFont; import games.rednblack.editor.view.ui.widget.actors.basic.WhitePixel; +import games.rednblack.h2d.extension.talos.ResourceRetrieverAssetProvider; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; @@ -57,10 +59,10 @@ public class ResourceManager extends Proxy implements IResourceRetriever { private final HashMap particleEffects = new HashMap<>(1); private final HashMap talosVFXs = new HashMap<>(1); private final HashMap talosVFXsFiles = new HashMap<>(1); - private TextureAtlas currentProjectAtlas; + private HashMap currentProjectAtlas = new HashMap<>(1); private final HashMap spineAnimAtlases = new HashMap<>(); - private final HashMap spriteAnimAtlases = new HashMap<>(); + private final HashMap> spriteAnimAtlases = new HashMap<>(); private final HashMap bitmapFonts = new HashMap<>(); private final HashMap shaderPrograms = new HashMap<>(1); @@ -144,17 +146,17 @@ public class ResourceManager extends Proxy implements IResourceRetriever { @Override public TextureRegion getTextureRegion(String name) { - TextureRegion reg = currentProjectAtlas.findRegion(name); - - if(reg == null) { - reg = defaultRegion; + for (TextureAtlas atlas : currentProjectAtlas.values()) { + TextureRegion region = atlas.findRegion(name); + if (region != null) + return region; } - - return reg; + return defaultRegion; } - public TextureAtlas getTextureAtlas() { - return currentProjectAtlas; + @Override + public TextureAtlas getTextureAtlas(String atlasName) { + return currentProjectAtlas.get(atlasName); } @Override @@ -167,12 +169,6 @@ public class ResourceManager extends Proxy implements IResourceRetriever { return talosVFXsFiles.get(name); } - @Override - public TextureAtlas getSkeletonAtlas(String animationName) { - SpineAnimData animData = spineAnimAtlases.get(animationName); - return animData.atlas; - } - /** * Sets working resolution, please set before doing any loading * @param resolution String resolution name, default is "orig" later use resolution names created in editor @@ -192,7 +188,7 @@ public class ResourceManager extends Proxy implements IResourceRetriever { } @Override - public TextureAtlas getSpriteAnimation(String animationName) { + public Array getSpriteAnimation(String animationName) { return spriteAnimAtlases.get(animationName); } @@ -206,7 +202,11 @@ public class ResourceManager extends Proxy implements IResourceRetriever { @Override public boolean hasTextureRegion(String regionName) { - return currentProjectAtlas.findRegion(regionName) != null; + for (TextureAtlas atlas : currentProjectAtlas.values()) { + if (atlas.findRegion(regionName) != null) + return true; + } + return false; } @Override @@ -228,8 +228,7 @@ public class ResourceManager extends Proxy implements IResourceRetriever { public void loadCurrentProjectData(String projectPath, String curResolution) { packResolutionName = curResolution; - loadCurrentProjectAssets(projectPath + "/assets/" + curResolution + "/pack/pack.atlas"); - loadCurrentProjectSkin(projectPath + "/assets/orig/styles"); + loadCurrentProjectAssets(projectPath + "/assets/" + curResolution + "/pack"); loadCurrentProjectParticles(projectPath + "/assets/orig/particles"); loadCurrentProjectTalosVFXs(projectPath + "/assets/orig/talos-vfx"); loadCurrentProjectSpineAnimations(projectPath + "/assets/", curResolution); @@ -247,7 +246,13 @@ public class ResourceManager extends Proxy implements IResourceRetriever { if (file.isDirectory() || filename.endsWith(".DS_Store")) continue; ParticleEffect particleEffect = new ParticleEffect(); - particleEffect.load(Gdx.files.internal(file.getAbsolutePath()), currentProjectAtlas, ""); + particleEffect.loadEmitters(Gdx.files.internal(file.getAbsolutePath())); + for (TextureAtlas atlas : currentProjectAtlas.values()) { + try { + particleEffect.loadEmitterImages(atlas, ""); + break; + } catch (Exception ignore) { } + } particleEffects.put(filename, particleEffect); } } @@ -261,7 +266,7 @@ public class ResourceManager extends Proxy implements IResourceRetriever { String filename = file.getName(); if (file.isDirectory() || filename.endsWith(".DS_Store") || filename.endsWith("shdr") || filename.endsWith(".fga")) continue; - AtlasAssetProvider assetProvider = new AtlasAssetProvider(currentProjectAtlas); + ResourceRetrieverAssetProvider assetProvider = new ResourceRetrieverAssetProvider(this); assetProvider.setAssetHandler(ShaderDescriptor.class, this::findShaderDescriptorOnLoad); assetProvider.setAssetHandler(VectorField.class, this::findVectorFieldDescriptorOnLoad); ParticleEffectDescriptor effectDescriptor = new ParticleEffectDescriptor(); @@ -309,10 +314,8 @@ public class ResourceManager extends Proxy implements IResourceRetriever { for (FileHandle entry : sourceDir.list()) { if (entry.file().isDirectory()) { String animName = FilenameUtils.removeExtension(entry.file().getName()); - TextureAtlas atlas = new TextureAtlas(Gdx.files.internal(path + curResolution + "/spine-animations/" + File.separator + animName + File.separator + animName + ".atlas")); FileHandle animJsonFile = Gdx.files.internal(entry.file().getAbsolutePath() + File.separator + animName + ".json"); SpineAnimData data = new SpineAnimData(); - data.atlas = atlas; data.jsonFile = animJsonFile; data.animName = animName; spineAnimAtlases.put(animName, data); @@ -323,28 +326,29 @@ public class ResourceManager extends Proxy implements IResourceRetriever { private void loadCurrentProjectSpriteAnimations(String path, String curResolution) { spriteAnimAtlases.clear(); - FileHandle sourceDir = new FileHandle(path + curResolution + File.separator + "sprite-animations"); + FileHandle sourceDir = new FileHandle(path + "orig" + File.separator + "sprite-animations"); for (FileHandle entry : sourceDir.list()) { if (entry.file().isDirectory()) { String animName = FilenameUtils.removeExtension(entry.file().getName()); - FileHandle atlasFile = Gdx.files.internal(entry.file().getAbsolutePath() + File.separator + animName + ".atlas"); - if (!atlasFile.exists()) - continue; - try { - TextureAtlas atlas = new TextureAtlas(atlasFile); - spriteAnimAtlases.put(animName, atlas); - } catch (Exception e) { - e.printStackTrace(); + Array regions = null; + for (TextureAtlas atlas : currentProjectAtlas.values()) { + regions = atlas.findRegions(animName); + if (regions.size > 0) + break; } + if (regions != null) + spriteAnimAtlases.put(animName, regions); } } } - public void loadCurrentProjectAssets(String packPath) { - try { - currentProjectAtlas = new TextureAtlas(Gdx.files.getFileHandle(packPath, Files.FileType.Internal)); - } catch (Exception e) { - currentProjectAtlas = new TextureAtlas(); + public void loadCurrentProjectAssets(String packFolderPath) { + FileHandle folder = new FileHandle(packFolderPath); + for (FileHandle file : folder.list()) { + if (file.extension().equals("atlas")) { + String name = file.nameWithoutExtension().equals("pack") ? "main" : file.nameWithoutExtension(); + currentProjectAtlas.put(name, new TextureAtlas(file)); + } } } @@ -432,27 +436,6 @@ public class ResourceManager extends Proxy implements IResourceRetriever { } } - /** - * @param fontPath - * TODO currently useless, but could be reworked to include stuff from Skin Composer - * @deprecated - */ - @Deprecated - private void loadCurrentProjectSkin(String fontPath) { - /* - File styleFile = new File(fontPath, "styles.dt"); - FileHandle f = new FileHandle(styleFile); - - if (styleFile.isFile() && styleFile.exists()) { - projectSkin = new MySkin(f); - ObjectMap map = projectSkin.getAll(BitmapFont.class); - for (ObjectMap.Entry entry : map.entries()) { - projectSkin.getFont(entry.key).getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear); - } - } - */ - } - public FileHandle getTTFSafely(String fontName) throws IOException { FontManager fontManager = facade.retrieveProxy(FontManager.NAME); @@ -517,14 +500,10 @@ public class ResourceManager extends Proxy implements IResourceRetriever { return spineAnimAtlases; } - public HashMap getProjectSpriteAnimationsList() { + public HashMap> getProjectSpriteAnimationsList() { return spriteAnimAtlases; } - public TextureAtlas getProjectAssetsList() { - return currentProjectAtlas; - } - public HashMap getProjectParticleList() { return particleEffects; } @@ -549,9 +528,4 @@ public class ResourceManager extends Proxy implements IResourceRetriever { public HashMap getShaders() { return shaderPrograms; } - - @Override - public TextureAtlas getMainPack() { - return currentProjectAtlas; - } } diff --git a/src/main/java/games/rednblack/editor/utils/ImportUtils.java b/src/main/java/games/rednblack/editor/utils/ImportUtils.java index e6af9fa6..5b72b072 100644 --- a/src/main/java/games/rednblack/editor/utils/ImportUtils.java +++ b/src/main/java/games/rednblack/editor/utils/ImportUtils.java @@ -22,7 +22,6 @@ import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.utils.Array; import com.kotcrab.vis.ui.widget.file.FileTypeFilter; -import org.apache.commons.io.FilenameUtils; import java.io.BufferedReader; import java.io.File; @@ -138,23 +137,11 @@ public class ImportUtils { return regions.get(regions.size - 1).index == regions.size - 1; } - public static Array getAtlasPages(FileHandle fileHandle) { - Array imgs = new Array<>(); - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(fileHandle.read()), 64); - while (true) { - String line = reader.readLine(); - if (line == null) break; - //In atlas file format the name of the png is is preceded by an empty line - if (line.trim().length() == 0) { - line = reader.readLine(); - imgs.add(new File(FilenameUtils.getFullPath(fileHandle.path()) + line)); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - return imgs; + 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, prefix, tmpDir); } public static String getAtlasName(FileHandle fileHandle) { @@ -175,15 +162,4 @@ public class ImportUtils { } return name; } - - public static Array getAtlasPageHandles(FileHandle fileHandle) { - Array imgs = getAtlasPages(fileHandle); - - Array imgHandles = new Array<>(); - for (int i = 0; i < imgs.size; i++) { - imgHandles.add(new FileHandle(imgs.get(i))); - } - - return imgHandles; - } } 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/Asset.java b/src/main/java/games/rednblack/editor/utils/asset/Asset.java index d2021f6f..53e2faab 100644 --- a/src/main/java/games/rednblack/editor/utils/asset/Asset.java +++ b/src/main/java/games/rednblack/editor/utils/asset/Asset.java @@ -57,6 +57,7 @@ public abstract class Asset implements IAsset { executor.execute(() -> importAsset(files, progressHandler, skipRepack)); executor.execute(() -> { progressHandler.progressChanged(100); + projectManager.saveCurrentProject(); try { Thread.sleep(300); } catch (InterruptedException e) { diff --git a/src/main/java/games/rednblack/editor/utils/asset/impl/AtlasAsset.java b/src/main/java/games/rednblack/editor/utils/asset/impl/AtlasAsset.java index 78586309..7256e9c4 100644 --- a/src/main/java/games/rednblack/editor/utils/asset/impl/AtlasAsset.java +++ b/src/main/java/games/rednblack/editor/utils/asset/impl/AtlasAsset.java @@ -3,18 +3,20 @@ package games.rednblack.editor.utils.asset.impl; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.GdxRuntimeException; +import games.rednblack.editor.renderer.data.TexturePackVO; import games.rednblack.editor.utils.ImportUtils; import games.rednblack.editor.utils.asset.Asset; import games.rednblack.h2d.common.ProgressHandler; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; public class AtlasAsset extends Asset { @Override protected int getType() { - //TODO Atlas not suported yet - return ImportUtils.TYPE_UNKNOWN; - //return ImportUtils.TYPE_TEXTURE_ATLAS; + return ImportUtils.TYPE_TEXTURE_ATLAS; } @Override @@ -35,6 +37,34 @@ public class AtlasAsset extends Asset { @Override public void importAsset(Array files, ProgressHandler progressHandler, boolean skipRepack) { - throw new GdxRuntimeException("Atlas not suported yet."); + try { + for (FileHandle fileHandle : new Array.ArrayIterator<>(files)) { + FileHandle tmpDir = new FileHandle(projectManager.getCurrentProjectPath() + File.separator + "tmp"); + if (tmpDir.exists()) + FileUtils.forceDelete(tmpDir.file()); + FileUtils.forceMkdir(tmpDir.file()); + ImportUtils.unpackAtlasIntoTmpFolder(fileHandle.file(), null, tmpDir.path()); + Array images = new Array<>(tmpDir.list()); + projectManager.copyImageFilesForAllResolutionsIntoProject(images, true, progressHandler); + FileUtils.forceDelete(tmpDir.file()); + + TexturePackVO texturePackVO = projectManager.getCurrentProjectInfoVO().imagesPacks.get(fileHandle.nameWithoutExtension()); + if (texturePackVO == null) { + texturePackVO = new TexturePackVO(); + texturePackVO.name = fileHandle.nameWithoutExtension(); + + projectManager.getCurrentProjectInfoVO().imagesPacks.put(texturePackVO.name, texturePackVO); + } + + for (FileHandle image : images) { + texturePackVO.regions.add(image.nameWithoutExtension().replace(".9", "")); + } + } + + resolutionManager.rePackProjectImagesForAllResolutionsSync(); + } catch (IOException e) { + e.printStackTrace(); + progressHandler.progressFailed(); + } } } diff --git a/src/main/java/games/rednblack/editor/utils/asset/impl/ImageAsset.java b/src/main/java/games/rednblack/editor/utils/asset/impl/ImageAsset.java index f0cbe4f7..b90bb4c1 100644 --- a/src/main/java/games/rednblack/editor/utils/asset/impl/ImageAsset.java +++ b/src/main/java/games/rednblack/editor/utils/asset/impl/ImageAsset.java @@ -51,5 +51,9 @@ public class ImageAsset extends Asset { ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); resolutionManager.rePackProjectImagesForAllResolutionsSync(); } + + for (FileHandle handle : new Array.ArrayIterator<>(files)) { + projectManager.getCurrentProjectInfoVO().imagesPacks.get("main").regions.add(handle.nameWithoutExtension()); + } } } diff --git a/src/main/java/games/rednblack/editor/utils/asset/impl/ParticleEffectAsset.java b/src/main/java/games/rednblack/editor/utils/asset/impl/ParticleEffectAsset.java index 2fd207b9..4ba84e18 100644 --- a/src/main/java/games/rednblack/editor/utils/asset/impl/ParticleEffectAsset.java +++ b/src/main/java/games/rednblack/editor/utils/asset/impl/ParticleEffectAsset.java @@ -75,6 +75,10 @@ public class ParticleEffectAsset extends Asset { } if (images.size > 0) { projectManager.copyImageFilesForAllResolutionsIntoProject(images, false, progressHandler); + + for (FileHandle handle : new Array.ArrayIterator<>(images)) { + projectManager.getCurrentProjectInfoVO().imagesPacks.get("main").regions.add(handle.nameWithoutExtension()); + } } if (!skipRepack) { ResolutionManager resolutionManager = facade.retrieveProxy(ResolutionManager.NAME); 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 56475646..453b2bca 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 @@ -1,6 +1,7 @@ package games.rednblack.editor.utils.asset.impl; import com.badlogic.gdx.files.FileHandle; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.utils.Array; import com.kotcrab.vis.ui.util.dialog.Dialogs; import games.rednblack.editor.proxy.ProjectManager; @@ -53,17 +54,17 @@ public class SpineAsset extends Asset { @Override public void importAsset(Array files, ProgressHandler progressHandler, boolean skipRepack) { for (FileHandle handle : new Array.ArrayIterator<>(files)) { - File copiedFile = importExternalAnimationIntoProject(handle); + File copiedFile = importExternalAnimationIntoProject(handle, progressHandler); if (copiedFile == null) continue; - if (copiedFile.getName().toLowerCase().endsWith(".atlas")) { - resolutionManager.resizeSpineAnimationForAllResolutions(copiedFile, projectManager.getCurrentProjectInfoVO()); + if (copiedFile.getName().toLowerCase().endsWith(".json")) { + resolutionManager.rePackProjectImagesForAllResolutionsSync(); } } } - private File importExternalAnimationIntoProject(FileHandle animationFileSource) { + private File importExternalAnimationIntoProject(FileHandle animationFileSource, ProgressHandler progressHandler) { try { String fileName = animationFileSource.name(); if (!HyperLap2DUtils.JSON_FILTER.accept(null, fileName)) { @@ -85,11 +86,12 @@ public class SpineAsset extends Asset { "\nCould not find '" + atlasFileSource.name() +"'.\nCheck if the file exists in the same directory.").padBottom(20).pack(); return null; } - Array imageFiles = ImportUtils.getAtlasPages(atlasFileSource); - for (File imageFile : new Array.ArrayIterator<>(imageFiles)) { - if (!imageFile.exists()) { + + TextureAtlas.TextureAtlasData atlas = new TextureAtlas.TextureAtlasData(atlasFileSource, atlasFileSource.parent(), false); + for (TextureAtlas.TextureAtlasData.Page imageFile : new Array.ArrayIterator<>(atlas.getPages())) { + if (!imageFile.textureFile.exists()) { Dialogs.showErrorDialog(Sandbox.getInstance().getUIStage(), - "\nCould not find " + imageFile.getName() + ".\nCheck if the file exists in the same directory.").padBottom(20).pack(); + "\nCould not find " + imageFile.textureFile.name() + ".\nCheck if the file exists in the same directory.").padBottom(20).pack(); return null; } } @@ -103,19 +105,22 @@ public class SpineAsset extends Asset { FileUtils.forceMkdir(new File(targetPath)); File jsonFileTarget = new File(targetPath + File.separator + fileNameWithOutExt + ".json"); - File atlasFileTarget = new File(targetPath + File.separator + fileNameWithOutExt + ".atlas"); FileUtils.copyFile(animationFileSource.file(), jsonFileTarget); - FileUtils.copyFile(atlasFileSource.file(), atlasFileTarget); + FileHandle tmpDir = new FileHandle(projectManager.getCurrentProjectPath() + File.separator + "tmp"); + if (tmpDir.exists()) + FileUtils.forceDelete(tmpDir.file()); + FileUtils.forceMkdir(tmpDir.file()); + ImportUtils.unpackAtlasIntoTmpFolder(atlasFileSource.file(), fileNameWithOutExt, tmpDir.path()); + Array images = new Array<>(tmpDir.list()); + projectManager.copyImageFilesForAllResolutionsIntoProject(images, true, progressHandler); + FileUtils.forceDelete(tmpDir.file()); - for (File imageFile : new Array.ArrayIterator<>(imageFiles)) { - FileHandle imgFileTarget = new FileHandle(targetPath + File.separator + imageFile.getName()); - FileUtils.copyFile(imageFile, imgFileTarget.file()); + for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(atlas.getRegions())) { + projectManager.getCurrentProjectInfoVO().animationsPacks.get("main").regions.add(fileNameWithOutExt+region.name); } - return atlasFileTarget; - - + return jsonFileTarget; } } catch (IOException e) { e.printStackTrace(); 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 ceb0742a..d48f6658 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 @@ -44,10 +44,9 @@ public class SpriteAnimationAtlasAsset extends Asset { @Override public void importAsset(Array files, ProgressHandler progressHandler, boolean skipRepack) { for (FileHandle fileHandle : new Array.ArrayIterator<>(files)) { - String newAnimName = null; + String newAnimName; try { - Array imgs = ImportUtils.getAtlasPages(fileHandle); String fileNameWithoutExt = ImportUtils.getAtlasName(fileHandle); String targetPath = projectManager.getCurrentProjectPath() + "/assets/orig/sprite-animations" + File.separator + fileNameWithoutExt; @@ -55,9 +54,16 @@ public class SpriteAnimationAtlasAsset extends Asset { if (targetDir.exists()) { FileUtils.deleteDirectory(targetDir); } - for (File img : imgs) { - FileUtils.copyFileToDirectory(img, targetDir); - } + + FileHandle tmpDir = new FileHandle(projectManager.getCurrentProjectPath() + File.separator + "tmp"); + if (tmpDir.exists()) + FileUtils.forceDelete(tmpDir.file()); + FileUtils.forceMkdir(tmpDir.file()); + ImportUtils.unpackAtlasIntoTmpFolder(fileHandle.file(), null, tmpDir.path()); + Array images = new Array<>(tmpDir.list()); + projectManager.copyImageFilesForAllResolutionsIntoProject(images, true, progressHandler); + FileUtils.forceDelete(tmpDir.file()); + File atlasTargetPath = new File(targetPath + File.separator + fileNameWithoutExt + ".atlas"); FileUtils.copyFile(fileHandle.file(), atlasTargetPath); newAnimName = fileNameWithoutExt; @@ -68,7 +74,13 @@ public class SpriteAnimationAtlasAsset extends Asset { } if (newAnimName != null) { - resolutionManager.resizeSpriteAnimationForAllResolutions(newAnimName, projectManager.getCurrentProjectInfoVO()); + TextureAtlas.TextureAtlasData atlas = new TextureAtlas.TextureAtlasData(fileHandle, fileHandle.parent(), false); + + for (TextureAtlas.TextureAtlasData.Region region : new Array.ArrayIterator<>(atlas.getRegions())) { + projectManager.getCurrentProjectInfoVO().animationsPacks.get("main").regions.add(region.name); + } + + resolutionManager.rePackProjectImagesForAllResolutionsSync(); } } } diff --git a/src/main/java/games/rednblack/editor/utils/asset/impl/SpriteAnimationSequenceAsset.java b/src/main/java/games/rednblack/editor/utils/asset/impl/SpriteAnimationSequenceAsset.java index 11891d82..db2b6fbb 100644 --- a/src/main/java/games/rednblack/editor/utils/asset/impl/SpriteAnimationSequenceAsset.java +++ b/src/main/java/games/rednblack/editor/utils/asset/impl/SpriteAnimationSequenceAsset.java @@ -1,10 +1,8 @@ package games.rednblack.editor.utils.asset.impl; import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.tools.texturepacker.TexturePacker; import com.badlogic.gdx.utils.Array; import games.rednblack.editor.proxy.ProjectManager; -import games.rednblack.editor.utils.HyperLap2DUtils; import games.rednblack.editor.utils.ImportUtils; import games.rednblack.editor.utils.asset.Asset; import games.rednblack.h2d.common.ProgressHandler; @@ -49,7 +47,6 @@ public class SpriteAnimationSequenceAsset extends Asset { String newAnimName; String rawFileName = files.get(0).name(); - TexturePacker texturePacker = new TexturePacker(projectManager.getTexturePackerSettings()); String fileNameWithoutExt = FilenameUtils.removeExtension(rawFileName); String fileNameWithoutFrame = fileNameWithoutExt.replaceAll("\\d*$", "").replace("_", ""); @@ -61,15 +58,24 @@ public class SpriteAnimationSequenceAsset extends Asset { } String targetPath = projectManager.getCurrentProjectPath() + "/assets/orig/sprite-animations" + File.separator + fileNameWithoutFrame; + try { + FileUtils.writeStringToFile(new File(targetPath + File.separator + fileNameWithoutFrame + ".atlas"), fileNameWithoutFrame, "utf-8"); + } catch (IOException e) { + e.printStackTrace(); + progressHandler.progressFailed(); + return; + } + + String imagesPath = projectManager.getCurrentProjectPath() + File.separator + ProjectManager.IMAGE_DIR_PATH; for (FileHandle file : new Array.ArrayIterator<>(files)) { File src = file.file(); String destName; if (noFileNameWithoutFrame) { - destName = targetPath + "Tmp" + File.separator + fileNameWithoutFrame + src.getName().replaceAll("[_](?=.*[_])", ""); + destName = imagesPath + File.separator + fileNameWithoutFrame + src.getName().replaceAll("[_](?=.*[_])", ""); } else { - destName = targetPath + "Tmp" + File.separator + src.getName().replaceAll("[_](?=.*[_])", ""); + destName = imagesPath + File.separator + src.getName().replaceAll("[_](?=.*[_])", ""); } File dest = new File(destName); @@ -82,42 +88,11 @@ public class SpriteAnimationSequenceAsset extends Asset { } } - FileHandle pngsDir = new FileHandle(targetPath + "Tmp"); - for (FileHandle entry : pngsDir.list(HyperLap2DUtils.PNG_FILTER)) { - texturePacker.addImage(entry.file()); - } - - File targetDir = new File(targetPath); - if (targetDir.exists()) { - try { - FileUtils.deleteDirectory(targetDir); - } catch (IOException e) { - e.printStackTrace(); - progressHandler.progressFailed(); - return; - } - } - - try { - texturePacker.pack(targetDir, fileNameWithoutFrame); - } catch (Exception e) { - progressHandler.progressFailed(); - return; - } - - //delete newly created directory and images - try { - FileUtils.deleteDirectory(pngsDir.file()); - } catch (IOException e) { - e.printStackTrace(); - progressHandler.progressFailed(); - return; - } - newAnimName = fileNameWithoutFrame; if (newAnimName != null) { - resolutionManager.resizeSpriteAnimationForAllResolutions(newAnimName, projectManager.getCurrentProjectInfoVO()); + projectManager.getCurrentProjectInfoVO().animationsPacks.get("main").regions.add(newAnimName); + resolutionManager.rePackProjectImagesForAllResolutionsSync(); } } } diff --git a/src/main/java/games/rednblack/editor/utils/asset/impl/TalosVFXAsset.java b/src/main/java/games/rednblack/editor/utils/asset/impl/TalosVFXAsset.java index a8ea233f..34cd23b3 100644 --- a/src/main/java/games/rednblack/editor/utils/asset/impl/TalosVFXAsset.java +++ b/src/main/java/games/rednblack/editor/utils/asset/impl/TalosVFXAsset.java @@ -84,6 +84,10 @@ public class TalosVFXAsset extends Asset { } if (images.size > 0) { projectManager.copyImageFilesForAllResolutionsIntoProject(images, false, progressHandler); + + for (FileHandle handle : new Array.ArrayIterator<>(images)) { + projectManager.getCurrentProjectInfoVO().imagesPacks.get("main").regions.add(handle.nameWithoutExtension()); + } } if (assetsRes.size > 0) { for (FileHandle fileHandle : assetsRes) { diff --git a/src/main/java/games/rednblack/editor/view/menu/ResourcesMenu.java b/src/main/java/games/rednblack/editor/view/menu/ResourcesMenu.java index 9da2006e..8ff7a6a7 100644 --- a/src/main/java/games/rednblack/editor/view/menu/ResourcesMenu.java +++ b/src/main/java/games/rednblack/editor/view/menu/ResourcesMenu.java @@ -14,6 +14,8 @@ public class ResourcesMenu extends H2DMenu { public static final String IMPORT_TO_LIBRARY = HyperLap2DMenuBar.prefix + ".IMPORT_TO_LIBRARY"; public static final String CREATE_PLACEHOLDER = HyperLap2DMenuBar.prefix + ".CREATE_PLACEHOLDER"; public static final String CREATE_NOISE = HyperLap2DMenuBar.prefix + ".CREATE_NOISE"; + public static final String OPEN_IMAGES_PACK = HyperLap2DMenuBar.prefix + ".OPEN_IMAGES_PACK"; + public static final String OPEN_ANIMATIONS_PACK = HyperLap2DMenuBar.prefix + ".OPEN_ANIMATIONS_PACK"; public ResourcesMenu() { super("Resources"); @@ -21,10 +23,14 @@ public class ResourcesMenu extends H2DMenu { MenuItem placeholders = new MenuItem("Create Placeholder...", new MenuItemListener(CREATE_PLACEHOLDER, null, RESOURCE_MENU)); MenuItem noise = new MenuItem("Create Perlin Noise...", new MenuItemListener(CREATE_NOISE, null, RESOURCE_MENU)); MenuItem repack = new MenuItem("Repack Assets", new MenuItemListener(MsgAPI.ACTION_REPACK, null, RESOURCE_MENU)); + MenuItem imagesPack = new MenuItem("Images Atlases...", new MenuItemListener(OPEN_IMAGES_PACK, null, RESOURCE_MENU)); + MenuItem animationsPack = new MenuItem("Animations Atlases...", new MenuItemListener(OPEN_ANIMATIONS_PACK, null, RESOURCE_MENU)); addItem(importToLibrary); addSeparator(); addItem(repack); + addItem(imagesPack); + addItem(animationsPack); addSeparator(); addItem(placeholders); addItem(noise); diff --git a/src/main/java/games/rednblack/editor/view/stage/tools/SelectionTool.java b/src/main/java/games/rednblack/editor/view/stage/tools/SelectionTool.java index 4a638cad..c5ec711c 100644 --- a/src/main/java/games/rednblack/editor/view/stage/tools/SelectionTool.java +++ b/src/main/java/games/rednblack/editor/view/stage/tools/SelectionTool.java @@ -245,15 +245,6 @@ public class SelectionTool extends SimpleTool { newX = MathUtils.floor(x / gridSize) * gridSize; newY = MathUtils.floor(y / gridSize) * gridSize; - if (isShiftPressed()) { - if (directionVector.x == 0) { - newX = dragMouseStartPosition.x; - } - if (directionVector.y == 0) { - newY = dragMouseStartPosition.y; - } - } - // Selection rectangles should move and follow along for (Entity itemInstance : sandbox.getSelector().getCurrentSelection()) { transformComponent = ComponentRetriever.get(itemInstance, TransformComponent.class); @@ -264,8 +255,16 @@ public class SelectionTool extends SimpleTool { diff.x = MathUtils.floor(diff.x / gridSize) * gridSize; diff.y = MathUtils.floor(diff.y / gridSize) * gridSize; - transformComponent.x = (newX - diff.x); - transformComponent.y = (newY - diff.y); + if (isShiftPressed()) { + if (directionVector.x == 0) { + transformComponent.y = (newY - diff.y); + } else if (directionVector.y == 0) { + transformComponent.x = (newX - diff.x); + } + } else { + transformComponent.x = (newX - diff.x); + transformComponent.y = (newY - diff.y); + } //value.hide(); // pining UI to update current item properties tools @@ -332,7 +331,7 @@ public class SelectionTool extends SimpleTool { } isDragging = false; - + directionVector = null; } @Override diff --git a/src/main/java/games/rednblack/editor/view/ui/box/resourcespanel/UIImagesTabMediator.java b/src/main/java/games/rednblack/editor/view/ui/box/resourcespanel/UIImagesTabMediator.java index 2fc3a5af..46480376 100644 --- a/src/main/java/games/rednblack/editor/view/ui/box/resourcespanel/UIImagesTabMediator.java +++ b/src/main/java/games/rednblack/editor/view/ui/box/resourcespanel/UIImagesTabMediator.java @@ -27,7 +27,9 @@ import com.badlogic.gdx.utils.Array; import games.rednblack.editor.controller.commands.resource.DeleteImageResource; import games.rednblack.editor.factory.ItemFactory; +import games.rednblack.editor.proxy.ProjectManager; import games.rednblack.editor.proxy.ResourceManager; +import games.rednblack.editor.renderer.data.ProjectInfoVO; import games.rednblack.editor.view.ui.box.resourcespanel.draggable.DraggableResource; import games.rednblack.editor.view.ui.box.resourcespanel.draggable.box.ImageResource; @@ -68,24 +70,31 @@ public class UIImagesTabMediator extends UIResourcesTabMediator { @Override protected void initList(String searchText) { ResourceManager resourceManager = facade.retrieveProxy(ResourceManager.NAME); - - TextureAtlas atlas = resourceManager.getProjectAssetsList(); + ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME); + ProjectInfoVO projectInfoVO = projectManager.getCurrentProjectInfoVO(); Array thumbnailBoxes = new Array<>(); - Array atlasRegions = atlas.getRegions(); - for (TextureAtlas.AtlasRegion region : new Array.ArrayIterator<>(atlasRegions)) { - if(!region.name.contains(searchText))continue; - boolean is9patch = region.findValue("split") != null; - ImageResource imageResource = new ImageResource(region, new Color(1, 1, 1, 0.2f), new Color(1, 1, 1, 0.4f), - new Color(200f / 255f, 200f / 255f, 200f / 255f, 0.2f), new Color(255f / 255f, 94f / 255f, 0f / 255f, 1f), true); - DraggableResource draggableResource = new DraggableResource(imageResource); - if (is9patch) { - draggableResource.setFactoryFunction(ItemFactory.get()::create9Patch); - } else { - draggableResource.setFactoryFunction(ItemFactory.get()::createSimpleImage); + + for (String atlasName : projectInfoVO.imagesPacks.keySet()) { + TextureAtlas atlas = resourceManager.getTextureAtlas(atlasName); + Array atlasRegions = atlas.getRegions(); + + for (TextureAtlas.AtlasRegion region : new Array.ArrayIterator<>(atlasRegions)) { + if(!projectInfoVO.imagesPacks.get(atlasName).regions.contains(region.name) + || !region.name.contains(searchText)) continue; + + boolean is9patch = region.findValue("split") != null; + ImageResource imageResource = new ImageResource(region, new Color(1, 1, 1, 0.2f), new Color(1, 1, 1, 0.4f), + new Color(200f / 255f, 200f / 255f, 200f / 255f, 0.2f), new Color(255f / 255f, 94f / 255f, 0f / 255f, 1f), true); + DraggableResource draggableResource = new DraggableResource(imageResource); + if (is9patch) { + draggableResource.setFactoryFunction(ItemFactory.get()::create9Patch); + } else { + draggableResource.setFactoryFunction(ItemFactory.get()::createSimpleImage); + } + draggableResource.initDragDrop(); + thumbnailBoxes.add(draggableResource); } - draggableResource.initDragDrop(); - thumbnailBoxes.add(draggableResource); } thumbnailBoxes.sort(); diff --git a/src/main/java/games/rednblack/editor/view/ui/dialog/AboutDialog.java b/src/main/java/games/rednblack/editor/view/ui/dialog/AboutDialog.java index 1af0b3f7..96ae61ab 100644 --- a/src/main/java/games/rednblack/editor/view/ui/dialog/AboutDialog.java +++ b/src/main/java/games/rednblack/editor/view/ui/dialog/AboutDialog.java @@ -44,7 +44,7 @@ public class AboutDialog extends H2DDialog { scrollPane.setFadeScrollBars(false); mainTable.add(leftTable).top().padLeft(10).left(); - mainTable.add(scrollPane).maxHeight(300).top().width(550).padLeft(28).expand().left(); + mainTable.add(scrollPane).maxHeight(300).top().width(580).padLeft(28).expand().left(); leftTable.add(new VisImage(VisUI.getSkin().getDrawable("splash_logo"))).pad(5).row(); leftTable.add("HyperLap2D").padLeft(5).padRight(5).row(); diff --git a/src/main/java/games/rednblack/editor/view/ui/dialog/AnimationsPackDialogMediator.java b/src/main/java/games/rednblack/editor/view/ui/dialog/AnimationsPackDialogMediator.java new file mode 100644 index 00000000..4d022dab --- /dev/null +++ b/src/main/java/games/rednblack/editor/view/ui/dialog/AnimationsPackDialogMediator.java @@ -0,0 +1,112 @@ +package games.rednblack.editor.view.ui.dialog; + +import games.rednblack.editor.HyperLap2DFacade; +import games.rednblack.editor.controller.commands.resource.DeleteImageResource; +import games.rednblack.editor.controller.commands.resource.DeleteSpineAnimation; +import games.rednblack.editor.controller.commands.resource.DeleteSpriteAnimation; +import games.rednblack.editor.proxy.ProjectManager; +import games.rednblack.editor.renderer.data.TexturePackVO; +import games.rednblack.editor.view.menu.ResourcesMenu; +import games.rednblack.editor.view.stage.Sandbox; +import games.rednblack.editor.view.stage.UIStage; +import org.puremvc.java.interfaces.INotification; +import org.puremvc.java.patterns.mediator.Mediator; + +public class AnimationsPackDialogMediator extends Mediator { + private static final String TAG = AnimationsPackDialogMediator.class.getCanonicalName(); + private static final String NAME = TAG; + + private static final String NEW_IMAGES_PACK = "games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator.NEW_IMAGES_PACK"; + private static final String MOVE_REGION_TO_PACK = "games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator.MOVE_REGION_TO_PACK"; + private static final String UPDATE_CURRENT_LIST = "games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator.UPDATE_CURRENT_LIST"; + private static final String REMOVE_PACK = "games.rednblack.editor.view.ui.dialog.AnimationsPackDialogMediator.REMOVE_PACK"; + + public AnimationsPackDialogMediator() { + super(NAME, new AtlasesPackDialog("Animations Atlases", NEW_IMAGES_PACK, MOVE_REGION_TO_PACK, UPDATE_CURRENT_LIST, REMOVE_PACK)); + } + + @Override + public void onRegister() { + super.onRegister(); + facade = HyperLap2DFacade.getInstance(); + } + + @Override + public String[] listNotificationInterests() { + return new String[]{ + ResourcesMenu.OPEN_ANIMATIONS_PACK, + ProjectManager.PROJECT_OPENED, + NEW_IMAGES_PACK, + MOVE_REGION_TO_PACK, + UPDATE_CURRENT_LIST, + REMOVE_PACK, + ProjectManager.PROJECT_DATA_UPDATED, + DeleteImageResource.DONE, + DeleteSpineAnimation.DONE, + DeleteSpriteAnimation.DONE + }; + } + + @Override + public void handleNotification(INotification notification) { + Sandbox sandbox = Sandbox.getInstance(); + UIStage uiStage = sandbox.getUIStage(); + ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME); + String currentTab; + switch (notification.getName()) { + case ResourcesMenu.OPEN_ANIMATIONS_PACK: + viewComponent.show(uiStage); + break; + case ProjectManager.PROJECT_DATA_UPDATED: + case DeleteImageResource.DONE: + case DeleteSpineAnimation.DONE: + case DeleteSpriteAnimation.DONE: + viewComponent.updateMainPack(projectManager.currentProjectInfoVO.animationsPacks.get("main").regions); + currentTab = viewComponent.getSelectedTab(); + if (currentTab != null) + viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.animationsPacks.get(currentTab).regions); + break; + case ProjectManager.PROJECT_OPENED: + viewComponent.initPacks(projectManager.currentProjectInfoVO.animationsPacks.keySet()); + viewComponent.updateMainPack(projectManager.currentProjectInfoVO.animationsPacks.get("main").regions); + break; + case NEW_IMAGES_PACK: + TexturePackVO newVo = new TexturePackVO(); + newVo.name = notification.getBody(); + + projectManager.currentProjectInfoVO.animationsPacks.put(newVo.name, newVo); + + viewComponent.addNewPack(newVo.name); + projectManager.saveCurrentProject(); + break; + case UPDATE_CURRENT_LIST: + currentTab = viewComponent.getSelectedTab(); + System.out.println(currentTab); + if (currentTab != null) + viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.animationsPacks.get(currentTab).regions); + break; + case MOVE_REGION_TO_PACK: + String toPack = viewComponent.getMainSelected() != null ? viewComponent.getSelectedTab() : "main"; + String fromPack = viewComponent.getMainSelected() == null ? viewComponent.getSelectedTab() : "main"; + String region = viewComponent.getMainSelected() != null ? viewComponent.getMainSelected() : viewComponent.getCurrentSelected(); + + projectManager.currentProjectInfoVO.animationsPacks.get(fromPack).regions.remove(region); + projectManager.currentProjectInfoVO.animationsPacks.get(toPack).regions.add(region); + + viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.animationsPacks.get(viewComponent.getSelectedTab()).regions); + viewComponent.updateMainPack(projectManager.currentProjectInfoVO.animationsPacks.get("main").regions); + projectManager.saveCurrentProject(); + break; + case REMOVE_PACK: + String packToRemove = notification.getBody(); + projectManager.currentProjectInfoVO.animationsPacks.get("main").regions.addAll( + projectManager.currentProjectInfoVO.animationsPacks.get(packToRemove).regions + ); + projectManager.currentProjectInfoVO.animationsPacks.remove(packToRemove); + viewComponent.updateMainPack(projectManager.currentProjectInfoVO.animationsPacks.get("main").regions); + viewComponent.clearCurrentPack(); + projectManager.saveCurrentProject(); + break; + } + } +} diff --git a/src/main/java/games/rednblack/editor/view/ui/dialog/AtlasesPackDialog.java b/src/main/java/games/rednblack/editor/view/ui/dialog/AtlasesPackDialog.java new file mode 100644 index 00000000..9e3d5138 --- /dev/null +++ b/src/main/java/games/rednblack/editor/view/ui/dialog/AtlasesPackDialog.java @@ -0,0 +1,280 @@ +package games.rednblack.editor.view.ui.dialog; + +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.utils.Align; +import com.badlogic.gdx.utils.Array; +import com.kotcrab.vis.ui.util.adapter.AbstractListAdapter; +import com.kotcrab.vis.ui.util.adapter.SimpleListAdapter; +import com.kotcrab.vis.ui.util.dialog.Dialogs; +import com.kotcrab.vis.ui.util.dialog.OptionDialogAdapter; +import com.kotcrab.vis.ui.widget.*; +import com.kotcrab.vis.ui.widget.tabbedpane.Tab; +import com.kotcrab.vis.ui.widget.tabbedpane.TabbedPane; +import com.kotcrab.vis.ui.widget.tabbedpane.TabbedPaneAdapter; +import games.rednblack.editor.HyperLap2DFacade; +import games.rednblack.editor.view.stage.Sandbox; +import games.rednblack.h2d.common.H2DDialog; +import games.rednblack.h2d.common.view.ui.StandardWidgetsFactory; +import games.rednblack.h2d.common.view.ui.listener.ScrollFocusListener; + +import java.util.Set; + +public class AtlasesPackDialog extends H2DDialog { + + private final TabbedPane tabbedPane; + private final String addNewNotification; + private final String moveRegionNotification, updateCurrentNotification, removeNotification; + private final SimpleListAdapter mainPackAdapter, currentPackAdapter; + private final VisTextButton insertButton, removeButton; + private final VisLabel currentSelectedPackLabel; + + private final HyperLap2DFacade facade = HyperLap2DFacade.getInstance(); + + private final Array mainList = new Array<>(); + private final Array currentList = new Array<>(); + + private String mainSelected = null, currentSelected = null; + + public AtlasesPackDialog(String title, String add, String move, String updateList, String removeNotification) { + super(title); + addNewNotification = add; + moveRegionNotification = move; + updateCurrentNotification = updateList; + this.removeNotification = removeNotification; + + addCloseButton(); + getContentTable().top().left(); + + tabbedPane = new TabbedPane() { + @Override + public boolean remove(Tab tab, boolean ignoreTabDirty) { + Dialogs.showOptionDialog(Sandbox.getInstance().getUIStage(), "Remove Pack", "Are you sure to remove this pack?", + Dialogs.OptionDialogType.YES_NO_CANCEL, new OptionDialogAdapter() { + @Override + public void yes () { + facade.sendNotification(removeNotification, tab.getTabTitle()); + packRemove(tab, ignoreTabDirty); + } + + @Override + public void no () { + + } + }); + return false; + } + + private boolean packRemove(Tab tab, boolean ignoreTabDirty) { + return super.remove(tab, ignoreTabDirty); + } + }; + tabbedPane.addListener(new TabbedPaneAdapter() { + @Override + public void switchedTab(Tab tab) { + facade.sendNotification(updateCurrentNotification); + updateOpButtons(); + currentSelectedPackLabel.setText(tab.getTabTitle()); + } + }); + + VisTable addNewPackTable = new VisTable(); + VisTextField newPackName = StandardWidgetsFactory.createTextField(); + newPackName.setMessageText("Add new atlas pack"); + VisTextButton newPackButton = StandardWidgetsFactory.createTextButton("Add"); + newPackButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + if (!newPackName.getText().equals("")) + facade.sendNotification(addNewNotification, newPackName.getText()); + newPackName.setText(""); + } + }); + addNewPackTable.add(newPackName).growX(); + addNewPackTable.add(newPackButton).width(80); + + mainPackAdapter = new SimpleListAdapter<>(mainList); + mainPackAdapter.setSelectionMode(AbstractListAdapter.SelectionMode.SINGLE); + mainPackAdapter.getSelectionManager().setProgrammaticChangeEvents(false); + + currentPackAdapter = new SimpleListAdapter<>(currentList); + currentPackAdapter.setSelectionMode(AbstractListAdapter.SelectionMode.SINGLE); + currentPackAdapter.getSelectionManager().setProgrammaticChangeEvents(false); + + ListView mainPackList = new ListView<>(mainPackAdapter); + mainPackList.getScrollPane().addListener(new ScrollFocusListener()); + ListView currentPackList = new ListView<>(currentPackAdapter); + currentPackList.getScrollPane().addListener(new ScrollFocusListener()); + + mainPackList.setItemClickListener(this::selectMainItem); + currentPackList.setItemClickListener(this::selectCurrentItem); + + getContentTable().add(addNewPackTable).growX().row(); + getContentTable().add(tabbedPane.getTable()).height(30).growX().row(); + + insertButton = StandardWidgetsFactory.createTextButton("->"); + insertButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + if (!insertButton.isDisabled()) + facade.sendNotification(moveRegionNotification); + } + }); + removeButton = StandardWidgetsFactory.createTextButton("<-"); + removeButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + if (!removeButton.isDisabled()) + facade.sendNotification(moveRegionNotification); + } + }); + updateOpButtons(); + VisTable opButtonsContainer = new VisTable(); + VisTable opButtons = new VisTable(); + opButtons.add(insertButton).width(80).row(); + opButtons.add(removeButton).width(80).row(); + opButtonsContainer.addSeparator(true); + opButtonsContainer.add(opButtons); + opButtonsContainer.addSeparator(true); + + VisTable opTable = new VisTable(); + opTable.add(new VisLabel("Main Pack", Align.center)).uniformX().growX(); + opTable.add().width(80); + currentSelectedPackLabel = new VisLabel("Select Pack", Align.center); + opTable.add(currentSelectedPackLabel).uniformX().growX().row(); + opTable.addSeparator().colspan(3); + opTable.add(mainPackList.getMainTable()).uniformX().grow(); + opTable.add(opButtonsContainer).growY(); + opTable.add(currentPackList.getMainTable()).uniformX().grow().row(); + + getContentTable().add(opTable).grow().row(); + } + + private void selectCurrentItem(String item) { + mainPackAdapter.getSelectionManager().deselectAll(); + mainSelected = null; + currentSelected = item; + + updateOpButtons(); + } + + private void selectMainItem(String item) { + currentPackAdapter.getSelectionManager().deselectAll(); + currentSelected = null; + mainSelected = item; + + updateOpButtons(); + } + + public void initPacks(Set packs) { + tabbedPane.removeAll(); + + for (String name : packs) { + if (name.equals("main")) continue; + tabbedPane.add(new PackTab(name)); + } + + if (tabbedPane.getTabs().size > 0) tabbedPane.switchTab(0); + } + + public void clearCurrentPack() { + currentList.clear(); + currentPackAdapter.itemsChanged(); + } + + public void updateCurrentPack(Set regions) { + String toSelect = null; + if (currentPackAdapter.getSelection().size > 0) { + String selected = currentPackAdapter.getSelection().get(0); + int nextIndex = currentList.indexOf(selected, false); + if (nextIndex + 1 < currentList.size) + toSelect = currentList.get(nextIndex + 1); + + } + currentList.clear(); + for (String item : regions) + currentList.addAll(item); + currentList.sort(); + if (currentPackAdapter.getSelection().size > 0) { + selectCurrentItem(currentList.contains(toSelect, false) ? toSelect : null); + } + + currentPackAdapter.itemsChanged(); + if (toSelect != null && currentList.contains(toSelect, false)) { + currentPackAdapter.getSelectionManager().select(toSelect); + } + } + + public void updateMainPack(Set regions) { + String toSelect = null; + if (mainPackAdapter.getSelection().size > 0) { + String selected = mainPackAdapter.getSelection().get(0); + int nextIndex = mainList.indexOf(selected, false); + if (nextIndex + 1 < mainList.size) + toSelect = mainList.get(nextIndex + 1); + selectMainItem(toSelect); + } + mainList.clear(); + for (String item : regions) + mainList.addAll(item); + mainList.sort(); + + mainPackAdapter.itemsChanged(); + if (toSelect != null) { + mainPackAdapter.getSelectionManager().select(toSelect); + } + } + + public void addNewPack(String name) { + tabbedPane.add(new PackTab(name)); + pack(); + } + + public String getSelectedTab() { + if (tabbedPane.getActiveTab() == null) + return null; + return tabbedPane.getActiveTab().getTabTitle(); + } + + private void updateOpButtons() { + insertButton.setDisabled(tabbedPane.getActiveTab() == null || mainSelected == null); + removeButton.setDisabled(tabbedPane.getActiveTab() == null || currentSelected == null); + } + + public String getCurrentSelected() { + return currentSelected; + } + + public String getMainSelected() { + return mainSelected; + } + + @Override + public float getPrefWidth() { + return Sandbox.getInstance().getUIStage().getWidth() * 0.5f; + } + + @Override + public float getPrefHeight() { + return Sandbox.getInstance().getUIStage().getHeight() * 0.5f; + } + + public static class PackTab extends Tab { + String name; + public PackTab (String name) { + super(false, true); + this.name = name; + } + + @Override + public String getTabTitle() { + return name; + } + + @Override + public Table getContentTable() { + return null; + } + } +} diff --git a/src/main/java/games/rednblack/editor/view/ui/dialog/ImagesPackDialogMediator.java b/src/main/java/games/rednblack/editor/view/ui/dialog/ImagesPackDialogMediator.java new file mode 100644 index 00000000..5e6364a6 --- /dev/null +++ b/src/main/java/games/rednblack/editor/view/ui/dialog/ImagesPackDialogMediator.java @@ -0,0 +1,112 @@ +package games.rednblack.editor.view.ui.dialog; + +import games.rednblack.editor.HyperLap2DFacade; +import games.rednblack.editor.controller.commands.resource.DeleteImageResource; +import games.rednblack.editor.controller.commands.resource.DeleteSpineAnimation; +import games.rednblack.editor.controller.commands.resource.DeleteSpriteAnimation; +import games.rednblack.editor.proxy.ProjectManager; +import games.rednblack.editor.renderer.data.TexturePackVO; +import games.rednblack.editor.view.menu.ResourcesMenu; +import games.rednblack.editor.view.stage.Sandbox; +import games.rednblack.editor.view.stage.UIStage; +import org.puremvc.java.interfaces.INotification; +import org.puremvc.java.patterns.mediator.Mediator; + +public class ImagesPackDialogMediator extends Mediator { + private static final String TAG = ImagesPackDialogMediator.class.getCanonicalName(); + private static final String NAME = TAG; + + private static final String NEW_IMAGES_PACK = "games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator.NEW_IMAGES_PACK"; + private static final String MOVE_REGION_TO_PACK = "games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator.MOVE_REGION_TO_PACK"; + private static final String UPDATE_CURRENT_LIST = "games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator.UPDATE_CURRENT_LIST"; + private static final String REMOVE_PACK = "games.rednblack.editor.view.ui.dialog.ImagesPackDialogMediator.REMOVE_PACK"; + + public ImagesPackDialogMediator() { + super(NAME, new AtlasesPackDialog("Images Atlases", NEW_IMAGES_PACK, MOVE_REGION_TO_PACK, UPDATE_CURRENT_LIST, REMOVE_PACK)); + } + + @Override + public void onRegister() { + super.onRegister(); + facade = HyperLap2DFacade.getInstance(); + } + + @Override + public String[] listNotificationInterests() { + return new String[]{ + ResourcesMenu.OPEN_IMAGES_PACK, + ProjectManager.PROJECT_OPENED, + NEW_IMAGES_PACK, + MOVE_REGION_TO_PACK, + UPDATE_CURRENT_LIST, + REMOVE_PACK, + ProjectManager.PROJECT_DATA_UPDATED, + DeleteImageResource.DONE, + DeleteSpineAnimation.DONE, + DeleteSpriteAnimation.DONE + }; + } + + @Override + public void handleNotification(INotification notification) { + Sandbox sandbox = Sandbox.getInstance(); + UIStage uiStage = sandbox.getUIStage(); + ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME); + String currentTab; + switch (notification.getName()) { + case ResourcesMenu.OPEN_IMAGES_PACK: + viewComponent.show(uiStage); + break; + case ProjectManager.PROJECT_DATA_UPDATED: + case DeleteImageResource.DONE: + case DeleteSpineAnimation.DONE: + case DeleteSpriteAnimation.DONE: + viewComponent.updateMainPack(projectManager.currentProjectInfoVO.imagesPacks.get("main").regions); + currentTab = viewComponent.getSelectedTab(); + if (currentTab != null) + viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.imagesPacks.get(currentTab).regions); + break; + case ProjectManager.PROJECT_OPENED: + viewComponent.initPacks(projectManager.currentProjectInfoVO.imagesPacks.keySet()); + viewComponent.updateMainPack(projectManager.currentProjectInfoVO.imagesPacks.get("main").regions); + break; + case NEW_IMAGES_PACK: + TexturePackVO newVo = new TexturePackVO(); + newVo.name = notification.getBody(); + + projectManager.currentProjectInfoVO.imagesPacks.put(newVo.name, newVo); + + viewComponent.addNewPack(newVo.name); + projectManager.saveCurrentProject(); + break; + case UPDATE_CURRENT_LIST: + currentTab = viewComponent.getSelectedTab(); + if (currentTab != null) + viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.imagesPacks.get(currentTab).regions); + break; + case MOVE_REGION_TO_PACK: + String toPack = viewComponent.getMainSelected() != null ? viewComponent.getSelectedTab() : "main"; + String fromPack = viewComponent.getMainSelected() == null ? viewComponent.getSelectedTab() : "main"; + String region = viewComponent.getMainSelected() != null ? viewComponent.getMainSelected() : viewComponent.getCurrentSelected(); + + projectManager.currentProjectInfoVO.imagesPacks.get(fromPack).regions.remove(region); + projectManager.currentProjectInfoVO.imagesPacks.get(toPack).regions.add(region); + + viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.imagesPacks.get(viewComponent.getSelectedTab()).regions); + viewComponent.updateMainPack(projectManager.currentProjectInfoVO.imagesPacks.get("main").regions); + projectManager.saveCurrentProject(); + break; + case REMOVE_PACK: + String packToRemove = notification.getBody(); + projectManager.currentProjectInfoVO.imagesPacks.get("main").regions.addAll( + projectManager.currentProjectInfoVO.imagesPacks.get(packToRemove).regions + ); + projectManager.currentProjectInfoVO.imagesPacks.remove(packToRemove); + viewComponent.updateMainPack(projectManager.currentProjectInfoVO.imagesPacks.get("main").regions); + viewComponent.updateCurrentPack(projectManager.currentProjectInfoVO.imagesPacks.get(viewComponent.getSelectedTab()).regions); + viewComponent.clearCurrentPack(); + projectManager.saveCurrentProject(); + break; + } + } +} 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 f857bb2e..c2fad424 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.ResourceRetrieverAttachmentLoader; public class SpineActor extends Actor { @@ -80,7 +81,7 @@ public class SpineActor extends Actor { } private void initSkeletonData() { - skeletonJson = new SkeletonJson(irr.getSkeletonAtlas(animationName)); + skeletonJson = new SkeletonJson(new ResourceRetrieverAttachmentLoader(animationName, irr)); skeletonData = skeletonJson.readSkeletonData((irr.getSkeletonJSON(animationName))); } diff --git a/src/main/java/games/rednblack/editor/view/ui/widget/actors/SpriteAnimationActor.java b/src/main/java/games/rednblack/editor/view/ui/widget/actors/SpriteAnimationActor.java index c309d607..e0776719 100644 --- a/src/main/java/games/rednblack/editor/view/ui/widget/actors/SpriteAnimationActor.java +++ b/src/main/java/games/rednblack/editor/view/ui/widget/actors/SpriteAnimationActor.java @@ -2,6 +2,7 @@ package games.rednblack.editor.view.ui.widget.actors; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Actor; import games.rednblack.editor.renderer.resources.IResourceRetriever; @@ -11,10 +12,10 @@ import games.rednblack.editor.renderer.resources.IResourceRetriever; */ public class SpriteAnimationActor extends Actor { - private String animationName; - private IResourceRetriever rm; + private final String animationName; + private final IResourceRetriever rm; - private Animation animation; + private final Animation animation; private float stateTime = 0; private int fps; @@ -24,17 +25,17 @@ public class SpriteAnimationActor extends Actor { public SpriteAnimationActor(String animationName, IResourceRetriever rm) { this.animationName = animationName; this.rm = rm; - animation = new Animation(1/24f, rm.getSpriteAnimation(animationName).getRegions()); + animation = new Animation<>(1/24f, rm.getSpriteAnimation(animationName)); animation.setPlayMode(Animation.PlayMode.LOOP); - TextureRegion region = (TextureRegion) animation.getKeyFrame(stateTime); + TextureRegion region = animation.getKeyFrame(stateTime); setWidth(region.getRegionWidth()); setHeight(region.getRegionHeight()); } @Override public void draw(Batch batch, float parentAlpha) { - TextureRegion region = (TextureRegion) animation.getKeyFrame(stateTime); + TextureRegion region = animation.getKeyFrame(stateTime); setWidth(region.getRegionWidth()); setHeight(region.getRegionHeight());