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 8fdb6c0b..fc0552f5 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 @@ -25,8 +25,11 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.kotcrab.vis.ui.widget.VisLabel; import com.kotcrab.vis.ui.widget.VisTable; +import games.rednblack.editor.plugin.tiled.data.AutoTileVO; import games.rednblack.editor.plugin.tiled.data.TileVO; import games.rednblack.editor.plugin.tiled.manager.ResourcesManager; +import games.rednblack.editor.plugin.tiled.view.tabs.AbstractGridTilesTab; +import games.rednblack.editor.plugin.tiled.view.tabs.AutoGridTilesTab; import games.rednblack.editor.plugin.tiled.view.tabs.GridTilesTab; import games.rednblack.editor.plugin.tiled.view.tabs.SettingsTab; import games.rednblack.h2d.common.UIDraggablePanel; @@ -39,11 +42,11 @@ import games.rednblack.h2d.common.view.ui.widget.imagetabbedpane.ImageTabbedPane */ public class TiledPanel extends UIDraggablePanel { - public static final float GRID_WIDTH = 220f; + public static final float GRID_WIDTH = 240f; public static final float GRID_HEIGHT = 250f; - public static final float DROP_WIDTH = 220f; + public static final float DROP_WIDTH = 240f; public static final float DROP_HEIGHT = 140f; - public static final float SETTINGS_WIDTH = 220f; + public static final float SETTINGS_WIDTH = 240f; public static final float SETTINGS_HEIGHT = 150f; public TiledPlugin tiledPlugin; @@ -55,10 +58,13 @@ public class TiledPanel extends UIDraggablePanel { private GridTilesTab tilesTab; private SettingsTab settingsTab; + private AutoGridTilesTab autoGridTilesTab; private VisTable mainTable; private Engine engine; private ResourcesManager resourcesManager; + private boolean isAutoGridTabSelected; + public TiledPanel(TiledPlugin tiledPlugin) { super("Tiles"); this.tiledPlugin = tiledPlugin; @@ -104,8 +110,11 @@ public class TiledPanel extends UIDraggablePanel { if (tab instanceof SettingsTab) { WIDTH = SETTINGS_WIDTH; HEIGHT = SETTINGS_HEIGHT; - } else if (tab instanceof GridTilesTab) { - if (GridTilesTab.isDrop) { + } else if (tab instanceof AbstractGridTilesTab) { + isAutoGridTabSelected = tab instanceof AutoGridTilesTab; + tiledPlugin.setAutoGridTilesTabSelected(isAutoGridTabSelected); + + if (((AbstractGridTilesTab) tab).isDrop) { WIDTH = DROP_WIDTH; HEIGHT = DROP_HEIGHT; } else { @@ -140,8 +149,10 @@ public class TiledPanel extends UIDraggablePanel { }); initTabs(); + } - pack(); + public boolean isAutoGridTilesTabSelected() { + return isAutoGridTabSelected; } public void setFixedPosition() { @@ -152,6 +163,10 @@ public class TiledPanel extends UIDraggablePanel { return tilesTab.getContentTable(); } + public Table getAutoGridDropTable() { + return autoGridTilesTab.getContentTable(); + } + public void reInitGridSettings() { settingsTab.resetGridCategory(); } @@ -160,22 +175,36 @@ public class TiledPanel extends UIDraggablePanel { tilesTab.addTile(tileName, type); } + public void addAutoTile(String tileName, int type) { + autoGridTilesTab.addTile(tileName, type); + } + public void selectTile(TileVO tileVO) { tilesTab.selectTile(tileVO); } + public void selectAutoTile(AutoTileVO tileVO) { + autoGridTilesTab.selectTile(tileVO); + } + public void removeTile() { tilesTab.removeTile(); - reInitTabTable(); + reInitTabTable(tilesTab); tilesTab.scrollTiles(); } public void removeAllTiles() { tilesTab.removeAllTiles(); - reInitTabTable(); + reInitTabTable(tilesTab); tilesTab.scrollTiles(); } + public void removeAutoTile() { + autoGridTilesTab.removeTile(); + reInitTabTable(autoGridTilesTab); + autoGridTilesTab.scrollTiles(); + } + private void initTabs() { tilesTab = new GridTilesTab(this, 0); tilesTab.initView(); @@ -184,15 +213,27 @@ public class TiledPanel extends UIDraggablePanel { settingsTab = new SettingsTab(this, "Settings", 1); settingsTab.initView(); tabbedPane.insert(settingsTab.getTabIndex(), settingsTab); + + autoGridTilesTab = new AutoGridTilesTab(this, "Auto Tiling", 2); + autoGridTilesTab.initView(); + tabbedPane.insert(autoGridTilesTab.getTabIndex(), autoGridTilesTab); - reInitTabTable(); + // reinit the currently visible tab + if (isAutoGridTabSelected) { + reInitTabTable(autoGridTilesTab); + } else { + reInitTabTable(tilesTab); + } } - public void reInitTabTable() { - float width = GridTilesTab.isDrop ? DROP_WIDTH : GRID_WIDTH; - float height = GridTilesTab.isDrop ? DROP_HEIGHT : GRID_HEIGHT; + public void reInitTabTable(AbstractGridTilesTab tab) { + isAutoGridTabSelected = tab instanceof AutoGridTilesTab; + tiledPlugin.setAutoGridTilesTabSelected(isAutoGridTabSelected); + + float width = tab.isDrop ? DROP_WIDTH : GRID_WIDTH; + float height = tab.isDrop ? DROP_HEIGHT : GRID_HEIGHT; tabTable.clear(); - tabTable.add(tilesTab.getContentTable()) + tabTable.add(tab.getContentTable()) .width(width) .height(height); tabTable.pack(); 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 055c13ab..a0262f03 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 @@ -18,8 +18,11 @@ package games.rednblack.editor.plugin.tiled; +import java.io.File; import java.util.HashMap; +import java.util.Iterator; +import games.rednblack.editor.renderer.data.TexturePackVO; import org.puremvc.java.interfaces.INotification; import org.puremvc.java.patterns.mediator.Mediator; @@ -27,12 +30,21 @@ 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.files.FileHandle; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.PixmapIO; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop; + +import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop.Target; import com.kotcrab.vis.ui.util.dialog.Dialogs; import com.kotcrab.vis.ui.util.dialog.OptionDialogAdapter; +import games.rednblack.editor.plugin.tiled.data.AlternativeAutoTileVO; +import games.rednblack.editor.plugin.tiled.data.AutoTileVO; import games.rednblack.editor.plugin.tiled.data.TileVO; +import games.rednblack.editor.plugin.tiled.manager.AutoGridTileManager; import games.rednblack.editor.plugin.tiled.tools.DeleteTileTool; import games.rednblack.editor.plugin.tiled.tools.DrawTileTool; import games.rednblack.editor.plugin.tiled.view.SpineDrawable; @@ -51,11 +63,16 @@ public class TiledPanelMediator extends Mediator { public static final String NAME = TAG; private TiledPlugin tiledPlugin; - private DragAndDrop.Target target; + private DragAndDrop.Target targetGrid; + private DragAndDrop.Target targetAutoGrid; + + private AutoGridTileManager autoGridTileManager; public TiledPanelMediator(TiledPlugin tiledPlugin) { super(NAME, new TiledPanel(tiledPlugin)); this.tiledPlugin = tiledPlugin; + + autoGridTileManager = new AutoGridTileManager(tiledPlugin); viewComponent.initLockView(); } @@ -71,6 +88,11 @@ public class TiledPanelMediator extends Mediator { TiledPlugin.ACTION_SET_GRID_SIZE_FROM_LIST, TiledPlugin.ACTION_SET_OFFSET, TiledPlugin.OPEN_DROP_DOWN, + TiledPlugin.AUTO_TILE_SELECTED, + TiledPlugin.ACTION_DELETE_AUTO_TILE, + TiledPlugin.AUTO_OPEN_DROP_DOWN, + TiledPlugin.AUTO_FILL_TILES, + TiledPlugin.ACTION_SETUP_ALTERNATIVES_AUTO_TILE, TiledPlugin.GRID_CHANGED, SettingsTab.OK_BTN_CLICKED, TiledPlugin.ACTION_SET_GRID_SIZE_FROM_ITEM, @@ -94,31 +116,8 @@ public class TiledPanelMediator extends Mediator { tiledPlugin.initSaveData(); viewComponent.initView(); - 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; - } - - @Override - public void drop(DragAndDrop.Source source, DragAndDrop.Payload payload, float x, float y, int pointer) { - ResourcePayloadObject resourcePayloadObject = (ResourcePayloadObject) payload.getObject(); - int type = mapClassNameToEntityType(resourcePayloadObject.className); - if (type == EntityFactory.UNKNOWN_TYPE) return; //only some resources can become a tile! - - String tileName = resourcePayloadObject.name; - // we send a notifier even in the case when the tile is not already added - tiledPlugin.facade.sendNotification(TiledPlugin.TILE_ADDED, new Object[]{tileName, type}); - if (type == EntityFactory.IMAGE_TYPE) { - // ensure that all selected images are dropped - // the respective listener is responsible for dropping one-by-one, since he tracks the selected ones - tiledPlugin.facade.sendNotification(MsgAPI.IMAGE_BUNDLE_DROP, new Object[]{tileName, type}); - } - } - }; - tiledPlugin.facade.sendNotification(MsgAPI.ADD_TARGET, target); + targetGrid = initTarget(targetGrid, viewComponent.getDropTable(), false); + targetAutoGrid = initTarget(targetAutoGrid, viewComponent.getAutoGridDropTable(), true); Engine engine = tiledPlugin.getAPI().getEngine(); viewComponent.setEngine(engine); viewComponent.setFixedPosition(); @@ -129,17 +128,40 @@ public class TiledPanelMediator extends Mediator { Object[] payload = notification.getBody(); tileName = (String) payload[0]; int type = (int) payload[1]; - // we only add tiles that have not been added previously - if (tiledPlugin.dataToSave.containsTile(tileName)) return; + boolean isAutoTilesTarget = (boolean) payload[2]; - viewComponent.addTile(tileName, type); + if (isAutoTilesTarget) { + // we only add tiles that have not been added previously + if (tiledPlugin.dataToSave.containsAutoTile(tileName)) return; - tiledPlugin.dataToSave.addTile(tileName, type); + // retract the images for the auto-tiles + retractAutoTiles(tileName); + + viewComponent.addAutoTile(tileName, type); + + tiledPlugin.dataToSave.addAutoTile(tileName, type); + } else { + // we only add tiles that have not been added previously + if (tiledPlugin.dataToSave.containsTile(tileName)) return; + + viewComponent.addTile(tileName, type); + + tiledPlugin.dataToSave.addTile(tileName, type); + } + tiledPlugin.saveDataManager.save(); break; case TiledPlugin.TILE_SELECTED: - viewComponent.selectTile(notification.getBody()); + case TiledPlugin.AUTO_TILE_SELECTED: + if (viewComponent.isAutoGridTilesTabSelected()) { + viewComponent.selectAutoTile(notification.getBody()); + } else { + viewComponent.selectTile(notification.getBody()); + } break; + case TiledPlugin.AUTO_FILL_TILES: + autoGridTileManager.autoFill(); + break; case TiledPlugin.OPEN_DROP_DOWN: tileName = notification.getBody(); HashMap actionsSet = new HashMap<>(); @@ -150,24 +172,41 @@ public class TiledPanelMediator extends Mediator { tiledPlugin.facade.sendNotification(TiledPlugin.TILE_SELECTED, tiledPlugin.dataToSave.getTile(tileName)); tiledPlugin.getAPI().showPopup(actionsSet, tileName); break; + case TiledPlugin.AUTO_OPEN_DROP_DOWN: + tileName = notification.getBody(); + HashMap autoActionsSet = new HashMap<>(); + autoActionsSet.put(TiledPlugin.ACTION_SET_GRID_SIZE_FROM_LIST, "Set grid size"); + autoActionsSet.put(TiledPlugin.ACTION_DELETE_AUTO_TILE, "Delete"); +// autoActionsSet.put(TiledPlugin.ACTION_OPEN_OFFSET_PANEL, "Set offset"); + autoActionsSet.put(TiledPlugin.ACTION_SETUP_ALTERNATIVES_AUTO_TILE, "Setup alternatives"); + tiledPlugin.facade.sendNotification(TiledPlugin.AUTO_TILE_SELECTED, tiledPlugin.dataToSave.getAutoTile(tileName)); + tiledPlugin.getAPI().showPopup(autoActionsSet, tileName); + break; case MsgAPI.ACTION_DELETE_IMAGE_RESOURCE: tileName = notification.getBody(); tiledPlugin.facade.sendNotification(TiledPlugin.ACTION_DELETE_TILE, tileName); + tiledPlugin.facade.sendNotification(TiledPlugin.ACTION_DELETE_AUTO_TILE, tileName); break; case TiledPlugin.ACTION_SET_GRID_SIZE_FROM_LIST: 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 { + if (tiledPlugin.isAutoGridTilesTabSelected()) { + AutoTileVO t = tiledPlugin.dataToSave.getAutoTile(notification.getBody()); TextureRegion r = tiledPlugin.pluginRM.getTextureRegion(t.regionName, t.entityType); - width = r.getRegionWidth(); - height = r.getRegionHeight(); + width = r.getRegionWidth() / TiledPlugin.AUTO_TILE_COLS; + height = r.getRegionHeight() / TiledPlugin.AUTO_TILE_ROWS; + } else { + 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; @@ -180,6 +219,25 @@ public class TiledPanelMediator extends Mediator { viewComponent.removeTile(); break; + case TiledPlugin.ACTION_DELETE_AUTO_TILE: + String tn2 = notification.getBody(); + if (!tiledPlugin.dataToSave.containsAutoTile(tn2)) return; + tiledPlugin.dataToSave.removeAutoTile(tn2); + tiledPlugin.saveDataManager.save(); + tiledPlugin.setSelectedAutoTileVO(new AutoTileVO()); + + for (AutoTileVO autoTile : tiledPlugin.dataToSave.getAutoTiles()) { + Iterator iter = autoTile.alternativeAutoTileList.iterator(); + while (iter.hasNext()) { + AlternativeAutoTileVO alternativeAutoTileVO = iter.next(); + if (alternativeAutoTileVO.region.equals(tn2)) { + iter.remove(); + } + } + } + + viewComponent.removeAutoTile(); + tiledPlugin.facade.sendNotification(TiledPlugin.ACTION_RECALC_PERCENT_ALTERNATIVES_AUTO_TILE); case TiledPlugin.ACTION_DELETE_TILE_ALL: Dialogs.showOptionDialog(tiledPlugin.getAPI().getUIStage(), "Delete all...", "Do you really want to delete all tiles?", Dialogs.OptionDialogType.YES_NO, new OptionDialogAdapter() { @@ -242,6 +300,99 @@ public class TiledPanelMediator extends Mediator { } } + /** + * Retracts all auto-tiles from the given auto-tile-template. + * + * @param tileName The name of the tile from that the auto-tiles are retracted from. + */ + private void retractAutoTiles(String tileName) { + TextureRegion tr = tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(tileName); + tr.getTexture().getTextureData().prepare(); + Pixmap pixmap = tr.getTexture().getTextureData().consumePixmap(); + String name = tileName; + + int tileW = tr.getRegionWidth() / TiledPlugin.AUTO_TILE_COLS; + int tileH = tr.getRegionHeight() / TiledPlugin.AUTO_TILE_ROWS; + int maxX = tr.getRegionWidth() + tr.getRegionX(); + int maxY = tr.getRegionHeight() + tr.getRegionY(); + + //Create new atlas packing settings if doesn't exists + String atlasName = name + TiledPlugin.AUTO_TILE_ATLAS_SUFFIX; + TexturePackVO texturePackVO = tiledPlugin.getAPI().getCurrentProjectInfoVO().imagesPacks.get(atlasName); + if (texturePackVO == null) { + texturePackVO = new TexturePackVO(); + texturePackVO.name = atlasName; + + tiledPlugin.getAPI().getCurrentProjectInfoVO().imagesPacks.put(texturePackVO.name, texturePackVO); + } + + int i = 0; + for (int x = tr.getRegionX(); x < maxX; x += tileW) { + for (int y = tr.getRegionY(); y < maxY; y += tileH) { + // skip non used + if (i != 4 && i != 9 && i != 14 && i != 19 && i != 49 && i != 50 && i != 51) { + int w = x + tileW <= pixmap.getWidth() ? tileW : pixmap.getWidth() - x; + int h = y + tileH <= pixmap.getHeight() ? tileH : pixmap.getHeight() - y; + Pixmap tilePixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888); + tilePixmap.drawPixmap(pixmap, 0, 0, x, y, w, h); + + String tilePngName = name + i; + String imagesPath = tiledPlugin.getCurrentRawImagesPath() + File.separator + tilePngName + ".png"; + FileHandle path = new FileHandle(imagesPath); + PixmapIO.writePNG(path, tilePixmap); + + tilePixmap.dispose(); + texturePackVO.regions.add(tilePngName); + } + i++; + } + } + + // create mini image + Pixmap tilePixmap = new Pixmap(tileW, tileH, Pixmap.Format.RGBA8888); + tilePixmap.drawPixmap(pixmap, tr.getRegionX(), tr.getRegionY(), tr.getRegionWidth(), tr.getRegionHeight(), 0, 0, tileW, tileH); + String miniImageName = name + TiledPlugin.AUTO_TILE_MINI_SUFFIX; + String imagesPath = tiledPlugin.getCurrentRawImagesPath() + File.separator + miniImageName + ".png"; + FileHandle path = new FileHandle(imagesPath); + PixmapIO.writePNG(path, tilePixmap); + tilePixmap.dispose(); + + pixmap.dispose(); + texturePackVO.regions.add(miniImageName); + + facade.sendNotification(MsgAPI.ACTION_REPACK); + } + + private Target initTarget(Target targetGrid, Table dropTable, boolean isAutoGridTarget) { + if (targetGrid != null) + tiledPlugin.facade.sendNotification(MsgAPI.REMOVE_TARGET, targetGrid); + targetGrid = new DragAndDrop.Target(dropTable) { + @Override + public boolean drag(DragAndDrop.Source source, DragAndDrop.Payload payload, float x, float y, int pointer) { + return true; + } + + @Override + public void drop(DragAndDrop.Source source, DragAndDrop.Payload payload, float x, float y, int pointer) { + ResourcePayloadObject resourcePayloadObject = (ResourcePayloadObject) payload.getObject(); + int type = mapClassNameToEntityType(resourcePayloadObject.className); + if (type == EntityFactory.UNKNOWN_TYPE) return; //only some resources can become a tile! + + String tileName = resourcePayloadObject.name; + // we send a notifier even in the case when the tile is not already added + tiledPlugin.facade.sendNotification(TiledPlugin.TILE_ADDED, new Object[]{tileName, type, isAutoGridTarget}); + if (type == EntityFactory.IMAGE_TYPE) { + // ensure that all selected images are dropped + // the respective listener is responsible for dropping one-by-one, since he tracks the selected ones + tiledPlugin.facade.sendNotification(MsgAPI.IMAGE_BUNDLE_DROP, new Object[]{tileName, type, isAutoGridTarget}); + } + } + }; + tiledPlugin.facade.sendNotification(MsgAPI.ADD_TARGET, targetGrid); + + return targetGrid; + } + private int mapClassNameToEntityType(String className) { if (className.endsWith(".ImageResource")) return EntityFactory.IMAGE_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 884065d3..3ccbec1e 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 @@ -18,6 +18,7 @@ package games.rednblack.editor.plugin.tiled; +import java.io.File; import java.util.Set; import com.badlogic.ashley.core.Entity; @@ -29,6 +30,7 @@ import com.badlogic.gdx.utils.Array; import com.kotcrab.vis.ui.VisUI; import com.kotcrab.vis.ui.widget.VisImageButton; +import games.rednblack.editor.plugin.tiled.data.AutoTileVO; import games.rednblack.editor.plugin.tiled.data.TileVO; import games.rednblack.editor.plugin.tiled.manager.ResourcesManager; import games.rednblack.editor.plugin.tiled.offset.OffsetPanel; @@ -37,6 +39,7 @@ import games.rednblack.editor.plugin.tiled.save.DataToSave; import games.rednblack.editor.plugin.tiled.save.SaveDataManager; import games.rednblack.editor.plugin.tiled.tools.DeleteTileTool; import games.rednblack.editor.plugin.tiled.tools.DrawTileTool; +import games.rednblack.editor.plugin.tiled.view.dialog.AlternativeAutoTileDialogMediator; import games.rednblack.editor.plugin.tiled.view.dialog.ImportTileSetDialogMediator; import games.rednblack.editor.renderer.components.MainItemComponent; import games.rednblack.editor.renderer.components.TextureRegionComponent; @@ -58,21 +61,38 @@ 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 AUTO_TILE_SELECTED = CLASS_NAME + ".AUTO_TILE_SELECTED"; + public static final String AUTO_FILL_TILES = CLASS_NAME + ".FILL_AUTO_TILE"; public static final String OPEN_DROP_DOWN = CLASS_NAME + ".OPEN_DROP_DOWN"; + public static final String AUTO_OPEN_DROP_DOWN = CLASS_NAME + ".AUTO_OPEN_DROP_DOWN"; public static final String GRID_CHANGED = CLASS_NAME + ".GRID_CHANGED"; public static final String IMPORT_TILESET_PANEL_OPEN = CLASS_NAME + ".IMPORT_TILESET_PANEL_OPEN"; public static final String ACTION_DELETE_TILE = CLASS_NAME + ".ACTION_DELETE_TILE"; + public static final String ACTION_DELETE_AUTO_TILE = CLASS_NAME + ".ACTION_DELETE_AUTO_TILE"; public static final String ACTION_DELETE_TILE_ALL = CLASS_NAME + ".ACTION_DELETE_TILE_ALL"; public static final String ACTION_SET_OFFSET = CLASS_NAME + ".ACTION_SET_OFFSET"; public static final String ACTION_OPEN_OFFSET_PANEL = CLASS_NAME + ".ACTION_OPEN_OFFSET_PANEL"; public static final String TILE_GRID_OFFSET_ADDED = CLASS_NAME + ".TILE_GRID_OFFSET_ADDED"; public static final String ACTION_SET_GRID_SIZE_FROM_ITEM = CLASS_NAME + ".ACTION_SET_GRID_SIZE_FROM_ITEM"; public static final String ACTION_SET_GRID_SIZE_FROM_LIST = CLASS_NAME + ".ACTION_SET_GRID_SIZE_FROM_LIST"; + public static final String ACTION_SAVE_ALTERNATIVES_AUTO_TILE = CLASS_NAME + ".ACTION_SAVE_ALTERNATIVES_AUTO_TILE"; + public static final String ACTION_SETUP_ALTERNATIVES_AUTO_TILE = CLASS_NAME + ".ACTION_SETUP_ALTERNATIVES_AUTO_TILE"; + public static final String ACTION_RECALC_PERCENT_ALTERNATIVES_AUTO_TILE = CLASS_NAME + ".ACTION_RECALC_PERCENT_ALTERNATIVES_AUTO_TILE"; //-------end--------// public static final String TILE_TAG = "TILE"; public static final String ROW = "ROW"; public static final String COLUMN = "COLUMN"; + public static final String REGION = "REGION"; + public static final String ORIG_AUTO_TILE = "ORIG_AUTO_TILE"; + + public static final String AUTO_TILE_TAG = "AUTO_TILE"; + public static final String AUTO_TILE_ATLAS_SUFFIX = "-autotile"; + public static final String AUTO_TILE_MINI_SUFFIX = "-mini"; + public static final String AUTO_TILE_DRAW_SUFFIX = "18"; + + public static final int AUTO_TILE_ROWS = 5; + public static final int AUTO_TILE_COLS = 11; public DataToSave dataToSave; public SaveDataManager saveDataManager; @@ -83,13 +103,17 @@ public class TiledPlugin extends H2DPluginAdapter { public OffsetPanel offsetPanel; private TileVO selectedTileVO; + private AutoTileVO selectedAutoTileVO; private CustomVariables currentEntityCustomVariables; private MainItemComponent currentEntityMainItemComponent; private TransformComponent currentEntityTransformComponent; + private boolean isAutoGridTabSelected; + public TiledPlugin() { super(CLASS_NAME); selectedTileVO = new TileVO(); + selectedAutoTileVO = new AutoTileVO(); currentEntityCustomVariables = new CustomVariables(); } @@ -97,6 +121,7 @@ public class TiledPlugin extends H2DPluginAdapter { public void initPlugin() { facade.registerMediator(new TiledPanelMediator(this)); facade.registerMediator(new ImportTileSetDialogMediator(pluginAPI, facade)); + facade.registerMediator(new AlternativeAutoTileDialogMediator(this)); pluginRM = new ResourcesManager(this); offsetPanel = new OffsetPanel(this); @@ -200,8 +225,20 @@ public class TiledPlugin extends H2DPluginAdapter { } public String getSelectedTileName() { + if (isAutoGridTabSelected) { + return selectedAutoTileVO.regionName; + } return selectedTileVO.regionName; } + + /** + * Explicitly returns the selected auto tile name, regardless of whether the auto grid tab is shown or any other. + * + * @return The selected auto tile name. + */ + public String getSelectedAutoTileName() { + return selectedAutoTileVO.regionName; + } public int getSelectedTileType() { return selectedTileVO.entityType; @@ -223,6 +260,14 @@ public class TiledPlugin extends H2DPluginAdapter { this.selectedTileVO = selectedTileVO; } + public AutoTileVO getSelectedAutoTileVO() { + return selectedAutoTileVO; + } + + public void setSelectedAutoTileVO(AutoTileVO selectedAutoTileVO) { + this.selectedAutoTileVO = selectedAutoTileVO; + } + public void applySelectedTileGridOffset() { pluginAPI.getProjectEntities().forEach(entity -> { if (!(isTile(entity))) return; @@ -236,8 +281,21 @@ public class TiledPlugin extends H2DPluginAdapter { saveOffsetChanges(); } + public boolean isAutoGridTilesTabSelected() { + return isAutoGridTabSelected; + } + + public void setAutoGridTilesTabSelected(boolean isAutoGridTabSelected) { + this.isAutoGridTabSelected = isAutoGridTabSelected; + } + private void saveOffsetChanges() { dataToSave.setTileGridOffset(selectedTileVO); saveDataManager.save(); } + + public String getCurrentRawImagesPath() { + return getAPI().getProjectPath() + File.separator + "assets" + File.separator + "orig" + File.separator + "images"; + } + } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/AlternativeAutoTileVO.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/AlternativeAutoTileVO.java new file mode 100644 index 00000000..34f174bc --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/AlternativeAutoTileVO.java @@ -0,0 +1,44 @@ +package games.rednblack.editor.plugin.tiled.data; + +/** + * This class represents an alternative to an auto-tile. It contains a region to paint when selected and a probabilty to be selected. + * + * @author Jan-Thierry Wegener + */ +public class AlternativeAutoTileVO { + + /** + * The region to paint when selected. + */ + public String region = ""; + /** + * The probability to be selected by the auto-tile drawing strategy. + */ + public Float percent = Float.valueOf(0.0f); + + public AlternativeAutoTileVO() { + } + + /** + * Creates a new alternative from the given region and probability. + * + * @param region The region to paint. + * @param percent The probability to be selected. + */ + public AlternativeAutoTileVO(String region, Float percent) { + this.region = region; + this.percent = percent; + } + + /** + * Creates a new alternative from the given region and probability. + * + * @param region The region to paint. + * @param percent The probability to be selected. + */ + public AlternativeAutoTileVO(String region, String percent) { + this.region = region; + this.percent = Float.valueOf(percent); + } + +} diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/AutoTileVO.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/AutoTileVO.java new file mode 100644 index 00000000..d0830b96 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/AutoTileVO.java @@ -0,0 +1,42 @@ +package games.rednblack.editor.plugin.tiled.data; + +import com.badlogic.gdx.math.Vector2; + +import games.rednblack.editor.renderer.factory.EntityFactory; + +public class AutoTileVO implements TextureRegionVO { + + public String regionName = ""; + public Vector2 gridOffset; + public int entityType = EntityFactory.IMAGE_TYPE; + + /** + * The list of alternative auto-tiles. + */ + public final DefaultValueList alternativeAutoTileList = new DefaultValueList<>(); + + public AutoTileVO() { + gridOffset = new Vector2(); + } + + public AutoTileVO(String regionName) { + this.regionName = regionName; + gridOffset = new Vector2(); + } + + public AutoTileVO(String regionName, Vector2 offset) { + this.regionName = regionName; + this.gridOffset = offset; + } + + @Override + public String getRegionName() { + return regionName; + } + + @Override + public int getEntityType() { + return entityType; + } + +} diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/DefaultValueList.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/DefaultValueList.java new file mode 100644 index 00000000..6a3a5fb8 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/DefaultValueList.java @@ -0,0 +1,38 @@ +package games.rednblack.editor.plugin.tiled.data; + +import java.util.ArrayList; + +/** + * A list that provides a default value when the index is out-of-upper-bound. + * + * @author Jan-Thierry Wegener + * + * @param The list element type. + */ +public class DefaultValueList extends ArrayList { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public DefaultValueList() { + super(); + } + + /** + * Returns the element at the given index or the default value if the index is greater than or equal to the size. + * + * @param index The index of the element. + * @param defaultValue The default element if the index is out-of-upper-bound. + * + * @return The element at the given index or the default value. + */ + public E get(int index, E defaultValue) { + if (index >= size()) { + return defaultValue; + } + return super.get(index); + } + +} diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/TextureRegionVO.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/TextureRegionVO.java new file mode 100644 index 00000000..3e27beb8 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/data/TextureRegionVO.java @@ -0,0 +1,9 @@ +package games.rednblack.editor.plugin.tiled.data; + +public interface TextureRegionVO { + + public String getRegionName(); + + public int getEntityType(); + +} 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 39f93f53..625bd40b 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,28 +1,40 @@ 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. */ -public class TileVO { +public class TileVO implements TextureRegionVO { - public String regionName = ""; - public Vector2 gridOffset; - public int entityType = EntityFactory.IMAGE_TYPE; + public String regionName = ""; + public Vector2 gridOffset; + public int entityType = EntityFactory.IMAGE_TYPE; - public TileVO() { - gridOffset = new Vector2(); - } + public TileVO() { + gridOffset = new Vector2(); + } - public TileVO(String regionName) { - this.regionName = regionName; - gridOffset = new Vector2(); - } + public TileVO(String regionName) { + this.regionName = regionName; + gridOffset = new Vector2(); + } + + public TileVO(String regionName, Vector2 offset) { + this.regionName = regionName; + this.gridOffset = offset; + } + + @Override + public String getRegionName() { + return regionName; + } + + @Override + public int getEntityType() { + return entityType; + } - public TileVO(String regionName, Vector2 offset) { - this.regionName = regionName; - this.gridOffset = offset; - } } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/manager/AutoGridTileManager.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/manager/AutoGridTileManager.java new file mode 100644 index 00000000..fa10de33 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/manager/AutoGridTileManager.java @@ -0,0 +1,241 @@ +package games.rednblack.editor.plugin.tiled.manager; + +import com.badlogic.ashley.core.Entity; + +import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.renderer.components.MainItemComponent; +import games.rednblack.editor.renderer.utils.ComponentRetriever; +import games.rednblack.h2d.common.command.ReplaceRegionCommandBuilder; + +public class AutoGridTileManager { + + private static final int UL = 1; + private static final int U = 2; + private static final int UR = 4; + private static final int R = 8; + private static final int DR = 16; + private static final int D = 32; + private static final int DL = 64; + private static final int L = 128; + + private final ReplaceRegionCommandBuilder replaceRegionCommandBuilder = new ReplaceRegionCommandBuilder(); + + private TiledPlugin tiledPlugin; + + public AutoGridTileManager(TiledPlugin tiledPlugin) { + this.tiledPlugin = tiledPlugin; + } + + public void autoFill() { + for (Entity entity : tiledPlugin.getAPI().getProjectEntities()) { + MainItemComponent mainItemComponent = ComponentRetriever.get(entity, MainItemComponent.class); + if (!mainItemComponent.tags.contains(TiledPlugin.AUTO_TILE_TAG)) { + continue; + } + int col = mainItemComponent.customVariables.getIntegerVariable(TiledPlugin.COLUMN); + int row = mainItemComponent.customVariables.getIntegerVariable(TiledPlugin.ROW); + + int c = 0; + int val = 0; + Entity ul = tiledPlugin.getPluginEntityWithParams(row + 1, col - 1); + if (ul != null) { + c++; + val += UL; + } + Entity u = tiledPlugin.getPluginEntityWithParams(row + 1, col); + if (u != null) { + c++; + val += U; + } + Entity ur = tiledPlugin.getPluginEntityWithParams(row + 1, col + 1); + if (ur != null) { + c++; + val += UR; + } + Entity r = tiledPlugin.getPluginEntityWithParams(row, col + 1); + if (r != null) { + c++; + val += R; + } + Entity dr = tiledPlugin.getPluginEntityWithParams(row - 1, col + 1); + if (dr != null) { + c++; + val += DR; + } + Entity d = tiledPlugin.getPluginEntityWithParams(row - 1, col); + if (d != null) { + c++; + val += D; + } + Entity dl = tiledPlugin.getPluginEntityWithParams(row - 1, col - 1); + if (dl != null) { + c++; + val += DL; + } + Entity l = tiledPlugin.getPluginEntityWithParams(row, col - 1); + if (l != null) { + c++; + val += L; + } + + int index = getIndex(c, val); + + String region = mainItemComponent.customVariables.getStringVariable(TiledPlugin.REGION) + index; + replaceRegionCommandBuilder.begin(entity); + replaceRegionCommandBuilder.setRegion(tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(region)); + replaceRegionCommandBuilder.setRegionName(region); + replaceRegionCommandBuilder.execute(tiledPlugin.facade); + } + } + + /** + * Test whether the tiles in the given direction ({@link #UL} to {@link #L}) are all occupied. + * + * @param tiles The tiles ({@link #UL} to {@link #L}). + * @param val The value for the surroundings. + * + * @return true, if the tiles are all occupied by another tile, false otherwise. + */ + private boolean isOccupied(int val, int ... tiles) { + for (int t : tiles) { + if ((t & val) == 0) { + return false; + } + } + return true; + } + + /** + * Test whether the tiles in the given direction ({@link #UL} to {@link #L}) are all empty. + * + * @param tiles The tiles ({@link #UL} to {@link #L}). + * @param val The value for the surroundings. + * + * @return true, if the tiles are all empty, false otherwise. + */ + private boolean isEmpty(int val, int ... tiles) { + for (int t : tiles) { + if ((t & val) > 0) { + return false; + } + } + return true; + } + + // 24 + private int getIndex(int c, int val) { + switch (c) { + case 8: + return 6; + case 7: + if (isEmpty(val, DR)) { + return 26; + } else if (isEmpty(val, UR)) { + return 27; + } else if (isEmpty(val, DL)) { + return 31; + } else if (isEmpty(val, UL)) { + return 32; + } + case 6: + if (isOccupied(val, L, DL, D, R, U, UL) && isEmpty(val, DR, UR)) { + return 29; + } else if (isOccupied(val, L, U, UR, R, DR, D) && isEmpty(val, UL, DL)) { + return 34; + } else if (isOccupied(val, L, UL, U, UR, R, D) && isEmpty(val, DR, DL)) { + return 41; + } else if (isOccupied(val, L, U, R, DR, D, DL) && isEmpty(val, UR, UL)) { + return 42; + } else if (isOccupied(val, L, UL, U, R, DR, D) && isEmpty(val, DL, UR)) { + return 45; + } else if (isOccupied(val, D, DL, L, U, UR, R) && isEmpty(val, UL, DR)) { + return 46; + } + case 5: + if (isOccupied(val, U, UR, R, DR, D) && isEmpty(val, L)) { + return 1; + } else if (isOccupied(val, R, DR, D, DL, L) && isEmpty(val, U)) { + return 5; + } else if (isOccupied(val, L, UL, U, UR, R) && isEmpty(val, D)) { + return 7; + } else if (isOccupied(val, U, D, DL, L, UL) && isEmpty(val, R)) { + return 11; + } else if (isOccupied(val, L, U, R, DR, D) && isEmpty(val, DL, UL, UR)) { + return 47; + } else if (isOccupied(val, L, U, UR, R, D) && isEmpty(val, UL, DR, DL)) { + return 48; + } else if (isOccupied(val, L, U, R, D, DL) && isEmpty(val, UL, UR, DR)) { + return 52; + } else if (isOccupied(val, L, UL, U, R, D) && isEmpty(val, DL, UR, DR)) { + return 53; + } + case 4: + if (isOccupied(val, U, UR, R, D) && isEmpty(val, DR, L)) { + return 21; + } else if (isOccupied(val, U, R, DR, D) && isEmpty(val, UR, L)) { + return 22; + } else if (isOccupied(val, L, DL, D, R) && isEmpty(val, DR, U)) { + return 25; + } else if (isOccupied(val, L, UL, U, R) && isEmpty(val, UR, D)) { + return 28; + } else if (isOccupied(val, L, D, DR, R) && isEmpty(val, U, DL)) { + return 30; + } else if (isOccupied(val, L, U, UR, R) && isEmpty(val, UL, D)) { + return 33; + } else if (isOccupied(val, L, UL, U, D) && isEmpty(val, R, DL)) { + return 36; + } else if (isOccupied(val, U, D, DL, L) && isEmpty(val, UL, R)) { + return 37; + } else if (isOccupied(val, L, U, R, D) && isEmpty(val, DR, DL, UR, UL)) { + return 44; + } + case 3: + if (isOccupied(val, R, DR, D) && isEmpty(val, L, U)) { + return 0; + } else if (isOccupied(val, U, UR, R) && isEmpty(val, L, D)) { + return 2; + } else if (isOccupied(val, L, DL, D) && isEmpty(val, U, R)) { + return 10; + } else if (isOccupied(val, L, UL, U) && isEmpty(val, R, D)) { + return 12; + } else if (isOccupied(val, U, R, D) && isEmpty(val, L, UR, DR)) { + return 24; + } else if (isOccupied(val, U, D, L) && isEmpty(val, UL, R, DL)) { + return 39; + } else if (isOccupied(val, L, D, R) && isEmpty(val, DL, DR, U)) { + return 40; + } else if (isOccupied(val, L, U, R) && isEmpty(val, UL, UR, D)) { + return 43; + } + case 2: + if (isOccupied(val, L, R) && isEmpty(val, U, D)) { + return 8; + } else if (isOccupied(val, U, D) && isEmpty(val, L, R)) { + return 16; + } else if (isOccupied(val, R, D) && isEmpty(val, DR, U, L)) { + return 20; + } else if (isOccupied(val, U, R) && isEmpty(val, UR, D, L)) { + return 23; + } else if (isOccupied(val, L, U) && isEmpty(val, UL, R, D)) { + return 38; + } else if (isOccupied(val, L, D) && isEmpty(val, DL, U, R)) { + return 35; + } + case 1: + if (isOccupied(val, R) && isEmpty(val, U, D, L)) { + return 3; + } else if (isOccupied(val, L) && isEmpty(val, U, R, D)) { + return 13; + } else if (isOccupied(val, D) && isEmpty(val, L, U, R)) { + return 15; + } else if (isOccupied(val, U) && isEmpty(val, L, D, R)) { + return 17; + } + case 0: + return 18; + } + // default + return 54; + } + +} 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 bafb7cd1..2747016f 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 @@ -5,6 +5,7 @@ import java.util.stream.StreamSupport; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; +import games.rednblack.editor.plugin.tiled.data.AutoTileVO; import games.rednblack.editor.plugin.tiled.data.ParameterVO; import games.rednblack.editor.plugin.tiled.data.TileVO; @@ -14,10 +15,12 @@ import games.rednblack.editor.plugin.tiled.data.TileVO; public class DataToSave { private Array tiles; + private Array autoTiles; private ParameterVO parameterVO; public DataToSave() { tiles = new Array<>(); + autoTiles = new Array<>(); parameterVO = new ParameterVO(); } @@ -75,6 +78,38 @@ public class DataToSave { return StreamSupport.stream(tiles.spliterator(), false).anyMatch(tile -> tile.regionName.equals(regionName)); } + public void addAutoTile(String autoTileDrawableName, int type) { + AutoTileVO newTile = new AutoTileVO(autoTileDrawableName); + newTile.entityType = type; + if (!autoTiles.contains(newTile, false)) { + autoTiles.add(newTile); + } + } + + public AutoTileVO getAutoTile(String regionName) { + return StreamSupport.stream(autoTiles.spliterator(), false) + .filter(tile -> tile.regionName.equals(regionName)) + .findFirst() + .get(); + } + + public void removeAutoTile(String tileDrawableName) { + autoTiles.forEach(tile -> { + if (tile.regionName.equals(tileDrawableName)) { + autoTiles.removeValue(tile, false); + } + }); + + } + + public Array getAutoTiles() { + return autoTiles; + } + + public boolean containsAutoTile(String regionName) { + return StreamSupport.stream(autoTiles.spliterator(), false).anyMatch(tile -> tile.regionName.equals(regionName)); + } + public ParameterVO getParameterVO() { return parameterVO; } 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 6229091a..d51b461b 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 @@ -1,17 +1,19 @@ package games.rednblack.editor.plugin.tiled.tools; +import java.util.HashSet; +import java.util.Set; + +import org.puremvc.java.interfaces.INotification; + 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; -import java.util.Set; /** * Created by mariam on 4/5/16. @@ -51,6 +53,7 @@ public class DeleteTileTool implements Tool { @Override public void stageMouseUp(float x, float y) { + tiledPlugin.facade.sendNotification(TiledPlugin.AUTO_FILL_TILES); } @Override @@ -71,12 +74,13 @@ public class DeleteTileTool implements Tool { @Override public boolean itemMouseDown(Entity entity, float x, float y) { deleteEntityWithCoordinate(x, y); + tiledPlugin.facade.sendNotification(TiledPlugin.AUTO_FILL_TILES); return true; } @Override public void itemMouseUp(Entity entity, float x, float y) { - + tiledPlugin.facade.sendNotification(TiledPlugin.AUTO_FILL_TILES); } @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 52f5ad6f..bf45e72b 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 @@ -1,24 +1,26 @@ package games.rednblack.editor.plugin.tiled.tools; +import org.puremvc.java.interfaces.INotification; + 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.kotcrab.vis.ui.util.OsUtils; + import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.plugin.tiled.tools.drawStrategy.AutoTileDrawStrategy; 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.view.tools.Tool; import games.rednblack.h2d.common.vo.CursorData; -import org.puremvc.java.interfaces.INotification; /** * Created by mariam on 3/29/16. @@ -34,6 +36,7 @@ public class DrawTileTool implements Tool { private final ImageDrawStrategy imageDrawStrategy; private final SpriteDrawStrategy spriteDrawStrategy; private final SpineDrawStrategy spineDrawStrategy; + private final AutoTileDrawStrategy autoTileDrawStrategy; private IDrawStrategy currentDrawStrategy; public DrawTileTool(TiledPlugin tiledPlugin) { @@ -41,6 +44,7 @@ public class DrawTileTool implements Tool { imageDrawStrategy = new ImageDrawStrategy(tiledPlugin); spriteDrawStrategy = new SpriteDrawStrategy(tiledPlugin); spineDrawStrategy = new SpineDrawStrategy(tiledPlugin); + autoTileDrawStrategy = new AutoTileDrawStrategy(tiledPlugin); } @Override @@ -68,6 +72,7 @@ public class DrawTileTool implements Tool { @Override public void stageMouseUp(float x, float y) { + tiledPlugin.facade.sendNotification(TiledPlugin.AUTO_FILL_TILES); } @Override @@ -97,6 +102,7 @@ public class DrawTileTool implements Tool { @Override public void itemMouseUp(Entity entity, float x, float y) { + tiledPlugin.facade.sendNotification(TiledPlugin.AUTO_FILL_TILES); } @Override @@ -154,19 +160,23 @@ public class DrawTileTool implements Tool { } 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; - } + if (tiledPlugin.isAutoGridTilesTabSelected()) { + currentDrawStrategy = autoTileDrawStrategy; + } else { + 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 drawTile(float x, float y) { diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/AutoTileDrawStrategy.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/AutoTileDrawStrategy.java new file mode 100644 index 00000000..60007bba --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/tools/drawStrategy/AutoTileDrawStrategy.java @@ -0,0 +1,106 @@ +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.plugin.tiled.data.AutoTileVO; +import games.rednblack.editor.renderer.components.MainItemComponent; +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 AutoTileDrawStrategy extends BasicDrawStrategy { + + private final ReplaceRegionCommandBuilder replaceRegionCommandBuilder = new ReplaceRegionCommandBuilder(); + + private String tileToDraw; + + public AutoTileDrawStrategy(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); + tileToDraw = selectTileToDraw(); + if (itemFactory.createSimpleImage(tileToDraw + TiledPlugin.AUTO_TILE_DRAW_SUFFIX, temp)) { + Entity imageEntity = itemFactory.getCreatedEntity(); + postProcessEntity(imageEntity, x, y, row, column); + } + } + + private String selectTileToDraw() { + String retval; + + AutoTileVO selectedAutoTileVO = tiledPlugin.getSelectedAutoTileVO(); + if (selectedAutoTileVO.alternativeAutoTileList.isEmpty()) { + retval = selectedAutoTileVO.regionName; + } else { + retval = null; + double d = 0d; + double rnd = Math.random(); + int i = 0; + while (i < selectedAutoTileVO.alternativeAutoTileList.size() && retval == null) { + d += selectedAutoTileVO.alternativeAutoTileList.get(i).percent; + if (rnd < d) { + retval = selectedAutoTileVO.alternativeAutoTileList.get(i).region; + } + i++; + } + + if (retval == null) { + retval = selectedAutoTileVO.alternativeAutoTileList.get(i - 1).region; + } + } + return retval; + } + + @Override + public void updateTile(Entity entity) { + if (!checkValidTile(entity)) return; + + MainItemComponent mainItemComponent = ComponentRetriever.get(entity, MainItemComponent.class); + if (tiledPlugin.getSelectedAutoTileName().equals(mainItemComponent.customVariables.getStringVariable(TiledPlugin.ORIG_AUTO_TILE))) { + // we only allow an update when the auto-tiles is different + // firstly, it does not make any sense to randomly reselect another alternative tile + // secondly, when dragging it constantly reselects between the alternative, making rare tiles even rarer + return; + } + + TextureRegionComponent textureRegionComponent = ComponentRetriever.get(entity, TextureRegionComponent.class); + if (textureRegionComponent != null && textureRegionComponent.regionName != null) { + // there is already other tile under this one + String selectedAutoTileName = selectTileToDraw(); + String region = selectedAutoTileName + TiledPlugin.AUTO_TILE_DRAW_SUFFIX; + if (!textureRegionComponent.regionName.equals(region)) { + replaceRegionCommandBuilder.begin(entity); + replaceRegionCommandBuilder.setRegion(tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(region)); + replaceRegionCommandBuilder.setRegionName(region); + replaceRegionCommandBuilder.execute(tiledPlugin.facade); + + mainItemComponent.tags.add(TiledPlugin.AUTO_TILE_TAG); + mainItemComponent.setCustomVars(TiledPlugin.REGION, selectedAutoTileName); + mainItemComponent.setCustomVars(TiledPlugin.ORIG_AUTO_TILE, tiledPlugin.getSelectedAutoTileName()); + } + } + } + + @Override + protected void postProcessEntity(Entity entity, float x, float y, int row, int column) { + super.postProcessEntity(entity, x, y, row, column); + + MainItemComponent mainItemComponent = ComponentRetriever.get(entity, MainItemComponent.class); + mainItemComponent.tags.add(TiledPlugin.AUTO_TILE_TAG); + mainItemComponent.setCustomVars(TiledPlugin.REGION, tileToDraw); + mainItemComponent.setCustomVars(TiledPlugin.ORIG_AUTO_TILE, tiledPlugin.getSelectedAutoTileName()); + } + +} 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 index 3f90fca4..44ee762b 100644 --- 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 @@ -1,7 +1,9 @@ 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.MainItemComponent; import games.rednblack.editor.renderer.components.TextureRegionComponent; import games.rednblack.editor.renderer.utils.ComponentRetriever; import games.rednblack.h2d.common.command.ReplaceRegionCommandBuilder; @@ -43,6 +45,10 @@ public class ImageDrawStrategy extends BasicDrawStrategy { replaceRegionCommandBuilder.setRegion(tiledPlugin.getAPI().getSceneLoader().getRm().getTextureRegion(region)); replaceRegionCommandBuilder.setRegionName(region); replaceRegionCommandBuilder.execute(tiledPlugin.facade); + + MainItemComponent mainItemComponent = ComponentRetriever.get(entity, MainItemComponent.class); + mainItemComponent.tags.remove(TiledPlugin.AUTO_TILE_TAG); + mainItemComponent.removeCustomVars(TiledPlugin.REGION); } } } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/dialog/AlternativeAutoTileDialog.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/dialog/AlternativeAutoTileDialog.java new file mode 100644 index 00000000..b6bad1b9 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/dialog/AlternativeAutoTileDialog.java @@ -0,0 +1,187 @@ +package games.rednblack.editor.plugin.tiled.view.dialog; + +import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.ui.SelectBox; +import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Align; +import com.kotcrab.vis.ui.util.Validators.FloatValidator; +import com.kotcrab.vis.ui.widget.VisImageButton; +import com.kotcrab.vis.ui.widget.VisSelectBox; +import com.kotcrab.vis.ui.widget.VisTable; +import com.kotcrab.vis.ui.widget.VisTextButton; +import com.kotcrab.vis.ui.widget.VisValidatableTextField; + +import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.plugin.tiled.data.AlternativeAutoTileVO; +import games.rednblack.editor.plugin.tiled.data.AutoTileVO; +import games.rednblack.editor.renderer.factory.EntityFactory; +import games.rednblack.h2d.common.UIDraggablePanel; +import games.rednblack.h2d.common.view.ui.StandardWidgetsFactory; + +/** + * The dialog that handles the alternatives. + * + * @author Jan-Thierry Wegener + */ +public class AlternativeAutoTileDialog extends UIDraggablePanel { + + public AutoTileVO openingAutoTileVO; + + private TiledPlugin tiledPlugin; + + public VisSelectBox[] alternativeSelectBoxArray; + public VisValidatableTextField[] alternativePercentTextFieldArray; + + public AlternativeAutoTileDialog(TiledPlugin tiledPlugin) { + super("Setup alternatives"); + + this.tiledPlugin = tiledPlugin; + } + + /** + * Initiates the view of the dialog. + */ + public void initView() { + clear(); + + String[] allAutoTileVOArray = new String[tiledPlugin.dataToSave.getAutoTiles().size]; + int index = 0; + // add a "none" to the drop down list + allAutoTileVOArray[index++] = ""; + for (int i = 0; i < tiledPlugin.dataToSave.getAutoTiles().size; i++) { + AutoTileVO next = tiledPlugin.dataToSave.getAutoTiles().get(i); + if (!openingAutoTileVO.equals(next)) { + allAutoTileVOArray[index++] = next.regionName; + } + } + + alternativeSelectBoxArray = new VisSelectBox[allAutoTileVOArray.length - 1]; + alternativePercentTextFieldArray = new VisValidatableTextField[allAutoTileVOArray.length + 0]; + + VisTable table = new VisTable(); + table.row().padTop(20); + table.add(getVisImageButton(openingAutoTileVO.regionName)).maxHeight(32); + table.add(StandardWidgetsFactory.createLabel(openingAutoTileVO.regionName, Align.left)).padLeft(5).left();//.width(115); + alternativePercentTextFieldArray[0] = StandardWidgetsFactory.createValidableTextField(new FloatValidator()); + alternativePercentTextFieldArray[0].setText(openingAutoTileVO.alternativeAutoTileList.get(0, new AlternativeAutoTileVO()).percent.toString()); + table.add(alternativePercentTextFieldArray[0]).padLeft(5).padRight(5).fillX().left(); + table.row(); + for (int i = 0; i < allAutoTileVOArray.length - 1; i++) { + String region = openingAutoTileVO.alternativeAutoTileList.get(i + 1, new AlternativeAutoTileVO()).region; + + VisImageButton imgButton = getVisImageButton(region); + table.add(imgButton).maxHeight(32); + alternativeSelectBoxArray[i] = StandardWidgetsFactory.createSelectBox(String.class); + alternativeSelectBoxArray[i].setItems(allAutoTileVOArray); + alternativeSelectBoxArray[i].setSelected(openingAutoTileVO.alternativeAutoTileList.get(i + 1, new AlternativeAutoTileVO()).region); + alternativeSelectBoxArray[i].addListener(new ChangeListener() { + @Override + public void changed(ChangeEvent event, Actor actor) { + updateVisImageButton(imgButton, ((SelectBox) actor).getSelected()); + pack(); + } + }); + table.add(alternativeSelectBoxArray[i]).padLeft(5).left(); + + alternativePercentTextFieldArray[i + 1] = StandardWidgetsFactory.createValidableTextField(new FloatValidator()); + alternativePercentTextFieldArray[i + 1].setText(openingAutoTileVO.alternativeAutoTileList.get(i + 1, new AlternativeAutoTileVO()).percent.toString()); + table.add(alternativePercentTextFieldArray[i + 1]).padLeft(5).padRight(5).fillX().left(); + + table.row().padTop(5).padBottom(5); + } + + VisTextButton saveButton = StandardWidgetsFactory.createTextButton("Save"); + saveButton.addListener(new ClickListener() { + @Override + public void touchUp (InputEvent event, float x, float y, int pointer, int button) { + super.touchUp(event, x, y, pointer, button); + tiledPlugin.facade.sendNotification(TiledPlugin.ACTION_SAVE_ALTERNATIVES_AUTO_TILE); + hide(); + } + }); + + VisTextButton cancelButton = StandardWidgetsFactory.createTextButton("Cancel"); + cancelButton.addListener(new ClickListener() { + @Override + public void touchUp (InputEvent event, float x, float y, int pointer, int button) { + super.touchUp(event, x, y, pointer, button); + hide(); + } + + }); + + row(); + add(table); + row(); + add(saveButton).center().padLeft(5).padRight(5); + add(cancelButton).center().padLeft(5).padRight(5); + row(); + + pack(); + } + + /** + * Returns a button with the given region as image. + * + * @param regionName The name of the image. + * + * @return An image button. + */ + private VisImageButton getVisImageButton(String regionName) { + VisImageButton.VisImageButtonStyle imageBoxStyle = new VisImageButton.VisImageButtonStyle(); + Drawable tileDrawable = null; + if (!"".equals(regionName)) { + tileDrawable = new TextureRegionDrawable(tiledPlugin.pluginRM.getTextureRegion(regionName, EntityFactory.IMAGE_TYPE)); + } + imageBoxStyle.imageUp = tileDrawable; + imageBoxStyle.imageDown = tileDrawable; + imageBoxStyle.imageChecked = tileDrawable; + imageBoxStyle.imageOver = tileDrawable; + + VisImageButton ct = new VisImageButton(imageBoxStyle); + return ct; + } + + /** + * Updates the given button with the given image. + * + * @param button The button to update. + * @param regionName The name of the new image. + */ + private void updateVisImageButton(VisImageButton button, String regionName) { + VisImageButton.VisImageButtonStyle imageBoxStyle = button.getStyle(); + Drawable tileDrawable = null; + if (!"".equals(regionName)) { + tileDrawable = new TextureRegionDrawable(tiledPlugin.pluginRM.getTextureRegion(regionName, EntityFactory.IMAGE_TYPE)); + } + imageBoxStyle.imageUp = tileDrawable; + imageBoxStyle.imageDown = tileDrawable; + imageBoxStyle.imageChecked = tileDrawable; + imageBoxStyle.imageOver = tileDrawable; + + button.setStyle(imageBoxStyle); + } + + /** + * Returns the currently set auto-tile. + * + * @return The currently set auto-tile. + */ + public AutoTileVO getOpeningAutoTileVO() { + return openingAutoTileVO; + } + + /** + * Sets the current auto-tile. + * + * @param openingAutoTileVO The new auto-tile. + */ + public void setOpeningAutoTileVO(AutoTileVO openingAutoTileVO) { + this.openingAutoTileVO = openingAutoTileVO; + } + +} diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/dialog/AlternativeAutoTileDialogMediator.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/dialog/AlternativeAutoTileDialogMediator.java new file mode 100644 index 00000000..49c388be --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/dialog/AlternativeAutoTileDialogMediator.java @@ -0,0 +1,99 @@ +package games.rednblack.editor.plugin.tiled.view.dialog; + +import org.puremvc.java.interfaces.INotification; +import org.puremvc.java.patterns.mediator.Mediator; + +import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.plugin.tiled.data.AlternativeAutoTileVO; +import games.rednblack.editor.plugin.tiled.data.AutoTileVO; + +/** + * The mediator for messages for the alternatives. + * + * @author Jan-Thierry Wegener + */ +public class AlternativeAutoTileDialogMediator extends Mediator { + + public static final String NAME = AlternativeAutoTileDialogMediator.class.getName(); + + private TiledPlugin tiledPlugin; + + public AlternativeAutoTileDialogMediator(TiledPlugin tiledPlugin) { + super(NAME, new AlternativeAutoTileDialog(tiledPlugin)); + this.tiledPlugin = tiledPlugin; + } + + @Override + public String[] listNotificationInterests() { + return new String[] { + TiledPlugin.ACTION_SETUP_ALTERNATIVES_AUTO_TILE, + TiledPlugin.ACTION_SAVE_ALTERNATIVES_AUTO_TILE, + TiledPlugin.ACTION_RECALC_PERCENT_ALTERNATIVES_AUTO_TILE + }; + } + + @Override + public void handleNotification(INotification notification) { + switch (notification.getName()) { + case TiledPlugin.ACTION_SETUP_ALTERNATIVES_AUTO_TILE: + AutoTileVO autoTileVO = tiledPlugin.dataToSave.getAutoTile(notification.getBody()); + viewComponent.setOpeningAutoTileVO(autoTileVO); + viewComponent.initView(); + viewComponent.show(tiledPlugin.getAPI().getUIStage()); + break; + case TiledPlugin.ACTION_SAVE_ALTERNATIVES_AUTO_TILE: + viewComponent.openingAutoTileVO.alternativeAutoTileList.clear(); + + AlternativeAutoTileVO alternativeAutoTileVO = new AlternativeAutoTileVO(viewComponent.openingAutoTileVO.regionName, viewComponent.alternativePercentTextFieldArray[0].getText()); + viewComponent.openingAutoTileVO.alternativeAutoTileList.add(alternativeAutoTileVO); + for (int i = 0; i < viewComponent.alternativeSelectBoxArray.length; i++) { + String region = viewComponent.alternativeSelectBoxArray[i].getSelected(); + Float percent = Float.valueOf(viewComponent.alternativePercentTextFieldArray[i + 1].getText()); + viewComponent.openingAutoTileVO.alternativeAutoTileList.add(new AlternativeAutoTileVO(region, percent)); + } + + tiledPlugin.facade.sendNotification(TiledPlugin.ACTION_RECALC_PERCENT_ALTERNATIVES_AUTO_TILE, viewComponent.openingAutoTileVO.regionName); + break; + case TiledPlugin.ACTION_RECALC_PERCENT_ALTERNATIVES_AUTO_TILE: + String deletedAutoTileRegion = notification.getBody(); + if (deletedAutoTileRegion == null) { + for (AutoTileVO at : tiledPlugin.dataToSave.getAutoTiles()) { + recalculatePercent(at); + } + } else { + recalculatePercent(tiledPlugin.dataToSave.getAutoTile(deletedAutoTileRegion)); + } + + tiledPlugin.saveDataManager.save(); + break; + } + } + + /** + * Recalculates the probabilities of the alternatives of all or the given auto-tile. + * + * @param at The auto-tile to recalculate, or if null then all auto-tiles. + */ + private void recalculatePercent(AutoTileVO at) { + float total = 0; + for (AlternativeAutoTileVO aat : at.alternativeAutoTileList) { + if (!"".equals(aat.region)) { + total += Math.abs(aat.percent); + } + } + + if (total < 0.00001f) { + // kind of 0 + at.alternativeAutoTileList.get(0).percent = 1f; + } else { + for (AlternativeAutoTileVO aat : at.alternativeAutoTileList) { + if ("".equals(aat.region)) { + aat.percent = 0f; + } else { + aat.percent = Math.abs(aat.percent) / total; + } + } + } + } + +} diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/AbstractGridTilesTab.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/AbstractGridTilesTab.java new file mode 100644 index 00000000..f299fece --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/AbstractGridTilesTab.java @@ -0,0 +1,241 @@ +package games.rednblack.editor.plugin.tiled.view.tabs; + +import com.badlogic.gdx.graphics.g2d.NinePatch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Array; +import com.kotcrab.vis.ui.widget.VisImageButton; +import com.kotcrab.vis.ui.widget.VisLabel; +import com.kotcrab.vis.ui.widget.VisScrollPane; +import com.kotcrab.vis.ui.widget.VisTable; + +import games.rednblack.editor.plugin.tiled.TiledPanel; +import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.plugin.tiled.data.TextureRegionVO; +import games.rednblack.editor.plugin.tiled.manager.ResourcesManager; +import games.rednblack.editor.plugin.tiled.view.SpineDrawable; +import games.rednblack.editor.plugin.tiled.view.tabs.listener.GridTabInputListener; +import games.rednblack.editor.renderer.factory.EntityFactory; +import games.rednblack.h2d.common.view.ui.StandardWidgetsFactory; + +public abstract class AbstractGridTilesTab extends DefaultTab { + + public boolean isDrop; + + private int tilesCount = 19; + protected Array tiles; + protected Array savedTiles; + private int tileIndex; + protected VisScrollPane pane; + private boolean isBottomEdge; + + protected TiledPlugin tiledPlugin; + private ResourcesManager resourcesManager; + + public AbstractGridTilesTab(TiledPanel panel, String title, int tabIndex) { + super(panel, title, tabIndex); + + tiledPlugin = panel.tiledPlugin; + resourcesManager = tiledPlugin.pluginRM; + tiles = new Array<>(); + savedTiles = initSavedTiles(); + tileIndex = savedTiles.size; + } + + protected abstract Array initSavedTiles(); + + @Override + public void initView() { + if (isDrop = savedTiles.size == 0) { + VisImageButton.VisImageButtonStyle dropBoxStyle = new VisImageButton.VisImageButtonStyle(); + 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) + .center() + .padRight(6) + .padBottom(6) + .padTop(10) + .row(); + content.add(new VisLabel("Drop an image from resources box")) + .expandX() + .center() + .padBottom(5); + content.pack(); + } else { + if (tileIndex > tilesCount) { + tilesCount = tileIndex; + } + initTiles(); + } + } + + public void addTile(String tileName, int type) { + if (pane != null) isBottomEdge = pane.isBottomEdge(); + if (tileIndex == 0) { + setGridSizeToFirstTileSize(tileName, type); + isDrop = false; + panel.reInitTabTable(this); + } + initTiles(tileName, type); + panel.pack(); + scrollTiles(); + tiles.get(tileIndex).setChecked(true); + tiledPlugin.facade.sendNotification(TiledPlugin.TILE_SELECTED, getTextureRegionVO(tileName)); + tileIndex++; + } + + public void removeTile() { + if (pane != null) isBottomEdge = pane.isBottomEdge(); + tileIndex = --tileIndex < 0 ? 0 : tileIndex; + tilesCount = --tilesCount < 19 ? 19 : tilesCount; + tiles.clear(); + initView(); + } + + public void removeAllTiles() { + if (pane != null) isBottomEdge = pane.isBottomEdge(); + tileIndex = 0; + tilesCount = 19; + tiles.clear(); + initView(); + } + + public void scrollTiles() { + if(savedTiles.size + 1 >= tilesCount) { + pane.layout(); + pane.setSmoothScrolling(!isBottomEdge); + pane.setScrollY(100); + } + } + + protected 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, int type) { + content.clear(); + tiles.clear(); + + VisTable listTable = new VisTable(); + pane = StandardWidgetsFactory.createScrollPane(listTable); + pane.setScrollingDisabled(true, false); + content.add(pane) + .padTop(10); + listTable.top(); + + if(tileIndex >= tilesCount && !tileName.equals("")) { + tilesCount = tileIndex + 1; + } + + for (int i = 0; i < tilesCount + 1; i++) { + VisImageButton ct; + VisImageButton.VisImageButtonStyle imageBoxStyle = new VisImageButton.VisImageButtonStyle(); + NinePatchDrawable inactive = new NinePatchDrawable(new NinePatch(resourcesManager.getPluginNinePatch("image-Box-inactive"))); + NinePatchDrawable active = new NinePatchDrawable(new NinePatch(resourcesManager.getPluginNinePatch("image-Box-active"))); + imageBoxStyle.up = inactive; + imageBoxStyle.down = active; + imageBoxStyle.checked = active; + imageBoxStyle.over = active; + Drawable tileDrawable = null; + if (i < savedTiles.size) { + int t = savedTiles.get(i).getEntityType(); + if (t == EntityFactory.SPINE_TYPE) { + tileDrawable = resourcesManager.getSpineDrawable(savedTiles.get(i).getRegionName()); + } else { + tileDrawable = new TextureRegionDrawable(resourcesManager.getTextureRegion(savedTiles.get(i).getRegionName(), t)); + } + } else if (!tileName.equals("")) { + if (i == tileIndex) { + if (type == EntityFactory.SPINE_TYPE) { + tileDrawable = resourcesManager.getSpineDrawable(tileName); + } else { + tileDrawable = new TextureRegionDrawable(resourcesManager.getTextureRegion(tileName, type)); + } + } + } + imageBoxStyle.imageUp = tileDrawable; + imageBoxStyle.imageDown = tileDrawable; + imageBoxStyle.imageChecked = tileDrawable; + imageBoxStyle.imageOver = tileDrawable; + ct = new VisImageButton(imageBoxStyle); + if (i < savedTiles.size) { + ct.setUserObject(savedTiles.get(i).getRegionName()); + } + + int index = i; + ct.addListener(getGridTabInputListener(index)); + listTable.add(ct) + .width(40) + .height(40) + .pad(3); + if((i+1) % 4 == 0) { + listTable.row(); + } + tiles.add(ct); + } + + content.pack(); + } + + public void initTiles() { + initTiles("", -1); + } + + /** + * Returns the newly initialized input listener for the given tile index. + * + * @param index The index of the tile. + * + * @return The new input listener. + */ + protected abstract GridTabInputListener getGridTabInputListener(int index); + + /** + * Returns the notification string to send when selecting a tile. + * + * @return The notification when selecting a tile. + */ + protected abstract String getTileSelectedNotification(); + + /** + * Returns the notification string to send when opening a drop down. + * + * @return The notification when opening a drop down. + */ + protected abstract String getTiledOpenDropDownNotification(); + + /** + * Selects the given tile. + * + * @param tileVO The tile to select + */ + public abstract void selectTile(T tileVO); + + /** + * Returns the corresponding {@link TextureRegionVO} for the given tile name. + * + * @param tileName The tilename for the texture region. + * + * @return The texture region. + */ + protected abstract T getTextureRegionVO(String tileName); + +} diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/AutoGridTilesTab.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/AutoGridTilesTab.java new file mode 100644 index 00000000..13461a86 --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/AutoGridTilesTab.java @@ -0,0 +1,52 @@ +package games.rednblack.editor.plugin.tiled.view.tabs; + +import com.badlogic.gdx.utils.Array; +import com.kotcrab.vis.ui.widget.VisTable; + +import games.rednblack.editor.plugin.tiled.TiledPanel; +import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.plugin.tiled.data.AutoTileVO; +import games.rednblack.editor.plugin.tiled.view.tabs.listener.GridTabInputListener; + +public class AutoGridTilesTab extends AbstractGridTilesTab { + + public AutoGridTilesTab(TiledPanel panel, String tabTitle, int tabIndex) { + super(panel, tabTitle, tabIndex); + } + + @Override + protected GridTabInputListener getGridTabInputListener(int index) { + return new GridTabInputListener(this, index, tiledPlugin, (VisTable) pane.getActor(), getTileSelectedNotification(), getTiledOpenDropDownNotification(), savedTiles, tiles); + } + + @Override + protected Array initSavedTiles() { + return tiledPlugin.dataToSave.getAutoTiles(); + } + + @Override + protected String getTileSelectedNotification() { + return TiledPlugin.AUTO_TILE_SELECTED; + } + + @Override + protected String getTiledOpenDropDownNotification() { + return TiledPlugin.AUTO_OPEN_DROP_DOWN; + } + + @Override + public void selectTile(AutoTileVO tileVO) { + tiledPlugin.setSelectedAutoTileVO(tileVO); + } + + @Override + protected void setGridSizeToFirstTileSize(String tileName, int type) { + super.setGridSizeToFirstTileSize(tileName + TiledPlugin.AUTO_TILE_MINI_SUFFIX, type); + } + + @Override + protected AutoTileVO getTextureRegionVO(String tileName) { + return new AutoTileVO(tileName); + } + +} 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 56807579..75ddc622 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 @@ -1,306 +1,50 @@ package games.rednblack.editor.plugin.tiled.view.tabs; -import com.badlogic.gdx.Input; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.NinePatch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.scenes.scene2d.Actor; -import com.badlogic.gdx.scenes.scene2d.InputEvent; -import com.badlogic.gdx.scenes.scene2d.InputListener; -import com.badlogic.gdx.scenes.scene2d.ui.Image; -import com.badlogic.gdx.scenes.scene2d.utils.Drawable; -import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; -import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.Array; -import com.kotcrab.vis.ui.widget.VisImageButton; -import com.kotcrab.vis.ui.widget.VisLabel; -import com.kotcrab.vis.ui.widget.VisScrollPane; import com.kotcrab.vis.ui.widget.VisTable; 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; +import games.rednblack.editor.plugin.tiled.view.tabs.listener.GridTabInputListener; /** * Created by mariam on 2/11/16. */ -public class GridTilesTab extends DefaultTab { - - public static boolean isDrop; - - private int tilesCount = 19; - private Array tiles; - private Array savedTiles; - private int tileIndex; - private VisScrollPane pane; - private boolean isBottomEdge; - - private TiledPlugin tiledPlugin; - private ResourcesManager resourcesManager; +public class GridTilesTab extends AbstractGridTilesTab { public GridTilesTab(TiledPanel panel, int tabIndex) { - super(panel, "Tiles", tabIndex); - - tiledPlugin = panel.tiledPlugin; - resourcesManager = tiledPlugin.pluginRM; - tiles = new Array<>(); - savedTiles = tiledPlugin.dataToSave.getTiles(); - tileIndex = savedTiles.size; + super(panel, "Tiles", tabIndex); } @Override - public void initView() { - if (isDrop = savedTiles.size == 0) { - VisImageButton.VisImageButtonStyle dropBoxStyle = new VisImageButton.VisImageButtonStyle(); - 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) - .center() - .padRight(6) - .padBottom(6) - .padTop(10) - .row(); - content.add(new VisLabel("Drop an image from resources box")) - .expandX() - .center() - .padBottom(5); - content.pack(); - } else { - if (tileIndex > tilesCount) { - tilesCount = tileIndex; - } - initTiles(); - } + protected Array initSavedTiles() { + return tiledPlugin.dataToSave.getTiles(); } - public void addTile(String tileName, int type) { - if (pane != null) isBottomEdge = pane.isBottomEdge(); - if (tileIndex == 0) { - setGridSizeToFirstTileSize(tileName, type); - isDrop = false; - panel.reInitTabTable(); - } - initTiles(tileName, type); - panel.pack(); - scrollTiles(); - tiles.get(tileIndex).setChecked(true); - tiledPlugin.facade.sendNotification(TiledPlugin.TILE_SELECTED, new TileVO(tileName)); - tileIndex++; + @Override + protected GridTabInputListener getGridTabInputListener(int index) { + return new GridTabInputListener(this, index, tiledPlugin, (VisTable) pane.getActor(), getTileSelectedNotification(), getTiledOpenDropDownNotification(), savedTiles, tiles); } - public void selectTile(TileVO tileVO) { + @Override + protected String getTileSelectedNotification() { + return TiledPlugin.TILE_SELECTED; + } + + @Override + protected String getTiledOpenDropDownNotification() { + return TiledPlugin.OPEN_DROP_DOWN; + } + + @Override + public void selectTile(TileVO tileVO) { tiledPlugin.setSelectedTileVO(tileVO); } - public void removeTile() { - if (pane != null) isBottomEdge = pane.isBottomEdge(); - tileIndex = --tileIndex < 0 ? 0 : tileIndex; - tilesCount = --tilesCount < 19 ? 19 : tilesCount; - tiles.clear(); - initView(); - } - - public void removeAllTiles() { - if (pane != null) isBottomEdge = pane.isBottomEdge(); - tileIndex = 0; - tilesCount = 19; - tiles.clear(); - initView(); - } + @Override + protected TileVO getTextureRegionVO(String tileName) { + return new TileVO(tileName); + } - public void scrollTiles() { - if(savedTiles.size + 1 >= tilesCount) { - pane.layout(); - pane.setSmoothScrolling(!isBottomEdge); - pane.setScrollY(100); - } - } - - 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, int type) { - content.clear(); - tiles.clear(); - - VisTable listTable = new VisTable(); - pane = StandardWidgetsFactory.createScrollPane(listTable); - pane.setScrollingDisabled(true, false); - content.add(pane) - .padTop(10); - listTable.top(); - - if(tileIndex >= tilesCount && !tileName.equals("")) { - tilesCount = tileIndex + 1; - } - - for (int i = 0; i < tilesCount + 1; i++) { - VisImageButton ct; - VisImageButton.VisImageButtonStyle imageBoxStyle = new VisImageButton.VisImageButtonStyle(); - NinePatchDrawable inactive = new NinePatchDrawable(new NinePatch(resourcesManager.getPluginNinePatch("image-Box-inactive"))); - NinePatchDrawable active = new NinePatchDrawable(new NinePatch(resourcesManager.getPluginNinePatch("image-Box-active"))); - imageBoxStyle.up = inactive; - imageBoxStyle.down = active; - imageBoxStyle.checked = active; - imageBoxStyle.over = active; - Drawable tileDrawable = null; - if (i < savedTiles.size) { - 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) { - if (type == EntityFactory.SPINE_TYPE) { - tileDrawable = resourcesManager.getSpineDrawable(tileName); - } else { - tileDrawable = new TextureRegionDrawable(resourcesManager.getTextureRegion(tileName, type)); - } - } - } - imageBoxStyle.imageUp = tileDrawable; - imageBoxStyle.imageDown = tileDrawable; - imageBoxStyle.imageChecked = tileDrawable; - imageBoxStyle.imageOver = tileDrawable; - ct = new VisImageButton(imageBoxStyle); - if (i < savedTiles.size) { - ct.setUserObject(savedTiles.get(i).regionName); - } - - int index = i; - ct.addListener(new InputListener() { - private boolean isDragging = false; - private Actor draggingSource; - - @Override - public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { - if (button == Input.Buttons.LEFT) { - draggingSource = event.getListenerActor(); - } - - if (index >= savedTiles.size) return true; - - for (VisImageButton tile : tiles) { - if (tile.isChecked()) { - tile.setChecked(false); - } - } - - return true; - } - - @Override - public void touchUp(InputEvent event, float x, float y, int pointer, int button) { - super.touchUp(event, x, y, pointer, button); - if (isDragging && button == Input.Buttons.LEFT && draggingSource != null) { - // finished dragging - isDragging = false; - - handleDrop(x, y); - } else { - if(button == Input.Buttons.RIGHT && index < savedTiles.size) { - tiledPlugin.facade.sendNotification(TiledPlugin.OPEN_DROP_DOWN, savedTiles.get(index).regionName); - return; - } - - if (index >= savedTiles.size) { - tiles.get(index).setChecked(false); - return; - } - - tiledPlugin.facade.sendNotification(TiledPlugin.TILE_SELECTED, savedTiles.get(index)); - } - } - - @Override - public void touchDragged (InputEvent event, float x, float y, int pointer) { - isDragging = true; - if (draggingSource != null) - draggingSource.setColor(new Color(0 / 255f, 0 / 255f, 0f / 255f, 0.5f)); - } - - /** - * Handles the drop of a VisImageButton. - * - * @param x The coordinates relative to the source. Comes from the touchUp event. - * @param y The coordinates relative to the source. Comes from the touchUp event. - */ - private void handleDrop(float x, float y) { - VisTable t = (VisTable) pane.getActor(); - Actor draggingTarget = t.hit(draggingSource.getX() + x, draggingSource.getY() + y, false); - if (draggingTarget instanceof Image) { - for (VisImageButton imgButton : tiles) { - if (imgButton.getImage() == draggingTarget) { - draggingTarget = imgButton; - break; - } - } - } - if (draggingTarget != null && !draggingTarget.equals(draggingSource)) { - String sourceRegionName = String.valueOf(draggingSource.getUserObject()); - String targetRegionName = String.valueOf(draggingTarget.getUserObject()); - int sourceIndex = -1; - int targetIndex = -1; - for (int i = 0; i < savedTiles.size; i++) { - if (sourceRegionName.equals(savedTiles.get(i).regionName)) { - sourceIndex = i; - } - if (targetRegionName.equals(savedTiles.get(i).regionName)) { - targetIndex = i; - } - } - // if targetIndex < 0 we dropped at the end - // we already know that we hit another VisImageButton but could not find the name - // thus, an empty button, which are always after the ones with an image - if (targetIndex < 0) { - targetIndex = savedTiles.size - 1; - } - if (sourceIndex >= 0) { - TileVO sourceTileVO = savedTiles.removeIndex(sourceIndex); - savedTiles.insert(targetIndex, sourceTileVO); - initTiles(); - } - } - } - - }); - listTable.add(ct) - .width(40) - .height(40) - .pad(3); - if((i+1) % 4 == 0) { - listTable.row(); - } - tiles.add(ct); - } - - content.pack(); - } - - private void initTiles() { - initTiles("", -1); - } } diff --git a/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/listener/GridTabInputListener.java b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/listener/GridTabInputListener.java new file mode 100644 index 00000000..a1a4d90e --- /dev/null +++ b/plugin-tiled/src/main/java/games/rednblack/editor/plugin/tiled/view/tabs/listener/GridTabInputListener.java @@ -0,0 +1,143 @@ +package games.rednblack.editor.plugin.tiled.view.tabs.listener; + +import com.badlogic.gdx.Input; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.InputListener; +import com.badlogic.gdx.scenes.scene2d.ui.Image; +import com.badlogic.gdx.utils.Array; +import com.kotcrab.vis.ui.widget.VisImageButton; +import com.kotcrab.vis.ui.widget.VisTable; + +import games.rednblack.editor.plugin.tiled.TiledPlugin; +import games.rednblack.editor.plugin.tiled.data.TextureRegionVO; +import games.rednblack.editor.plugin.tiled.view.tabs.AbstractGridTilesTab; + +public class GridTabInputListener extends InputListener { + + private final int index; + + private AbstractGridTilesTab tab; + private String tileSelectedNotification; + private String openDropDownNotification; + + private TiledPlugin tiledPlugin; + + private VisTable table; + + private Array tiles; + + private boolean isDragging = false; + private Actor draggingSource; + + private Array savedTiles; + + public GridTabInputListener(AbstractGridTilesTab tab, int index, TiledPlugin tiledPlugin, VisTable table, String tileSelectedNotification, String openDropDownNotification, Array savedTiles, Array tiles) { + this.tab = tab; + this.index = index; + this.tiledPlugin = tiledPlugin; + this.tileSelectedNotification = tileSelectedNotification; + this.openDropDownNotification = openDropDownNotification; + this.table = table; + this.savedTiles = savedTiles; + this.tiles = tiles; + } + + @Override + public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { + if (button == Input.Buttons.LEFT) { + draggingSource = event.getListenerActor(); + } + + if (index >= savedTiles.size) return true; + + for (VisImageButton tile : tiles) { + if (tile.isChecked()) { + tile.setChecked(false); + } + } + + return true; + } + + @Override + public void touchUp(InputEvent event, float x, float y, int pointer, int button) { + super.touchUp(event, x, y, pointer, button); + if (isDragging && button == Input.Buttons.LEFT && draggingSource != null) { + // finished dragging + isDragging = false; + + handleDrop(x, y); + } else { + if(button == Input.Buttons.RIGHT && index < savedTiles.size) { + tiledPlugin.facade.sendNotification(openDropDownNotification, savedTiles.get(index).getRegionName()); + return; + } + + if (index >= savedTiles.size) { + tiles.get(index).setChecked(false); + return; + } + + tiledPlugin.facade.sendNotification(tileSelectedNotification, savedTiles.get(index)); + } + } + + @Override + public void touchDragged (InputEvent event, float x, float y, int pointer) { + isDragging = true; + if (draggingSource != null) { + // draggingSource can be null when dragging with the right mouse button + draggingSource.setColor(new Color(0 / 255f, 0 / 255f, 0f / 255f, 0.5f)); + } + } + + /** + * Handles the drop of a VisImageButton. + * + * @param x The coordinates relative to the source. Comes from the touchUp event. + * @param y The coordinates relative to the source. Comes from the touchUp event. + */ + private void handleDrop(float x, float y) { + Actor draggingTarget = table.hit(draggingSource.getX() + x, draggingSource.getY() + y, false); + if (draggingTarget instanceof Image) { + for (VisImageButton imgButton : tiles) { + if (imgButton.getImage() == draggingTarget) { + draggingTarget = imgButton; + break; + } + } + } + if (draggingTarget != null) { + String sourceRegionName = String.valueOf(draggingSource.getUserObject()); + String targetRegionName = String.valueOf(draggingTarget.getUserObject()); + int sourceIndex = -1; + int targetIndex = -1; + for (int i = 0; i < savedTiles.size; i++) { + if (sourceRegionName.equals(savedTiles.get(i).getRegionName())) { + sourceIndex = i; + } + if (targetRegionName.equals(savedTiles.get(i).getRegionName())) { + targetIndex = i; + } + } + // if targetIndex < 0 we dropped at the end + // we already know that we hit another VisImageButton but could not find the name + // thus, an empty button, which are always after the ones with an image + if (targetIndex < 0) { + targetIndex = savedTiles.size - 1; + } + if (sourceIndex >= 0) { + T sourceTileVO = savedTiles.removeIndex(sourceIndex); + savedTiles.insert(targetIndex, sourceTileVO); + tab.initTiles(); + // select the dropped button + tiledPlugin.facade.sendNotification(TiledPlugin.TILE_SELECTED, sourceTileVO); + tiles.get(targetIndex).setChecked(true); + } + + } + } + +} diff --git a/src/main/java/games/rednblack/editor/view/ui/BoxItemResourceSelectionUIMediator.java b/src/main/java/games/rednblack/editor/view/ui/BoxItemResourceSelectionUIMediator.java index 7b7755e5..4fc062bd 100644 --- a/src/main/java/games/rednblack/editor/view/ui/BoxItemResourceSelectionUIMediator.java +++ b/src/main/java/games/rednblack/editor/view/ui/BoxItemResourceSelectionUIMediator.java @@ -95,7 +95,7 @@ public class BoxItemResourceSelectionUIMediator extends Mediator { ); 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;