diff --git a/CHANGES b/CHANGES index 200df555..078c291e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +[0.0.7] += Editor = +- Huge improvements to Tiled Plugin: + * Sprite and Spine animated Tiles + * UI improvements and general refactoring + [0.0.6] - Update libGDX to 1.10.0 - Add flipX and flipY flag diff --git a/assets/plugins/plugin-tiled-0.0.7.jar b/assets/plugins/plugin-tiled-0.0.7.jar index f0371d63..8f3e9355 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/hyperlap2d-common-api b/hyperlap2d-common-api index 0a0603bf..b0cca697 160000 --- a/hyperlap2d-common-api +++ b/hyperlap2d-common-api @@ -1 +1 @@ -Subproject commit 0a0603bf88af552d890c41f477392ef3ef618a3e +Subproject commit b0cca697ccccef0fcb6122ae7b876a415611b650 diff --git a/hyperlap2d-runtime-libgdx b/hyperlap2d-runtime-libgdx index 7108be03..f20262c4 160000 --- a/hyperlap2d-runtime-libgdx +++ b/hyperlap2d-runtime-libgdx @@ -1 +1 @@ -Subproject commit 7108be03aa2915daa65d17c75bcdab01b781db48 +Subproject commit f20262c4b5e39695a14b80835f7aaca0321b2899 diff --git a/plugin-tiled/assets/textures/tile.png b/plugin-tiled/assets/pack/tile-cursor.png similarity index 100% rename from plugin-tiled/assets/textures/tile.png rename to plugin-tiled/assets/pack/tile-cursor.png diff --git a/plugin-tiled/assets/textures/tile-eraser.png b/plugin-tiled/assets/pack/tile-eraser-cursor.png similarity index 100% rename from plugin-tiled/assets/textures/tile-eraser.png rename to plugin-tiled/assets/pack/tile-eraser-cursor.png diff --git a/plugin-tiled/assets/pack/tiled.atlas b/plugin-tiled/assets/pack/tiled.atlas index 97034614..dea196d0 100644 --- a/plugin-tiled/assets/pack/tiled.atlas +++ b/plugin-tiled/assets/pack/tiled.atlas @@ -2,29 +2,16 @@ tiled.png size: 512, 128 filter: Linear, Linear image-Box-active - bounds: 87, 22, 4, 4 + bounds: 25, 20, 4, 4 split: 1, 1, 1, 1 image-Box-inactive - bounds: 436, 31, 4, 4 + bounds: 435, 95, 4, 4 split: 1, 1, 1, 1 -plugin-tab-active - bounds: 436, 105, 73, 21 - split: 4, 4, 3, 0 -plugin-tab-inactive - bounds: 2, 5, 83, 21 - split: 3, 3, 2, 1 -tab-back-line - bounds: 2, 2, 2, 1 - split: 0, 0, 0, 0 -tile - bounds: 436, 71, 32, 32 -tile-eraser - bounds: 436, 37, 32, 32 tiles-drop-here-normal - bounds: 2, 28, 215, 98 + bounds: 1, 26, 215, 98 tiles-drop-here-over - bounds: 219, 28, 215, 98 + bounds: 218, 26, 215, 98 tool-tilebrush - bounds: 470, 80, 22, 23 + bounds: 1, 1, 22, 23 tool-tileeraser - bounds: 470, 55, 22, 23 + bounds: 435, 101, 22, 23 diff --git a/plugin-tiled/assets/pack/tiled.png b/plugin-tiled/assets/pack/tiled.png index b4327c44..8d5cc1fe 100644 Binary files a/plugin-tiled/assets/pack/tiled.png and b/plugin-tiled/assets/pack/tiled.png differ diff --git a/plugin-tiled/assets/textures/plugin-tab-active.9.png b/plugin-tiled/assets/textures/plugin-tab-active.9.png deleted file mode 100644 index 44df0daf..00000000 Binary files a/plugin-tiled/assets/textures/plugin-tab-active.9.png and /dev/null differ diff --git a/plugin-tiled/assets/textures/plugin-tab-inactive.9.png b/plugin-tiled/assets/textures/plugin-tab-inactive.9.png deleted file mode 100644 index 25b6f1c4..00000000 Binary files a/plugin-tiled/assets/textures/plugin-tab-inactive.9.png and /dev/null differ diff --git a/plugin-tiled/assets/textures/tab-back-line.9.png b/plugin-tiled/assets/textures/tab-back-line.9.png deleted file mode 100644 index b0057876..00000000 Binary files a/plugin-tiled/assets/textures/tab-back-line.9.png and /dev/null differ diff --git a/plugin-tiled/build.gradle b/plugin-tiled/build.gradle index a27c9769..992bb055 100644 --- a/plugin-tiled/build.gradle +++ b/plugin-tiled/build.gradle @@ -19,10 +19,13 @@ dependencies { implementation "com.badlogicgames.ashley:ashley:$ashleyVersion" implementation "com.kotcrab.vis:vis-ui:$visuiVersion" + implementation "com.esotericsoftware.spine:spine-libgdx:$spineVersion" + implementation 'net.mountainblade:modular:1.0' implementation project(":hyperlap2d-common-api") implementation project(":hyperlap2d-runtime-libgdx") + implementation project(":h2d-libgdx-spine-extension") testImplementation group: 'junit', name: 'junit', version: '4.12' } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPanel.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPanel.java index 189ff2dc..ee8a8341 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPanel.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPanel.java @@ -21,6 +21,7 @@ package games.rednblack.editor.plugin.tiled; import com.badlogic.ashley.core.Engine; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Align; import com.kotcrab.vis.ui.VisUI; import com.kotcrab.vis.ui.widget.VisLabel; import com.kotcrab.vis.ui.widget.VisTable; @@ -40,11 +41,11 @@ import org.puremvc.java.interfaces.IFacade; */ public class TiledPanel extends UIDraggablePanel { - public static final float GRID_WIDTH = 200f; + public static final float GRID_WIDTH = 220f; public static final float GRID_HEIGHT = 250f; - public static final float DROP_WIDTH = 210f; + public static final float DROP_WIDTH = 220f; public static final float DROP_HEIGHT = 140f; - public static final float SETTINGS_WIDTH = 200f; + public static final float SETTINGS_WIDTH = 220f; public static final float SETTINGS_HEIGHT = 150f; public TiledPlugin tiledPlugin; @@ -79,11 +80,6 @@ public class TiledPanel extends UIDraggablePanel { this.resourcesManager = tiledPlugin.pluginRM; mainTable.clear(); - VisTextButton.VisTextButtonStyle btnStyle = new VisTextButton.VisTextButtonStyle(); - btnStyle.up = new TextureRegionDrawable(resourcesManager.getTextureRegion("plugin-tab-inactive")); - btnStyle.checked = new TextureRegionDrawable(resourcesManager.getTextureRegion("plugin-tab-active")); - btnStyle.font = VisUI.getSkin().getFont("default-font"); - btnStyle.fontColor = VisUI.getSkin().getColor("white"); tabbedPane = new ImageTabbedPane(); paneTable = tabbedPane.getTable(); @@ -127,9 +123,10 @@ public class TiledPanel extends UIDraggablePanel { .width(WIDTH) .height(HEIGHT) .row(); + float prevHeight = getHeight(); pack(); - - setFixedPosition(); + float heightDiff = getHeight() - prevHeight; + setY(getY() - heightDiff); } @Override @@ -161,8 +158,8 @@ public class TiledPanel extends UIDraggablePanel { settingsTab.resetGridCategory(); } - public void addTile(String tileName) { - tilesTab.addTile(tileName); + public void addTile(String tileName, int type) { + tilesTab.addTile(tileName, type); } public void selectTile(TileVO tileVO) { @@ -172,7 +169,6 @@ public class TiledPanel extends UIDraggablePanel { public void removeTile() { tilesTab.removeTile(); reInitTabTable(); - setFixedPosition(); tilesTab.scrollTiles(); } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPanelMediator.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPanelMediator.java index ab1bd3d7..0861f232 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPanelMediator.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPanelMediator.java @@ -22,8 +22,11 @@ import com.badlogic.ashley.core.Engine; import com.badlogic.ashley.core.Entity; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop; +import games.rednblack.editor.plugin.tiled.view.SpineDrawable; +import games.rednblack.editor.renderer.factory.EntityFactory; import games.rednblack.h2d.common.vo.CursorData; import games.rednblack.editor.plugin.tiled.data.TileVO; import games.rednblack.editor.plugin.tiled.tools.DeleteTileTool; @@ -46,6 +49,7 @@ public class TiledPanelMediator extends Mediator { public static final String NAME = TAG; private TiledPlugin tiledPlugin; + private DragAndDrop.Target target; public TiledPanelMediator(TiledPlugin tiledPlugin) { super(NAME, new TiledPanel(tiledPlugin)); @@ -63,7 +67,6 @@ public class TiledPanelMediator extends Mediator { TiledPlugin.ACTION_DELETE_TILE, TiledPlugin.ACTION_SET_GRID_SIZE_FROM_LIST, TiledPlugin.ACTION_SET_OFFSET, - TiledPlugin.PANEL_OPEN, TiledPlugin.OPEN_DROP_DOWN, TiledPlugin.GRID_CHANGED, SettingsTab.OK_BTN_CLICKED, @@ -87,7 +90,9 @@ public class TiledPanelMediator extends Mediator { tiledPlugin.initSaveData(); viewComponent.initView(); - DragAndDrop.Target target = new DragAndDrop.Target(viewComponent.getDropTable()) { + if (target != null) + tiledPlugin.facade.sendNotification(MsgAPI.REMOVE_TARGET, target); + target = new DragAndDrop.Target(viewComponent.getDropTable()) { @Override public boolean drag(DragAndDrop.Source source, DragAndDrop.Payload payload, float x, float y, int pointer) { return true; @@ -95,14 +100,14 @@ public class TiledPanelMediator extends Mediator { @Override public void drop(DragAndDrop.Source source, DragAndDrop.Payload payload, float x, float y, int pointer) { - ResourcePayloadObject resourcePayloadObject = (ResourcePayloadObject) payload.getObject(); - if (!resourcePayloadObject.className.endsWith(".ImageResource")) return; //only image resource can become a tile! + int type = mapClassNameToEntityType(resourcePayloadObject.className); + if (type == EntityFactory.UNKNOWN_TYPE) return; //only some resources can become a tile! String tileName = resourcePayloadObject.name; if (tiledPlugin.dataToSave.containsTile(tileName)) return; - tiledPlugin.facade.sendNotification(TiledPlugin.TILE_ADDED, tileName); + tiledPlugin.facade.sendNotification(TiledPlugin.TILE_ADDED, new Object[]{tileName, type}); } }; @@ -112,11 +117,12 @@ public class TiledPanelMediator extends Mediator { viewComponent.setFixedPosition(); break; case TiledPlugin.TILE_ADDED: - tileName = notification.getBody(); - viewComponent.addTile(tileName); - viewComponent.setFixedPosition(); + Object[] payload = notification.getBody(); + tileName = (String) payload[0]; + int type = (int) payload[1]; + viewComponent.addTile(tileName, type); - tiledPlugin.dataToSave.addTile(tileName); + tiledPlugin.dataToSave.addTile(tileName, type); tiledPlugin.saveDataManager.save(); break; case TiledPlugin.TILE_SELECTED: @@ -136,8 +142,20 @@ public class TiledPanelMediator extends Mediator { tiledPlugin.facade.sendNotification(TiledPlugin.ACTION_DELETE_TILE, tileName); break; case TiledPlugin.ACTION_SET_GRID_SIZE_FROM_LIST: - TextureRegion r = tiledPlugin.pluginRM.getTextureRegion(notification.getBody()); - tiledPlugin.dataToSave.setGrid(r.getRegionWidth() / tiledPlugin.getPixelToWorld(), r.getRegionHeight() / tiledPlugin.getPixelToWorld()); + float width = 0; + float height = 0; + TileVO t = tiledPlugin.dataToSave.getTile(notification.getBody()); + if (t.entityType == EntityFactory.SPINE_TYPE) { + SpineDrawable spineDrawable = tiledPlugin.pluginRM.getSpineDrawable(t.regionName); + width = spineDrawable.width; + height = spineDrawable.height; + } else { + TextureRegion r = tiledPlugin.pluginRM.getTextureRegion(t.regionName, t.entityType); + width = r.getRegionWidth(); + height = r.getRegionHeight(); + } + + tiledPlugin.dataToSave.setGrid(width / tiledPlugin.getPixelToWorld(), height / tiledPlugin.getPixelToWorld()); tiledPlugin.facade.sendNotification(TiledPlugin.GRID_CHANGED); break; case TiledPlugin.ACTION_DELETE_TILE: @@ -149,38 +167,25 @@ public class TiledPanelMediator extends Mediator { viewComponent.removeTile(); break; - case TiledPlugin.PANEL_OPEN: - if(viewComponent.isOpen) { - break; - } - - viewComponent.show(tiledPlugin.getAPI().getUIStage()); - - if(tiledPlugin.isSceneLoaded) { - viewComponent.setFixedPosition(); - } - break; case MsgAPI.TOOL_SELECTED: String body = notification.getBody(); - String cursorName = null; switch (body) { - case DrawTileTool.NAME: - cursorName = "tile"; - tiledPlugin.facade.sendNotification(TiledPlugin.PANEL_OPEN); - break; case DeleteTileTool.NAME: - cursorName = "tile-eraser"; + case DrawTileTool.NAME: + if(viewComponent.isOpen) { + break; + } + + viewComponent.show(tiledPlugin.getAPI().getUIStage()); + if(tiledPlugin.isSceneLoaded) { + viewComponent.setFixedPosition(); + } + break; default: viewComponent.hide(); break; } - if (cursorName != null) { - CursorData cursorData = new CursorData(cursorName, 14, 14); - TextureRegion region = tiledPlugin.pluginRM.getTextureRegion(cursorName); - //TODO A custom cursor has to be a Texture not a region of an atlas - //tiledPlugin.getAPI().setCursor(cursorData, region); - } break; case SettingsTab.OK_BTN_CLICKED: tiledPlugin.dataToSave.setParameterVO(notification.getBody()); @@ -207,5 +212,14 @@ public class TiledPanelMediator extends Mediator { } } + private int mapClassNameToEntityType(String className) { + if (className.endsWith(".ImageResource")) + return EntityFactory.IMAGE_TYPE; + else if (className.endsWith(".SpriteResource")) + return EntityFactory.SPRITE_TYPE; + else if (className.endsWith(".SpineResource")) + return EntityFactory.SPINE_TYPE; + return EntityFactory.UNKNOWN_TYPE; + } } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPlugin.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPlugin.java index ebd6c35f..c5eb273a 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPlugin.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/TiledPlugin.java @@ -45,7 +45,6 @@ import net.mountainblade.modular.annotations.Implementation; import java.util.Set; - /** * Created by mariam on 2/2/2016. */ @@ -56,7 +55,6 @@ public class TiledPlugin extends H2DPluginAdapter { public static final String CLASS_NAME = "games.rednblack.editor.plugin.tiled"; public static final String TILE_ADDED = CLASS_NAME + ".TILE_ADDED"; public static final String TILE_SELECTED = CLASS_NAME + ".TILE_SELECTED"; - public static final String PANEL_OPEN = CLASS_NAME + ".PANEL_OPEN"; public static final String OPEN_DROP_DOWN = CLASS_NAME + ".OPEN_DROP_DOWN"; public static final String GRID_CHANGED = CLASS_NAME + ".GRID_CHANGED"; public static final String ACTION_DELETE_TILE = CLASS_NAME + ".ACTION_DELETE_TILE"; @@ -107,7 +105,7 @@ public class TiledPlugin extends H2DPluginAdapter { tileAddButtonStyle.down = skin.getDrawable("toolbar-down"); tileAddButtonStyle.checked = skin.getDrawable("toolbar-down"); tileAddButtonStyle.over = skin.getDrawable("toolbar-over"); - tileAddButtonStyle.imageUp = new TextureRegionDrawable(pluginRM.getTextureRegion("tool-tilebrush")); + tileAddButtonStyle.imageUp = new TextureRegionDrawable(pluginRM.getTextureRegion("tool-tilebrush", -1)); pluginAPI.addTool(DrawTileTool.NAME, tileAddButtonStyle, true, drawTileTool); VisImageButton.VisImageButtonStyle tileDeleteButtonStyle = new VisImageButton.VisImageButtonStyle(); @@ -115,7 +113,7 @@ public class TiledPlugin extends H2DPluginAdapter { tileDeleteButtonStyle.down = skin.getDrawable("toolbar-down"); tileDeleteButtonStyle.checked = skin.getDrawable("toolbar-down"); tileDeleteButtonStyle.over = skin.getDrawable("toolbar-over"); - tileDeleteButtonStyle.imageUp = new TextureRegionDrawable(pluginRM.getTextureRegion("tool-tileeraser")); + tileDeleteButtonStyle.imageUp = new TextureRegionDrawable(pluginRM.getTextureRegion("tool-tileeraser", -1)); pluginAPI.addTool(DeleteTileTool.NAME, tileDeleteButtonStyle, false, deleteTileTool); pluginAPI.setDropDownItemName(ACTION_SET_GRID_SIZE_FROM_ITEM, "Set tile grid size"); @@ -197,6 +195,10 @@ public class TiledPlugin extends H2DPluginAdapter { return selectedTileVO.regionName; } + public int getSelectedTileType() { + return selectedTileVO.entityType; + } + public Vector2 getSelectedTileGridOffset() { return selectedTileVO.gridOffset; } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/TileVO.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/TileVO.java index 66b92a9d..39f93f53 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/TileVO.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/TileVO.java @@ -1,6 +1,7 @@ package games.rednblack.editor.plugin.tiled.data; import com.badlogic.gdx.math.Vector2; +import games.rednblack.editor.renderer.factory.EntityFactory; /** * Created by mariam on 5/13/16. @@ -9,6 +10,7 @@ public class TileVO { public String regionName = ""; public Vector2 gridOffset; + public int entityType = EntityFactory.IMAGE_TYPE; public TileVO() { gridOffset = new Vector2(); 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 35eca2b6..20b62c18 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 @@ -1,12 +1,19 @@ package games.rednblack.editor.plugin.tiled.manager; -import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.utils.ObjectMap; +import com.esotericsoftware.spine.Skeleton; +import com.esotericsoftware.spine.SkeletonData; +import com.esotericsoftware.spine.SkeletonJson; +import com.esotericsoftware.spine.SkeletonRenderer; 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 java.io.File; import java.io.FileOutputStream; @@ -23,22 +30,36 @@ public class ResourcesManager { private TiledPlugin tiledPlugin; private TextureAtlas textureAtlas; + private final SkeletonRenderer skeletonRenderer = new SkeletonRenderer(); + + private final ObjectMap textureCache = new ObjectMap<>(); + private final ObjectMap spineDrawableCache = new ObjectMap<>(); + public ResourcesManager(TiledPlugin tiledPlugin) { this.tiledPlugin = tiledPlugin; + skeletonRenderer.setPremultipliedAlpha(true); init(); } private void init() { - FileHandle atlasTempFile = getResourceFileFromJar(".atlas"); - FileHandle pngTempFile = getResourceFileFromJar(".png"); + FileHandle atlasTempFile = getResourceFileFromJar(RESOURCES_FILE_NAME + ".atlas"); + FileHandle pngTempFile = getResourceFileFromJar(RESOURCES_FILE_NAME + ".png"); textureAtlas = new TextureAtlas(atlasTempFile); atlasTempFile.file().deleteOnExit(); pngTempFile.file().deleteOnExit(); + + loadTexture("tile-cursor"); + loadTexture("tile-eraser-cursor"); } - private FileHandle getResourceFileFromJar(String extension) { - String fileName = RESOURCES_FILE_NAME+extension; + private void loadTexture(String name) { + FileHandle file = getResourceFileFromJar(name + ".png"); + file.file().deleteOnExit(); + textureCache.put(name, new Texture(file)); + } + + private FileHandle getResourceFileFromJar(String fileName) { File tempFile = new File(tiledPlugin.getAPI().getCacheDir()+ File.separator + fileName); try { @@ -53,17 +74,37 @@ public class ResourcesManager { return new FileHandle(tempFile); } - public TextureRegion getTextureRegion(String name) { + public Texture getTexture(String name) { + return textureCache.get(name); + } + + public TextureRegion getTextureRegion(String name, int type) { TextureRegion region = textureAtlas.findRegion(name); // try to get region from plugin assets - if (region != null) { -// System.out.println("region: "+name+", "+region.getRegionWidth()+" "+region.getRegionHeight()); - } if (region == null) { // take the region from hyperlap assets - region = tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(name); + switch (type) { + case EntityFactory.IMAGE_TYPE: + region = tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(name); + break; + case EntityFactory.SPRITE_TYPE: + region = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(name).getRegions().get(0); + break; + } } return region; } + public SpineDrawable getSpineDrawable(String name) { + if (spineDrawableCache.get(name) == null) { + SkeletonJson skeletonJson = new SkeletonJson(tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonAtlas(name)); + SkeletonData skeletonData = skeletonJson.readSkeletonData(tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonJSON(name)); + Skeleton skeleton = new Skeleton(skeletonData); + + spineDrawableCache.put(name, new SpineDrawable(skeleton, skeletonRenderer)); + } + + return spineDrawableCache.get(name); + } + public NinePatch getPluginNinePatch(String name) { TextureAtlas.AtlasRegion region = textureAtlas.findRegion(name); if(region == null) return null; diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/save/DataToSave.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/save/DataToSave.java index 539f6ffc..9819e409 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/save/DataToSave.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/save/DataToSave.java @@ -20,8 +20,9 @@ public class DataToSave { parameterVO = new ParameterVO(); } - public void addTile(String tileDrawableName) { + public void addTile(String tileDrawableName, int type) { TileVO newTile = new TileVO(tileDrawableName); + newTile.entityType = type; if (!tiles.contains(newTile, false)) { tiles.add(newTile); } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/DeleteTileTool.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/DeleteTileTool.java index 01e86dd3..6229091a 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/DeleteTileTool.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/DeleteTileTool.java @@ -2,9 +2,12 @@ package games.rednblack.editor.plugin.tiled.tools; import com.badlogic.ashley.core.Entity; import com.badlogic.gdx.Input; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import games.rednblack.editor.plugin.tiled.TiledPlugin; import games.rednblack.h2d.common.MsgAPI; import games.rednblack.h2d.common.view.tools.Tool; +import games.rednblack.h2d.common.vo.CursorData; import org.puremvc.java.interfaces.INotification; import java.util.HashSet; @@ -14,7 +17,7 @@ import java.util.Set; * Created by mariam on 4/5/16. */ public class DeleteTileTool implements Tool { - + private static final CursorData CURSOR = new CursorData("tile-eraser-cursor", 14, 14); public static final String NAME = "TILE_DELETE_TOOL"; private TiledPlugin tiledPlugin; @@ -27,6 +30,8 @@ public class DeleteTileTool implements Tool { @Override public void initTool() { + Texture cursorTexture = tiledPlugin.pluginRM.getTexture(CURSOR.region); + tiledPlugin.getAPI().setCursor(CURSOR, new TextureRegion(cursorTexture)); } @Override diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/DrawTileTool.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/DrawTileTool.java index 41946134..52f5ad6f 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/DrawTileTool.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/DrawTileTool.java @@ -2,38 +2,51 @@ package games.rednblack.editor.plugin.tiled.tools; import com.badlogic.ashley.core.Entity; import com.badlogic.gdx.Input; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.MathUtils; -import com.badlogic.gdx.math.Vector2; import com.kotcrab.vis.ui.util.OsUtils; import games.rednblack.editor.plugin.tiled.TiledPlugin; -import games.rednblack.editor.renderer.components.MainItemComponent; +import games.rednblack.editor.plugin.tiled.tools.drawStrategy.IDrawStrategy; +import games.rednblack.editor.plugin.tiled.tools.drawStrategy.ImageDrawStrategy; +import games.rednblack.editor.plugin.tiled.tools.drawStrategy.SpineDrawStrategy; +import games.rednblack.editor.plugin.tiled.tools.drawStrategy.SpriteDrawStrategy; import games.rednblack.editor.renderer.components.TextureRegionComponent; import games.rednblack.editor.renderer.components.TransformComponent; +import games.rednblack.editor.renderer.factory.EntityFactory; import games.rednblack.editor.renderer.utils.ComponentRetriever; import games.rednblack.h2d.common.command.TransformCommandBuilder; -import games.rednblack.h2d.common.command.UpdateRegionCommandBuilder; -import games.rednblack.h2d.common.factory.IFactory; import games.rednblack.h2d.common.view.tools.Tool; +import games.rednblack.h2d.common.vo.CursorData; import org.puremvc.java.interfaces.INotification; /** * Created by mariam on 3/29/16. */ public class DrawTileTool implements Tool { - + private static final CursorData CURSOR = new CursorData("tile-cursor", 14, 14); public static final String NAME = "TILE_ADD_TOOL"; private TiledPlugin tiledPlugin; private float gridWidth; private float gridHeight; + private final ImageDrawStrategy imageDrawStrategy; + private final SpriteDrawStrategy spriteDrawStrategy; + private final SpineDrawStrategy spineDrawStrategy; + private IDrawStrategy currentDrawStrategy; + public DrawTileTool(TiledPlugin tiledPlugin) { this.tiledPlugin = tiledPlugin; + imageDrawStrategy = new ImageDrawStrategy(tiledPlugin); + spriteDrawStrategy = new SpriteDrawStrategy(tiledPlugin); + spineDrawStrategy = new SpineDrawStrategy(tiledPlugin); } @Override public void initTool() { - + Texture cursorTexture = tiledPlugin.pluginRM.getTexture(CURSOR.region); + tiledPlugin.getAPI().setCursor(CURSOR, new TextureRegion(cursorTexture)); } @Override @@ -49,7 +62,7 @@ public class DrawTileTool implements Tool { @Override public boolean stageMouseDown(float x, float y) { initGridThings(); - drawImage(x, y); + drawTile(x, y); return true; } @@ -59,7 +72,7 @@ public class DrawTileTool implements Tool { @Override public void stageMouseDragged(float x, float y) { - drawImage(x, y); + drawTile(x, y); } @Override @@ -75,7 +88,10 @@ public class DrawTileTool implements Tool { @Override public boolean itemMouseDown(Entity entity, float x, float y) { initGridThings(); - drawOnEntity(entity, x, y); + if (entity == null) + drawTile(x, y); + else + drawOnEntity(entity); return true; } @@ -85,33 +101,27 @@ public class DrawTileTool implements Tool { @Override public void itemMouseDragged(Entity entity, float x, float y) { - drawImage(x, y); + drawTile(x, y); } @Override public void itemMouseDoubleClick(Entity entity, float x, float y) { if (!tiledPlugin.isOnCurrentSelectedLayer(entity)) return; - if (entity != null) { - TextureRegionComponent textureRegionComponent = ComponentRetriever.get(entity, TextureRegionComponent.class); - if (textureRegionComponent != null && tiledPlugin.isTile(entity)) { - // there is already other tile under this one - if (textureRegionComponent.regionName.equals(tiledPlugin.getSelectedTileName())) { - //rotate - TransformCommandBuilder commandBuilder = new TransformCommandBuilder(); - commandBuilder.begin(entity); - TransformComponent transformComponent = ComponentRetriever.get(entity, TransformComponent.class); - if (transformComponent.scaleX > 0 && transformComponent.scaleY > 0) { - commandBuilder.setScale(transformComponent.scaleX * -1f, transformComponent.scaleY); - } else if (transformComponent.scaleX < 0 && transformComponent.scaleY > 0) { - commandBuilder.setScale(transformComponent.scaleX, transformComponent.scaleY * -1f); - } else if (transformComponent.scaleX < 0 && transformComponent.scaleY < 0) { - commandBuilder.setScale(transformComponent.scaleX * -1f, transformComponent.scaleY); - } else if (transformComponent.scaleX > 0 && transformComponent.scaleY < 0) { - commandBuilder.setScale(transformComponent.scaleX, transformComponent.scaleY * -1f); - } - commandBuilder.execute(tiledPlugin.facade); - } + if (entity != null && tiledPlugin.isTile(entity)) { + //rotate + TransformCommandBuilder commandBuilder = new TransformCommandBuilder(); + commandBuilder.begin(entity); + TransformComponent transformComponent = ComponentRetriever.get(entity, TransformComponent.class); + if (transformComponent.scaleX > 0 && transformComponent.scaleY > 0) { + commandBuilder.setScale(transformComponent.scaleX * -1f, transformComponent.scaleY); + } else if (transformComponent.scaleX < 0 && transformComponent.scaleY > 0) { + commandBuilder.setScale(transformComponent.scaleX, transformComponent.scaleY * -1f); + } else if (transformComponent.scaleX < 0 && transformComponent.scaleY < 0) { + commandBuilder.setScale(transformComponent.scaleX * -1f, transformComponent.scaleY); + } else if (transformComponent.scaleX > 0 && transformComponent.scaleY < 0) { + commandBuilder.setScale(transformComponent.scaleX, transformComponent.scaleY * -1f); } + commandBuilder.execute(tiledPlugin.facade); } } @@ -143,9 +153,23 @@ public class DrawTileTool implements Tool { gridHeight = tiledPlugin.dataToSave.getParameterVO().gridHeight; } - private final Vector2 temp = new Vector2(); + private void chooseDrawStrategy() { + switch (tiledPlugin.getSelectedTileType()) { + case EntityFactory.IMAGE_TYPE: + currentDrawStrategy = imageDrawStrategy; + break; + case EntityFactory.SPRITE_TYPE: + currentDrawStrategy = spriteDrawStrategy; + break; + case EntityFactory.SPINE_TYPE: + currentDrawStrategy = spineDrawStrategy; + break; + default: + currentDrawStrategy = null; + } + } - private void drawImage(float x, float y) { + private void drawTile(float x, float y) { if (tiledPlugin.getSelectedTileName().equals("")) return; float newX = MathUtils.floor(x / gridWidth) * gridWidth + tiledPlugin.getSelectedTileGridOffset().x; @@ -153,53 +177,12 @@ public class DrawTileTool implements Tool { int row = MathUtils.floor(newY / gridHeight); int column = MathUtils.round(newX / gridWidth); - Entity underneathTile = tiledPlugin.getPluginEntityWithParams(row, column); - if (underneathTile != null) { - drawOnEntity(underneathTile, x, y); - return; - } - - IFactory itemFactory = tiledPlugin.getAPI().getItemFactory(); - temp.set(newX, newY); - if (itemFactory.createSimpleImage(tiledPlugin.getSelectedTileName(), temp)) { - Entity imageEntity = itemFactory.getCreatedEntity(); - MainItemComponent mainItemComponent = ComponentRetriever.get(imageEntity, MainItemComponent.class); - mainItemComponent.tags.add(TiledPlugin.TILE_TAG); - - mainItemComponent.setCustomVars(TiledPlugin.ROW, Integer.toString(row)); - mainItemComponent.setCustomVars(TiledPlugin.COLUMN, Integer.toString(column)); - - TransformComponent transformComponent = ComponentRetriever.get(imageEntity, TransformComponent.class); - transformComponent.x = newX; - transformComponent.y = newY; - } + chooseDrawStrategy(); + currentDrawStrategy.drawTile(newX, newY, row, column); } - private void drawOnEntity(Entity entity, float x, float y) { - if (!tiledPlugin.isOnCurrentSelectedLayer(entity)) return; - if (entity != null) { - TextureRegionComponent textureRegionComponent = ComponentRetriever.get(entity, TextureRegionComponent.class); - if (textureRegionComponent != null && textureRegionComponent.regionName != null - && tiledPlugin.isTile(entity)) { - // there is already other tile under this one - if(textureRegionComponent.regionName.equals(tiledPlugin.getSelectedTileName())) { - return; - } else { - //replace - updateRegion(entity, tiledPlugin.getSelectedTileName()); - } - } - return; - } - drawImage(x, y); + private void drawOnEntity(Entity entity) { + chooseDrawStrategy(); + currentDrawStrategy.updateTile(entity); } - - private void updateRegion(Entity entity, String region) { - UpdateRegionCommandBuilder builder = new UpdateRegionCommandBuilder(); - builder.begin(entity); - builder.setRegion(tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(region)); - builder.setRegionName(tiledPlugin.getSelectedTileName()); - builder.execute(tiledPlugin.facade); - } - } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/BasicDrawStrategy.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/BasicDrawStrategy.java new file mode 100644 index 00000000..583a4e8a --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/BasicDrawStrategy.java @@ -0,0 +1,34 @@ +package games.rednblack.editor.plugin.tiled.tools.drawStrategy; + +import com.badlogic.ashley.core.Entity; +import com.badlogic.gdx.math.Vector2; +import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.renderer.components.MainItemComponent; +import games.rednblack.editor.renderer.components.TransformComponent; +import games.rednblack.editor.renderer.utils.ComponentRetriever; + +public abstract class BasicDrawStrategy implements IDrawStrategy { + protected TiledPlugin tiledPlugin; + protected final Vector2 temp = new Vector2(); + + public BasicDrawStrategy(TiledPlugin plugin) { + tiledPlugin = plugin; + } + + protected void postProcessEntity(Entity entity, float x, float y, int row, int column) { + MainItemComponent mainItemComponent = ComponentRetriever.get(entity, MainItemComponent.class); + mainItemComponent.tags.add(TiledPlugin.TILE_TAG); + + mainItemComponent.setCustomVars(TiledPlugin.ROW, Integer.toString(row)); + mainItemComponent.setCustomVars(TiledPlugin.COLUMN, Integer.toString(column)); + + TransformComponent transformComponent = ComponentRetriever.get(entity, TransformComponent.class); + transformComponent.x = x; + transformComponent.y = y; + } + + protected boolean checkValidTile(Entity entity) { + return tiledPlugin.isOnCurrentSelectedLayer(entity) && tiledPlugin.isTile(entity) + && ComponentRetriever.get(entity, MainItemComponent.class).entityType == tiledPlugin.getSelectedTileType(); + } +} diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/IDrawStrategy.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/IDrawStrategy.java new file mode 100644 index 00000000..41ee1ad1 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/IDrawStrategy.java @@ -0,0 +1,8 @@ +package games.rednblack.editor.plugin.tiled.tools.drawStrategy; + +import com.badlogic.ashley.core.Entity; + +public interface IDrawStrategy { + void drawTile(float x, float y, int row, int column); + void updateTile(Entity entity); +} diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/ImageDrawStrategy.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/ImageDrawStrategy.java new file mode 100644 index 00000000..3f90fca4 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/ImageDrawStrategy.java @@ -0,0 +1,49 @@ +package games.rednblack.editor.plugin.tiled.tools.drawStrategy; + +import com.badlogic.ashley.core.Entity; +import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.renderer.components.TextureRegionComponent; +import games.rednblack.editor.renderer.utils.ComponentRetriever; +import games.rednblack.h2d.common.command.ReplaceRegionCommandBuilder; +import games.rednblack.h2d.common.factory.IFactory; + +public class ImageDrawStrategy extends BasicDrawStrategy { + private final ReplaceRegionCommandBuilder replaceRegionCommandBuilder = new ReplaceRegionCommandBuilder(); + + public ImageDrawStrategy(TiledPlugin plugin) { + super(plugin); + } + + @Override + public void drawTile(float x, float y, int row, int column) { + Entity underneathTile = tiledPlugin.getPluginEntityWithParams(row, column); + if (underneathTile != null) { + updateTile(underneathTile); + return; + } + + IFactory itemFactory = tiledPlugin.getAPI().getItemFactory(); + temp.set(x, y); + if (itemFactory.createSimpleImage(tiledPlugin.getSelectedTileName(), temp)) { + Entity imageEntity = itemFactory.getCreatedEntity(); + postProcessEntity(imageEntity, x, y, row, column); + } + } + + @Override + public void updateTile(Entity entity) { + if (!checkValidTile(entity)) return; + + TextureRegionComponent textureRegionComponent = ComponentRetriever.get(entity, TextureRegionComponent.class); + if (textureRegionComponent != null && textureRegionComponent.regionName != null) { + // there is already other tile under this one + if (!textureRegionComponent.regionName.equals(tiledPlugin.getSelectedTileName())) { + String region = tiledPlugin.getSelectedTileName(); + replaceRegionCommandBuilder.begin(entity); + replaceRegionCommandBuilder.setRegion(tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(region)); + replaceRegionCommandBuilder.setRegionName(region); + replaceRegionCommandBuilder.execute(tiledPlugin.facade); + } + } + } +} 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 new file mode 100644 index 00000000..514cbeca --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpineDrawStrategy.java @@ -0,0 +1,57 @@ +package games.rednblack.editor.plugin.tiled.tools.drawStrategy; + +import com.badlogic.ashley.core.Entity; +import com.esotericsoftware.spine.Skeleton; +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; + +public class SpineDrawStrategy extends BasicDrawStrategy { + + private final ReplaceSpineCommandBuilder replaceSpineCommandBuilder = new ReplaceSpineCommandBuilder(); + + public SpineDrawStrategy(TiledPlugin plugin) { + super(plugin); + } + + @Override + public void drawTile(float x, float y, int row, int column) { + Entity underneathTile = tiledPlugin.getPluginEntityWithParams(row, column); + if (underneathTile != null) { + updateTile(underneathTile); + return; + } + + IFactory itemFactory = tiledPlugin.getAPI().getItemFactory(); + temp.set(x, y); + + if (itemFactory.createSpineAnimation(tiledPlugin.getSelectedTileName(), temp)) { + Entity imageEntity = itemFactory.getCreatedEntity(); + postProcessEntity(imageEntity, x, y, row, column); + } + } + + @Override + public void updateTile(Entity entity) { + if (!checkValidTile(entity)) return; + + SpineDataComponent spineDataComponent = ComponentRetriever.get(entity, SpineDataComponent.class); + if (!spineDataComponent.animationName.equals(tiledPlugin.getSelectedTileName())) { + replaceSpineCommandBuilder.begin(entity); + String animName = tiledPlugin.getSelectedTileName(); + replaceSpineCommandBuilder.setAnimationName(animName); + SkeletonJson skeletonJson = new SkeletonJson(tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonAtlas(animName)); + replaceSpineCommandBuilder.setSkeletonJson(skeletonJson); + SkeletonData skeletonData = skeletonJson.readSkeletonData((tiledPlugin.getAPI().getSceneLoader().getRm().getSkeletonJSON(animName))); + replaceSpineCommandBuilder.setSkeleton(new Skeleton(skeletonData)); + replaceSpineCommandBuilder.execute(tiledPlugin.facade); + } + } +} 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 new file mode 100644 index 00000000..46b2e0c0 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/SpriteDrawStrategy.java @@ -0,0 +1,64 @@ +package games.rednblack.editor.plugin.tiled.tools.drawStrategy; + +import com.badlogic.ashley.core.Entity; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.utils.Array; +import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.renderer.components.sprite.SpriteAnimationComponent; +import games.rednblack.editor.renderer.utils.ComponentRetriever; +import games.rednblack.h2d.common.command.ReplaceSpriteAnimationCommandBuilder; +import games.rednblack.h2d.common.factory.IFactory; + +public class SpriteDrawStrategy extends BasicDrawStrategy { + ReplaceSpriteAnimationCommandBuilder replaceSpriteAnimationCommandBuilder = new ReplaceSpriteAnimationCommandBuilder(); + + public SpriteDrawStrategy(TiledPlugin plugin) { + super(plugin); + } + + @Override + public void drawTile(float x, float y, int row, int column) { + Entity underneathTile = tiledPlugin.getPluginEntityWithParams(row, column); + if (underneathTile != null) { + updateTile(underneathTile); + return; + } + + IFactory itemFactory = tiledPlugin.getAPI().getItemFactory(); + temp.set(x, y); + + if (itemFactory.createSpriteAnimation(tiledPlugin.getSelectedTileName(), temp)) { + Entity imageEntity = itemFactory.getCreatedEntity(); + postProcessEntity(imageEntity, x, y, row, column); + } + } + + @Override + public void updateTile(Entity entity) { + if (!checkValidTile(entity)) return; + + SpriteAnimationComponent spriteAnimationComponent = ComponentRetriever.get(entity, SpriteAnimationComponent.class); + + if (!spriteAnimationComponent.animationName.equals(tiledPlugin.getSelectedTileName())) { + Array regions = getRegions(tiledPlugin.getSelectedTileName()); + + replaceSpriteAnimationCommandBuilder.begin(entity); + replaceSpriteAnimationCommandBuilder.setAnimationName(tiledPlugin.getSelectedTileName()); + replaceSpriteAnimationCommandBuilder.setRegion(regions); + replaceSpriteAnimationCommandBuilder.execute(tiledPlugin.facade); + } + } + + private Array getRegions(String filter) { + // filtering regions by name + Array allRegions = tiledPlugin.getAPI().getSceneLoader().getRm().getSpriteAnimation(filter).getRegions(); + Array regions = new Array<>(); + for(TextureAtlas.AtlasRegion region: allRegions) { + if(region.name.contains(filter)) { + regions.add(region); + } + } + + return regions; + } +} diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/SpineDrawable.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/SpineDrawable.java new file mode 100644 index 00000000..a30dda35 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/SpineDrawable.java @@ -0,0 +1,108 @@ +package games.rednblack.editor.plugin.tiled.view; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.GL20; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.scenes.scene2d.utils.BaseDrawable; +import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.FloatArray; +import com.esotericsoftware.spine.*; +import com.esotericsoftware.spine.attachments.Attachment; +import com.esotericsoftware.spine.attachments.MeshAttachment; +import com.esotericsoftware.spine.attachments.RegionAttachment; + +public class SpineDrawable extends BaseDrawable { + private float minX = 0; + private float minY = 0; + + private Skeleton skeleton; + private AnimationState animationState; + private SkeletonRenderer skeletonRenderer; + + public float width, height; + private FloatArray temp; + + public SpineDrawable(Skeleton skeleton, SkeletonRenderer skeletonRenderer) { + temp = new FloatArray(); + this.skeletonRenderer = skeletonRenderer; + + this.skeleton = skeleton; + AnimationStateData animationStateData = new AnimationStateData(skeleton.getData()); + animationState = new AnimationState(animationStateData); + + computeBoundBox(); + + float scaleFactor; + if (this.width > this.height) { + //scale by width + scaleFactor = 1.0f / (this.width / 40); + } else { + scaleFactor = 1.0f / (this.height / 40); + } + skeleton.setScale(scaleFactor, scaleFactor); + } + + public Skeleton getSkeleton() { + return skeleton; + } + + public AnimationState getAnimationState() { + return animationState; + } + + private void computeBoundBox() { + skeleton.updateWorldTransform(); + + Array drawOrder = skeleton.getDrawOrder(); + minX = Float.MAX_VALUE; + minY = Float.MAX_VALUE; + float maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE; + for (int i = 0, n = drawOrder.size; i < n; i++) { + Slot slot = drawOrder.get(i); + if (!slot.getBone().isActive()) continue; + int verticesLength = 0; + float[] vertices = null; + Attachment attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + verticesLength = 8; + vertices = temp.setSize(8); + ((RegionAttachment)attachment).computeWorldVertices(slot.getBone(), vertices, 0, 2); + } else if (attachment instanceof MeshAttachment) { + MeshAttachment mesh = (MeshAttachment)attachment; + verticesLength = mesh.getWorldVerticesLength(); + vertices = temp.setSize(verticesLength); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + } + if (vertices != null) { + for (int ii = 0; ii < verticesLength; ii += 2) { + float x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + } + width = (maxX - minX); + height = (maxY - minY); + } + + @Override + public void draw(Batch batch, float x, float y, float width, float height) { + skeleton.updateWorldTransform(); + animationState.update(Gdx.graphics.getDeltaTime()); + animationState.apply(skeleton); + skeleton.setPosition(x, y - 20); + + Color color = skeleton.getColor(); + + float oldAlpha = color.a; + skeleton.getColor().a *= batch.getColor().a; + skeletonRenderer.draw(batch, skeleton); + color.a = oldAlpha; + + batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); + } +} + diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/GridTilesTab.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/GridTilesTab.java index 2f7d8be9..9fc0c72a 100644 --- a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/GridTilesTab.java +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/GridTilesTab.java @@ -2,6 +2,7 @@ package games.rednblack.editor.plugin.tiled.view.tabs; import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.g2d.NinePatch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; @@ -16,6 +17,8 @@ import games.rednblack.editor.plugin.tiled.TiledPanel; import games.rednblack.editor.plugin.tiled.TiledPlugin; import games.rednblack.editor.plugin.tiled.data.TileVO; import games.rednblack.editor.plugin.tiled.manager.ResourcesManager; +import games.rednblack.editor.plugin.tiled.view.SpineDrawable; +import games.rednblack.editor.renderer.factory.EntityFactory; import games.rednblack.h2d.common.view.ui.StandardWidgetsFactory; /** @@ -49,8 +52,8 @@ public class GridTilesTab extends DefaultTab { public void initView() { if (isDrop = savedTiles.size == 0) { VisImageButton.VisImageButtonStyle dropBoxStyle = new VisImageButton.VisImageButtonStyle(); - dropBoxStyle.up = new TextureRegionDrawable(resourcesManager.getTextureRegion("tiles-drop-here-normal")); - dropBoxStyle.imageOver = new TextureRegionDrawable(resourcesManager.getTextureRegion("tiles-drop-here-over")); + dropBoxStyle.up = new TextureRegionDrawable(resourcesManager.getTextureRegion("tiles-drop-here-normal", -1)); + dropBoxStyle.imageOver = new TextureRegionDrawable(resourcesManager.getTextureRegion("tiles-drop-here-over", -1)); VisImageButton dropRegion = new VisImageButton(dropBoxStyle); content.clear(); content.add(dropRegion) @@ -72,14 +75,14 @@ public class GridTilesTab extends DefaultTab { } } - public void addTile(String tileName) { + public void addTile(String tileName, int type) { if (pane != null) isBottomEdge = pane.isBottomEdge(); if (tileIndex == 0) { - setGridSizeToFirstTileSize(tileName); + setGridSizeToFirstTileSize(tileName, type); isDrop = false; panel.reInitTabTable(); } - initTiles(tileName); + initTiles(tileName, type); panel.pack(); scrollTiles(); tiles.get(tileIndex).setChecked(true); @@ -107,14 +110,25 @@ public class GridTilesTab extends DefaultTab { } } - private void setGridSizeToFirstTileSize(String tileName) { - float gridWidth = resourcesManager.getTextureRegion(tileName).getRegionWidth() / tiledPlugin.getPixelToWorld(); - float gridHeight = resourcesManager.getTextureRegion(tileName).getRegionHeight() / tiledPlugin.getPixelToWorld(); + private void setGridSizeToFirstTileSize(String tileName, int type) { + float width = 0; + float height = 0; + if (type == EntityFactory.SPINE_TYPE) { + SpineDrawable spineDrawable = tiledPlugin.pluginRM.getSpineDrawable(tileName); + width = spineDrawable.width; + height = spineDrawable.height; + } else { + TextureRegion r = tiledPlugin.pluginRM.getTextureRegion(tileName, type); + width = r.getRegionWidth(); + height = r.getRegionHeight(); + } + float gridWidth = width / tiledPlugin.getPixelToWorld(); + float gridHeight = height / tiledPlugin.getPixelToWorld(); tiledPlugin.dataToSave.setGrid(gridWidth, gridHeight); tiledPlugin.facade.sendNotification(TiledPlugin.GRID_CHANGED); } - private void initTiles(String tileName) { + private void initTiles(String tileName, int type) { content.clear(); tiles.clear(); @@ -140,10 +154,19 @@ public class GridTilesTab extends DefaultTab { imageBoxStyle.over = active; Drawable tileDrawable = null; if (i < savedTiles.size) { - tileDrawable = new TextureRegionDrawable(resourcesManager.getTextureRegion(savedTiles.get(i).regionName)); + int t = savedTiles.get(i).entityType; + if (t == EntityFactory.SPINE_TYPE) { + tileDrawable = resourcesManager.getSpineDrawable(savedTiles.get(i).regionName); + } else { + tileDrawable = new TextureRegionDrawable(resourcesManager.getTextureRegion(savedTiles.get(i).regionName, t)); + } } else if (!tileName.equals("")) { if (i == tileIndex) { - tileDrawable = new TextureRegionDrawable(resourcesManager.getTextureRegion(tileName)); + if (type == EntityFactory.SPINE_TYPE) { + tileDrawable = resourcesManager.getSpineDrawable(tileName); + } else { + tileDrawable = new TextureRegionDrawable(resourcesManager.getTextureRegion(tileName, type)); + } } } imageBoxStyle.imageUp = tileDrawable; @@ -198,6 +221,6 @@ public class GridTilesTab extends DefaultTab { } private void initTiles() { - initTiles(""); + initTiles("", -1); } } diff --git a/src/main/java/games/rednblack/editor/controller/BootstrapCommand.java b/src/main/java/games/rednblack/editor/controller/BootstrapCommand.java index ec29ceb6..391156d1 100644 --- a/src/main/java/games/rednblack/editor/controller/BootstrapCommand.java +++ b/src/main/java/games/rednblack/editor/controller/BootstrapCommand.java @@ -63,7 +63,9 @@ public class BootstrapCommand extends SimpleCommand { facade.registerCommand(MsgAPI.ACTION_ITEM_AND_CHILDREN_TO, ItemChildrenTransformCommand::new); facade.registerCommand(MsgAPI.ACTION_ITEM_TRANSFORM_TO, ItemTransformCommand::new); - facade.registerCommand(MsgAPI.ACTION_UPDATE_REGION_DATA, UpdateRegionCommand::new); + facade.registerCommand(MsgAPI.ACTION_REPLACE_REGION_DATA, ReplaceRegionCommand::new); + facade.registerCommand(MsgAPI.ACTION_REPLACE_SPRITE_ANIMATION_DATA, ReplaceSpriteAnimationCommand::new); + facade.registerCommand(MsgAPI.ACTION_REPLACE_SPINE_ANIMATION_DATA, ReplaceSpineCommand::new); facade.registerCommand(MsgAPI.ACTION_ADD_TO_LIBRARY, AddToLibraryCommand::new); facade.registerCommand(MsgAPI.ACTION_ADD_TO_LIBRARY_ACTION, AddToLibraryAction::new); facade.registerCommand(MsgAPI.ACTION_CONVERT_TO_BUTTON, ConvertToButtonCommand::new); diff --git a/src/main/java/games/rednblack/editor/controller/commands/UpdateRegionCommand.java b/src/main/java/games/rednblack/editor/controller/commands/component/ReplaceRegionCommand.java similarity index 78% rename from src/main/java/games/rednblack/editor/controller/commands/UpdateRegionCommand.java rename to src/main/java/games/rednblack/editor/controller/commands/component/ReplaceRegionCommand.java index 2924bd24..6ddb466c 100644 --- a/src/main/java/games/rednblack/editor/controller/commands/UpdateRegionCommand.java +++ b/src/main/java/games/rednblack/editor/controller/commands/component/ReplaceRegionCommand.java @@ -1,17 +1,19 @@ -package games.rednblack.editor.controller.commands; +package games.rednblack.editor.controller.commands.component; import com.badlogic.ashley.core.Entity; import com.badlogic.gdx.graphics.g2d.TextureRegion; import games.rednblack.editor.HyperLap2DFacade; +import games.rednblack.editor.controller.commands.EntityModifyRevertibleCommand; import games.rednblack.editor.renderer.components.DimensionsComponent; import games.rednblack.editor.renderer.components.TextureRegionComponent; +import games.rednblack.editor.renderer.components.TransformComponent; import games.rednblack.editor.renderer.data.ProjectInfoVO; import games.rednblack.editor.renderer.utils.ComponentRetriever; import games.rednblack.editor.utils.runtime.EntityUtils; import games.rednblack.editor.view.stage.Sandbox; import games.rednblack.h2d.common.MsgAPI; -public class UpdateRegionCommand extends EntityModifyRevertibleCommand { +public class ReplaceRegionCommand extends EntityModifyRevertibleCommand { private Integer entityId; private String backupRegionName; @@ -28,6 +30,7 @@ public class UpdateRegionCommand extends EntityModifyRevertibleCommand { TextureRegionComponent textureRegionComponent = ComponentRetriever.get(entity, TextureRegionComponent.class); DimensionsComponent size = ComponentRetriever.get(entity, DimensionsComponent.class); + TransformComponent transformComponent = ComponentRetriever.get(entity, TransformComponent.class); backupRegionName = textureRegionComponent.regionName; backupRegion = textureRegionComponent.region; @@ -39,6 +42,9 @@ public class UpdateRegionCommand extends EntityModifyRevertibleCommand { size.width = textureRegionComponent.region.getRegionWidth() / ppwu; size.height = textureRegionComponent.region.getRegionHeight() / ppwu; + transformComponent.originX = size.width / 2; + transformComponent.originY = size.height / 2; + HyperLap2DFacade.getInstance().sendNotification(MsgAPI.ITEM_DATA_UPDATED, entity); } @@ -48,6 +54,7 @@ public class UpdateRegionCommand extends EntityModifyRevertibleCommand { TextureRegionComponent textureRegionComponent = ComponentRetriever.get(entity, TextureRegionComponent.class); DimensionsComponent size = ComponentRetriever.get(entity, DimensionsComponent.class); + TransformComponent transformComponent = ComponentRetriever.get(entity, TransformComponent.class); textureRegionComponent.regionName = backupRegionName; textureRegionComponent.region = backupRegion; @@ -56,6 +63,9 @@ public class UpdateRegionCommand extends EntityModifyRevertibleCommand { size.width = textureRegionComponent.region.getRegionWidth() / ppwu; size.height = textureRegionComponent.region.getRegionHeight() / ppwu; + transformComponent.originX = size.width / 2; + transformComponent.originY = size.height / 2; + HyperLap2DFacade.getInstance().sendNotification(MsgAPI.ITEM_DATA_UPDATED, entity); } } diff --git a/src/main/java/games/rednblack/editor/controller/commands/component/ReplaceSpineCommand.java b/src/main/java/games/rednblack/editor/controller/commands/component/ReplaceSpineCommand.java new file mode 100644 index 00000000..ff01a67b --- /dev/null +++ b/src/main/java/games/rednblack/editor/controller/commands/component/ReplaceSpineCommand.java @@ -0,0 +1,94 @@ +package games.rednblack.editor.controller.commands.component; + +import com.badlogic.ashley.core.Entity; +import com.esotericsoftware.spine.*; +import games.rednblack.editor.HyperLap2DFacade; +import games.rednblack.editor.controller.commands.EntityModifyRevertibleCommand; +import games.rednblack.editor.renderer.components.DimensionsComponent; +import games.rednblack.editor.renderer.components.SpineDataComponent; +import games.rednblack.editor.renderer.components.TransformComponent; +import games.rednblack.editor.renderer.utils.ComponentRetriever; +import games.rednblack.editor.utils.runtime.EntityUtils; +import games.rednblack.h2d.common.MsgAPI; +import games.rednblack.h2d.extention.spine.SpineObjectComponent; + +public class ReplaceSpineCommand extends EntityModifyRevertibleCommand { + + private Integer entityId; + private String backupAnimName; + private SkeletonJson backupSkeletonJson; + private Skeleton backupSkeleton; + + @Override + public void doAction() { + Object[] payload = getNotification().getBody(); + Entity entity = (Entity) payload[0]; + String animName = (String) payload[1]; + SkeletonJson skeletonJson = (SkeletonJson) payload[2]; + Skeleton skeleton = (Skeleton) payload[3]; + SkeletonData skeletonData = skeleton.getData(); + + entityId = EntityUtils.getEntityId(entity); + + SpineDataComponent spineDataComponent = ComponentRetriever.get(entity, SpineDataComponent.class); + SpineObjectComponent spineObjectComponent = ComponentRetriever.get(entity, SpineObjectComponent.class); + DimensionsComponent dimensionsComponent = ComponentRetriever.get(entity, DimensionsComponent.class); + TransformComponent transformComponent = ComponentRetriever.get(entity, TransformComponent.class); + + backupAnimName = spineDataComponent.animationName; + backupSkeletonJson = spineObjectComponent.skeletonJson; + backupSkeleton = spineObjectComponent.skeleton; + + spineDataComponent.animationName = animName; + spineObjectComponent.skeletonJson = skeletonJson; + spineObjectComponent.skeletonData = skeletonData; + spineObjectComponent.skeleton = skeleton; + + AnimationStateData stateData = new AnimationStateData(skeletonData); + spineObjectComponent.state = new AnimationState(stateData); + + spineObjectComponent.computeBoundBox(dimensionsComponent); + dimensionsComponent.width *= spineObjectComponent.worldMultiplier; + dimensionsComponent.height *= spineObjectComponent.worldMultiplier; + + transformComponent.originX = dimensionsComponent.width / 2f; + transformComponent.originY = dimensionsComponent.height / 2f; + + String currentAnimName = skeletonData.getAnimations().get(0).getName(); + spineDataComponent.currentAnimationName = currentAnimName; + spineObjectComponent.setAnimation(currentAnimName); + + HyperLap2DFacade.getInstance().sendNotification(MsgAPI.ITEM_DATA_UPDATED, entity); + } + + @Override + public void undoAction() { + Entity entity = EntityUtils.getByUniqueId(entityId); + + SpineDataComponent spineDataComponent = ComponentRetriever.get(entity, SpineDataComponent.class); + SpineObjectComponent spineObjectComponent = ComponentRetriever.get(entity, SpineObjectComponent.class); + DimensionsComponent dimensionsComponent = ComponentRetriever.get(entity, DimensionsComponent.class); + TransformComponent transformComponent = ComponentRetriever.get(entity, TransformComponent.class); + + spineDataComponent.animationName = backupAnimName; + spineObjectComponent.skeletonJson = backupSkeletonJson; + spineObjectComponent.skeletonData = backupSkeleton.getData(); + spineObjectComponent.skeleton = backupSkeleton; + + AnimationStateData stateData = new AnimationStateData(spineObjectComponent.skeletonData); + spineObjectComponent.state = new AnimationState(stateData); + + spineObjectComponent.computeBoundBox(dimensionsComponent); + dimensionsComponent.width *= spineObjectComponent.worldMultiplier; + dimensionsComponent.height *= spineObjectComponent.worldMultiplier; + + transformComponent.originX = dimensionsComponent.width / 2f; + transformComponent.originY = dimensionsComponent.height / 2f; + + String currentAnimName = spineObjectComponent.skeletonData.getAnimations().get(0).getName(); + spineDataComponent.currentAnimationName = currentAnimName; + spineObjectComponent.setAnimation(currentAnimName); + + HyperLap2DFacade.getInstance().sendNotification(MsgAPI.ITEM_DATA_UPDATED, entity); + } +} diff --git a/src/main/java/games/rednblack/editor/controller/commands/component/ReplaceSpriteAnimationCommand.java b/src/main/java/games/rednblack/editor/controller/commands/component/ReplaceSpriteAnimationCommand.java new file mode 100644 index 00000000..2d8eb4af --- /dev/null +++ b/src/main/java/games/rednblack/editor/controller/commands/component/ReplaceSpriteAnimationCommand.java @@ -0,0 +1,100 @@ +package games.rednblack.editor.controller.commands.component; + +import com.badlogic.ashley.core.Entity; +import com.badlogic.gdx.graphics.g2d.Animation; +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.utils.Array; +import games.rednblack.editor.HyperLap2DFacade; +import games.rednblack.editor.controller.commands.EntityModifyRevertibleCommand; +import games.rednblack.editor.renderer.components.DimensionsComponent; +import games.rednblack.editor.renderer.components.TextureRegionComponent; +import games.rednblack.editor.renderer.components.TransformComponent; +import games.rednblack.editor.renderer.components.sprite.SpriteAnimationComponent; +import games.rednblack.editor.renderer.components.sprite.SpriteAnimationStateComponent; +import games.rednblack.editor.renderer.data.FrameRange; +import games.rednblack.editor.renderer.data.ProjectInfoVO; +import games.rednblack.editor.renderer.utils.ComponentRetriever; +import games.rednblack.editor.utils.runtime.EntityUtils; +import games.rednblack.editor.view.stage.Sandbox; +import games.rednblack.h2d.common.MsgAPI; + +public class ReplaceSpriteAnimationCommand extends EntityModifyRevertibleCommand { + + private Integer entityId; + private String backupAnimName; + private Array backupAnimRegions; + + @Override + public void doAction() { + Object[] payload = getNotification().getBody(); + Entity entity = (Entity) payload[0]; + String animName = (String) payload[1]; + Array regions = (Array) payload[2]; + + entityId = EntityUtils.getEntityId(entity); + + SpriteAnimationComponent spriteAnimationComponent = ComponentRetriever.get(entity, SpriteAnimationComponent.class); + SpriteAnimationStateComponent spriteAnimationStateComponent = ComponentRetriever.get(entity, SpriteAnimationStateComponent.class); + TextureRegionComponent textureRegionComponent = ComponentRetriever.get(entity, TextureRegionComponent.class); + DimensionsComponent size = ComponentRetriever.get(entity, DimensionsComponent.class); + TransformComponent transformComponent = ComponentRetriever.get(entity, TransformComponent.class); + + backupAnimName = spriteAnimationComponent.animationName; + backupAnimRegions = spriteAnimationStateComponent.allRegions; + + spriteAnimationComponent.animationName = animName; + spriteAnimationComponent.frameRangeMap.clear(); + + spriteAnimationComponent.frameRangeMap.put("Default", new FrameRange("Default", 0, regions.size-1)); + spriteAnimationComponent.currentAnimation = "Default"; + spriteAnimationComponent.playMode = Animation.PlayMode.LOOP; + + spriteAnimationStateComponent.setAllRegions(regions); + spriteAnimationStateComponent.set(spriteAnimationComponent); + + textureRegionComponent.region = regions.get(0); + + ProjectInfoVO projectInfoVO = Sandbox.getInstance().getSceneControl().sceneLoader.getRm().getProjectVO(); + float ppwu = projectInfoVO.pixelToWorld; + size.width = textureRegionComponent.region.getRegionWidth() / ppwu; + size.height = textureRegionComponent.region.getRegionHeight() / ppwu; + + transformComponent.originX = size.width / 2; + transformComponent.originY = size.height / 2; + + HyperLap2DFacade.getInstance().sendNotification(MsgAPI.ITEM_DATA_UPDATED, entity); + } + + @Override + public void undoAction() { + Entity entity = EntityUtils.getByUniqueId(entityId); + + SpriteAnimationComponent spriteAnimationComponent = ComponentRetriever.get(entity, SpriteAnimationComponent.class); + SpriteAnimationStateComponent spriteAnimationStateComponent = ComponentRetriever.get(entity, SpriteAnimationStateComponent.class); + TextureRegionComponent textureRegionComponent = ComponentRetriever.get(entity, TextureRegionComponent.class); + DimensionsComponent size = ComponentRetriever.get(entity, DimensionsComponent.class); + TransformComponent transformComponent = ComponentRetriever.get(entity, TransformComponent.class); + + spriteAnimationComponent.animationName = backupAnimName; + spriteAnimationComponent.frameRangeMap.clear(); + + spriteAnimationComponent.frameRangeMap.put("Default", new FrameRange("Default", 0, backupAnimRegions.size-1)); + spriteAnimationComponent.currentAnimation = "Default"; + spriteAnimationComponent.playMode = Animation.PlayMode.LOOP; + + spriteAnimationStateComponent.setAllRegions(backupAnimRegions); + spriteAnimationStateComponent.set(spriteAnimationComponent); + + textureRegionComponent.region = backupAnimRegions.get(0); + + ProjectInfoVO projectInfoVO = Sandbox.getInstance().getSceneControl().sceneLoader.getRm().getProjectVO(); + float ppwu = projectInfoVO.pixelToWorld; + size.width = textureRegionComponent.region.getRegionWidth() / ppwu; + size.height = textureRegionComponent.region.getRegionHeight() / ppwu; + + transformComponent.originX = size.width / 2; + transformComponent.originY = size.height / 2; + + HyperLap2DFacade.getInstance().sendNotification(MsgAPI.ITEM_DATA_UPDATED, entity); + } +}