Added undoing for map editor

This commit is contained in:
Anuken
2018-05-22 00:02:43 -04:00
parent 2d65c9734c
commit d97a585eba
7 changed files with 113 additions and 35 deletions

View File

@@ -1,38 +1,68 @@
package io.anuke.mindustry.editor; package io.anuke.mindustry.editor;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable; import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.IntSet;
import io.anuke.mindustry.io.MapTileData; import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
import java.nio.ByteBuffer; import io.anuke.ucore.util.Bits;
public class DrawOperation implements Disposable{ public class DrawOperation implements Disposable{
/**Data to apply operation to.*/ /**Data to apply operation to.*/
MapTileData data; private MapTileData data;
/**Format: /**List of per-tile operations that occurred.*/
* position (int) private Array<TileOperation> operations = new Array<>();
* packed data FROM (use TileDataMarker's read/write methods) /**Checks for duplicate operations, useful for brushes.*/
* packed data TO (use TileDataMarker's read/write methods) private IntSet checks = new IntSet();
*/
ByteBuffer operation;
//TileDataMarker writer = new TileDataMarker();
public DrawOperation(MapTileData data){ public DrawOperation(MapTileData data){
this.data = data; this.data = data;
} }
public void set(ByteBuffer operation) { public boolean isEmpty(){
this.operation = operation; return operations.size == 0;
} }
public void undo() { public boolean checkDuplicate(short x, short y){
//TODO implement int i = Bits.packInt(x, y);
if(checks.contains(i)) return true;
checks.add(i);
return false;
} }
public void redo() { public void addOperation(TileOperation op){
//TODO implement 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 @Override
public void dispose() {} 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;
}
}
} }

View File

@@ -67,7 +67,7 @@ public enum EditorTool{
else else
writer.wall = (byte)editor.getDrawBlock().id; writer.wall = (byte)editor.getDrawBlock().id;
editor.getMap().write(px, py, writer); editor.write(px, py, writer, false);
editor.renderer().updatePoint(px, py); editor.renderer().updatePoint(px, py);
if(px > 0 && !set.contains(asInt(px - 1, py, width))) points.add(asInt(px - 1, py, width)); if(px > 0 && !set.contains(asInt(px - 1, py, width))) points.add(asInt(px - 1, py, width));

View File

@@ -1,6 +1,8 @@
package io.anuke.mindustry.editor; package io.anuke.mindustry.editor;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.editor.DrawOperation.TileOperation;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.io.MapTileData; import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.TileDataMarker; import io.anuke.mindustry.io.MapTileData.TileDataMarker;
@@ -111,7 +113,7 @@ public class MapEditor{
writer.team = (byte)drawTeam.ordinal(); writer.team = (byte)drawTeam.ordinal();
writer.floor = floor; writer.floor = floor;
writer.link = Bits.packByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8)); 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); renderer.updatePoint(worldx, worldy);
} }
@@ -129,7 +131,7 @@ public class MapEditor{
writer.team = (byte)drawTeam.ordinal(); writer.team = (byte)drawTeam.ordinal();
writer.rotation = 0; writer.rotation = 0;
writer.link = 0; writer.link = 0;
map.write(x, y, writer); write(x, y, writer, false);
renderer.updatePoint(x, y); renderer.updatePoint(x, y);
}else{ }else{
@@ -140,7 +142,7 @@ public class MapEditor{
if (x + rx < 0 || y + ry < 0 || x + rx >= map.width() || y + ry >= map.height()) { if (x + rx < 0 || y + ry < 0 || x + rx >= map.width() || y + ry >= map.height()) {
continue; continue;
} }
map.write(x + rx, y + ry, writer); write(x + rx, y + ry, writer, true);
renderer.updatePoint(x + rx, y + ry); renderer.updatePoint(x + rx, y + ry);
} }
} }
@@ -163,7 +165,7 @@ public class MapEditor{
marker.wall = 0; marker.wall = 0;
marker.rotation = 0; marker.rotation = 0;
marker.team = 0; marker.team = 0;
map.write(worldx, worldy, marker); write(worldx, worldy, marker, false);
if(worldx == x && worldy == y){ if(worldx == x && worldy == y){
renderer.updatePoint(worldx, worldy); 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() { public MapRenderer renderer() {
return renderer; return renderer;
} }

View File

@@ -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) //ctrl keys (undo, redo, save)
if(UIUtils.ctrl()){ if(UIUtils.ctrl()){
if(Inputs.keyTap(Input.Z)){ if(Inputs.keyTap(Input.Z)){
@@ -434,14 +442,6 @@ public class MapEditorDialog extends Dialog{
saveDialog.save(); 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)){ if(Inputs.keyTap(Input.G)){
view.setGrid(!view.isGrid()); view.setGrid(!view.isGrid());
} }

View File

@@ -10,6 +10,7 @@ import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack; import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.editor.DrawOperation.TileOperation;
import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.ui.GridImage; import io.anuke.mindustry.ui.GridImage;
import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Core;
@@ -77,16 +78,24 @@ public class MapView extends Element implements GestureListener{
public void undo(){ public void undo(){
if(stack.canUndo()){ if(stack.canUndo()){
stack.undo(); stack.undo(editor);
} }
} }
public void redo(){ public void redo(){
if(stack.canRedo()){ 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){ public MapView(MapEditor editor){
this.editor = editor; this.editor = editor;
@@ -114,6 +123,8 @@ public class MapView extends Element implements GestureListener{
return false; return false;
} }
op = new DrawOperation(editor.getMap());
updated = false; updated = false;
GridPoint2 p = project(x, y); GridPoint2 p = project(x, y);
@@ -146,6 +157,14 @@ public class MapView extends Element implements GestureListener{
} }
updated = true; updated = true;
} }
if(op != null && updated){
if(!op.isEmpty()){
stack.add(op);
}
op = null;
}
} }
@Override @Override

View File

@@ -37,18 +37,18 @@ public class OperationStack{
return !(index > -1 || stack.size + index < 0); return !(index > -1 || stack.size + index < 0);
} }
public void undo(){ public void undo(MapEditor editor){
if(!canUndo()) return; if(!canUndo()) return;
stack.get(stack.size - 1 + index).undo(); stack.get(stack.size - 1 + index).undo(editor);
index --; index --;
} }
public void redo(){ public void redo(MapEditor editor){
if(!canRedo()) return; if(!canRedo()) return;
index ++; index ++;
stack.get(stack.size - 1 + index).redo(); stack.get(stack.size - 1 + index).redo(editor);
} }
} }

View File

@@ -68,6 +68,12 @@ public class MapTileData {
return tile; 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.*/ /**Reads and returns the next tile data.*/
public TileDataMarker readAt(int x, int y){ public TileDataMarker readAt(int x, int y){
position(x, y); position(x, y);