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:
co-authored by
Arkanic
parent
c5b8133ff9
commit
a5de131711
@@ -1227,6 +1227,7 @@ setting.showweather.name = Show Weather Graphics
|
|||||||
setting.hidedisplays.name = Hide Logic Displays
|
setting.hidedisplays.name = Hide Logic Displays
|
||||||
setting.dynamicjumpheights.name = Dynamic Jump Heights
|
setting.dynamicjumpheights.name = Dynamic Jump Heights
|
||||||
setting.coloredjumps.name = Colored Jumps
|
setting.coloredjumps.name = Colored Jumps
|
||||||
|
setting.trapezoidaljumps.name = Trapezoidal Jumps
|
||||||
setting.macnotch.name = Adapt interface to display notch
|
setting.macnotch.name = Adapt interface to display notch
|
||||||
setting.macnotch.description = Restart required to apply changes
|
setting.macnotch.description = Restart required to apply changes
|
||||||
steam.friendsonly = Friends Only
|
steam.friendsonly = Friends Only
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ import mindustry.logic.LStatements.*;
|
|||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
|
|
||||||
public class LCanvas extends Table{
|
public class LCanvas extends Table{
|
||||||
public static final int maxJumpsDrawn = 100;
|
|
||||||
private static final int invalidJump = Integer.MAX_VALUE; // terrible hack
|
private static final int invalidJump = Integer.MAX_VALUE; // terrible hack
|
||||||
//ew static variables
|
//ew static variables
|
||||||
static LCanvas canvas;
|
static LCanvas canvas;
|
||||||
private static boolean dynamicJumpHeights = false;
|
private static boolean dynamicJumpHeights = false;
|
||||||
private static boolean coloredJumps = false;
|
private static boolean coloredJumps = false;
|
||||||
|
private static boolean trapezoidalJumps = false;
|
||||||
|
|
||||||
public DragLayout statements;
|
public DragLayout statements;
|
||||||
public ScrollPane pane;
|
public ScrollPane pane;
|
||||||
@@ -35,7 +35,6 @@ public class LCanvas extends Table{
|
|||||||
StatementElem dragging;
|
StatementElem dragging;
|
||||||
StatementElem hovered;
|
StatementElem hovered;
|
||||||
float targetWidth;
|
float targetWidth;
|
||||||
int jumpCount = 0;
|
|
||||||
boolean privileged;
|
boolean privileged;
|
||||||
Seq<Tooltip> tooltips = new Seq<>();
|
Seq<Tooltip> tooltips = new Seq<>();
|
||||||
|
|
||||||
@@ -114,6 +113,7 @@ public class LCanvas extends Table{
|
|||||||
|
|
||||||
dynamicJumpHeights = Core.settings.getBool("dynamicjumpheights", false);
|
dynamicJumpHeights = Core.settings.getBool("dynamicjumpheights", false);
|
||||||
coloredJumps = Core.settings.getBool("coloredjumps", false);
|
coloredJumps = Core.settings.getBool("coloredjumps", false);
|
||||||
|
trapezoidalJumps = Core.settings.getBool("trapezoidaljumps", false);
|
||||||
|
|
||||||
pane = pane(t -> {
|
pane = pane(t -> {
|
||||||
t.center();
|
t.center();
|
||||||
@@ -132,7 +132,6 @@ public class LCanvas extends Table{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
jumpCount = 0;
|
|
||||||
super.draw();
|
super.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,6 +204,8 @@ public class LCanvas extends Table{
|
|||||||
boolean invalidated;
|
boolean invalidated;
|
||||||
public Group jumps = new WidgetGroup();
|
public Group jumps = new WidgetGroup();
|
||||||
private Seq<JumpCurve> processedJumps = new Seq<JumpCurve>();
|
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;
|
public boolean updateJumpHeights = true;
|
||||||
private Color[] jumpColors = new Color[LExecutor.maxInstructions];
|
private Color[] jumpColors = new Color[LExecutor.maxInstructions];
|
||||||
|
|
||||||
@@ -321,14 +322,32 @@ public class LCanvas extends Table{
|
|||||||
private void setJumpHeights(){
|
private void setJumpHeights(){
|
||||||
SnapshotSeq<Element> jumpsChildren = jumps.getChildren();
|
SnapshotSeq<Element> jumpsChildren = jumps.getChildren();
|
||||||
processedJumps.clear();
|
processedJumps.clear();
|
||||||
jumpsChildren.each(e -> {
|
if(trapezoidalJumps){
|
||||||
if(e instanceof JumpCurve e2){
|
reprBefore.clear();
|
||||||
|
reprAfter.clear();
|
||||||
|
jumpsChildren.each(e -> {
|
||||||
|
if(!(e instanceof JumpCurve e2)) return;
|
||||||
e2.prepareHeight();
|
e2.prepareHeight();
|
||||||
if(e2.jumpUIBegin != invalidJump){
|
if(e2.jumpUIBegin == invalidJump) return;
|
||||||
processedJumps.add(e2);
|
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);
|
processedJumps.sort((a,b) -> a.jumpUIBegin - b.jumpUIBegin);
|
||||||
|
|
||||||
Seq<JumpCurve> occupiers = Pools.obtain(Seq.class, Seq<JumpCurve>::new);
|
Seq<JumpCurve> occupiers = Pools.obtain(Seq.class, Seq<JumpCurve>::new);
|
||||||
@@ -351,6 +370,15 @@ public class LCanvas extends Table{
|
|||||||
occupiers.clear();
|
occupiers.clear();
|
||||||
Pools.free(occupied);
|
Pools.free(occupied);
|
||||||
Pools.free(occupiers);
|
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){
|
private int getJumpHeight(int index, Seq<JumpCurve> occupiers, Bits occupied){
|
||||||
@@ -661,8 +689,9 @@ public class LCanvas extends Table{
|
|||||||
public int predHeight = 0;
|
public int predHeight = 0;
|
||||||
public boolean markedDone = false;
|
public boolean markedDone = false;
|
||||||
public int jumpUIBegin = 0, jumpUIEnd = 0;
|
public int jumpUIBegin = 0, jumpUIEnd = 0;
|
||||||
|
public boolean flipped = false;
|
||||||
|
|
||||||
private float uiHeight = 100f;
|
private float uiHeight = 60f;
|
||||||
|
|
||||||
public JumpCurve(JumpButton button){
|
public JumpCurve(JumpButton button){
|
||||||
this.button = button;
|
this.button = button;
|
||||||
@@ -679,12 +708,6 @@ public class LCanvas extends Table{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
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();
|
Element hover = button.to.get() == null && button.selecting ? canvas.hovered : button.to.get();
|
||||||
boolean draw = false;
|
boolean draw = false;
|
||||||
Vec2 t = Tmp.v1, r = Tmp.v2;
|
Vec2 t = Tmp.v1, r = Tmp.v2;
|
||||||
@@ -723,18 +746,19 @@ public class LCanvas extends Table{
|
|||||||
Draw.color(button.color);
|
Draw.color(button.color);
|
||||||
|
|
||||||
// exponential smoothing
|
// exponential smoothing
|
||||||
uiHeight = Mathf.lerp(100f + 100f * (float) predHeight, uiHeight, dynamicJumpHeights ? Mathf.pow(0.9f, Time.delta) : 0);
|
uiHeight = Mathf.lerp(
|
||||||
|
trapezoidalJumps ? 60f + 20f * (float) predHeight : 100f + 100f * (float) predHeight,
|
||||||
//square jumps
|
uiHeight,
|
||||||
if(false){
|
dynamicJumpHeights ? Mathf.pow(0.9f, Time.delta) : 0
|
||||||
float len = Scl.scl(Mathf.randomSeed(hashCode(), 10, 50));
|
);
|
||||||
|
|
||||||
float maxX = Math.max(x, x2) + len;
|
|
||||||
|
|
||||||
|
//trapezoidal jumps
|
||||||
|
if(trapezoidalJumps){
|
||||||
|
float dy = (y2 == y ? 0f : y2 > y ? 1f : -1f) * uiHeight * 0.5f;
|
||||||
Lines.beginLine();
|
Lines.beginLine();
|
||||||
Lines.linePoint(x, y);
|
Lines.linePoint(x, y);
|
||||||
Lines.linePoint(maxX, y);
|
Lines.linePoint(x + uiHeight, y + dy);
|
||||||
Lines.linePoint(maxX, y2);
|
Lines.linePoint(x + uiHeight, y2 - dy);
|
||||||
Lines.linePoint(x2, y2);
|
Lines.linePoint(x2, y2);
|
||||||
Lines.endLine();
|
Lines.endLine();
|
||||||
return;
|
return;
|
||||||
@@ -753,11 +777,13 @@ public class LCanvas extends Table{
|
|||||||
if(this.button.to.get() == null){
|
if(this.button.to.get() == null){
|
||||||
this.markedDone = true;
|
this.markedDone = true;
|
||||||
this.predHeight = 0;
|
this.predHeight = 0;
|
||||||
|
this.flipped = false;
|
||||||
this.jumpUIBegin = this.jumpUIEnd = invalidJump;
|
this.jumpUIBegin = this.jumpUIEnd = invalidJump;
|
||||||
} else {
|
} else {
|
||||||
this.markedDone = false;
|
this.markedDone = false;
|
||||||
int i = this.button.elem.index;
|
int i = this.button.elem.index;
|
||||||
int j = this.button.to.get().index;
|
int j = this.button.to.get().index;
|
||||||
|
this.flipped = i >= j;
|
||||||
this.jumpUIBegin = Math.min(i,j);
|
this.jumpUIBegin = Math.min(i,j);
|
||||||
this.jumpUIEnd = Math.max(i,j);
|
this.jumpUIEnd = Math.max(i,j);
|
||||||
// height will be recalculated later
|
// height will be recalculated later
|
||||||
|
|||||||
@@ -505,6 +505,7 @@ public class SettingsMenuDialog extends BaseDialog{
|
|||||||
|
|
||||||
graphics.checkPref("dynamicjumpheights", true);
|
graphics.checkPref("dynamicjumpheights", true);
|
||||||
graphics.checkPref("coloredjumps", true);
|
graphics.checkPref("coloredjumps", true);
|
||||||
|
graphics.checkPref("trapezoidaljumps", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exportData(Fi file) throws IOException{
|
public void exportData(Fi file) throws IOException{
|
||||||
|
|||||||
Reference in New Issue
Block a user