[editor only] Sprite Sheet to Animation splitter
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
- Fixed import Spine animations exported in compatibility mode
|
||||
- Add support to path as atlas region name
|
||||
- Hide `white-pixel` resource because mandatory
|
||||
- Check updates for Snapshot builds
|
||||
- Sprite Sheet to Animation splitter
|
||||
|
||||
**Runtime**
|
||||
- [BREAK CHANGE] Improve `ActionEventListener` with `entity` parameter
|
||||
|
||||
@@ -89,6 +89,7 @@ public class BootstrapViewCommand extends SimpleCommand {
|
||||
facade.registerMediator(new NodeEditorDialogMediator());
|
||||
facade.registerMediator(new CreatePlaceholderDialogMediator());
|
||||
facade.registerMediator(new CreateNoiseDialogMediator());
|
||||
facade.registerMediator(new ImportSpriteSheetDialogMediator());
|
||||
facade.registerMediator(new ConsoleDialogMediator());
|
||||
facade.registerMediator(new ImagesPackDialogMediator());
|
||||
facade.registerMediator(new AnimationsPackDialogMediator());
|
||||
|
||||
@@ -12,6 +12,7 @@ import static games.rednblack.h2d.common.MenuAPI.RESOURCE_MENU;
|
||||
public class ResourcesMenu extends H2DMenu {
|
||||
|
||||
public static final String IMPORT_TO_LIBRARY = HyperLap2DMenuBar.prefix + ".IMPORT_TO_LIBRARY";
|
||||
public static final String IMPORT_SPRITE_SHEET = HyperLap2DMenuBar.prefix + ".IMPORT_SPRITE_SHEET";
|
||||
public static final String CREATE_PLACEHOLDER = HyperLap2DMenuBar.prefix + ".CREATE_PLACEHOLDER";
|
||||
public static final String CREATE_NOISE = HyperLap2DMenuBar.prefix + ".CREATE_NOISE";
|
||||
public static final String OPEN_IMAGES_PACK = HyperLap2DMenuBar.prefix + ".OPEN_IMAGES_PACK";
|
||||
@@ -21,6 +22,7 @@ public class ResourcesMenu extends H2DMenu {
|
||||
public ResourcesMenu() {
|
||||
super("Resources");
|
||||
MenuItem importToLibrary = new MenuItem("Import Resources...", new MenuItemListener(IMPORT_TO_LIBRARY, null, FILE_MENU)).setShortcut(KeyBindingsLayout.getShortcutList(KeyBindingsLayout.IMPORT_TO_LIBRARY));
|
||||
MenuItem importSpriteSheet = new MenuItem("Import Sprite Sheet Animation...", new MenuItemListener(IMPORT_SPRITE_SHEET, null, RESOURCE_MENU));
|
||||
MenuItem placeholders = new MenuItem("Create Placeholder...", new MenuItemListener(CREATE_PLACEHOLDER, null, RESOURCE_MENU));
|
||||
MenuItem noise = new MenuItem("Create Perlin Noise...", new MenuItemListener(CREATE_NOISE, null, RESOURCE_MENU));
|
||||
MenuItem repack = new MenuItem("Repack Assets", new MenuItemListener(MsgAPI.ACTION_REPACK, null, RESOURCE_MENU));
|
||||
@@ -38,6 +40,7 @@ public class ResourcesMenu extends H2DMenu {
|
||||
addSeparator();
|
||||
addItem(placeholders);
|
||||
addItem(noise);
|
||||
addItem(importSpriteSheet);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -49,7 +49,7 @@ public class ConsoleDialog extends H2DDialog {
|
||||
private Color lastBackgroundColor = Color.CLEAR;
|
||||
private H2DHighlight.TextFormat lastTextFormat = H2DHighlight.TextFormat.NORMAL;
|
||||
|
||||
public static int MAX_TEXT_LENGTH = 5000;
|
||||
public static int MAX_TEXT_LENGTH = 10000;
|
||||
|
||||
public ConsoleDialog() {
|
||||
super("Console", "console");
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package games.rednblack.editor.view.ui.dialog;
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
import com.kotcrab.vis.ui.util.Validators;
|
||||
import com.kotcrab.vis.ui.widget.VisLabel;
|
||||
import com.kotcrab.vis.ui.widget.VisTable;
|
||||
import com.kotcrab.vis.ui.widget.VisTextButton;
|
||||
import com.kotcrab.vis.ui.widget.VisValidatableTextField;
|
||||
import com.kotcrab.vis.ui.widget.file.FileChooser;
|
||||
import games.rednblack.editor.HyperLap2DFacade;
|
||||
import games.rednblack.h2d.common.H2DDialog;
|
||||
import games.rednblack.h2d.common.view.ui.StandardWidgetsFactory;
|
||||
import games.rednblack.h2d.common.view.ui.widget.InputFileWidget;
|
||||
import org.puremvc.java.interfaces.IFacade;
|
||||
|
||||
public class ImportSpriteSheetDialog extends H2DDialog {
|
||||
private static final String prefix = "games.rednblack.editor.view.ui.dialog.ImportSpriteSheetDialog";
|
||||
public static final String IMPORT_SPRITE_SHEET = prefix + ".IMPORT_SPRITE_SHEET";
|
||||
|
||||
private final VisValidatableTextField width, height;
|
||||
private final InputFileWidget imagePathField;
|
||||
private final VisTextButton importButton;
|
||||
private final IFacade facade;
|
||||
|
||||
public ImportSpriteSheetDialog() {
|
||||
super("Import Sprite Sheet Animation");
|
||||
addCloseButton();
|
||||
|
||||
this.facade = HyperLap2DFacade.getInstance();
|
||||
|
||||
setModal(true);
|
||||
VisTable fileTable = new VisTable();
|
||||
fileTable.pad(6);
|
||||
//
|
||||
fileTable.add(new VisLabel("Sprite Sheet:")).right().padRight(5);
|
||||
imagePathField = new InputFileWidget(FileChooser.Mode.OPEN, FileChooser.SelectionMode.FILES, false);
|
||||
imagePathField.setTextFieldWidth(156);
|
||||
fileTable.add(imagePathField);
|
||||
getContentTable().add(fileTable);
|
||||
//
|
||||
getContentTable().row().padTop(10);
|
||||
//
|
||||
|
||||
Validators.IntegerValidator validator = new Validators.IntegerValidator();
|
||||
|
||||
width = StandardWidgetsFactory.createValidableTextField(validator);
|
||||
height = StandardWidgetsFactory.createValidableTextField(validator);
|
||||
|
||||
VisTable sizeTable = new VisTable();
|
||||
sizeTable.add("Sprite Width:").padRight(3);
|
||||
sizeTable.add(width).width(60);
|
||||
sizeTable.add("px").padLeft(5);
|
||||
sizeTable.row().padTop(5);
|
||||
sizeTable.add("Sprite Height:").padRight(3);
|
||||
sizeTable.add(height).width(60);
|
||||
sizeTable.add("px").padLeft(5);
|
||||
getContentTable().add(sizeTable);
|
||||
|
||||
importButton = StandardWidgetsFactory.createTextButton("Import");
|
||||
getButtonsTable().add(importButton);
|
||||
pack();
|
||||
|
||||
setListeners();
|
||||
}
|
||||
|
||||
public int getSpriteWidth() {
|
||||
return Integer.parseInt(width.getText());
|
||||
}
|
||||
|
||||
public int getSpriteHeight() {
|
||||
return Integer.parseInt(height.getText());
|
||||
}
|
||||
|
||||
private void setListeners() {
|
||||
importButton.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
if (width.isInputValid() && height.isInputValid() && imagePathField.getValue() != null) {
|
||||
facade.sendNotification(IMPORT_SPRITE_SHEET, imagePathField.getValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package games.rednblack.editor.view.ui.dialog;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.PixmapIO;
|
||||
import com.badlogic.gdx.tools.texturepacker.TexturePacker;
|
||||
import games.rednblack.editor.HyperLap2DFacade;
|
||||
import games.rednblack.editor.proxy.ProjectManager;
|
||||
import games.rednblack.editor.view.menu.ResourcesMenu;
|
||||
import games.rednblack.editor.view.stage.Sandbox;
|
||||
import games.rednblack.editor.view.stage.UIStage;
|
||||
import games.rednblack.h2d.common.MsgAPI;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.puremvc.java.interfaces.INotification;
|
||||
import org.puremvc.java.patterns.mediator.Mediator;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class ImportSpriteSheetDialogMediator extends Mediator<ImportSpriteSheetDialog> {
|
||||
private static final String TAG = ImportSpriteSheetDialogMediator.class.getCanonicalName();
|
||||
private static final String NAME = TAG;
|
||||
|
||||
public ImportSpriteSheetDialogMediator() {
|
||||
super(NAME, new ImportSpriteSheetDialog());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegister() {
|
||||
super.onRegister();
|
||||
facade = HyperLap2DFacade.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] listNotificationInterests() {
|
||||
return new String[]{
|
||||
ResourcesMenu.IMPORT_SPRITE_SHEET,
|
||||
ImportSpriteSheetDialog.IMPORT_SPRITE_SHEET
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleNotification(INotification notification) {
|
||||
super.handleNotification(notification);
|
||||
Sandbox sandbox = Sandbox.getInstance();
|
||||
UIStage uiStage = sandbox.getUIStage();
|
||||
|
||||
switch (notification.getName()) {
|
||||
case ResourcesMenu.IMPORT_SPRITE_SHEET:
|
||||
viewComponent.show(uiStage);
|
||||
break;
|
||||
case ImportSpriteSheetDialog.IMPORT_SPRITE_SHEET:
|
||||
FileHandle spriteSheet = notification.getBody();
|
||||
importSpriteSheet(spriteSheet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void importSpriteSheet(FileHandle spriteSheet) {
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
executor.execute(() -> {
|
||||
facade.sendNotification(MsgAPI.SHOW_LOADING_DIALOG);
|
||||
|
||||
byte[] image = spriteSheet.readBytes();
|
||||
Pixmap pixmap = new Pixmap(image, 0, image.length);
|
||||
String name = spriteSheet.nameWithoutExtension();
|
||||
|
||||
int spriteW = viewComponent.getSpriteWidth();
|
||||
int spriteH = viewComponent.getSpriteHeight();
|
||||
|
||||
ProjectManager projectManager = facade.retrieveProxy(ProjectManager.NAME);
|
||||
projectManager.getCurrentProjectInfoVO().animationsPacks.get("main").regions.add(name);
|
||||
|
||||
String targetPath = projectManager.getCurrentProjectPath() + File.separator
|
||||
+ ProjectManager.SPRITE_DIR_PATH + File.separator + name;
|
||||
File targetDir = new File(targetPath);
|
||||
try {
|
||||
FileUtils.forceMkdir(targetDir);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
facade.sendNotification(MsgAPI.HIDE_LOADING_DIALOG);
|
||||
return;
|
||||
}
|
||||
|
||||
TexturePacker.Settings settings = projectManager.getTexturePackerSettings();
|
||||
TexturePacker tp = new TexturePacker(settings);
|
||||
|
||||
int i = 0;
|
||||
for (int x = 0; x < pixmap.getWidth(); x += spriteW) {
|
||||
for (int y = 0; y < pixmap.getHeight(); y += spriteH) {
|
||||
int w = x + spriteW <= pixmap.getWidth() ? spriteW : pixmap.getWidth() - x;
|
||||
int h = y + spriteH <= pixmap.getHeight() ? spriteH : pixmap.getHeight() - y;
|
||||
Pixmap tilePixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888);
|
||||
tilePixmap.drawPixmap(pixmap, 0, 0, x, y, w, h);
|
||||
|
||||
String imagesPath = projectManager.getCurrentRawImagesPath() + File.separator + name + "_" + i + ".png";
|
||||
FileHandle path = new FileHandle(imagesPath);
|
||||
PixmapIO.writePNG(path, tilePixmap);
|
||||
|
||||
tilePixmap.dispose();
|
||||
tp.addImage(path.file());
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
pixmap.dispose();
|
||||
|
||||
tp.pack(targetDir, name);
|
||||
|
||||
viewComponent.close();
|
||||
|
||||
facade.sendNotification(MsgAPI.HIDE_LOADING_DIALOG);
|
||||
|
||||
Gdx.app.postRunnable(() -> {
|
||||
facade.sendNotification(MsgAPI.UPDATE_ATLAS_PACK_LIST);
|
||||
facade.sendNotification(MsgAPI.ACTION_REPACK);
|
||||
});
|
||||
});
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user