Trapezoidal jumps
I haven't checked this yet, but it seems like it also reduces the complexity (runtime) from ≈O(n^2) to ≈O(k^2 + n) (n = number of jump curves) (k = number of unique destinations) The worst case, that is k = n, is still O(n^2) but generally it's much more (scalably) performant. Thanks Arkanic for suggesting this! https://discord.com/channels/391020510269669376/663854113418641429/1256161815503704104 Co-authored-by: Arkanic <50847107+Arkanic@users.noreply.github.com>
This commit is contained in:
@@ -21,12 +21,12 @@ import mindustry.logic.LStatements.*;
|
||||
import mindustry.ui.*;
|
||||
|
||||
public class LCanvas extends Table{
|
||||
public static final int maxJumpsDrawn = 100;
|
||||
private static final int invalidJump = Integer.MAX_VALUE; // terrible hack
|
||||
//ew static variables
|
||||
static LCanvas canvas;
|
||||
private static boolean dynamicJumpHeights = false;
|
||||
private static boolean coloredJumps = false;
|
||||
private static boolean trapezoidalJumps = false;
|
||||
|
||||
public DragLayout statements;
|
||||
public ScrollPane pane;
|
||||
@@ -35,7 +35,6 @@ public class LCanvas extends Table{
|
||||
StatementElem dragging;
|
||||
StatementElem hovered;
|
||||
float targetWidth;
|
||||
int jumpCount = 0;
|
||||
boolean privileged;
|
||||
Seq<Tooltip> tooltips = new Seq<>();
|
||||
|
||||
@@ -114,6 +113,7 @@ public class LCanvas extends Table{
|
||||
|
||||
dynamicJumpHeights = Core.settings.getBool("dynamicjumpheights", false);
|
||||
coloredJumps = Core.settings.getBool("coloredjumps", false);
|
||||
trapezoidalJumps = Core.settings.getBool("trapezoidaljumps", false);
|
||||
|
||||
pane = pane(t -> {
|
||||
t.center();
|
||||
@@ -132,7 +132,6 @@ public class LCanvas extends Table{
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
jumpCount = 0;
|
||||
super.draw();
|
||||
}
|
||||
|
||||
@@ -205,6 +204,8 @@ public class LCanvas extends Table{
|
||||
boolean invalidated;
|
||||
public Group jumps = new WidgetGroup();
|
||||
private Seq<JumpCurve> processedJumps = new Seq<JumpCurve>();
|
||||
private IntMap<JumpCurve> reprBefore = new IntMap<JumpCurve>();
|
||||
private IntMap<JumpCurve> reprAfter = new IntMap<JumpCurve>();
|
||||
public boolean updateJumpHeights = true;
|
||||
private Color[] jumpColors = new Color[LExecutor.maxInstructions];
|
||||
|
||||
@@ -321,14 +322,32 @@ public class LCanvas extends Table{
|
||||
private void setJumpHeights(){
|
||||
SnapshotSeq<Element> jumpsChildren = jumps.getChildren();
|
||||
processedJumps.clear();
|
||||
jumpsChildren.each(e -> {
|
||||
if(e instanceof JumpCurve e2){
|
||||
if(trapezoidalJumps){
|
||||
reprBefore.clear();
|
||||
reprAfter.clear();
|
||||
jumpsChildren.each(e -> {
|
||||
if(!(e instanceof JumpCurve e2)) return;
|
||||
e2.prepareHeight();
|
||||
if(e2.jumpUIBegin != invalidJump){
|
||||
processedJumps.add(e2);
|
||||
if(e2.jumpUIBegin == invalidJump) return;
|
||||
if(e2.flipped){
|
||||
JumpCurve prev = reprAfter.get(e2.jumpUIBegin);
|
||||
if(prev != null && prev.jumpUIEnd >= e2.jumpUIEnd) return;
|
||||
reprAfter.put(e2.jumpUIBegin, e2);
|
||||
}else{
|
||||
JumpCurve prev = reprBefore.get(e2.jumpUIEnd);
|
||||
if(prev != null && prev.jumpUIBegin <= e2.jumpUIBegin) return;
|
||||
reprBefore.put(e2.jumpUIEnd, e2);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
processedJumps.add(reprBefore.values().toArray());
|
||||
processedJumps.add(reprAfter.values().toArray());
|
||||
} else {
|
||||
jumpsChildren.each(e -> {
|
||||
if(!(e instanceof JumpCurve e2)) return;
|
||||
e2.prepareHeight();
|
||||
processedJumps.add(e2);
|
||||
});
|
||||
}
|
||||
processedJumps.sort((a,b) -> a.jumpUIBegin - b.jumpUIBegin);
|
||||
|
||||
Seq<JumpCurve> occupiers = Pools.obtain(Seq.class, Seq<JumpCurve>::new);
|
||||
@@ -351,6 +370,15 @@ public class LCanvas extends Table{
|
||||
occupiers.clear();
|
||||
Pools.free(occupied);
|
||||
Pools.free(occupiers);
|
||||
|
||||
if(trapezoidalJumps){
|
||||
jumpsChildren.each(e -> {
|
||||
if(!(e instanceof JumpCurve e2)) return;
|
||||
if(e2.jumpUIBegin == invalidJump) return;
|
||||
e2.predHeight = e2.flipped ? reprAfter.get(e2.jumpUIBegin).predHeight : reprBefore.get(e2.jumpUIEnd).predHeight;
|
||||
e2.markedDone = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private int getJumpHeight(int index, Seq<JumpCurve> occupiers, Bits occupied){
|
||||
@@ -661,8 +689,9 @@ public class LCanvas extends Table{
|
||||
public int predHeight = 0;
|
||||
public boolean markedDone = false;
|
||||
public int jumpUIBegin = 0, jumpUIEnd = 0;
|
||||
public boolean flipped = false;
|
||||
|
||||
private float uiHeight = 100f;
|
||||
private float uiHeight = 60f;
|
||||
|
||||
public JumpCurve(JumpButton button){
|
||||
this.button = button;
|
||||
@@ -679,12 +708,6 @@ public class LCanvas extends Table{
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
canvas.jumpCount ++;
|
||||
|
||||
if(canvas.jumpCount > maxJumpsDrawn && !button.selecting && !button.listener.isOver()){
|
||||
return;
|
||||
}
|
||||
|
||||
Element hover = button.to.get() == null && button.selecting ? canvas.hovered : button.to.get();
|
||||
boolean draw = false;
|
||||
Vec2 t = Tmp.v1, r = Tmp.v2;
|
||||
@@ -723,18 +746,19 @@ public class LCanvas extends Table{
|
||||
Draw.color(button.color);
|
||||
|
||||
// exponential smoothing
|
||||
uiHeight = Mathf.lerp(100f + 100f * (float) predHeight, uiHeight, dynamicJumpHeights ? Mathf.pow(0.9f, Time.delta) : 0);
|
||||
|
||||
//square jumps
|
||||
if(false){
|
||||
float len = Scl.scl(Mathf.randomSeed(hashCode(), 10, 50));
|
||||
|
||||
float maxX = Math.max(x, x2) + len;
|
||||
uiHeight = Mathf.lerp(
|
||||
trapezoidalJumps ? 60f + 20f * (float) predHeight : 100f + 100f * (float) predHeight,
|
||||
uiHeight,
|
||||
dynamicJumpHeights ? Mathf.pow(0.9f, Time.delta) : 0
|
||||
);
|
||||
|
||||
//trapezoidal jumps
|
||||
if(trapezoidalJumps){
|
||||
float dy = (y2 == y ? 0f : y2 > y ? 1f : -1f) * uiHeight * 0.5f;
|
||||
Lines.beginLine();
|
||||
Lines.linePoint(x, y);
|
||||
Lines.linePoint(maxX, y);
|
||||
Lines.linePoint(maxX, y2);
|
||||
Lines.linePoint(x + uiHeight, y + dy);
|
||||
Lines.linePoint(x + uiHeight, y2 - dy);
|
||||
Lines.linePoint(x2, y2);
|
||||
Lines.endLine();
|
||||
return;
|
||||
@@ -753,11 +777,13 @@ public class LCanvas extends Table{
|
||||
if(this.button.to.get() == null){
|
||||
this.markedDone = true;
|
||||
this.predHeight = 0;
|
||||
this.flipped = false;
|
||||
this.jumpUIBegin = this.jumpUIEnd = invalidJump;
|
||||
} else {
|
||||
this.markedDone = false;
|
||||
int i = this.button.elem.index;
|
||||
int j = this.button.to.get().index;
|
||||
this.flipped = i >= j;
|
||||
this.jumpUIBegin = Math.min(i,j);
|
||||
this.jumpUIEnd = Math.max(i,j);
|
||||
// height will be recalculated later
|
||||
|
||||
@@ -505,6 +505,7 @@ public class SettingsMenuDialog extends BaseDialog{
|
||||
|
||||
graphics.checkPref("dynamicjumpheights", true);
|
||||
graphics.checkPref("coloredjumps", true);
|
||||
graphics.checkPref("trapezoidaljumps", true);
|
||||
}
|
||||
|
||||
public void exportData(Fi file) throws IOException{
|
||||
|
||||
Reference in New Issue
Block a user