Added undoing for map editor
This commit is contained in:
@@ -1,38 +1,68 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
import com.badlogic.gdx.utils.IntSet;
|
||||
import io.anuke.mindustry.io.MapTileData;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
|
||||
import io.anuke.ucore.util.Bits;
|
||||
|
||||
public class DrawOperation implements Disposable{
|
||||
/**Data to apply operation to.*/
|
||||
MapTileData data;
|
||||
/**Format:
|
||||
* position (int)
|
||||
* packed data FROM (use TileDataMarker's read/write methods)
|
||||
* packed data TO (use TileDataMarker's read/write methods)
|
||||
*/
|
||||
ByteBuffer operation;
|
||||
//TileDataMarker writer = new TileDataMarker();
|
||||
private MapTileData data;
|
||||
/**List of per-tile operations that occurred.*/
|
||||
private Array<TileOperation> operations = new Array<>();
|
||||
/**Checks for duplicate operations, useful for brushes.*/
|
||||
private IntSet checks = new IntSet();
|
||||
|
||||
public DrawOperation(MapTileData data){
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void set(ByteBuffer operation) {
|
||||
this.operation = operation;
|
||||
public boolean isEmpty(){
|
||||
return operations.size == 0;
|
||||
}
|
||||
|
||||
public void undo() {
|
||||
//TODO implement
|
||||
public boolean checkDuplicate(short x, short y){
|
||||
int i = Bits.packInt(x, y);
|
||||
if(checks.contains(i)) return true;
|
||||
|
||||
checks.add(i);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void redo() {
|
||||
//TODO implement
|
||||
public void addOperation(TileOperation op){
|
||||
operations.add(op);
|
||||
}
|
||||
|
||||
public void undo(MapEditor editor) {
|
||||
for(int i = operations.size - 1; i >= 0; i --){
|
||||
TileOperation op = operations.get(i);
|
||||
data.write(op.x, op.y, op.from);
|
||||
editor.renderer().updatePoint(op.x, op.y);
|
||||
}
|
||||
}
|
||||
|
||||
public void redo(MapEditor editor) {
|
||||
for(TileOperation op : operations){
|
||||
data.write(op.x, op.y, op.to);
|
||||
editor.renderer().updatePoint(op.x, op.y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {}
|
||||
|
||||
public static class TileOperation{
|
||||
public short x, y;
|
||||
public TileDataMarker from;
|
||||
public TileDataMarker to;
|
||||
|
||||
public TileOperation(short x, short y, TileDataMarker from, TileDataMarker to) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public enum EditorTool{
|
||||
else
|
||||
writer.wall = (byte)editor.getDrawBlock().id;
|
||||
|
||||
editor.getMap().write(px, py, writer);
|
||||
editor.write(px, py, writer, false);
|
||||
editor.renderer().updatePoint(px, py);
|
||||
|
||||
if(px > 0 && !set.contains(asInt(px - 1, py, width))) points.add(asInt(px - 1, py, width));
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.content.blocks.Blocks;
|
||||
import io.anuke.mindustry.editor.DrawOperation.TileOperation;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.io.MapTileData;
|
||||
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
|
||||
@@ -111,7 +113,7 @@ public class MapEditor{
|
||||
writer.team = (byte)drawTeam.ordinal();
|
||||
writer.floor = floor;
|
||||
writer.link = Bits.packByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8));
|
||||
map.write(worldx, worldy, writer);
|
||||
write(worldx, worldy, writer, false);
|
||||
|
||||
renderer.updatePoint(worldx, worldy);
|
||||
}
|
||||
@@ -129,7 +131,7 @@ public class MapEditor{
|
||||
writer.team = (byte)drawTeam.ordinal();
|
||||
writer.rotation = 0;
|
||||
writer.link = 0;
|
||||
map.write(x, y, writer);
|
||||
write(x, y, writer, false);
|
||||
|
||||
renderer.updatePoint(x, y);
|
||||
}else{
|
||||
@@ -140,7 +142,7 @@ public class MapEditor{
|
||||
if (x + rx < 0 || y + ry < 0 || x + rx >= map.width() || y + ry >= map.height()) {
|
||||
continue;
|
||||
}
|
||||
map.write(x + rx, y + ry, writer);
|
||||
write(x + rx, y + ry, writer, true);
|
||||
renderer.updatePoint(x + rx, y + ry);
|
||||
}
|
||||
}
|
||||
@@ -163,7 +165,7 @@ public class MapEditor{
|
||||
marker.wall = 0;
|
||||
marker.rotation = 0;
|
||||
marker.team = 0;
|
||||
map.write(worldx, worldy, marker);
|
||||
write(worldx, worldy, marker, false);
|
||||
|
||||
if(worldx == x && worldy == y){
|
||||
renderer.updatePoint(worldx, worldy);
|
||||
@@ -173,6 +175,27 @@ public class MapEditor{
|
||||
}
|
||||
}
|
||||
|
||||
public void write(int x, int y, TileDataMarker writer, boolean checkDupes){
|
||||
boolean dupe = checkDupes && Vars.ui.editor.getView().checkForDuplicates((short) x, (short) y);
|
||||
TileDataMarker prev = null;
|
||||
|
||||
if(!dupe) {
|
||||
prev = map.new TileDataMarker();
|
||||
map.position(x, y);
|
||||
map.read(prev);
|
||||
}
|
||||
|
||||
map.write(x, y, writer);
|
||||
|
||||
if(!dupe) {
|
||||
TileDataMarker current = map.new TileDataMarker();
|
||||
map.position(x, y);
|
||||
map.read(current);
|
||||
|
||||
Vars.ui.editor.getView().addTileOp(new TileOperation((short) x, (short) y, prev, current));
|
||||
}
|
||||
}
|
||||
|
||||
public MapRenderer renderer() {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
@@ -420,6 +420,14 @@ public class MapEditorDialog extends Dialog{
|
||||
}
|
||||
}
|
||||
|
||||
if(Inputs.keyTap(Input.R)){
|
||||
editor.setDrawRotation((editor.getDrawRotation() + 1)%4);
|
||||
}
|
||||
|
||||
if(Inputs.keyTap(Input.E)){
|
||||
editor.setDrawRotation(Mathf.mod((editor.getDrawRotation() + 1), 4));
|
||||
}
|
||||
|
||||
//ctrl keys (undo, redo, save)
|
||||
if(UIUtils.ctrl()){
|
||||
if(Inputs.keyTap(Input.Z)){
|
||||
@@ -434,14 +442,6 @@ public class MapEditorDialog extends Dialog{
|
||||
saveDialog.save();
|
||||
}
|
||||
|
||||
if(Inputs.keyTap(Input.R)){
|
||||
editor.setDrawRotation((editor.getDrawRotation() + 1)%4);
|
||||
}
|
||||
|
||||
if(Inputs.keyTap(Input.E)){
|
||||
editor.setDrawRotation(Mathf.mod((editor.getDrawRotation() + 1), 4));
|
||||
}
|
||||
|
||||
if(Inputs.keyTap(Input.G)){
|
||||
view.setGrid(!view.isGrid());
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.editor.DrawOperation.TileOperation;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.ui.GridImage;
|
||||
import io.anuke.ucore.core.Core;
|
||||
@@ -77,16 +78,24 @@ public class MapView extends Element implements GestureListener{
|
||||
|
||||
public void undo(){
|
||||
if(stack.canUndo()){
|
||||
stack.undo();
|
||||
stack.undo(editor);
|
||||
}
|
||||
}
|
||||
|
||||
public void redo(){
|
||||
if(stack.canRedo()){
|
||||
stack.redo();
|
||||
stack.redo(editor);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTileOp(TileOperation t){
|
||||
op.addOperation(t);
|
||||
}
|
||||
|
||||
public boolean checkForDuplicates(short x, short y){
|
||||
return op.checkDuplicate(x, y);
|
||||
}
|
||||
|
||||
public MapView(MapEditor editor){
|
||||
this.editor = editor;
|
||||
|
||||
@@ -114,6 +123,8 @@ public class MapView extends Element implements GestureListener{
|
||||
return false;
|
||||
}
|
||||
|
||||
op = new DrawOperation(editor.getMap());
|
||||
|
||||
updated = false;
|
||||
|
||||
GridPoint2 p = project(x, y);
|
||||
@@ -146,6 +157,14 @@ public class MapView extends Element implements GestureListener{
|
||||
}
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if(op != null && updated){
|
||||
if(!op.isEmpty()){
|
||||
stack.add(op);
|
||||
}
|
||||
op = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,18 +37,18 @@ public class OperationStack{
|
||||
return !(index > -1 || stack.size + index < 0);
|
||||
}
|
||||
|
||||
public void undo(){
|
||||
public void undo(MapEditor editor){
|
||||
if(!canUndo()) return;
|
||||
|
||||
stack.get(stack.size - 1 + index).undo();
|
||||
stack.get(stack.size - 1 + index).undo(editor);
|
||||
index --;
|
||||
}
|
||||
|
||||
public void redo(){
|
||||
public void redo(MapEditor editor){
|
||||
if(!canRedo()) return;
|
||||
|
||||
index ++;
|
||||
stack.get(stack.size - 1 + index).redo();
|
||||
stack.get(stack.size - 1 + index).redo(editor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,12 @@ public class MapTileData {
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**Reads and returns the next tile data.*/
|
||||
public TileDataMarker read(TileDataMarker marker){
|
||||
marker.read(buffer);
|
||||
return marker;
|
||||
}
|
||||
|
||||
/**Reads and returns the next tile data.*/
|
||||
public TileDataMarker readAt(int x, int y){
|
||||
position(x, y);
|
||||
|
||||
Reference in New Issue
Block a user