Logic hint tooltips

This commit is contained in:
Anuken 2021-02-09 14:52:23 -05:00
parent ce8b32f022
commit e22fccf5b1
12 changed files with 152 additions and 24 deletions

View File

@ -796,6 +796,7 @@ setting.shadows.name = Shadows
setting.blockreplace.name = Automatic Block Suggestions
setting.linear.name = Linear Filtering
setting.hints.name = Hints
setting.logichints.name = Logic Hints
setting.flow.name = Display Resource Flow Rate
setting.backgroundpause.name = Pause In Background
setting.buildautopause.name = Auto-Pause Building
@ -1513,3 +1514,102 @@ unit.omura.description = Fires a long-range piercing railgun bolt at enemies. Co
unit.alpha.description = Defends the Shard core from enemies. Builds structures.
unit.beta.description = Defends the Foundation core from enemies. Builds structures.
unit.gamma.description = Defends the Nucleus core from enemies. Builds structures.
lst.read = Read a number from a linked memory cell.
lst.write = Write a number to a linked memory cell.
lst.print = Add text to the print buffer.\nDoes not display anything until [accent]Print Flush[] is used.
lst.draw = Add an operation to the drawing buffer.\nDoes not display anything until [accent]Draw Flush[] is used.
lst.drawflush = Flush queued [accent]Draw[] operations to a display.
lst.printflush = Flush queued [accent]Print[] operations to a message block.
lst.getlink = Get a processor link by index. Starts at 0.
lst.control = Control a building.
lst.radar = Locate units around a building with range.
lst.sensor = Get data from a building or unit.
lst.set = Set a variable.
lst.operation = Perform an operation on 1-2 variables.
lst.end = Jump to the top of the instruction stack.
lst.jump = Conditionally jump to another statement.
lst.unitbind = Bind to the next unit of a type, and store it in [accent]@unit[].
lst.unitcontrol = Control the currently bound unit.
lst.unitradar = Locate units around the currently bound unit.
lst.unitlocate = Locate a specific type of position/building anywhere on the map.\nRequires a bound unit.
lenum.type = Type of building/unit.\ne.g. for any router, this will return [accent]@router[].\nNot a string.
lenum.shoot = Shoot at a position.
lenum.shootp = Shoot at a unit/building with velocity prediction.
lenum.configure = Building configuration, e.g. sorter item.
lenum.enabled = Whether the block is enabled.
lenum.color = Illuminator color.
lenum.always = Always true.
lenum.idiv = Integer division.
lenum.div = Division.\nReturns [accent]null[] on divide-by-zero.
lenum.mod = Modulo.
lenum.equal = Equal. Coerces types.\nNon-null objects compared with numbers become 1, otherwise 0.
lenum.notequal = Not equal. Coerces types.
lenum.strictequal = Strict equality. Does not coerce types.\nCan be used to check for [accent]null[].
lenum.shl = Bit-shift left.
lenum.shr = Bit-shift right.
lenum.or = Bitwise OR.
lenum.land = Logical AND.
lenum.and = Bitwise AND.
lenum.not = Bitwise flip.
lenum.xor = Bitwise XOR.
lenum.min = Minimum of two numbers.
lenum.max = Maximum of two numbers.
lenum.angle = Angle of vector in degrees.
lenum.len = Length of vector.
lenum.sin = Sine, in degrees.
lenum.cos = Cosine, in degrees.
lenum.tan = Tangent, in degrees.
lenum.rand = Random number in range [0, value).
lenum.log = Natural logarithm (ln).
lenum.log10 = Base 10 logarithm.
lenum.noise = 2D simplex noise.
lenum.abs = Absolute value.
lenum.sqrt = Square root.
lenum.any = Any unit.
lenum.ally = Ally unit.
lenum.attacker = Unit with a weapon.
lenum.enemy = Enemy unit.
lenum.boss = Guardian unit.
lenum.flying = Flying unit.
lenum.ground = Ground unit.
lenum.player = Unit controlled by a player.
lenum.ore = Ore deposit.
lenum.damaged = Damaged ally building.
lenum.spawn = Enemy spawn point.\nMay be a core or a position.
lenum.building = Building in a specific group.
lenum.core = Any core.
lenum.storage = Storage building, e.g. Vault.
sensor.in = The building/unit to sense.
radar.from = Building to sense from.\nSensor range is limited by building range.
radar.target = Filter for units to sense.
radar.and = Additional filters.
radar.order = Sorting order. 0 to reverse.
radar.sort = Metric to sort results by.
radar.output = Variable to write output unit to.
unitradar.target = Filter for units to sense.
unitradar.and = Additional filters.
unitradar.order = Sorting order. 0 to reverse.
unitradar.sort = Metric to sort results by.
unitradar.output = Variable to write output unit to.
control.of = Building to control.
control.unit = Unit/building to aim at.
control.shoot = Whether to shoot.
unitlocate.enemy = Whether to locate enemy buildings.
unitlocate.found = Whether the object was found.
unitlocate.building = Output variable for located building.
unitlocate.outx = Output X coordinate.
unitlocate.outy = Output Y coordinate.
unitlocate.group = Building group to look for.

View File

@ -108,7 +108,7 @@ public class UI implements ApplicationListener, Loadable{
Dialog.setHideAction(() -> sequence(fadeOut(0.1f)));
Tooltips.getInstance().animations = false;
Tooltips.getInstance().textProvider = text -> new Tooltip(t -> t.background(Styles.black5).margin(4f).add(text));
Tooltips.getInstance().textProvider = text -> new Tooltip(t -> t.background(Styles.black6).margin(4f).add(text));
Core.settings.setErrorHandler(e -> {
Log.err(e);

View File

@ -7,6 +7,7 @@ public enum ConditionOp{
lessThanEq("<=", (a, b) -> a <= b),
greaterThan(">", (a, b) -> a > b),
greaterThanEq(">=", (a, b) -> a >= b),
strictEqual("===", (a, b) -> false),
always("always", (a, b) -> true);
public static final ConditionOp[] all = values();

View File

@ -41,6 +41,13 @@ public class LCanvas extends Table{
return Core.graphics.getWidth() < Scl.scl(900f) * 1.2f;
}
public static void tooltip(Cell<?> cell, String key){
String lkey = key.toLowerCase().replace(" ", "");
if(Core.settings.getBool("logichints", true) && Core.bundle.has(lkey)){
cell.get().addListener(new Tooltip(t -> t.background(Styles.black8).margin(4f).add("[lightgray]" + Core.bundle.get(lkey)).style(Styles.outlineLabel)));
}
}
public void rebuild(){
targetWidth = useRows() ? 400f : 900f;
float s = pane != null ? pane.getScrollPercentY() : 0f;

View File

@ -966,7 +966,9 @@ public class LExecutor{
Var vb = exec.var(compare);
boolean cmp;
if(op.objFunction != null && va.isobj && vb.isobj){
if(op == ConditionOp.strictEqual){
cmp = va.isobj == vb.isobj && ((va.isobj && va.objval == vb.objval) || (!va.isobj && va.numval == vb.numval));
}else if(op.objFunction != null && va.isobj && vb.isobj){
//use object function if both are objects
cmp = op.objFunction.get(exec.obj(value), exec.obj(compare));
}else{

View File

@ -15,6 +15,8 @@ import mindustry.logic.LCanvas.*;
import mindustry.logic.LExecutor.*;
import mindustry.ui.*;
import static mindustry.logic.LCanvas.*;
/**
* A statement is an intermediate representation of an instruction, to be used mostly in UI.
* Contains all relevant variable information. */
@ -38,13 +40,18 @@ public abstract class LStatement{
//protected methods are only for internal UI layout utilities
protected void param(Cell<Label> label){
String text = name() + "." + label.get().getText().toString().trim();
tooltip(label, text);
}
protected Cell<TextField> field(Table table, String value, Cons<String> setter){
return table.field(value, Styles.nodeField, setter)
.size(144f, 40f).pad(2f).color(table.color).maxTextLength(LAssembler.maxTokenLength).addInputDialog();
}
protected Cell<TextField> fields(Table table, String desc, String value, Cons<String> setter){
table.add(desc).padLeft(10).left();
table.add(desc).padLeft(10).left().self(this::param);;
return field(table, value, setter).width(85f).padRight(10).left();
}
@ -58,7 +65,7 @@ public abstract class LStatement{
}
}
protected <T> void showSelect(Button b, T[] values, T current, Cons<T> getter, int cols, Cons<Cell> sizer){
protected <T extends Enum<T>> void showSelect(Button b, T[] values, T current, Cons<T> getter, int cols, Cons<Cell> sizer){
showSelectTable(b, (t, hide) -> {
ButtonGroup<Button> group = new ButtonGroup<>();
int i = 0;
@ -68,14 +75,14 @@ public abstract class LStatement{
sizer.get(t.button(p.toString(), Styles.logicTogglet, () -> {
getter.get(p);
hide.run();
}).checked(current == p).group(group));
}).self(c -> tooltip(c, "lenum." + p.name())).checked(current == p).group(group));
if(++i % cols == 0) t.row();
}
});
}
protected <T> void showSelect(Button b, T[] values, T current, Cons<T> getter){
protected <T extends Enum<T>> void showSelect(Button b, T[] values, T current, Cons<T> getter){
showSelect(b, values, current, getter, 4, c -> {});
}
@ -151,4 +158,5 @@ public abstract class LStatement{
public String name(){
return Strings.insertSpaces(getClass().getSimpleName().replace("Statement", ""));
}
}

View File

@ -15,6 +15,7 @@ import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.meta.*;
import static mindustry.logic.LCanvas.*;
import static mindustry.world.blocks.logic.LogicDisplay.*;
public class LStatements{
@ -355,7 +356,7 @@ public class LStatements{
}, 2, cell -> cell.size(100, 50)));
}, Styles.logict, () -> {}).size(90, 40).color(table.color).left().padLeft(2);
table.add(" of ");
table.add(" of ").self(this::param);
field(table, target, v -> target = v);
@ -394,7 +395,7 @@ public class LStatements{
table.defaults().left();
if(buildFrom()){
table.add(" from ");
table.add(" from ").self(this::param);
fields(table, radar, v -> radar = v);
@ -405,7 +406,7 @@ public class LStatements{
int fi = i;
Prov<RadarTarget> get = () -> (fi == 0 ? target1 : fi == 1 ? target2 : target3);
table.add(i == 0 ? " target " : " and ");
table.add(i == 0 ? " target " : " and ").self(this::param);
table.button(b -> {
b.label(() -> get.get().name());
@ -419,13 +420,13 @@ public class LStatements{
}
}
table.add(" order ");
table.add(" order ").self(this::param);
fields(table, sortOrder, v -> sortOrder = v);
table.row();
table.add(" sort ");
table.add(" sort ").self(this::param);
table.button(b -> {
b.label(() -> sort.name());
@ -434,7 +435,7 @@ public class LStatements{
}, 2, cell -> cell.size(100, 50)));
}, Styles.logict, () -> {}).size(90, 40).color(table.color).left().padLeft(2);
table.add(" output ");
table.add(" output ").self(this::param);
fields(table, output, v -> output = v);
}
@ -511,7 +512,7 @@ public class LStatements{
i.button(sensor.name(), Styles.cleart, () -> {
stype("@" + sensor.name());
hide.run();
}).size(240f, 40f).row();
}).size(240f, 40f).self(c -> tooltip(c, "lenum." + sensor.name())).row();
}
})
};
@ -538,7 +539,7 @@ public class LStatements{
}));
}, Styles.logict, () -> {}).size(40f).padLeft(-1).color(table.color);
table.add(" in ");
table.add(" in ").self(this::param);
field(table, from, str -> from = str);
}
@ -900,7 +901,7 @@ public class LStatements{
void rebuild(Table table){
table.clearChildren();
table.add(" find ").left();
table.add(" find ").left().self(this::param);;
table.button(b -> {
b.label(() -> locate.name());
@ -913,14 +914,14 @@ public class LStatements{
switch(locate){
case building -> {
row(table);
table.add(" type ").left();
table.add(" group ").left().self(this::param);;
table.button(b -> {
b.label(() -> flag.name());
b.clicked(() -> showSelect(b, BlockFlag.all, flag, t -> flag = t, 2, cell -> cell.size(110, 50)));
}, Styles.logict, () -> {}).size(110, 40).color(table.color).left().padLeft(2);
row(table);
table.add(" enemy ").left();
table.add(" enemy ").left().self(this::param);;
fields(table, enemy, str -> enemy = str);
@ -928,7 +929,7 @@ public class LStatements{
}
case ore -> {
table.add(" ore ").left();
table.add(" ore ").left().self(this::param);
table.table(ts -> {
ts.color.set(table.color);
@ -965,19 +966,19 @@ public class LStatements{
}
}
table.add(" outX ").left();
table.add(" outX ").left().self(this::param);
fields(table, outX, str -> outX = str);
table.add(" outY ").left();
table.add(" outY ").left().self(this::param);
fields(table, outY, str -> outY = str);
row(table);
table.add(" found ").left();
table.add(" found ").left().self(this::param);
fields(table, outFound, str -> outFound = str);
if(locate != LLocate.ore){
table.add(" building ").left();
table.add(" building ").left().self(this::param);
fields(table, outBuild, str -> outBuild = str);
}

View File

@ -10,6 +10,7 @@ import mindustry.ui.*;
import mindustry.ui.dialogs.*;
import static mindustry.Vars.*;
import static mindustry.logic.LCanvas.*;
public class LogicDialog extends BaseDialog{
public LCanvas canvas;
@ -72,7 +73,7 @@ public class LogicDialog extends BaseDialog{
t.button(example.name(), style, () -> {
canvas.add(prov.get());
dialog.hide();
}).size(140f, 50f);
}).size(140f, 50f).self(c -> tooltip(c, "lst." + example.name()));
if(++i % 2 == 0) t.row();
}
});

View File

@ -320,6 +320,7 @@ public class SettingsMenuDialog extends SettingsDialog{
game.checkPref("blockreplace", true);
game.checkPref("conveyorpathfinding", true);
game.checkPref("hints", true);
game.checkPref("logichints", true);
if(!mobile){
game.checkPref("backgroundpause", true);

View File

@ -56,6 +56,7 @@ public enum SAchievement{
enablePixelation,
openWiki,
useAccelerator,
unlockAllZones,
;

View File

@ -54,6 +54,9 @@ public class SStats implements SteamUserStatsCallback{
if(Items.thorium.unlocked()) obtainThorium.complete();
if(Items.titanium.unlocked()) obtainTitanium.complete();
if(!content.sectors().contains(s -> s.locked())){
unlockAllZones.complete();
}
});
}
@ -197,6 +200,9 @@ public class SStats implements SteamUserStatsCallback{
Events.on(UnlockEvent.class, e -> {
if(e.content == Items.thorium) obtainThorium.complete();
if(e.content == Items.titanium) obtainTitanium.complete();
if(e.content instanceof SectorPreset && !content.sectors().contains(s -> s.locked())){
unlockAllZones.complete();
}
});
Events.run(Trigger.openWiki, openWiki::complete);

View File

@ -1,3 +1,3 @@
org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m
archash=6cf4a11de0770c3789face7fd32e3adee2b6792d
archash=8b6d59e004463585b333c8cda9ea91dd66f3bcee