Push to BitBucket

This commit is contained in:
fgnm
2020-06-26 16:49:10 +02:00
commit cc18e2c5e4
839 changed files with 86083 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
plugins {
id 'java'
}
group 'games.rednblack'
version '0.0.1'
ext {
gdxVersion = '1.9.10'
box2DLightsVersion = '1.5'
ashleyVersion = '1.7.3'
visUIVersion = '1.4.4'
}
repositories {
mavenCentral()
}
dependencies {
implementation "com.badlogicgames.gdx:gdx:$gdxVersion"
implementation "com.badlogicgames.ashley:ashley:$ashleyVersion"
implementation "com.kotcrab.vis:vis-ui:$visUIVersion"
implementation 'net.mountainblade:modular:1.0'
implementation project(":hyperlap2d-common-api")
implementation project(":hyperlap2d-runtime-libgdx")
testCompile group: 'junit', name: 'junit', version: '4.12'
}
task dist(type: Jar) {
from files(sourceSets.main.output.classesDirs)
from files(sourceSets.main.output.resourcesDir)
}
@@ -0,0 +1,265 @@
package games.rednblack.editor.plugin.ninepatch;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Circle;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
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.utils.ScissorStack;
/**
* Created by azakhary on 8/18/2015.
*/
public class EditingZone extends Actor {
private ShapeRenderer shapeRenderer;
private TextureRegion texture;
private static final Color BG = new Color(43f / 255f, 43f / 255f, 43f / 255f, 1f);
private static final Color GUIDE_COLOR = new Color(255f/255f, 94f/255f, 0f/255f, 0.5f);
private static final Color OVER_GUIDE_COLOR = new Color(255f/255f, 173f/255f, 125f/255f, 1f);
private float currZoom = 1f;
private Vector2 shift = new Vector2(0, 0);
private int mouseOverSplit = -1;
private float[] splitPositions = new float[4];
private int[] splits = new int[4];
public interface PatchChangeListener {
public void changed(int[] splits);
}
private PatchChangeListener listener;
public EditingZone() {
shapeRenderer = new ShapeRenderer();
addListener(new InputListener() {
private Vector2 lastPoint;
private int selectedSplit = -1;
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
selectedSplit = splitCollision(x, y);
if(selectedSplit >= 0) {
} else {
lastPoint = new Vector2(x, y);
}
return true;
}
public void touchDragged(InputEvent event, float x, float y, int pointer) {
if (selectedSplit >= 0) {
if(selectedSplit == 0) { //left
splits[0] = (int) ((x-shift.x-getWidth()/2f)/currZoom+texture.getRegionWidth()/2f);
if(splits[0] > texture.getRegionWidth()-splits[1]) {
int tmp = splits[1]; splits[1] = texture.getRegionWidth()-splits[0]; splits[0] = texture.getRegionWidth() - tmp;
selectedSplit = 1;
mouseOverSplit = selectedSplit;
}
splitUpdate();
return;
}
if(selectedSplit == 1) {
splits[1] = -(int) ((x-shift.x-getWidth()/2f)/currZoom-texture.getRegionWidth()/2f);
if(texture.getRegionWidth()-splits[1] < splits[0]) {
int tmp = splits[0]; splits[0] = texture.getRegionWidth() - splits[1]; splits[1] = texture.getRegionWidth() - tmp;
selectedSplit = 0;
mouseOverSplit = selectedSplit;
}
splitUpdate();
return;
}
if(selectedSplit == 2) { // top
splits[2] = -(int) ((y-shift.y-getHeight()/2f)/currZoom-texture.getRegionHeight()/2f);
if(texture.getRegionHeight()-splits[2] < splits[3]) {
int tmp = splits[2]; splits[2] = texture.getRegionHeight()-splits[3]; splits[3] = texture.getRegionHeight()-tmp;
selectedSplit = 3;
mouseOverSplit = selectedSplit;
}
splitUpdate();
return;
}
if(selectedSplit == 3) {
splits[3] = (int) ((y-shift.y-getHeight()/2f)/currZoom+texture.getRegionHeight()/2f);
if(splits[3] > texture.getRegionHeight()-splits[2]) {
int tmp = splits[3]; splits[3] = texture.getRegionHeight()-splits[2]; splits[2] = texture.getRegionHeight()-tmp;
selectedSplit = 2;
mouseOverSplit = selectedSplit;
}
splitUpdate();
return;
}
} else {
Vector2 diff = new Vector2(x - lastPoint.x, y - lastPoint.y);
shiftBy(diff);
lastPoint = new Vector2(x, y);
}
}
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
selectedSplit = -1;
if(listener != null) {
listener.changed(splits.clone());
}
}
public boolean mouseMoved(InputEvent event, float x, float y) {
mouseOverSplit = splitCollision(x, y);
return false;
}
});
}
public void setListener(PatchChangeListener listener) {
this.listener = listener;
}
public void splitUpdate() {
if(splits[0] < 0) splits[0] = 0;
if(splits[1] < 0) splits[1] = 0;
if(splits[2] < 0) splits[2] = 0;
if(splits[3] < 0) splits[3] = 0;
}
public int[] getSplits() {
return splits.clone();
}
public void setTexture(TextureRegion texture) {
this.texture = texture;
splits[0] = ((TextureAtlas.AtlasRegion)texture).splits[0];
splits[1] = ((TextureAtlas.AtlasRegion)texture).splits[1];
splits[2] = ((TextureAtlas.AtlasRegion)texture).splits[2];
splits[3] = ((TextureAtlas.AtlasRegion)texture).splits[3];
}
@Override
public void draw (Batch batch, float parentAlpha) {
Rectangle scissors = new Rectangle();
Rectangle clipBounds = new Rectangle(getX(),getY(),getWidth(),getHeight());
ScissorStack.calculateScissors(getStage().getCamera(), batch.getTransformMatrix(), clipBounds, scissors);
ScissorStack.pushScissors(scissors);
drawBg(batch, parentAlpha);
batch.draw(texture,
getX() + getWidth() / 2 - texture.getRegionWidth() / 2 + shift.x,
getY() + getHeight() / 2 - texture.getRegionHeight() / 2 + shift.y,
texture.getRegionWidth() / 2f,
texture.getRegionHeight() / 2f,
texture.getRegionWidth(), texture.getRegionHeight(),
currZoom, currZoom, 0);
drawSplits(batch, parentAlpha);
batch.flush();
ScissorStack.popScissors();
}
public void drawBg(Batch batch, float parentAlpha) {
batch.end();
Gdx.gl.glLineWidth(1.0f);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
shapeRenderer.setProjectionMatrix(getStage().getCamera().combined);
Matrix4 matrix = batch.getTransformMatrix();
shapeRenderer.setTransformMatrix(matrix);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
BG.a = parentAlpha;
shapeRenderer.setColor(BG);
shapeRenderer.rect(getX(), getY(), getWidth(), getHeight());
shapeRenderer.end();
Gdx.gl.glDisable(GL20.GL_BLEND);
batch.begin();
batch.setColor(Color.WHITE.r, Color.WHITE.g, Color.WHITE.b, Color.WHITE.a * parentAlpha);
}
public void drawSplits(Batch batch, float parentAlpha) {
batch.end();
Gdx.gl.glLineWidth(1.0f);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
shapeRenderer.setProjectionMatrix(getStage().getCamera().combined);
Matrix4 matrix = batch.getTransformMatrix();
shapeRenderer.setTransformMatrix(matrix);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
// left, right, top , bottom
Color guideColor = new Color(GUIDE_COLOR);
guideColor.a*=parentAlpha;
Color overColor = new Color(OVER_GUIDE_COLOR);
overColor.a*=parentAlpha;
splitPositions[0] = shift.x + getWidth() / 2f + (-texture.getRegionWidth() / 2f + splits[0]) * currZoom;
splitPositions[1] = shift.x + getWidth() / 2f + (texture.getRegionWidth() / 2f - splits[1]) * currZoom;
splitPositions[2] = shift.y + getHeight()/2f + (texture.getRegionHeight()/2 - splits[2])*currZoom;
splitPositions[3] = shift.y + getHeight() / 2f + (-texture.getRegionHeight() / 2 + splits[3]) * currZoom;
if(mouseOverSplit == 0) shapeRenderer.setColor(overColor); else shapeRenderer.setColor(guideColor);
shapeRenderer.line(getX() + splitPositions[0], getY(), getX() + splitPositions[0], getY() + getHeight());
if(mouseOverSplit == 1) shapeRenderer.setColor(overColor); else shapeRenderer.setColor(guideColor);
shapeRenderer.line(getX() + splitPositions[1], getY(), getX() + splitPositions[1], getY() + getHeight());
if(mouseOverSplit == 2) shapeRenderer.setColor(overColor); else shapeRenderer.setColor(guideColor);
shapeRenderer.line(getX(), getY() + splitPositions[2], getX() + getWidth(), getY() + splitPositions[2]);
if(mouseOverSplit == 3) shapeRenderer.setColor(overColor); else shapeRenderer.setColor(guideColor);
shapeRenderer.line(getX(), getY() + splitPositions[3], getX() + getWidth(), getY() + splitPositions[3]);
shapeRenderer.end();
Gdx.gl.glDisable(GL20.GL_BLEND);
batch.begin();
batch.setColor(Color.WHITE.r, Color.WHITE.g, Color.WHITE.b, Color.WHITE.a * parentAlpha);
}
public void zoomBy(int amount) {
float defaultSize = 1.0f - amount*0.12f;
currZoom*=defaultSize;
}
public void shiftBy(Vector2 diff) {
shift.add(diff);
}
public int splitCollision(float x, float y) {
Circle touchCircle = new Circle();
touchCircle.radius = 5f;
touchCircle.setPosition(x, y);
if(touchCircle.contains(splitPositions[0], touchCircle.y)) {
return 0;
}
if(touchCircle.contains(splitPositions[1], touchCircle.y)) {
return 1;
}
if(touchCircle.contains(touchCircle.x, splitPositions[2])) {
return 2;
}
if(touchCircle.contains(touchCircle.x, splitPositions[3])) {
return 3;
}
return -1;
}
}
@@ -0,0 +1,232 @@
package games.rednblack.editor.plugin.ninepatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
/**
* Created by various artists on 8/18/2015.
*/
public class ImageUtils {
private static final int NINEPATCH_PADDING = 1;
private static final String OUTPUT_TYPE = "png";
/** Returns the pads, or null if the image had no pads or the pads match the splits. Pads are an int[4] that has left, right,
* top, bottom. */
public int[] getPads (BufferedImage image, String name, int[] splits) {
WritableRaster raster = image.getRaster();
int bottom = raster.getHeight() - 1;
int right = raster.getWidth() - 1;
int startX = getSplitPoint(raster, name, 1, bottom, true, true);
int startY = getSplitPoint(raster, name, right, 1, true, false);
// No need to hunt for the end if a start was never found.
int endX = 0;
int endY = 0;
if (startX != 0) endX = getSplitPoint(raster, name, startX + 1, bottom, false, true);
if (startY != 0) endY = getSplitPoint(raster, name, right, startY + 1, false, false);
// Ensure pixels after the end are not invalid.
getSplitPoint(raster, name, endX + 1, bottom, true, true);
getSplitPoint(raster, name, right, endY + 1, true, false);
// No pads.
if (startX == 0 && endX == 0 && startY == 0 && endY == 0) {
return null;
}
// -2 here is because the coordinates were computed before the 1px border was stripped.
if (startX == 0 && endX == 0) {
startX = -1;
endX = -1;
} else {
if (startX > 0) {
startX--;
endX = raster.getWidth() - 2 - (endX - 1);
} else {
// If no start point was ever found, we assume full stretch.
endX = raster.getWidth() - 2;
}
}
if (startY == 0 && endY == 0) {
startY = -1;
endY = -1;
} else {
if (startY > 0) {
startY--;
endY = raster.getHeight() - 2 - (endY - 1);
} else {
// If no start point was ever found, we assume full stretch.
endY = raster.getHeight() - 2;
}
}
int[] pads = new int[] {startX, endX, startY, endY};
if (splits != null && Arrays.equals(pads, splits)) {
return null;
}
return pads;
}
/** Returns the splits, or null if the image had no splits or the splits were only a single region. Splits are an int[4] that
* has left, right, top, bottom. */
public int[] getSplits (BufferedImage image, String name) {
WritableRaster raster = image.getRaster();
int startX = getSplitPoint(raster, name, 1, 0, true, true);
int endX = getSplitPoint(raster, name, startX, 0, false, true);
int startY = getSplitPoint(raster, name, 0, 1, true, false);
int endY = getSplitPoint(raster, name, 0, startY, false, false);
// Ensure pixels after the end are not invalid.
getSplitPoint(raster, name, endX + 1, 0, true, true);
getSplitPoint(raster, name, 0, endY + 1, true, false);
// No splits, or all splits.
if (startX == 0 && endX == 0 && startY == 0 && endY == 0) return null;
// Subtraction here is because the coordinates were computed before the 1px border was stripped.
if (startX != 0) {
startX--;
endX = raster.getWidth() - 2 - (endX - 1);
} else {
// If no start point was ever found, we assume full stretch.
endX = raster.getWidth() - 2;
}
if (startY != 0) {
startY--;
endY = raster.getHeight() - 2 - (endY - 1);
} else {
// If no start point was ever found, we assume full stretch.
endY = raster.getHeight() - 2;
}
return new int[] {startX, endX, startY, endY};
}
/** Hunts for the start or end of a sequence of split pixels. Begins searching at (startX, startY) then follows along the x or y
* axis (depending on value of xAxis) for the first non-transparent pixel if startPoint is true, or the first transparent pixel
* if startPoint is false. Returns 0 if none found, as 0 is considered an invalid split point being in the outer border which
* will be stripped. */
static private int getSplitPoint (WritableRaster raster, String name, int startX, int startY, boolean startPoint, boolean xAxis) {
int[] rgba = new int[4];
int next = xAxis ? startX : startY;
int end = xAxis ? raster.getWidth() : raster.getHeight();
int breakA = startPoint ? 255 : 0;
int x = startX;
int y = startY;
while (next != end) {
if (xAxis)
x = next;
else
y = next;
raster.getPixel(x, y, rgba);
if (rgba[3] == breakA) return next;
if (!startPoint && (rgba[0] != 0 || rgba[1] != 0 || rgba[2] != 0 || rgba[3] != 255)) {
// error
}
next++;
}
return 0;
}
public BufferedImage extractImage(TextureAtlas.TextureAtlasData atlas, String regionName, int[] splits) {
for (TextureAtlas.TextureAtlasData.Region region : atlas.getRegions()) {
if(region.name.equals(regionName)) {
TextureAtlas.TextureAtlasData.Page page = region.page;
BufferedImage img = null;
try {
img = ImageIO.read(page.textureFile.file());
} catch (IOException e) {
}
region.splits = splits;
return extractNinePatch(img, region);
}
}
return null;
}
private BufferedImage extractImage (BufferedImage page, TextureAtlas.TextureAtlasData.Region region, int padding) {
BufferedImage splitImage = null;
// get the needed part of the page and rotate if needed
if (region.rotate) {
BufferedImage srcImage = page.getSubimage(region.left, region.top, region.height, region.width);
splitImage = new BufferedImage(region.width, region.height, page.getType());
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(90.0));
transform.translate(0, -region.width);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
op.filter(srcImage, splitImage);
} else {
splitImage = page.getSubimage(region.left, region.top, region.width, region.height);
}
// draw the image to a bigger one if padding is needed
if (padding > 0) {
BufferedImage paddedImage = new BufferedImage(splitImage.getWidth() + padding * 2, splitImage.getHeight() + padding * 2,
page.getType());
Graphics2D g2 = paddedImage.createGraphics();
g2.drawImage(splitImage, padding, padding, null);
g2.dispose();
return paddedImage;
} else {
return splitImage;
}
}
private BufferedImage extractNinePatch (BufferedImage page, TextureAtlas.TextureAtlasData.Region region) {
BufferedImage splitImage = extractImage(page, region, NINEPATCH_PADDING);
Graphics2D g2 = splitImage.createGraphics();
g2.setColor(Color.BLACK);
// Draw the four lines to save the ninepatch's padding and splits
int startX = region.splits[0] + NINEPATCH_PADDING;
int endX = region.width - region.splits[1] + NINEPATCH_PADDING - 1;
int startY = region.splits[2] + NINEPATCH_PADDING;
int endY = region.height - region.splits[3] + NINEPATCH_PADDING - 1;
if (endX >= startX) g2.drawLine(startX, 0, endX, 0);
if (endY >= startY) g2.drawLine(0, startY, 0, endY);
if (region.pads != null) {
int padStartX = region.pads[0] + NINEPATCH_PADDING;
int padEndX = region.width - region.pads[1] + NINEPATCH_PADDING - 1;
int padStartY = region.pads[2] + NINEPATCH_PADDING;
int padEndY = region.height - region.pads[3] + NINEPATCH_PADDING - 1;
g2.drawLine(padStartX, splitImage.getHeight() - 1, padEndX, splitImage.getHeight() - 1);
g2.drawLine(splitImage.getWidth() - 1, padStartY, splitImage.getWidth() - 1, padEndY);
}
g2.dispose();
return splitImage;
}
public void saveImage(BufferedImage image, String path) {
try {
ImageIO.write(image, OUTPUT_TYPE, new File(path));
} catch (IOException e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,113 @@
package games.rednblack.editor.plugin.ninepatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Align;
import com.kotcrab.vis.ui.widget.VisLabel;
import com.kotcrab.vis.ui.widget.VisTable;
import com.kotcrab.vis.ui.widget.VisTextButton;
import com.puremvc.patterns.facade.SimpleFacade;
import games.rednblack.h2d.common.H2DDialog;
/**
* Created by azakhary on 8/18/2015.
*/
public class MainPanel extends H2DDialog {
public static final String CLASS_NAME = "ames.rednblack.editor.plugin.ninepatch.MainPanel";
public static final String SAVE_CLICKED = CLASS_NAME + ".SAVE_CLICKED";
private SimpleFacade facade;
private VisTable mainTable;
private TextureRegion texture;
private VisTable editingTable;
private VisTable previewTable;
private EditingZone editingZone;
private PreviewWidget previewWidget;
public MainPanel() {
super("Nine Patch");
addCloseButton();
facade = SimpleFacade.getInstance();
mainTable = new VisTable();
add(mainTable).width(520).height(310).padBottom(7);
editingTable = new VisTable();
previewTable = new VisTable();
mainTable.add(editingTable).width(310).expandY();
mainTable.add(previewTable).expandX().expandY();
mainTable.row();
}
private void initView() {
editingTable.clear();
editingZone = new EditingZone();
editingZone.setTexture(texture);
editingTable.add(editingZone);
editingZone.setWidth(310);
editingZone.setHeight(310);
editingZone.setListener(new EditingZone.PatchChangeListener() {
@Override
public void changed(int[] splits) {
previewWidget.update((TextureAtlas.AtlasRegion) texture, splits);
}
});
}
private void initPreView() {
previewTable.clear();
previewWidget = new PreviewWidget();
previewWidget.setHeight(205);
previewTable.add(previewWidget).width(200).height(205).top();
previewTable.row();
previewWidget.update((TextureAtlas.AtlasRegion) texture, ((TextureAtlas.AtlasRegion) texture).splits);
VisLabel label = new VisLabel("Note: after saving, your \n scene will reload to \n apply changes.");
label.setAlignment(Align.center);
previewTable.add(label).pad(10).fillY().expandY();
previewTable.row();
VisTextButton saveBtn = new VisTextButton("apply and save");
previewTable.add(saveBtn).pad(5);
previewTable.row();
saveBtn.addListener(new ClickListener() {
public void clicked (InputEvent event, float x, float y) {
facade.sendNotification(SAVE_CLICKED);
}
});
}
public void setTexture(TextureRegion texture) {
this.texture = texture;
initView();
initPreView();
}
public void setListeners(Stage stage) {
stage.addListener(new InputListener() {
@Override
public boolean scrolled(InputEvent event, float x, float y, int amount) {
editingZone.zoomBy(amount);
return false;
}
});
}
public int[] getSplits() {
return editingZone.getSplits();
}
}
@@ -0,0 +1,155 @@
package games.rednblack.editor.plugin.ninepatch;
import com.badlogic.ashley.core.Entity;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.NinePatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.puremvc.patterns.mediator.SimpleMediator;
import com.puremvc.patterns.observer.Notification;
import games.rednblack.editor.renderer.components.MainItemComponent;
import games.rednblack.editor.renderer.components.NinePatchComponent;
import games.rednblack.editor.renderer.components.TextureRegionComponent;
import games.rednblack.editor.renderer.factory.EntityFactory;
import games.rednblack.editor.renderer.utils.ComponentRetriever;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* Created by azakhary on 8/18/2015.
*/
public class MainPanelMediator extends SimpleMediator<MainPanel> {
private static final String TAG = MainPanelMediator.class.getCanonicalName();
public static final String NAME = TAG;
private NinePatchPlugin plugin;
private ImageUtils imageUtils = new ImageUtils();
public MainPanelMediator(NinePatchPlugin plugin) {
super(NAME, new MainPanel());
this.plugin = plugin;
}
@Override
public String[] listNotificationInterests() {
return new String[]{
NinePatchPlugin.EDIT_NINE_PATCH,
NinePatchPlugin.CONVERT_TO_NINE_PATCH,
MainPanel.SAVE_CLICKED
};
}
@Override
public void handleNotification(Notification notification) {
super.handleNotification(notification);
switch (notification.getName()) {
case NinePatchPlugin.EDIT_NINE_PATCH:
loadNinePatch();
break;
case NinePatchPlugin.CONVERT_TO_NINE_PATCH:
convertImageToNinePatch();
loadNinePatch();
break;
case MainPanel.SAVE_CLICKED:
Entity entity = plugin.currEditingEntity;
NinePatchComponent ninePatchComponent = ComponentRetriever.get(entity, NinePatchComponent.class);
applyNewSplits(ninePatchComponent.textureRegionName, viewComponent.getSplits());
viewComponent.hide();
break;
}
}
private void convertImageToNinePatch() {
Entity entity = plugin.currEditingEntity;
MainItemComponent mainItemComponent = ComponentRetriever.get(entity, MainItemComponent.class);
mainItemComponent.entityType = EntityFactory.NINE_PATCH;
TextureRegionComponent textureRegionComponent = ComponentRetriever.get(entity, TextureRegionComponent.class);
String regionName = textureRegionComponent.regionName;
NinePatchComponent ninePatchComponent = new NinePatchComponent();
ninePatchComponent.textureRegionName = regionName;
TextureAtlas.AtlasRegion newRegion = (TextureAtlas.AtlasRegion) textureRegionComponent.region;
int[] splits = {0, 0, 0, 0};
newRegion.splits = splits;
ninePatchComponent.ninePatch = new NinePatch(textureRegionComponent.region, 0, 0, 0, 0);
entity.add(ninePatchComponent);
//remove original image
File originalImg = new File(plugin.getAPI().getProjectPath() + "/assets/orig/images/"+regionName+".png");
originalImg.delete();
//save project
plugin.getAPI().saveProject();
//save split data
addSplitsToImageInAtlas(regionName, splits);
applyNewSplits(regionName, splits);
}
private void loadNinePatch() {
Entity entity = plugin.currEditingEntity;
NinePatchComponent ninePatchComponent = ComponentRetriever.get(entity, NinePatchComponent.class);
loadRegion(ninePatchComponent.textureRegionName);
viewComponent.show(plugin.getAPI().getUIStage());
}
private void addSplitsToImageInAtlas(String textureRegionName, int[] splits) {
FileHandle packAtlas = Gdx.files.internal(plugin.getAPI().getProjectPath() + "/assets/orig/pack/pack.atlas");
String content = packAtlas.readString();
int regionIndex = content.indexOf(textureRegionName);
int splitEnd = content.indexOf("orig: ", regionIndex);
String splitStr = "split: "+splits[0]+", "+splits[1]+", "+splits[2]+", "+splits[3]+"\n ";
String newContent = content.substring(0, splitEnd) + splitStr + content.substring(splitEnd, content.length());
File test = new File(plugin.getAPI().getProjectPath() + "/assets/orig/pack/pack.atlas");
writeFile(newContent, test);
}
private void applyNewSplits(String textureRegionName, int[] splits) {
// first need to modify original image
FileHandle packAtlas = Gdx.files.internal(plugin.getAPI().getProjectPath() + "/assets/orig/pack/pack.atlas");
FileHandle imagesDir = Gdx.files.internal(plugin.getAPI().getProjectPath() + "/assets/orig/pack/");
TextureAtlas.TextureAtlasData atlas = new TextureAtlas.TextureAtlasData(packAtlas, imagesDir, false);
BufferedImage finalImage = imageUtils.extractImage(atlas, textureRegionName, splits);
imageUtils.saveImage(finalImage, plugin.getAPI().getProjectPath() + "/assets/orig/images/"+textureRegionName+".9.png");
// now need to modify the pack
String content = packAtlas.readString();
int regionIndex = content.indexOf(textureRegionName);
int splitStart = content.indexOf("split: ", regionIndex) + "split: ".length();
int splitEnd = content.indexOf("orig: ", splitStart);
String splitStr = splits[0]+", "+splits[1]+", "+splits[2]+", "+splits[3]+"\n ";
String newContent = content.substring(0, splitStart) + splitStr + content.substring(splitEnd, content.length());
File test = new File(plugin.getAPI().getProjectPath() + "/assets/orig/pack/pack.atlas");
writeFile(newContent, test);
// reload
plugin.getAPI().reLoadProject();
}
private void writeFile(String content, File file) {
BufferedWriter output = null;
try {
output = new BufferedWriter(new FileWriter(file));
output.write(content);
} catch ( IOException e ) {
e.printStackTrace();
} finally {
if ( output != null ) try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void loadRegion(String name) {
TextureAtlas atlas = plugin.getAPI().getProjectTextureAtlas();
viewComponent.setTexture(atlas.findRegion(name));
viewComponent.setListeners(plugin.getAPI().getUIStage());
}
}
@@ -0,0 +1,57 @@
package games.rednblack.editor.plugin.ninepatch;
import com.badlogic.ashley.core.Entity;
import com.badlogic.gdx.utils.Array;
import games.rednblack.editor.renderer.components.MainItemComponent;
import games.rednblack.editor.renderer.factory.EntityFactory;
import games.rednblack.editor.renderer.utils.ComponentRetriever;
import games.rednblack.h2d.common.plugins.H2DPluginAdapter;
import net.mountainblade.modular.annotations.Implementation;
import java.util.Set;
/**
* Created by azakhary on 8/18/2015.
* Plugin to edit Nine Patch data on imported texture region
*/
@Implementation(authors = "azakhary", version = "0.0.1")
public class NinePatchPlugin extends H2DPluginAdapter {
public static final String CLASS_NAME = "games.rednblack.editor.plugin.ninepatch.NinePatchPlugin";
public static final String EDIT_NINE_PATCH = CLASS_NAME + ".EDIT_NINE_PATCH";
public static final String CONVERT_TO_NINE_PATCH = CLASS_NAME + ".CONVERT_TO_NINE_PATCH";
private MainPanelMediator performancePanelMediator;
public Entity currEditingEntity;
public NinePatchPlugin() {
performancePanelMediator = new MainPanelMediator(this);
}
@Override
public void initPlugin() {
facade.registerMediator(performancePanelMediator);
pluginAPI.setDropDownItemName(EDIT_NINE_PATCH, "Edit NinePatch");
pluginAPI.setDropDownItemName(CONVERT_TO_NINE_PATCH, "Convert to NinePatch");
}
@Override
public void onDropDownOpen(Set<Entity> selectedEntities, Array<String> actionsSet) {
if(selectedEntities.size() == 1) {
Entity entity = selectedEntities.stream().findFirst().get();
MainItemComponent mainItemComponent = ComponentRetriever.get(entity, MainItemComponent.class);
if(mainItemComponent.entityType == EntityFactory.NINE_PATCH) {
// it's our guy
currEditingEntity = entity;
actionsSet.add(EDIT_NINE_PATCH);
}
if(mainItemComponent.entityType == EntityFactory.IMAGE_TYPE) {
// it's our guy
currEditingEntity = entity;
actionsSet.add(CONVERT_TO_NINE_PATCH);
}
}
}
}
@@ -0,0 +1,79 @@
package games.rednblack.editor.plugin.ninepatch;
import com.badlogic.gdx.graphics.g2d.NinePatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
/**
* Created by azakhary on 8/19/2015.
*/
public class PreviewWidget extends Group {
private TextureAtlas.AtlasRegion region;
float horizontalHeight, horizontalWidth;
float verticalHeight, verticalWidth;
float squareWidth, squareHeight;
private Image horizontal, vertical, square;
public PreviewWidget() {
horizontalWidth = 200f;
horizontalHeight = 50f;
verticalWidth = 50f;
verticalHeight = 150f;
squareWidth = 145f;
squareHeight = 150f;
}
public void update(TextureAtlas.AtlasRegion region, int[] splits) {
this.region = region;
clear();
NinePatch horizontalPatch = new NinePatch(region, splits[0], splits[1], splits[2], splits[3]);
NinePatch verticalPatch = new NinePatch(region, splits[0], splits[1], splits[2], splits[3]);
NinePatch squarePatch = new NinePatch(region, splits[0], splits[1], splits[2], splits[3]);
float minSclH = getMinScale(horizontalPatch, horizontalWidth, horizontalHeight);
float minSclV = getMinScale(verticalPatch, verticalWidth, verticalHeight);
float minSclS = getMinScale(squarePatch, squareWidth, squareHeight);
float minScl = Math.min(minSclH, minSclV);
minScl = Math.min(minScl, minSclS);
horizontal = fitNinePatch(horizontalPatch, horizontalWidth, horizontalHeight, minScl);
addActor(horizontal);
vertical = fitNinePatch(verticalPatch, verticalWidth, verticalHeight, minScl);
addActor(vertical);
square = fitNinePatch(squarePatch, squareWidth, squareHeight, minScl);
addActor(square);
horizontal.setY(getHeight() - horizontalHeight);
vertical.setY(horizontal.getY() - verticalHeight - 5);
square.setX(verticalWidth + 5);
square.setY(vertical.getY());
}
private float getMinScale(NinePatch horizontalPatch, float width, float height) {
float scaleX = width/horizontalPatch.getTotalWidth();
float scaleY = height/horizontalPatch.getTotalHeight();
float scl = Math.min(scaleX, scaleY);
if(scl > 1f) scl = 1f;
return scl;
}
private Image fitNinePatch(NinePatch horizontalPatch, float width, float height, float scl) {
horizontalPatch.scale(scl, scl);
Image img = new Image(horizontalPatch);
img.setScaleX(width / horizontalPatch.getTotalWidth());
img.setScaleY(height / horizontalPatch.getTotalHeight());
return img;
}
}