More logic
This commit is contained in:
@@ -1,79 +0,0 @@
|
|||||||
package mindustry.annotations.misc;
|
|
||||||
|
|
||||||
import arc.struct.*;
|
|
||||||
import arc.util.*;
|
|
||||||
import com.squareup.javapoet.*;
|
|
||||||
import mindustry.annotations.Annotations.*;
|
|
||||||
import mindustry.annotations.*;
|
|
||||||
import mindustry.annotations.util.*;
|
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
|
||||||
import javax.lang.model.element.*;
|
|
||||||
import javax.lang.model.type.*;
|
|
||||||
|
|
||||||
@SupportedAnnotationTypes("mindustry.annotations.Annotations.Slot")
|
|
||||||
public class NodeSlotProcessor extends BaseProcessor{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(RoundEnvironment env) throws Exception{
|
|
||||||
TypeSpec.Builder slotClass = TypeSpec.classBuilder("LogicSlotMap")
|
|
||||||
.addModifiers(Modifier.PUBLIC);
|
|
||||||
|
|
||||||
ObjectMap<Stype, Seq<String>> fields = new ObjectMap<>();
|
|
||||||
for(Svar var : fields(Slot.class)){
|
|
||||||
String type = var.mirror().toString();
|
|
||||||
|
|
||||||
boolean overrideInput = var.annotation(Slot.class).input();
|
|
||||||
boolean output = (type.contains("SetObj") || type.contains("SetNum") || type.contains("Runnable")) && !overrideInput;
|
|
||||||
|
|
||||||
String objType = output ?
|
|
||||||
type.contains("SetNum") ? "double" :
|
|
||||||
type.contains("SetObj") ? ((DeclaredType)var.mirror()).getTypeArguments().get(0).toString() :
|
|
||||||
type : type;
|
|
||||||
|
|
||||||
String dataType = objType.equals("double") ? "number" :
|
|
||||||
objType.contains("Content") ? "content" :
|
|
||||||
objType.equals("mindustry.gen.Building") ? "building" :
|
|
||||||
objType.equals("mindustry.gen.Unit") ? "unit" :
|
|
||||||
objType.equals("java.lang.Void") || objType.equals("java.lang.Runnable") ? "control" :
|
|
||||||
objType.equals("java.lang.String") ? "string" :
|
|
||||||
"<<invalid>>";
|
|
||||||
|
|
||||||
if(dataType.equals("<<invalid>>")) err("Unknown logic node type: " + objType, var);
|
|
||||||
|
|
||||||
boolean numeric = dataType.equals("number");
|
|
||||||
|
|
||||||
String name = Strings.capitalize(var.name());
|
|
||||||
|
|
||||||
String lambda = output ?
|
|
||||||
"(" + var.enclosingType() + " node, " + objType + " val__) -> node." + var.name() + (objType.contains("Runnable") ? ".run()" : ".set(val__)") :
|
|
||||||
"(" + var.enclosingType() + " node, " + objType + " val__) -> node." + var.name() + " = val__";
|
|
||||||
|
|
||||||
//NodeSlot(String name, boolean input, DataType type, NumOutput<N> numOutput, ObjOutput<N, T> setObject)
|
|
||||||
String constructed = Strings.format(
|
|
||||||
"new mindustry.logic.LogicNode.NodeSlot(\"@\", @, mindustry.logic.LogicNode.DataType.@, @, @)",
|
|
||||||
name,
|
|
||||||
!output,
|
|
||||||
dataType,
|
|
||||||
numeric ? lambda : "null",
|
|
||||||
!numeric ? lambda : "null"
|
|
||||||
);
|
|
||||||
|
|
||||||
fields.get(var.enclosingType(), Seq::new).add(constructed);
|
|
||||||
}
|
|
||||||
|
|
||||||
slotClass.addField(FieldSpec.builder(
|
|
||||||
ParameterizedTypeName.get(ClassName.get(ObjectMap.class),
|
|
||||||
TypeName.get(Class.class),
|
|
||||||
TypeName.OBJECT), //screw type safety, I don't care anymore
|
|
||||||
"map", Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC).initializer("new ObjectMap<>()").build());
|
|
||||||
|
|
||||||
|
|
||||||
CodeBlock.Builder code = CodeBlock.builder();
|
|
||||||
fields.each((type, inits) -> code.addStatement("map.put($L.class, new mindustry.logic.LogicNode.NodeSlot[]{$L})", type.toString(), inits.toString(",")));
|
|
||||||
|
|
||||||
slotClass.addStaticBlock(code.build());
|
|
||||||
|
|
||||||
write(slotClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1502,7 +1502,7 @@ public class Blocks implements ContentList{
|
|||||||
health = 160 * size * size;
|
health = 160 * size * size;
|
||||||
rotateSpeed = 10;
|
rotateSpeed = 10;
|
||||||
|
|
||||||
consumes.power(3f);
|
consumes.powerCond(3f, (TractorBeamEntity e) -> e.target != null);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
swarmer = new ItemTurret("swarmer"){{
|
swarmer = new ItemTurret("swarmer"){{
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import mindustry.editor.*;
|
|||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.logic2.LDialog;
|
import mindustry.logic.LDialog;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
import mindustry.ui.dialogs.*;
|
import mindustry.ui.dialogs.*;
|
||||||
import mindustry.ui.fragments.*;
|
import mindustry.ui.fragments.*;
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
transient boolean updateFlow;
|
transient boolean updateFlow;
|
||||||
transient byte dump;
|
transient byte dump;
|
||||||
transient int rotation;
|
transient int rotation;
|
||||||
|
transient boolean enabled = true;
|
||||||
|
|
||||||
PowerModule power;
|
PowerModule power;
|
||||||
ItemModule items;
|
ItemModule items;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public enum BinaryOp{
|
|||||||
mul("*", (a, b) -> a * b),
|
mul("*", (a, b) -> a * b),
|
||||||
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),
|
||||||
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),
|
||||||
@@ -16,7 +16,9 @@ public enum BinaryOp{
|
|||||||
shr("<<", (a, b) -> (int)a << (int)b),
|
shr("<<", (a, b) -> (int)a << (int)b),
|
||||||
or("or", (a, b) -> (int)a | (int)b),
|
or("or", (a, b) -> (int)a | (int)b),
|
||||||
and("and", (a, b) -> (int)a & (int)b),
|
and("and", (a, b) -> (int)a & (int)b),
|
||||||
xor("xor", (a, b) -> (int)a ^ (int)b);
|
xor("xor", (a, b) -> (int)a ^ (int)b),
|
||||||
|
max("max", Math::max),
|
||||||
|
min("min", Math::min);
|
||||||
|
|
||||||
public static final BinaryOp[] all = values();
|
public static final BinaryOp[] all = values();
|
||||||
|
|
||||||
|
|||||||
24
core/src/mindustry/logic/DataType.java
Normal file
24
core/src/mindustry/logic/DataType.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package mindustry.logic;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
|
||||||
|
/** The types of data a node field can be. */
|
||||||
|
public enum DataType{
|
||||||
|
/** A double. Used for integer calculations as well. */
|
||||||
|
number(Pal.place),
|
||||||
|
/** Any type of content, e.g. item. */
|
||||||
|
content(Color.cyan),
|
||||||
|
/** A building of a tile. */
|
||||||
|
building(Pal.items),
|
||||||
|
/** A unit on the map. */
|
||||||
|
unit(Pal.health),
|
||||||
|
/** Java string */
|
||||||
|
string(Color.royal);
|
||||||
|
|
||||||
|
public final Color color;
|
||||||
|
|
||||||
|
DataType(Color color){
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
49
core/src/mindustry/logic/LBuilder.java
Normal file
49
core/src/mindustry/logic/LBuilder.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package mindustry.logic;
|
||||||
|
|
||||||
|
import arc.struct.*;
|
||||||
|
|
||||||
|
/** "Compiles" a sequence of statements into instructions. */
|
||||||
|
public class LBuilder{
|
||||||
|
private int lastVar;
|
||||||
|
/** Maps names to variable IDs. */
|
||||||
|
private ObjectIntMap<String> vars = new ObjectIntMap<>();
|
||||||
|
/** Maps variable IDs to their constant value. */
|
||||||
|
private IntMap<Object> constants = new IntMap<>();
|
||||||
|
|
||||||
|
public LBuilder(){
|
||||||
|
//add default constant variables
|
||||||
|
putConst("false", 0);
|
||||||
|
putConst("true", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return a variable ID by name.
|
||||||
|
* This may be a constant variable referring to a number or object. */
|
||||||
|
public int var(String symbol){
|
||||||
|
try{
|
||||||
|
double value = Double.parseDouble(symbol);
|
||||||
|
//this creates a hidden const variable with the specified value
|
||||||
|
String key = "___" + value;
|
||||||
|
return putConst(key, value);
|
||||||
|
}catch(NumberFormatException e){
|
||||||
|
return putVar(symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a constant value by name. */
|
||||||
|
private int putConst(String name, double value){
|
||||||
|
int id = putVar(name);
|
||||||
|
constants.put(id, value);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Registers a variable name mapping. */
|
||||||
|
private int putVar(String name){
|
||||||
|
if(vars.containsKey(name)){
|
||||||
|
return vars.get(name);
|
||||||
|
}else{
|
||||||
|
int id = lastVar++;
|
||||||
|
vars.put(name, id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
348
core/src/mindustry/logic/LCanvas.java
Normal file
348
core/src/mindustry/logic/LCanvas.java
Normal file
@@ -0,0 +1,348 @@
|
|||||||
|
package mindustry.logic;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.func.*;
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.input.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.scene.*;
|
||||||
|
import arc.scene.event.*;
|
||||||
|
import arc.scene.ui.*;
|
||||||
|
import arc.scene.ui.layout.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.logic.LStatements.*;
|
||||||
|
import mindustry.ui.*;
|
||||||
|
|
||||||
|
public class LCanvas extends Table{
|
||||||
|
private static final Color backgroundCol = Pal.darkMetal.cpy().mul(0.1f), gridCol = Pal.darkMetal.cpy().mul(0.5f);
|
||||||
|
private Vec2 offset = new Vec2();
|
||||||
|
|
||||||
|
private DragLayout statements;
|
||||||
|
private StatementElem dragging;
|
||||||
|
|
||||||
|
public LCanvas(){
|
||||||
|
//left();
|
||||||
|
|
||||||
|
statements = new DragLayout();
|
||||||
|
|
||||||
|
pane(statements).grow().get().setClip(false);
|
||||||
|
|
||||||
|
add(new LStatements.AssignStatement());
|
||||||
|
add(new FetchBuildStatement());
|
||||||
|
add(new JumpStatement());
|
||||||
|
add(new ToggleStatement());
|
||||||
|
add(new LStatements.OpStatement());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawGrid(){
|
||||||
|
Draw.color(backgroundCol);
|
||||||
|
|
||||||
|
Fill.crect(x, y, width, height);
|
||||||
|
|
||||||
|
Draw.color(gridCol);
|
||||||
|
|
||||||
|
float spacing = Scl.scl(50f);
|
||||||
|
int xbars = (int)(width / spacing) + 2, ybars = (int)(width / spacing) + 2;
|
||||||
|
float ox = offset.x % spacing, oy = offset.y % spacing;
|
||||||
|
|
||||||
|
Lines.stroke(Scl.scl(3f));
|
||||||
|
|
||||||
|
for(int i = 0; i < xbars; i++){
|
||||||
|
float cx = x + width/2f + (i - xbars/2) * spacing + ox;
|
||||||
|
Lines.line(cx, y, cx, y + height);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < ybars; i++){
|
||||||
|
float cy = y + height/2f + (i - ybars/2) * spacing + oy;
|
||||||
|
Lines.line(0, cy, x + width, cy);
|
||||||
|
}
|
||||||
|
|
||||||
|
Draw.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(LStatement statement){
|
||||||
|
StatementElem e = new StatementElem(statement);
|
||||||
|
|
||||||
|
statements.addChild(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DragLayout extends WidgetGroup{
|
||||||
|
float margin = 4f;
|
||||||
|
float space = 10f, width = 400f;
|
||||||
|
Seq<Element> seq = new Seq<>();
|
||||||
|
int insertPosition = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void layout(){
|
||||||
|
float cy = 0;
|
||||||
|
seq.clear();
|
||||||
|
|
||||||
|
//layout everything normally
|
||||||
|
for(int i = 0; i < getChildren().size; i++){
|
||||||
|
Element e = getChildren().get(i);
|
||||||
|
|
||||||
|
//ignore the dragged element
|
||||||
|
if(dragging == e) continue;
|
||||||
|
|
||||||
|
e.setSize(width - margin * 2f, e.getPrefHeight());
|
||||||
|
e.setPosition(x + margin, height + y - margin - cy, Align.topLeft);
|
||||||
|
|
||||||
|
cy += e.getPrefHeight() + space;
|
||||||
|
seq.add(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//insert the dragged element if necessary
|
||||||
|
if(dragging != null){
|
||||||
|
//find real position of dragged element top
|
||||||
|
float realY = dragging.getY(Align.top) + dragging.translation.y;
|
||||||
|
|
||||||
|
insertPosition = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < seq.size; i++){
|
||||||
|
Element cur = seq.get(i);
|
||||||
|
//find fit point
|
||||||
|
if(realY < cur.y && (i == seq.size - 1 || realY > seq.get(i + 1).y)){
|
||||||
|
insertPosition = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float shiftAmount = dragging.getHeight() + space;
|
||||||
|
|
||||||
|
//shift elements below insertion point down
|
||||||
|
for(int i = insertPosition; i < seq.size; i++){
|
||||||
|
seq.get(i).y -= shiftAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
|
||||||
|
//draw selection box indicating placement position
|
||||||
|
if(dragging != null && insertPosition <= seq.size){
|
||||||
|
float shiftAmount = dragging.getHeight();
|
||||||
|
float lastX = x + margin;
|
||||||
|
float lastY = insertPosition == 0 ? height + y - margin : seq.get(insertPosition - 1).y - space;
|
||||||
|
|
||||||
|
Tex.pane.draw(lastX, lastY - shiftAmount, width - margin*2f, dragging.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
super.draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void finishLayout(){
|
||||||
|
if(dragging != null){
|
||||||
|
//reset translation first
|
||||||
|
for(Element child : getChildren()){
|
||||||
|
child.setTranslation(0, 0);
|
||||||
|
}
|
||||||
|
clearChildren();
|
||||||
|
|
||||||
|
//reorder things
|
||||||
|
for(int i = 0; i <= insertPosition - 1 && i < seq.size; i++){
|
||||||
|
addChild(seq.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
addChild(dragging);
|
||||||
|
|
||||||
|
for(int i = insertPosition; i < seq.size; i++){
|
||||||
|
addChild(seq.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
dragging = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StatementElem extends Table{
|
||||||
|
LStatement st;
|
||||||
|
|
||||||
|
public StatementElem(LStatement st){
|
||||||
|
this.st = st;
|
||||||
|
|
||||||
|
background(Tex.whitePane);
|
||||||
|
setColor(st.category().color);
|
||||||
|
margin(0f);
|
||||||
|
touchable = Touchable.enabled;
|
||||||
|
|
||||||
|
table(Tex.whiteui, t -> {
|
||||||
|
t.color.set(color);
|
||||||
|
t.addListener(new HandCursorListener());
|
||||||
|
|
||||||
|
t.margin(6f);
|
||||||
|
t.touchable = Touchable.enabled;
|
||||||
|
|
||||||
|
t.add(st.name()).style(Styles.outlineLabel).color(color).padRight(8);
|
||||||
|
t.add().growX();
|
||||||
|
t.button(Icon.cancel, Styles.onlyi, () -> {
|
||||||
|
remove();
|
||||||
|
dragging = null;
|
||||||
|
statements.layout();
|
||||||
|
});
|
||||||
|
|
||||||
|
t.addListener(new InputListener(){
|
||||||
|
float lastx, lasty;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
|
||||||
|
Vec2 v = localToStageCoordinates(Tmp.v1.set(x, y));
|
||||||
|
lastx = v.x;
|
||||||
|
lasty = v.y;
|
||||||
|
dragging = StatementElem.this;
|
||||||
|
toFront();
|
||||||
|
statements.layout();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void touchDragged(InputEvent event, float x, float y, int pointer){
|
||||||
|
Vec2 v = localToStageCoordinates(Tmp.v1.set(x, y));
|
||||||
|
|
||||||
|
translation.add(v.x - lastx, v.y - lasty);
|
||||||
|
lastx = v.x;
|
||||||
|
lasty = v.y;
|
||||||
|
|
||||||
|
statements.layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){
|
||||||
|
statements.finishLayout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).growX();
|
||||||
|
|
||||||
|
row();
|
||||||
|
|
||||||
|
table(t -> {
|
||||||
|
t.left();
|
||||||
|
t.marginLeft(4);
|
||||||
|
t.setColor(color);
|
||||||
|
st.build(t);
|
||||||
|
}).pad(4).padTop(2).left().grow();
|
||||||
|
|
||||||
|
marginBottom(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
float pad = 5f;
|
||||||
|
Fill.dropShadow(x + width/2f, y + height/2f, width + pad, height + pad, 10f, 0.9f);
|
||||||
|
|
||||||
|
Draw.color(0, 0, 0, 0.3f);
|
||||||
|
Fill.crect(x, y, width, height);
|
||||||
|
Draw.reset();
|
||||||
|
|
||||||
|
super.draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class JumpButton extends ImageButton{
|
||||||
|
StatementElem to;
|
||||||
|
boolean selecting;
|
||||||
|
float mx, my;
|
||||||
|
|
||||||
|
public JumpButton(Color color, Cons<StatementElem> setter){
|
||||||
|
super(Tex.logicNode, Styles.colori);
|
||||||
|
|
||||||
|
getStyle().imageUpColor = color;
|
||||||
|
|
||||||
|
addListener(new InputListener(){
|
||||||
|
@Override
|
||||||
|
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode code){
|
||||||
|
selecting = true;
|
||||||
|
setter.get(to = null);
|
||||||
|
mx = x;
|
||||||
|
my = y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void touchDragged(InputEvent event, float x, float y, int pointer){
|
||||||
|
mx = x;
|
||||||
|
my = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode code){
|
||||||
|
localToStageCoordinates(Tmp.v1.set(x, y));
|
||||||
|
StatementElem elem = hovered();
|
||||||
|
|
||||||
|
if(elem != null && !isDescendantOf(elem)){
|
||||||
|
to = elem;
|
||||||
|
}else{
|
||||||
|
to = null;
|
||||||
|
}
|
||||||
|
setter.get(to);
|
||||||
|
selecting = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
update(() -> {
|
||||||
|
if(to != null && to.parent == null){
|
||||||
|
setter.get(to = null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
super.draw();
|
||||||
|
Element hover = to == null && selecting ? hovered() : to;
|
||||||
|
float tx = 0, ty = 0;
|
||||||
|
boolean draw = false;
|
||||||
|
|
||||||
|
if(hover != null){
|
||||||
|
tx = hover.getX(Align.right) + hover.translation.x;
|
||||||
|
ty = hover.getY(Align.right) + hover.translation.y;
|
||||||
|
draw = true;
|
||||||
|
}else if(selecting){
|
||||||
|
tx = x + mx;
|
||||||
|
ty = y + my;
|
||||||
|
draw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(draw){
|
||||||
|
drawCurve(x + width/2f, y + height/2f, tx, ty, color);
|
||||||
|
|
||||||
|
float s = width;
|
||||||
|
Tex.logicNode.draw(tx + s*0.75f, ty - s/2f, -s, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementElem hovered(){
|
||||||
|
Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
|
||||||
|
if(e != null){
|
||||||
|
while(e != null && !(e instanceof StatementElem)){
|
||||||
|
e = e.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(e == null || isDescendantOf(e)) return null;
|
||||||
|
return (StatementElem)e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawCurve(float x, float y, float x2, float y2, Color color){
|
||||||
|
Lines.stroke(4f, color);
|
||||||
|
|
||||||
|
float dist = 100f;
|
||||||
|
|
||||||
|
Lines.curve(
|
||||||
|
x, y,
|
||||||
|
x + dist, y,
|
||||||
|
x2 + dist, y2,
|
||||||
|
x2, y2,
|
||||||
|
Math.max(20, (int)(Mathf.dst(x, y, x2, y2) / 5))
|
||||||
|
);
|
||||||
|
|
||||||
|
Draw.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
core/src/mindustry/logic/LCategory.java
Normal file
16
core/src/mindustry/logic/LCategory.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package mindustry.logic;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import mindustry.graphics.*;
|
||||||
|
|
||||||
|
public enum LCategory{
|
||||||
|
blocks(Pal.accentBack),
|
||||||
|
control(Color.cyan.cpy().shiftSaturation(-0.6f).mul(0.7f)),
|
||||||
|
operations(Pal.place.cpy().shiftSaturation(-0.5f).mul(0.7f));
|
||||||
|
|
||||||
|
public final Color color;
|
||||||
|
|
||||||
|
LCategory(Color color){
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package mindustry.logic2;
|
package mindustry.logic;
|
||||||
|
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import mindustry.ui.dialogs.*;
|
import mindustry.ui.dialogs.*;
|
||||||
|
|
||||||
public class LDialog extends BaseDialog{
|
public class LDialog extends BaseDialog{
|
||||||
LCanvas canvas;
|
mindustry.logic.LCanvas canvas;
|
||||||
|
|
||||||
public LDialog(){
|
public LDialog(){
|
||||||
super("logic");
|
super("logic");
|
||||||
179
core/src/mindustry/logic/LExecutor.java
Normal file
179
core/src/mindustry/logic/LExecutor.java
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
package mindustry.logic;
|
||||||
|
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
|
|
||||||
|
public class LExecutor{
|
||||||
|
LInstruction[] instructions;
|
||||||
|
int counter;
|
||||||
|
|
||||||
|
//values of all the variables
|
||||||
|
Var[] vars;
|
||||||
|
|
||||||
|
/** Runs all the instructions at once. Debugging only. */
|
||||||
|
public void runAll(){
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
while(counter < instructions.length){
|
||||||
|
instructions[counter++].run(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable Building building(int index){
|
||||||
|
Object o = vars[index].objval;
|
||||||
|
return o == null && o instanceof Building ? (Building)o : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean bool(int index){
|
||||||
|
Var v = vars[index];
|
||||||
|
return v.isobj ? v.objval != null : Math.abs(v.numval) < 0.0001;
|
||||||
|
}
|
||||||
|
|
||||||
|
double num(int index){
|
||||||
|
Var v = vars[index];
|
||||||
|
return v.isobj ? 0 : v.numval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numi(int index){
|
||||||
|
return (int)num(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setnum(int index, double value){
|
||||||
|
Var v = vars[index];
|
||||||
|
if(v.constant) return;
|
||||||
|
v.numval = value;
|
||||||
|
v.objval = null;
|
||||||
|
v.isobj = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setobj(int index, Object value){
|
||||||
|
Var v = vars[index];
|
||||||
|
if(v.constant) return;
|
||||||
|
v.objval = value;
|
||||||
|
v.isobj = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Var{
|
||||||
|
boolean isobj, constant;
|
||||||
|
|
||||||
|
Object objval;
|
||||||
|
double numval;
|
||||||
|
}
|
||||||
|
|
||||||
|
//region instruction types
|
||||||
|
|
||||||
|
public interface LInstruction{
|
||||||
|
void run(LExecutor exec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enables/disables a building. */
|
||||||
|
public static class ToggleI implements LInstruction{
|
||||||
|
public int target, value;
|
||||||
|
|
||||||
|
public ToggleI(int target, int value){
|
||||||
|
this.target = target;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
Building b = exec.building(target);
|
||||||
|
if(b != null) b.enabled = exec.bool(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SenseI implements LInstruction{
|
||||||
|
public int from, to;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AssignI implements LInstruction{
|
||||||
|
public int from, to;
|
||||||
|
|
||||||
|
public AssignI(int from, int to){
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
Var v = exec.vars[to];
|
||||||
|
Var f = exec.vars[from];
|
||||||
|
|
||||||
|
//TODO error out when the from-value is a constant
|
||||||
|
if(!v.constant){
|
||||||
|
if(f.isobj){
|
||||||
|
v.objval = f.objval;
|
||||||
|
v.isobj = true;
|
||||||
|
}else{
|
||||||
|
v.numval = f.numval;
|
||||||
|
v.isobj = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BinaryOpI implements LInstruction{
|
||||||
|
public mindustry.logic.BinaryOp op;
|
||||||
|
public int a, b, dest;
|
||||||
|
|
||||||
|
public BinaryOpI(BinaryOp op, int a, int b, int dest){
|
||||||
|
this.op = op;
|
||||||
|
this.a = a;
|
||||||
|
this.b = b;
|
||||||
|
this.dest = dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
exec.setnum(dest, op.function.get(exec.num(a), exec.num(b)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EndI implements LInstruction{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
exec.counter = exec.instructions.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class JumpI implements LInstruction{
|
||||||
|
public int cond, to;
|
||||||
|
|
||||||
|
public JumpI(int cond, int to){
|
||||||
|
this.cond = cond;
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
if(to != -1 && exec.bool(cond)){
|
||||||
|
exec.counter = to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FetchBuildI implements LInstruction{
|
||||||
|
public int dest;
|
||||||
|
public int x, y;
|
||||||
|
|
||||||
|
public FetchBuildI(int dest, int x, int y){
|
||||||
|
this.dest = dest;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
exec.setobj(dest, Vars.world.build(exec.numi(x), exec.numi(y)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
}
|
||||||
15
core/src/mindustry/logic/LStatement.java
Normal file
15
core/src/mindustry/logic/LStatement.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package mindustry.logic;
|
||||||
|
|
||||||
|
import arc.scene.ui.layout.*;
|
||||||
|
|
||||||
|
/** A statement is an intermediate representation of an instruction, to be used in UI. */
|
||||||
|
public abstract class LStatement{
|
||||||
|
|
||||||
|
public abstract void build(Table table);
|
||||||
|
public abstract LCategory category();
|
||||||
|
public abstract LExecutor.LInstruction build(LBuilder builder);
|
||||||
|
|
||||||
|
public String name(){
|
||||||
|
return getClass().getSimpleName().replace("Statement", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
171
core/src/mindustry/logic/LStatements.java
Normal file
171
core/src/mindustry/logic/LStatements.java
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
package mindustry.logic;
|
||||||
|
|
||||||
|
import arc.graphics.*;
|
||||||
|
import arc.scene.ui.*;
|
||||||
|
import arc.scene.ui.layout.*;
|
||||||
|
import mindustry.logic.LExecutor.*;
|
||||||
|
import mindustry.logic.LCanvas.*;
|
||||||
|
import mindustry.ui.*;
|
||||||
|
|
||||||
|
public class LStatements{
|
||||||
|
|
||||||
|
public static class AssignStatement extends LStatement{
|
||||||
|
public String to = "result";
|
||||||
|
public String from = "0";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(Table table){
|
||||||
|
table.field(to, Styles.nodeField, str -> to = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
table.add(" = ");
|
||||||
|
|
||||||
|
table.field(from, Styles.nodeField, str -> from = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LCategory category(){
|
||||||
|
return LCategory.operations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LExecutor.LInstruction build(LBuilder builder){
|
||||||
|
//TODO internal consts need to start with ___ and not be assignable to
|
||||||
|
return new LExecutor.AssignI(builder.var(from), builder.var(to));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ToggleStatement extends LStatement{
|
||||||
|
public String target = "result";
|
||||||
|
public String value = "0";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(Table table){
|
||||||
|
table.field(target, Styles.nodeField, str -> target = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
table.add(" -> ");
|
||||||
|
|
||||||
|
table.field(value, Styles.nodeField, str -> value = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LCategory category(){
|
||||||
|
return LCategory.operations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LExecutor.LInstruction build(LBuilder builder){
|
||||||
|
return new LExecutor.ToggleI(builder.var(target), builder.var(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class OpStatement extends LStatement{
|
||||||
|
public mindustry.logic.BinaryOp op = mindustry.logic.BinaryOp.add;
|
||||||
|
public String a = "a", b = "b", dest = "result";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(Table table){
|
||||||
|
table.field(dest, Styles.nodeField, str -> dest = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
table.add(" = ");
|
||||||
|
|
||||||
|
table.field(a, Styles.nodeField, str -> a = str)
|
||||||
|
.size(90f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
|
||||||
|
TextButton[] button = {null};
|
||||||
|
button[0] = table.button(op.symbol, Styles.cleart, () -> {
|
||||||
|
op = mindustry.logic.BinaryOp.all[(op.ordinal() + 1) % BinaryOp.all.length];
|
||||||
|
button[0].setText(op.symbol);
|
||||||
|
}).size(50f, 30f).pad(4f).get();
|
||||||
|
|
||||||
|
table.field(b, Styles.nodeField, str -> b = str)
|
||||||
|
.size(90f, 40f).pad(2f).color(table.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LInstruction build(LBuilder builder){
|
||||||
|
return new BinaryOpI(op,builder.var(a), builder.var(b), builder.var(dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LCategory category(){
|
||||||
|
return LCategory.operations;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EndStatement extends LStatement{
|
||||||
|
@Override
|
||||||
|
public void build(Table table){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LInstruction build(LBuilder builder){
|
||||||
|
return new EndI();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LCategory category(){
|
||||||
|
return LCategory.control;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class JumpStatement extends LStatement{
|
||||||
|
public StatementElem dest;
|
||||||
|
public String condition = " true";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(Table table){
|
||||||
|
table.add("if ").padLeft(6);
|
||||||
|
table.field(condition, Styles.nodeField, str -> condition = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
table.add().growX();
|
||||||
|
table.add(new JumpButton(Color.white, s -> dest = s)).size(30).right().padRight(-17);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LInstruction build(LBuilder builder){
|
||||||
|
return new JumpI(builder.var(condition), dest == null ? -1 : dest.parent.getChildren().indexOf(dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LCategory category(){
|
||||||
|
return LCategory.control;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FetchBuildStatement extends LStatement{
|
||||||
|
public String x = "0", y = "0", dest = "result";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(Table table){
|
||||||
|
table.field(dest, Styles.nodeField, str -> dest = str)
|
||||||
|
.size(100f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
table.add(" = ");
|
||||||
|
|
||||||
|
table.field(x, Styles.nodeField, str -> x = str)
|
||||||
|
.size(90f, 40f).pad(2f).color(table.color);
|
||||||
|
|
||||||
|
table.add(", ");
|
||||||
|
|
||||||
|
table.field(y, Styles.nodeField, str -> y = str)
|
||||||
|
.size(90f, 40f).pad(2f).color(table.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LExecutor.LInstruction build(LBuilder builder){
|
||||||
|
return new FetchBuildI(builder.var(dest), builder.var(x), builder.var(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LCategory category(){
|
||||||
|
return LCategory.blocks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,388 +0,0 @@
|
|||||||
package mindustry.logic;
|
|
||||||
|
|
||||||
import arc.*;
|
|
||||||
import arc.graphics.*;
|
|
||||||
import arc.graphics.g2d.*;
|
|
||||||
import arc.input.*;
|
|
||||||
import arc.math.*;
|
|
||||||
import arc.math.geom.*;
|
|
||||||
import arc.scene.*;
|
|
||||||
import arc.scene.event.*;
|
|
||||||
import arc.scene.ui.*;
|
|
||||||
import arc.scene.ui.layout.*;
|
|
||||||
import arc.util.*;
|
|
||||||
import mindustry.gen.*;
|
|
||||||
import mindustry.graphics.*;
|
|
||||||
import mindustry.io.*;
|
|
||||||
import mindustry.logic.LogicNode.*;
|
|
||||||
import mindustry.logic.LogicNodes.*;
|
|
||||||
import mindustry.logic.SavedLogic.*;
|
|
||||||
import mindustry.ui.*;
|
|
||||||
|
|
||||||
public class LogicCanvas extends WidgetGroup{
|
|
||||||
private static final Color backgroundCol = Pal.darkMetal.cpy().mul(0.1f), gridCol = Pal.darkMetal.cpy().mul(0.5f);
|
|
||||||
|
|
||||||
private Element selected;
|
|
||||||
private Element entered;
|
|
||||||
private Vec2 offset = new Vec2();
|
|
||||||
|
|
||||||
{
|
|
||||||
addListener(new InputListener(){
|
|
||||||
float lastX, lastY;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void touchDragged(InputEvent event, float mx, float my, int pointer){
|
|
||||||
if(Core.app.isMobile() && pointer != 0) return;
|
|
||||||
|
|
||||||
float dx = mx - lastX, dy = my - lastY;
|
|
||||||
offset.add(dx, dy);
|
|
||||||
|
|
||||||
for(Element e : getChildren()){
|
|
||||||
e.moveBy(dx, dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastX = mx;
|
|
||||||
lastY = my;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
|
|
||||||
if((Core.app.isMobile() && pointer != 0) || (Core.app.isDesktop() && button != KeyCode.mouseMiddle)) return false;
|
|
||||||
|
|
||||||
lastX = x;
|
|
||||||
lastY = y;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//TODO debug stuff
|
|
||||||
add(new BinaryOpNode());
|
|
||||||
add(new BinaryOpNode());
|
|
||||||
add(new BinaryOpNode());
|
|
||||||
add(new NumberNode());
|
|
||||||
add(new NumberNode());
|
|
||||||
add(new NumberNode());
|
|
||||||
add(new ConditionNode());
|
|
||||||
add(new ConditionNode());
|
|
||||||
add(new SignalNode());
|
|
||||||
add(new SequenceNode());
|
|
||||||
|
|
||||||
Log.info(JsonIO.print(JsonIO.write(save())));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void add(LogicNode node){
|
|
||||||
NodeElement e = new NodeElement(node);
|
|
||||||
e.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight()/2f);
|
|
||||||
addChild(e);
|
|
||||||
e.pack();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SavedLogic save(){
|
|
||||||
|
|
||||||
//convert elements to saved nodes for writing to JSON
|
|
||||||
return new SavedLogic(getChildren().<NodeElement>as().map(e -> {
|
|
||||||
SavedNode node = new SavedNode();
|
|
||||||
node.state = e.node;
|
|
||||||
node.x = e.x;
|
|
||||||
node.y = e.y;
|
|
||||||
node.connections = new SavedConnection[e.slots.length];
|
|
||||||
|
|
||||||
for(int i = 0; i < e.slots.length; i++){
|
|
||||||
SavedConnection con = (node.connections[i] = new SavedConnection());
|
|
||||||
SlotElement slot = e.slots[i];
|
|
||||||
|
|
||||||
if(slot.connection != null){
|
|
||||||
SlotElement to = slot.connection;
|
|
||||||
|
|
||||||
con.node = getChildren().indexOf(to.node);
|
|
||||||
con.slot = Structs.indexOf(to.node.slots, to);
|
|
||||||
}else{
|
|
||||||
con.node = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}).toArray(SavedNode.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(SavedLogic state){
|
|
||||||
clear();
|
|
||||||
|
|
||||||
//add nodes as children first to make sure they can be accessed.
|
|
||||||
for(SavedNode node : state.nodes){
|
|
||||||
NodeElement elem = new NodeElement(node.state);
|
|
||||||
elem.setPosition(node.x, node.y);
|
|
||||||
addChild(elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
//assign connection data
|
|
||||||
for(int i = 0; i < state.nodes.length; i++){
|
|
||||||
SavedNode node = state.nodes[i];
|
|
||||||
NodeElement elem = (NodeElement)getChildren().get(i);
|
|
||||||
|
|
||||||
for(int j = 0; j < node.connections.length; j++){
|
|
||||||
SavedConnection con = node.connections[j];
|
|
||||||
if(con.node >= 0 && con.node < state.nodes.length){
|
|
||||||
SlotElement slot = elem.slots[j];
|
|
||||||
slot.connection = ((NodeElement)getChildren().get(con.node)).slots[con.slot];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
elem.pack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(){
|
|
||||||
Draw.color(backgroundCol);
|
|
||||||
|
|
||||||
Fill.crect(x, y, width, height);
|
|
||||||
|
|
||||||
Draw.color(gridCol);
|
|
||||||
|
|
||||||
float spacing = Scl.scl(50f);
|
|
||||||
int xbars = (int)(width / spacing) + 2, ybars = (int)(width / spacing) + 2;
|
|
||||||
float ox = offset.x % spacing, oy = offset.y % spacing;
|
|
||||||
|
|
||||||
Lines.stroke(Scl.scl(3f));
|
|
||||||
|
|
||||||
for(int i = 0; i < xbars; i++){
|
|
||||||
float cx = x + width/2f + (i - xbars/2) * spacing + ox;
|
|
||||||
Lines.line(cx, y, cx, y + height);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < ybars; i++){
|
|
||||||
float cy = y + height/2f + (i - ybars/2) * spacing + oy;
|
|
||||||
Lines.line(0, cy, x + width, cy);
|
|
||||||
}
|
|
||||||
|
|
||||||
Draw.reset();
|
|
||||||
|
|
||||||
super.draw();
|
|
||||||
|
|
||||||
for(Element e : getChildren()){
|
|
||||||
if(e instanceof NodeElement){
|
|
||||||
NodeElement l = (NodeElement)e;
|
|
||||||
|
|
||||||
for(SlotElement field : l.slots){
|
|
||||||
field.drawConnection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(selected != null){
|
|
||||||
SlotElement field = (SlotElement)selected.userObject;
|
|
||||||
Vec2 dest = selected.localToStageCoordinates(Tmp.v1.set(selected.getWidth()/2f, selected.getHeight()/2f));
|
|
||||||
Vec2 mouse = Core.input.mouse();
|
|
||||||
drawCurve(dest.x, dest.y, mouse.x, mouse.y, field.color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawCurve(float x, float y, float x2, float y2, Color color){
|
|
||||||
Lines.stroke(4f, color);
|
|
||||||
|
|
||||||
float dist = Math.abs(x - x2)/2f;
|
|
||||||
|
|
||||||
Lines.curve(
|
|
||||||
x, y,
|
|
||||||
x + dist, y,
|
|
||||||
x2 - dist, y2,
|
|
||||||
x2, y2,
|
|
||||||
Math.max(3, (int)(Mathf.dst(x, y, x2, y2) / 5))
|
|
||||||
);
|
|
||||||
|
|
||||||
Draw.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
class NodeElement extends Table{
|
|
||||||
final LogicNode node;
|
|
||||||
SlotElement[] slots;
|
|
||||||
Table slotTable;
|
|
||||||
|
|
||||||
NodeElement(LogicNode node){
|
|
||||||
this.node = node;
|
|
||||||
|
|
||||||
background(Tex.whitePane);
|
|
||||||
setColor(node.category().color);
|
|
||||||
margin(0f);
|
|
||||||
|
|
||||||
table(Tex.whiteui, t -> {
|
|
||||||
t.update(() -> {
|
|
||||||
t.setColor(color);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.margin(8f);
|
|
||||||
t.touchable = Touchable.enabled;
|
|
||||||
|
|
||||||
t.add(node.name()).style(Styles.outlineLabel).color(color).padRight(8);
|
|
||||||
t.add().growX();
|
|
||||||
t.button(Icon.cancel, Styles.onlyi, () -> {
|
|
||||||
//TODO disconnect things
|
|
||||||
remove();
|
|
||||||
});
|
|
||||||
t.addListener(new InputListener(){
|
|
||||||
float lastx, lasty;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
|
|
||||||
Vec2 v = localToStageCoordinates(Tmp.v1.set(x, y));
|
|
||||||
lastx = v.x;
|
|
||||||
lasty = v.y;
|
|
||||||
toFront();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void touchDragged(InputEvent event, float x, float y, int pointer){
|
|
||||||
Vec2 v = localToStageCoordinates(Tmp.v1.set(x, y));
|
|
||||||
|
|
||||||
moveBy(v.x - lastx, v.y - lasty);
|
|
||||||
lastx = v.x;
|
|
||||||
lasty = v.y;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).growX().padBottom(6);
|
|
||||||
|
|
||||||
row();
|
|
||||||
|
|
||||||
node.build(this);
|
|
||||||
|
|
||||||
row();
|
|
||||||
|
|
||||||
table(t -> slotTable = t).fill();
|
|
||||||
|
|
||||||
rebuildSlots();
|
|
||||||
|
|
||||||
marginBottom(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rebuildSlots(){
|
|
||||||
slotTable.clear();
|
|
||||||
slotTable.defaults().height(30);
|
|
||||||
|
|
||||||
NodeSlot[] nslots = node.slots();
|
|
||||||
|
|
||||||
this.slots = new SlotElement[nslots.length];
|
|
||||||
for(int i = 0; i < nslots.length; i++){
|
|
||||||
this.slots[i] = new SlotElement(this, nslots[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(SlotElement field : slots){
|
|
||||||
slotTable.add(field).growX().align(field.slot.input ? Align.left : Align.right);
|
|
||||||
slotTable.row();
|
|
||||||
}
|
|
||||||
|
|
||||||
pack();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(){
|
|
||||||
float pad = 10f;
|
|
||||||
Fill.dropShadow(x + width/2f, y + height/2f, width + pad, height + pad, 20f, 0.95f);
|
|
||||||
|
|
||||||
Draw.color(0, 0, 0, 0.3f);
|
|
||||||
Fill.crect(x, y, width, height);
|
|
||||||
Draw.reset();
|
|
||||||
|
|
||||||
super.draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SlotElement extends Table{
|
|
||||||
final NodeSlot slot;
|
|
||||||
final NodeElement node;
|
|
||||||
|
|
||||||
ImageButton button;
|
|
||||||
SlotElement connection;
|
|
||||||
|
|
||||||
SlotElement(NodeElement node, NodeSlot slot){
|
|
||||||
this.slot = slot;
|
|
||||||
this.node = node;
|
|
||||||
|
|
||||||
setColor(slot.type.color);
|
|
||||||
|
|
||||||
float marg = 24f;
|
|
||||||
|
|
||||||
if(slot.input){
|
|
||||||
addIcon();
|
|
||||||
left();
|
|
||||||
marginRight(marg);
|
|
||||||
}else{
|
|
||||||
right();
|
|
||||||
marginLeft(marg);
|
|
||||||
}
|
|
||||||
|
|
||||||
add(slot.name).padLeft(5).padRight(5).style(Styles.outlineLabel).color(color);
|
|
||||||
|
|
||||||
if(!slot.input){
|
|
||||||
addIcon();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawConnection(){
|
|
||||||
if(connection != null){
|
|
||||||
ImageButton cb = connection.button;
|
|
||||||
Vec2 from = localToStageCoordinates(Tmp.v2.set(button.x + button.getWidth()/2f, button.y + button.getHeight()/2f));
|
|
||||||
Vec2 to = cb.localToStageCoordinates(Tmp.v1.set(cb.getWidth()/2f, cb.getHeight()/2f));
|
|
||||||
|
|
||||||
drawCurve(from.x, from.y, to.x, to.y, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addIcon(){
|
|
||||||
float s = 30f;
|
|
||||||
Cell<ImageButton> c = button(Tex.logicNode, Styles.colori, () -> {
|
|
||||||
|
|
||||||
}).size(s);
|
|
||||||
|
|
||||||
button = c.get();
|
|
||||||
button.userObject = this;
|
|
||||||
button.getStyle().imageUpColor = color;
|
|
||||||
|
|
||||||
float pad = s/2f - 3f;
|
|
||||||
|
|
||||||
if(slot.input){
|
|
||||||
c.padLeft(-pad);
|
|
||||||
}else{
|
|
||||||
c.padRight(-pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
button.addListener(new InputListener(){
|
|
||||||
@Override
|
|
||||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode code){
|
|
||||||
|
|
||||||
if(selected == null && !slot.input){
|
|
||||||
selected = button;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enter(InputEvent event, float x, float y, int pointer, Element fromActor){
|
|
||||||
entered = button;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode code){
|
|
||||||
localToStageCoordinates(Tmp.v1.set(x, y));
|
|
||||||
Element element = entered;
|
|
||||||
|
|
||||||
if(element != null && element.userObject instanceof SlotElement){
|
|
||||||
SlotElement field = (SlotElement)element.userObject;
|
|
||||||
//make sure inputs are matched to outputs, and that slot types match
|
|
||||||
if(field != SlotElement.this && field.slot.input != slot.input && field.slot.type == slot.type){
|
|
||||||
connection = field;
|
|
||||||
//field.connection = button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(selected == button){
|
|
||||||
selected = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package mindustry.logic;
|
|
||||||
|
|
||||||
import mindustry.logic.LogicNode.*;
|
|
||||||
import mindustry.logic.SavedLogic.*;
|
|
||||||
|
|
||||||
public class LogicExecutor{
|
|
||||||
/** all logical operations to be executed */
|
|
||||||
private LogicOp[] ops = {};
|
|
||||||
/** current operation index */
|
|
||||||
private int index;
|
|
||||||
|
|
||||||
/** Set up executor state based on saved data. */
|
|
||||||
public void setup(SavedLogic save){
|
|
||||||
LogicNode[] out = new LogicNode[save.nodes.length];
|
|
||||||
|
|
||||||
//copy over the state so connections can be assigned
|
|
||||||
for(int i = 0; i < out.length; i++){
|
|
||||||
out[i] = save.nodes[i].state;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < out.length; i++){
|
|
||||||
LogicNode node = out[i];
|
|
||||||
NodeSlot[] slots = node.slots();
|
|
||||||
|
|
||||||
//connect node's slots to other nodes' slots
|
|
||||||
for(int j = 0; j < save.nodes[i].connections.length; j++){
|
|
||||||
SavedConnection con = save.nodes[i].connections[j];
|
|
||||||
NodeSlot slot = slots[j];
|
|
||||||
|
|
||||||
if(con.node != -1){
|
|
||||||
LogicNode other = out[con.node];
|
|
||||||
NodeSlot[] otherSlots = other.slots();
|
|
||||||
NodeSlot otherSlot = otherSlots[con.slot];
|
|
||||||
|
|
||||||
//slot.objOutput = (aslot, aobj) -> ((ObjOutput)otherSlot.objOutput).set(other, aobj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A single logical statement. */
|
|
||||||
static class LogicOp{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
package mindustry.logic;
|
|
||||||
|
|
||||||
import arc.graphics.*;
|
|
||||||
import arc.scene.ui.layout.*;
|
|
||||||
import mindustry.gen.*;
|
|
||||||
import mindustry.graphics.*;
|
|
||||||
|
|
||||||
/** Base class for a type of logic node. */
|
|
||||||
public abstract class LogicNode{
|
|
||||||
|
|
||||||
/** Runs the calculation(s) and sets the output value. */
|
|
||||||
public void run(){}
|
|
||||||
|
|
||||||
public NodeSlot[] slots(){
|
|
||||||
return (NodeSlot[])LogicSlotMap.map.get(getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract NodeCategory category();
|
|
||||||
|
|
||||||
public void build(Table table){}
|
|
||||||
|
|
||||||
public String name(){
|
|
||||||
return getClass().getSimpleName().replace("Node", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A field for a node, either an input or output. */
|
|
||||||
public static class NodeSlot{
|
|
||||||
/** The slot's display name. */
|
|
||||||
public final String name;
|
|
||||||
/** If true this field accepts values. */
|
|
||||||
public final boolean input;
|
|
||||||
/** The type of data accepted or returned by this slot. */
|
|
||||||
public final DataType type;
|
|
||||||
|
|
||||||
public final NumOutput<?> numOutput;
|
|
||||||
public final ObjOutput<?, ?> objOutput;
|
|
||||||
|
|
||||||
public NodeSlot(String name, boolean input, DataType type, NumOutput<?> numOutput, ObjOutput<?, ?> objOutput){
|
|
||||||
this.name = name;
|
|
||||||
this.input = input;
|
|
||||||
this.type = type;
|
|
||||||
this.numOutput = numOutput;
|
|
||||||
this.objOutput = objOutput;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface NumOutput<N>{
|
|
||||||
void set(N node, double val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ObjOutput<N, T>{
|
|
||||||
void set(N node, T val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface SetNum{
|
|
||||||
void set(double val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface SetObj<T>{
|
|
||||||
void set(T val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum NodeCategory{
|
|
||||||
controlFlow(Pal.accentBack),
|
|
||||||
operations(Pal.place.cpy().shiftSaturation(-0.4f).mul(0.7f));
|
|
||||||
|
|
||||||
public final Color color;
|
|
||||||
|
|
||||||
NodeCategory(Color color){
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The types of data a node field can be. */
|
|
||||||
public enum DataType{
|
|
||||||
/** A double. Used for integer calculations as well. */
|
|
||||||
number(Pal.place),
|
|
||||||
/** Any type of content, e.g. item. */
|
|
||||||
content(Color.cyan),
|
|
||||||
/** A building of a tile. */
|
|
||||||
building(Pal.items),
|
|
||||||
/** A unit on the map. */
|
|
||||||
unit(Pal.health),
|
|
||||||
/** Control flow (void)*/
|
|
||||||
control(Color.white),
|
|
||||||
/** Java string */
|
|
||||||
string(Color.royal);
|
|
||||||
|
|
||||||
public final Color color;
|
|
||||||
|
|
||||||
DataType(Color color){
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
package mindustry.logic;
|
|
||||||
|
|
||||||
import arc.graphics.*;
|
|
||||||
import arc.scene.ui.*;
|
|
||||||
import arc.scene.ui.layout.*;
|
|
||||||
import arc.util.*;
|
|
||||||
import mindustry.annotations.Annotations.*;
|
|
||||||
import mindustry.ui.*;
|
|
||||||
|
|
||||||
public class LogicNodes{
|
|
||||||
public static class BinaryOpNode extends LogicNode{
|
|
||||||
public BinaryOp op = BinaryOp.add;
|
|
||||||
@Slot
|
|
||||||
public double a, b;
|
|
||||||
@Slot
|
|
||||||
public transient SetNum result = val -> {};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void build(Table table){
|
|
||||||
//TODO replace with dropdown menu
|
|
||||||
TextButton[] button = {null};
|
|
||||||
button[0] = table.button(op.symbol, Styles.cleart, () -> {
|
|
||||||
op = BinaryOp.all[(op.ordinal() + 1) % BinaryOp.all.length];
|
|
||||||
button[0].setText(op.symbol);
|
|
||||||
}).size(100f, 40f).pad(2f).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(){
|
|
||||||
result.set(op.function.get(a, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeCategory category(){
|
|
||||||
return NodeCategory.operations;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ConditionNode extends LogicNode{
|
|
||||||
@Slot(input = true)
|
|
||||||
public transient Runnable input = this::run;
|
|
||||||
@Slot
|
|
||||||
public double condition;
|
|
||||||
@Slot
|
|
||||||
public transient Runnable yes, no;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(){
|
|
||||||
if(condition > 0){
|
|
||||||
yes.run();
|
|
||||||
}else{
|
|
||||||
no.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeCategory category(){
|
|
||||||
return NodeCategory.controlFlow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class NumberNode extends LogicNode{
|
|
||||||
@Slot
|
|
||||||
public transient SetNum value;
|
|
||||||
public double var;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void build(Table table){
|
|
||||||
table.field(var + "", Styles.nodeField, str -> var = parseDouble(str))
|
|
||||||
.size(100f, 40f).pad(2f).color(table.color)
|
|
||||||
.update(f -> f.setColor(f.isValid() ? table.color : Color.white));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(){
|
|
||||||
value.set(var);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeCategory category(){
|
|
||||||
return NodeCategory.controlFlow;
|
|
||||||
}
|
|
||||||
|
|
||||||
static double parseDouble(String s){
|
|
||||||
return s.equals("yes") || s.equals("true") ? 1 :
|
|
||||||
s.equals("no") || s.equals("false") ? 0 :
|
|
||||||
Strings.parseDouble(s, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SequenceNode extends LogicNode{
|
|
||||||
@Slot(input = true)
|
|
||||||
public transient Runnable input = this::run;
|
|
||||||
@Slot
|
|
||||||
public transient Runnable first, second;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(){
|
|
||||||
first.run();
|
|
||||||
second.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeCategory category(){
|
|
||||||
return NodeCategory.controlFlow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SignalNode extends LogicNode{
|
|
||||||
@Slot
|
|
||||||
public transient Runnable run;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(){
|
|
||||||
run.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeCategory category(){
|
|
||||||
return NodeCategory.controlFlow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package mindustry.logic;
|
|
||||||
|
|
||||||
/** The saved state of a logic board. */
|
|
||||||
public class SavedLogic{
|
|
||||||
public SavedNode[] nodes;
|
|
||||||
|
|
||||||
public SavedLogic(SavedNode[] nodes){
|
|
||||||
this.nodes = nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SavedNode{
|
|
||||||
/** Uninitialized state containing only relevant configuration. */
|
|
||||||
public LogicNode state;
|
|
||||||
/** Connections of this node. */
|
|
||||||
public SavedConnection[] connections;
|
|
||||||
/** x/y positions of the bottom left corner of the node */
|
|
||||||
public float x, y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SavedConnection{
|
|
||||||
/** Node ID (in the array) that is being connected to. -1 means no connection */
|
|
||||||
public int node;
|
|
||||||
/** Slot number in the node */
|
|
||||||
public int slot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
package mindustry.logic2;
|
|
||||||
|
|
||||||
import arc.input.*;
|
|
||||||
import arc.math.geom.*;
|
|
||||||
import arc.scene.event.*;
|
|
||||||
import arc.scene.ui.layout.*;
|
|
||||||
import arc.struct.*;
|
|
||||||
import arc.util.*;
|
|
||||||
import mindustry.gen.*;
|
|
||||||
import mindustry.logic2.LStatements.*;
|
|
||||||
import mindustry.ui.*;
|
|
||||||
|
|
||||||
public class LCanvas extends Table{
|
|
||||||
|
|
||||||
private Table statements;
|
|
||||||
private Seq<StatementElem> elems = new Seq<>();
|
|
||||||
|
|
||||||
public LCanvas(){
|
|
||||||
//left();
|
|
||||||
|
|
||||||
pane(t -> {
|
|
||||||
t.setClip(false);
|
|
||||||
statements = t;
|
|
||||||
statements.defaults().width(300f).pad(4f);
|
|
||||||
t.marginRight(1);
|
|
||||||
}).growY().get().setClip(false);
|
|
||||||
|
|
||||||
add(new AssignStatement());
|
|
||||||
add(new AssignStatement());
|
|
||||||
add(new OpStatement());
|
|
||||||
}
|
|
||||||
|
|
||||||
void add(LStatement statement){
|
|
||||||
StatementElem e = new StatementElem(statement);
|
|
||||||
elems.add(e);
|
|
||||||
|
|
||||||
statements.add(e);
|
|
||||||
statements.row();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class StatementElem extends Table{
|
|
||||||
LStatement st;
|
|
||||||
|
|
||||||
public StatementElem(LStatement st){
|
|
||||||
this.st = st;
|
|
||||||
|
|
||||||
background(Tex.whitePane);
|
|
||||||
setColor(st.category().color);
|
|
||||||
margin(0f);
|
|
||||||
|
|
||||||
table(Tex.whiteui, t -> {
|
|
||||||
t.color.set(color);
|
|
||||||
|
|
||||||
t.margin(8f);
|
|
||||||
t.touchable = Touchable.enabled;
|
|
||||||
|
|
||||||
t.add(st.name()).style(Styles.outlineLabel).color(color).padRight(8);
|
|
||||||
t.add().growX();
|
|
||||||
t.button(Icon.cancel, Styles.onlyi, () -> {
|
|
||||||
//TODO disconnect things
|
|
||||||
remove();
|
|
||||||
elems.remove(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
t.addListener(new InputListener(){
|
|
||||||
float lastx, lasty;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
|
|
||||||
Vec2 v = localToStageCoordinates(Tmp.v1.set(x, y));
|
|
||||||
lastx = v.x;
|
|
||||||
lasty = v.y;
|
|
||||||
toFront();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void touchDragged(InputEvent event, float x, float y, int pointer){
|
|
||||||
Vec2 v = localToStageCoordinates(Tmp.v1.set(x, y));
|
|
||||||
|
|
||||||
translation.add(v.x - lastx, v.y - lasty);
|
|
||||||
lastx = v.x;
|
|
||||||
lasty = v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){
|
|
||||||
translation.setZero();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).growX().padBottom(6);
|
|
||||||
|
|
||||||
row();
|
|
||||||
|
|
||||||
table(t -> {
|
|
||||||
t.setColor(color);
|
|
||||||
st.build(t);
|
|
||||||
}).pad(8).padTop(2);
|
|
||||||
|
|
||||||
marginBottom(7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package mindustry.logic2;
|
|
||||||
|
|
||||||
import arc.graphics.*;
|
|
||||||
import mindustry.graphics.*;
|
|
||||||
|
|
||||||
public enum LCategory{
|
|
||||||
control(Pal.accentBack),
|
|
||||||
operations(Pal.place.cpy().shiftSaturation(-0.4f).mul(0.7f));
|
|
||||||
|
|
||||||
public final Color color;
|
|
||||||
|
|
||||||
LCategory(Color color){
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package mindustry.logic2;
|
|
||||||
|
|
||||||
public class LExecutor{
|
|
||||||
LStatement[] statements;
|
|
||||||
int counter;
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package mindustry.logic2;
|
|
||||||
|
|
||||||
import arc.scene.ui.layout.*;
|
|
||||||
|
|
||||||
public abstract class LStatement{
|
|
||||||
|
|
||||||
public abstract void run(LExecutor exec);
|
|
||||||
public abstract void build(Table table);
|
|
||||||
public abstract LCategory category();
|
|
||||||
|
|
||||||
public String name(){
|
|
||||||
return getClass().getSimpleName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package mindustry.logic2;
|
|
||||||
|
|
||||||
import arc.scene.ui.layout.*;
|
|
||||||
import arc.util.*;
|
|
||||||
import mindustry.logic.*;
|
|
||||||
import mindustry.ui.*;
|
|
||||||
|
|
||||||
public class LStatements{
|
|
||||||
|
|
||||||
public static class AssignStatement extends LStatement{
|
|
||||||
public int output;
|
|
||||||
public double value;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(LExecutor exec){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void build(Table table){
|
|
||||||
table.field(value + "", Styles.nodeField, str -> value = parseDouble(str))
|
|
||||||
.size(100f, 40f).pad(2f).color(table.color).padRight(20);
|
|
||||||
|
|
||||||
table.field(value + "", Styles.nodeField, str -> value = parseDouble(str))
|
|
||||||
.size(100f, 40f).pad(2f).color(table.color);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LCategory category(){
|
|
||||||
return LCategory.operations;
|
|
||||||
}
|
|
||||||
|
|
||||||
static double parseDouble(String s){
|
|
||||||
return s.equals("yes") || s.equals("true") ? 1 :
|
|
||||||
s.equals("no") || s.equals("false") ? 0 :
|
|
||||||
Strings.parseDouble(s, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class OpStatement extends LStatement{
|
|
||||||
public BinaryOp op = BinaryOp.add;
|
|
||||||
public int output;
|
|
||||||
public double result;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(LExecutor exec){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void build(Table table){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LCategory category(){
|
|
||||||
return LCategory.operations;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -75,7 +75,7 @@ public class TractorBeamTurret extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//look at target
|
//look at target
|
||||||
if(target != null && target.within(this, range) && target.team() != team && target.type().flying){
|
if(target != null && target.within(this, range) && target.team() != team && target.type().flying && efficiency() > 0.01f){
|
||||||
any = true;
|
any = true;
|
||||||
float dest = angleTo(target);
|
float dest = angleTo(target);
|
||||||
rotation = Angles.moveToward(rotation, dest, rotateSpeed * edelta());
|
rotation = Angles.moveToward(rotation, dest, rotateSpeed * edelta());
|
||||||
@@ -84,7 +84,7 @@ public class TractorBeamTurret extends Block{
|
|||||||
strength = Mathf.lerpDelta(strength, 1f, 0.1f);
|
strength = Mathf.lerpDelta(strength, 1f, 0.1f);
|
||||||
|
|
||||||
if(damage > 0){
|
if(damage > 0){
|
||||||
target.damageContinuous(damage);
|
target.damageContinuous(damage * efficiency());
|
||||||
}
|
}
|
||||||
|
|
||||||
//shoot when possible
|
//shoot when possible
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ public class Consumers{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a consumer which only consumes power when the condition is met. */
|
/** Creates a consumer which only consumes power when the condition is met. */
|
||||||
public ConsumePower powerCond(float usage, Boolf<Building> cons){
|
public <T extends Building> ConsumePower powerCond(float usage, Boolf<T> cons){
|
||||||
return add(new ConditionalConsumePower(usage, cons));
|
return add(new ConditionalConsumePower(usage, (Boolf<Building>)cons));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user