Clipboard export / Conditional jumps / Saving of state

This commit is contained in:
Anuken
2020-08-09 18:26:54 -04:00
parent 4efba475de
commit 73d9348c83
20 changed files with 172 additions and 35 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 841 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 776 B

After

Width:  |  Height:  |  Size: 776 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 KiB

After

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -1912,7 +1912,7 @@ public class Blocks implements ContentList{
logicDisplay = new LogicDisplay("logic-display"){{ logicDisplay = new LogicDisplay("logic-display"){{
requirements(Category.effect, with(Items.copper, 200, Items.lead, 120, Items.silicon, 100, Items.metaglass, 50)); requirements(Category.effect, with(Items.copper, 200, Items.lead, 120, Items.silicon, 100, Items.metaglass, 50));
displaySize = 64; displaySize = 80;
size = 3; size = 3;
}}; }};

View File

@ -7,6 +7,7 @@ public enum BinaryOp{
div("/", (a, b) -> a / b), div("/", (a, b) -> a / b),
mod("%", (a, b) -> a % b), mod("%", (a, b) -> a % b),
equal("==", (a, b) -> Math.abs(a - b) < 0.000001 ? 1 : 0), equal("==", (a, b) -> Math.abs(a - b) < 0.000001 ? 1 : 0),
notEqual("not", (a, b) -> Math.abs(a - b) < 0.000001 ? 0 : 1),
lessThan("<", (a, b) -> a < b ? 1 : 0), lessThan("<", (a, b) -> a < b ? 1 : 0),
lessThanEq("<=", (a, b) -> a <= b ? 1 : 0), lessThanEq("<=", (a, b) -> a <= b ? 1 : 0),
greaterThan(">", (a, b) -> a > b ? 1 : 0), greaterThan(">", (a, b) -> a > b ? 1 : 0),

View File

@ -0,0 +1,29 @@
package mindustry.logic;
public enum ConditionOp{
equal("==", (a, b) -> Math.abs(a - b) < 0.000001),
notEqual("not", (a, b) -> Math.abs(a - b) >= 0.000001),
lessThan("<", (a, b) -> a < b),
lessThanEq("<=", (a, b) -> a <= b),
greaterThan(">", (a, b) -> a > b),
greaterThanEq(">=", (a, b) -> a >= b);
public static final ConditionOp[] all = values();
public final CondOpLambda function;
public final String symbol;
ConditionOp(String symbol, CondOpLambda function){
this.symbol = symbol;
this.function = function;
}
@Override
public String toString(){
return symbol;
}
interface CondOpLambda{
boolean get(double a, double b);
}
}

View File

@ -102,19 +102,14 @@ public class LCanvas extends Table{
} }
void load(String asm){ void load(String asm){
statements.clearChildren(); Seq<LStatement> statements = LAssembler.read(asm);
try{ this.statements.clearChildren();
Seq<LStatement> statements = LAssembler.read(asm); for(LStatement st : statements){
for(LStatement st : statements){ add(st);
add(st); }
}
for(LStatement st : statements){ for(LStatement st : statements){
st.setupUI(); st.setupUI();
}
}catch(Exception e){
//ignore errors reading asm
e.printStackTrace();
} }
this.statements.layout(); this.statements.layout();
@ -272,6 +267,20 @@ public class LCanvas extends Table{
@Override @Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
if(button == KeyCode.mouseMiddle){
LStatement copy = st.copy();
if(copy != null){
StatementElem s = new StatementElem(copy);
statements.addChildAfter(StatementElem.this,s);
statements.layout();
copy.elem = s;
copy.setupUI();
}
return false;
}
Vec2 v = localToStageCoordinates(Tmp.v1.set(x, y)); Vec2 v = localToStageCoordinates(Tmp.v1.set(x, y));
lastx = v.x; lastx = v.x;
lasty = v.y; lasty = v.y;

View File

@ -373,19 +373,23 @@ public class LExecutor{
} }
public static class JumpI implements LInstruction{ public static class JumpI implements LInstruction{
public int cond, to; public ConditionOp op = ConditionOp.notEqual;
public int value, compare, address;
public JumpI(int cond, int to){ public JumpI(ConditionOp op, int value, int compare, int address){
this.cond = cond; this.op = op;
this.to = to; this.value = value;
this.compare = compare;
this.address = address;
} }
JumpI(){} public JumpI(){
}
@Override @Override
public void run(LExecutor exec){ public void run(LExecutor exec){
if(to != -1 && exec.bool(cond)){ if(address != -1 && op.function.get(exec.num(value), exec.num(compare))){
exec.vars[varCounter].numval = to; exec.vars[varCounter].numval = address;
} }
} }
} }

View File

@ -24,6 +24,13 @@ public abstract class LStatement{
public abstract LCategory category(); public abstract LCategory category();
public abstract LInstruction build(LAssembler builder); public abstract LInstruction build(LAssembler builder);
//TODO doesn't work with modded stuff
public LStatement copy(){
StringBuilder build = new StringBuilder();
write(build);
return LogicIO.read(build.toString().split(" "));
}
//protected methods are only for internal UI layout utilities //protected methods are only for internal UI layout utilities
protected Cell<TextField> field(Table table, String value, Cons<String> setter){ protected Cell<TextField> field(Table table, String value, Cons<String> setter){

View File

@ -458,21 +458,31 @@ public class LStatements{
public transient StatementElem dest; public transient StatementElem dest;
public int destIndex; public int destIndex;
public String condition = "true";
public ConditionOp op = ConditionOp.notEqual;
public String value = "x", compare = "false";
@Override @Override
public void build(Table table){ public void build(Table table){
table.add("if ").padLeft(6); table.add("if ").padLeft(4);
field(table, condition, str -> condition = str);
field(table, value, str -> value = str);
table.button(b -> {
b.label(() -> op.symbol);
b.clicked(() -> showSelect(b, ConditionOp.all, op, o -> op = o));
}, Styles.logict, () -> {}).size(48f, 40f).pad(4f).color(table.color);
field(table, compare, str -> compare = str);
table.add().growX(); table.add().growX();
table.add(new JumpButton(Color.white, () -> dest, s -> dest = s)).size(30).right().padRight(-17); table.add(new JumpButton(Color.white, () -> dest, s -> dest = s)).size(30).right().padLeft(-8);
} }
//elements need separate conversion logic //elements need separate conversion logic
@Override @Override
public void setupUI(){ public void setupUI(){
if(elem != null){ if(elem != null && destIndex > 0 && destIndex < elem.parent.getChildren().size){
dest = (StatementElem)elem.parent.getChildren().get(destIndex); dest = (StatementElem)elem.parent.getChildren().get(destIndex);
} }
} }
@ -486,7 +496,7 @@ public class LStatements{
@Override @Override
public LInstruction build(LAssembler builder){ public LInstruction build(LAssembler builder){
return new JumpI(builder.var(condition),destIndex); return new JumpI(op, builder.var(value), builder.var(compare), destIndex);
} }
@Override @Override

View File

@ -1,10 +1,16 @@
package mindustry.logic; package mindustry.logic;
import arc.*;
import arc.func.*; import arc.func.*;
import arc.scene.ui.TextButton.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.util.*; import arc.util.*;
import mindustry.gen.*;
import mindustry.ui.*;
import mindustry.ui.dialogs.*; import mindustry.ui.dialogs.*;
import static mindustry.Vars.*;
public class LogicDialog extends BaseDialog{ public class LogicDialog extends BaseDialog{
LCanvas canvas; LCanvas canvas;
Cons<String> consumer = s -> Log.info(s); Cons<String> consumer = s -> Log.info(s);
@ -17,6 +23,34 @@ public class LogicDialog extends BaseDialog{
canvas = new LCanvas(); canvas = new LCanvas();
addCloseButton(); addCloseButton();
buttons.button("@edit", Icon.edit, () -> {
BaseDialog dialog = new BaseDialog("@editor.export");
dialog.cont.pane(p -> {
p.margin(10f);
p.table(Tex.button, t -> {
TextButtonStyle style = Styles.cleart;
t.defaults().size(280f, 60f).left();
t.row();
t.button("@schematic.copy.import", Icon.download, style, () -> {
dialog.hide();
try{
canvas.load(Core.app.getClipboardText());
}catch(Throwable e){
ui.showException(e);
}
}).marginLeft(12f).disabled(b -> Core.app.getClipboardText() == null);
t.row();
t.button("@schematic.copy", Icon.copy, style, () -> {
dialog.hide();
Core.app.setClipboardText(canvas.save());
}).marginLeft(12f);
});
});
dialog.addCloseButton();
dialog.show();
});
stack(canvas, new Table(t -> { stack(canvas, new Table(t -> {
t.bottom(); t.bottom();
t.add(buttons); t.add(buttons);
@ -28,7 +62,12 @@ public class LogicDialog extends BaseDialog{
} }
public void show(String code, Cons<String> consumer){ public void show(String code, Cons<String> consumer){
canvas.load(code); try{
canvas.load(code);
}catch(Throwable t){
t.printStackTrace();
canvas.load("");
}
this.consumer = consumer; this.consumer = consumer;
show(); show();

View File

@ -1,6 +1,7 @@
package mindustry.world.blocks.logic; package mindustry.world.blocks.logic;
import arc.func.*; import arc.func.*;
import arc.math.geom.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
@ -30,7 +31,24 @@ public class LogicBlock extends Block{
update = true; update = true;
configurable = true; configurable = true;
config(String.class, (LogicEntity entity, String code) -> entity.updateCode(code)); config(String.class, (LogicEntity entity, String value) -> {
if(value.startsWith("{")){ //it's json
try{
LogicConfig conf = JsonIO.read(LogicConfig.class, value);
for(int i = 0; i < conf.connections.size; i++){
int pos = conf.connections.items[i];
conf.connections.items[i] = Point2.pack(Point2.x(pos) + entity.tileX(), Point2.y(pos) + entity.tileY());
}
entity.connections = conf.connections;
entity.updateCode(conf.code);
}catch(Exception e){
//malformed json
e.printStackTrace();
}
}else{ //it's (probably) asm or just garbage
entity.updateCode(value);
}
});
config(Integer.class, (LogicEntity entity, Integer pos) -> { config(Integer.class, (LogicEntity entity, Integer pos) -> {
if(entity.connections.contains(pos)){ if(entity.connections.contains(pos)){
@ -56,10 +74,10 @@ public class LogicBlock extends Block{
} }
public void updateCode(String str){ public void updateCode(String str){
updateCode(str, null); updateCodeVars(str, null);
} }
public void updateCode(String str, Cons<LAssembler> assemble){ public void updateCodeVars(String str, Cons<LAssembler> assemble){
if(str != null){ if(str != null){
code = str; code = str;
@ -113,7 +131,6 @@ public class LogicBlock extends Block{
@Override @Override
public void updateTile(){ public void updateTile(){
//remove invalid links //remove invalid links
//TODO remove variables
removal.clear(); removal.clear();
for(int i = 0; i < connections.size; i++){ for(int i = 0; i < connections.size; i++){
@ -143,7 +160,13 @@ public class LogicBlock extends Block{
@Override @Override
public String config(){ public String config(){
return code; //set connections to use relative coordinates, not absolute (TODO maybe just store them like this?)
IntSeq copy = new IntSeq(connections);
for(int i = 0; i < copy.size; i++){
int pos = copy.items[i];
copy.items[i] = Point2.pack(Point2.x(pos) - tileX(), Point2.y(pos) - tileY());
}
return JsonIO.write(new LogicConfig(code, copy));
} }
@Override @Override
@ -275,7 +298,7 @@ public class LogicBlock extends Block{
memorybank[i] = read.d(); memorybank[i] = read.d();
} }
updateCode(code, asm -> { updateCodeVars(code, asm -> {
//load up the variables that were stored //load up the variables that were stored
for(int i = 0; i < varcount; i++){ for(int i = 0; i < varcount; i++){
@ -289,4 +312,17 @@ public class LogicBlock extends Block{
executor.memory = memorybank; executor.memory = memorybank;
} }
} }
public static class LogicConfig{
public String code;
public IntSeq connections;
public LogicConfig(String code, IntSeq connections){
this.code = code;
this.connections = connections;
}
public LogicConfig(){
}
}
} }

View File

@ -22,6 +22,8 @@ public class LogicDisplay extends Block{
commandLinePoly = 7, commandLinePoly = 7,
commandFlush = 8; commandFlush = 8;
public int maxSides = 25;
public int displaySize = 64; public int displaySize = 64;
public LogicDisplay(String name){ public LogicDisplay(String name){
@ -70,8 +72,8 @@ public class LogicDisplay extends Block{
case commandLine: Lines.line(x, y, p1, p2); break; case commandLine: Lines.line(x, y, p1, p2); break;
case commandRect: Fill.crect(x, y, p1, p2); break; case commandRect: Fill.crect(x, y, p1, p2); break;
case commandLineRect: Lines.rect(x, y, p1, p2); break; case commandLineRect: Lines.rect(x, y, p1, p2); break;
case commandPoly: Fill.poly(x, y, p1, p2, p3); break; case commandPoly: Fill.poly(x, y, Math.min(p1, maxSides), p2, p3); break;
case commandLinePoly: Lines.poly(x, y, p1, p2, p3); break; case commandLinePoly: Lines.poly(x, y, Math.min(p1, maxSides), p2, p3); break;
case commandColor: this.color = Color.toFloatBits(x, y, p1, 255); Draw.color(this.color); break; case commandColor: this.color = Color.toFloatBits(x, y, p1, 255); Draw.color(this.color); break;
case commandStroke: this.stroke = x; Lines.stroke(x); break; case commandStroke: this.stroke = x; Lines.stroke(x); break;
} }