package org.shadebob.skineditor; import java.awt.Frame; import java.io.File; import javax.swing.JFileChooser; import javax.swing.filechooser.FileNameExtensionFilter; import org.shadebob.skineditor.actors.RangeSelector; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.PixmapIO; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.ui.Dialog; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle; import com.badlogic.gdx.scenes.scene2d.ui.TextField; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; import com.badlogic.gdx.tools.texturepacker.TexturePacker; import com.esotericsoftware.tablelayout.Cell; public class NinePatchEditorDialog extends Dialog { private SkinEditorGame game; private TextField textName; private TextField textSourceImage; private float currentZoom = 1.0f; private Table table; private Table tableEditor; private Table tablePreview; private Image image; private float imgWidth; private float imgHeight; private Cell cellImage; private RangeSelector rangeTop; private RangeSelector rangeBottom; private RangeSelector rangeLeft; private RangeSelector rangeRight; private TextButton buttonPreview1; private TextButton buttonPreview2; private TextButton buttonPreview3; private Cell cellPreview1; private Cell cellPreview2; private Cell cellPreview3; private FileHandle tmpFile; /** * */ public NinePatchEditorDialog(final SkinEditorGame game) { super("Create NinePatch", game.skin); this.game = game; tmpFile = new FileHandle(System.getProperty("java.io.tmpdir")).child("skin_ninepatch"); if (tmpFile.exists() == false) { tmpFile.mkdirs(); } tmpFile = tmpFile.child("button.9.png"); table = new Table(game.skin); // table.debug(); table.defaults().pad(10); table.top(); table.left(); textName = new TextField("default_button", game.skin); Table tableTop = new Table(game.skin); tableTop.add("NinePatch Name:").padRight(10); tableTop.add(textName).padRight(10); tableTop.add("Source Image:").padRight(10); textSourceImage = new TextField("resources/default_button.png", game.skin); textSourceImage.setDisabled(true); tableTop.add(textSourceImage).expandX().fill().padRight(10); TextButton buttonChoose = new TextButton("...", game.skin); tableTop.add(buttonChoose).width(32); buttonChoose.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { // Need to steal focus first with this hack (Thanks to Z-Man) Frame frame = new Frame(); frame.setUndecorated(true); frame.setOpacity(0); frame.setLocationRelativeTo(null); frame.setVisible(true); frame.toFront(); frame.setVisible(false); frame.dispose(); JFileChooser chooser = new JFileChooser(); FileNameExtensionFilter filter = new FileNameExtensionFilter("Images", "png"); chooser.setFileFilter(filter); int returnVal = chooser.showOpenDialog(null); if (returnVal != JFileChooser.APPROVE_OPTION) { return; } File selectedFile = chooser.getSelectedFile(); if (selectedFile == null) { return; } String name = new FileHandle(selectedFile).nameWithoutExtension(); name = name.replace(" ", "_"); name = name.replace("-", "_"); textName.setText(name); textSourceImage.setText(selectedFile.getAbsolutePath()); TextureRegionDrawable trd = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal(textSourceImage.getText())))); image.setDrawable(trd); image.setWidth(trd.getMinWidth()); image.setHeight(trd.getMinHeight()); imgWidth = image.getWidth(); imgHeight = image.getHeight(); refreshPreview(); refreshImage(); } }); table.add(tableTop).colspan(2).expandX().fillX(); table.row(); rangeTop = new RangeSelector(false, game.skin); rangeRight = new RangeSelector(true, game.skin); rangeBottom = new RangeSelector(false, game.skin); rangeLeft = new RangeSelector(true, game.skin); ChangeListener listener = new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { refreshPreview(); } }; rangeTop.addListener(listener); rangeRight.addListener(listener); rangeBottom.addListener(listener); rangeLeft.addListener(listener); tableEditor = new Table(game.skin); //tableEditor.debug(); tableEditor.add(); tableEditor.add(rangeTop).fillX().height(10); tableEditor.row(); tableEditor.add(rangeLeft).width(10).fillY(); image = new Image(new Texture(Gdx.files.internal(textSourceImage.getText()))); imgWidth = image.getWidth(); imgHeight = image.getHeight(); cellImage = tableEditor.add(image); cellImage.width(imgWidth * currentZoom).height(imgHeight * currentZoom); tableEditor.add(rangeRight).width(10).fillY(); tableEditor.row(); tableEditor.add(); tableEditor.add(rangeBottom).fillX().height(10); tableEditor.row(); ScrollPane scrollPane = new ScrollPane(tableEditor,game.skin); scrollPane.setOverscroll(false, false); scrollPane.setFadeScrollBars(false); scrollPane.setFlingTime(0); table.add(scrollPane).width(500).expand().fill(); tablePreview = new Table(game.skin); reviewTablePreview(); table.add(new ScrollPane(tablePreview,game.skin)).width(360).expand().fill().row(); Table tableButtons = new Table(game.skin); tableButtons.center(); TextButton buttonSave = new TextButton("Save NinePatch", game.skin); tableButtons.add(buttonSave).padRight(10); TextButton buttonZoomIn = new TextButton("+", game.skin); tableButtons.add(buttonZoomIn).width(32).padRight(10); TextButton buttonZoomOut = new TextButton("-", game.skin); tableButtons.add(buttonZoomOut).width(32).padRight(10); TextButton buttonCancel = new TextButton("Cancel", game.skin); tableButtons.add(buttonCancel); table.add(tableButtons).colspan(2).row(); getContentTable().add(table).width(900).height(640).pad(20); getButtonTable().padBottom(15); buttonSave.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { if (textName.getText().isEmpty() == true) { game.showNotice("Error", "Empty name!", getStage()); return; } // First check if the name is already in use if (game.skinProject.has(textName.getText(), NinePatch.class)) { game.showNotice("Error", "A ninepatch with the same name already exists!", getStage()); return; } FileHandle targetImage = new FileHandle("projects/" + game.screenMain.getcurrentProject() + "/assets/" + textName.getText() + ".9.png"); if (targetImage.exists() == true) { game.showNotice("Error", "A file with the same name already exists!", getStage()); return; } tmpFile.copyTo(targetImage); game.screenMain.saveToSkin(); game.screenMain.refreshResources(); hide(); } }); buttonZoomIn.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { if (currentZoom < 16) { currentZoom *= 2; refreshImage(); } } }); buttonZoomOut.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { if (currentZoom > 0.5f) { currentZoom /= 2; refreshImage(); } } }); buttonCancel.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { cancel(); hide(); } }); key(com.badlogic.gdx.Input.Keys.ESCAPE, false); refreshPreview(); } private void reviewTablePreview() { tablePreview.clear(); //tablePreview.debug(); tablePreview.center().left(); TextButtonStyle stylePreview = new TextButton.TextButtonStyle(); stylePreview.font = game.skin.getFont("default-font"); buttonPreview1 = new TextButton("1x Button", stylePreview); buttonPreview1.setSize(imgWidth, imgHeight); cellPreview1 = tablePreview.add(buttonPreview1).width(buttonPreview1.getWidth()).height(buttonPreview1.getHeight()).padBottom(15); tablePreview.row(); buttonPreview2 = new TextButton("2x Button", stylePreview); buttonPreview2.setSize(imgWidth * 2.0f, imgHeight * 2.0f); cellPreview2 = tablePreview.add(buttonPreview2).width(buttonPreview2.getWidth()).height(buttonPreview2.getHeight()).padBottom(15); tablePreview.row(); buttonPreview3 = new TextButton("3x Button", stylePreview); buttonPreview3.setSize(imgWidth * 3.0f, imgHeight * 3.0f); cellPreview3 = tablePreview.add(buttonPreview3).width(buttonPreview3.getWidth()).height(buttonPreview3.getHeight()).padBottom(15); tablePreview.row(); } /** * */ private void refreshImage() { float newX = imgWidth * currentZoom; float newY = imgHeight * currentZoom; image.setSize(newX, newY); cellImage.width(newX).height(newY); tableEditor.setWidth(newX); tableEditor.setHeight(newY); ScrollPane sp = (ScrollPane) tableEditor.getParent(); sp.layout(); } public void refreshPreview() { Gdx.app.log("NinePatchEditorDialog","refresh preview."); Pixmap pixmapImage = new Pixmap(Gdx.files.internal(textSourceImage.getText())); Pixmap pixmap = new Pixmap((int) (pixmapImage.getWidth()+2), (int) (pixmapImage.getHeight()+2), Pixmap.Format.RGBA8888); pixmap.drawPixmap(pixmapImage,1,1); pixmap.setColor(Color.BLACK); // Range left int h = pixmapImage.getHeight()+1; pixmap.drawLine(0, (int) (h * rangeLeft.rangeStart),0, (int) (h * rangeLeft.rangeStop)); // Range top int w = pixmapImage.getWidth()+1; pixmap.drawLine((int) (w * rangeTop.rangeStart), 0,(int) (w * rangeTop.rangeStop), 0); // Range right h = pixmapImage.getHeight()+1; pixmap.drawLine(pixmapImage.getWidth()+1, (int) (h * rangeRight.rangeStart),pixmapImage.getWidth()+1, (int) (h * rangeRight.rangeStop)); // Range bottom w = pixmapImage.getWidth()+1; pixmap.drawLine((int) (w * rangeBottom.rangeStart), pixmap.getHeight()-1,(int) (w * rangeBottom.rangeStop), pixmap.getHeight()-1); PixmapIO.writePNG(tmpFile, pixmap); pixmapImage.dispose(); pixmap.dispose(); FileHandle fh = new FileHandle(System.getProperty("java.io.tmpdir")).child("skin_ninepatch"); TexturePacker.Settings settings = new TexturePacker.Settings(); TexturePacker.process(settings, fh.path(), fh.path(), "pack"); TextureAtlas ta = new TextureAtlas(fh.child("pack.atlas")); NinePatch np = ta.createPatch("button"); NinePatchDrawable drawable = new NinePatchDrawable(np); reviewTablePreview(); buttonPreview1.getStyle().up = drawable; } }