Clipboard export / Conditional jumps / Saving of state
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 841 B |
Before Width: | Height: | Size: 776 B After Width: | Height: | Size: 776 B |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 184 KiB |
Before Width: | Height: | Size: 386 KiB After Width: | Height: | Size: 385 KiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.8 MiB |
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 185 KiB |
Before Width: | Height: | Size: 391 KiB After Width: | Height: | Size: 391 KiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
@ -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;
|
||||||
}};
|
}};
|
||||||
|
@ -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),
|
||||||
|
29
core/src/mindustry/logic/ConditionOp.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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){
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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(){
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|