diff --git a/core/src/mindustry/editor/WaveGraph.java b/core/src/mindustry/editor/WaveGraph.java index 2d64af5be9..8b5e2abae7 100644 --- a/core/src/mindustry/editor/WaveGraph.java +++ b/core/src/mindustry/editor/WaveGraph.java @@ -3,8 +3,11 @@ package mindustry.editor; 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.struct.*; @@ -19,7 +22,6 @@ import mindustry.ui.*; public class WaveGraph extends Table{ public Seq groups = new Seq<>(); - public int from = 0, to = 20; private Mode mode = Mode.counts; private int[][] values; @@ -30,9 +32,52 @@ public class WaveGraph extends Table{ private ObjectSet hidden = new ObjectSet<>(); private StringBuilder countStr = new StringBuilder(); + private float pan; + private float zoom = 1f; + private int from = 0, to = 20; + private int lastFrom = -1, lastTo = -1; + private float lastZoom = -1f; + + private float defaultSpace = Scl.scl(40f); + private FloatSeq points = new FloatSeq(40); + public WaveGraph(){ background(Tex.pane); + scrolled((scroll) -> { + zoom -= scroll * 2f / 10f * zoom; + clampZoom(); + }); + + touchable = Touchable.enabled; + addListener(new InputListener(){ + + @Override + public void enter(InputEvent event, float x, float y, int pointer, Element fromActor){ + requestScroll(); + } + }); + + addListener(new ElementGestureListener(){ + @Override + public void pan(InputEvent event, float x, float y, float deltaX, float deltaY){ + pan -= deltaX/zoom; + } + + @Override + public void zoom(InputEvent event, float initialDistance, float distance){ + if(lastZoom < 0) lastZoom = zoom; + + zoom = distance / initialDistance * lastZoom; + clampZoom(); + } + + @Override + public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){ + lastZoom = zoom; + } + }); + rect((x, y, width, height) -> { Lines.stroke(Scl.scl(3f)); countStr.setLength(0); @@ -42,39 +87,57 @@ public class WaveGraph extends Table{ GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new); Font font = Fonts.outline; - lay.setText(font, "1"); - int maxY = switch(mode){ case counts -> nextStep(max); case health -> nextStep((int)maxHealth); case totals -> nextStep(maxTotal); }; + lay.setText(font, maxY + ""); + + float spacing = zoom * defaultSpace; + pan = Math.max(pan, (width/2f)/zoom-defaultSpace); + float fh = lay.height; - float offsetX = Scl.scl(lay.width * (maxY + "").length() * 2), offsetY = Scl.scl(22f) + fh + Scl.scl(5f); + float offsetX = lay.width, offsetY = Scl.scl(22f) + fh + Scl.scl(5f); + float graphX = x + offsetX - pan * zoom + width/2f, graphY = y + offsetY, graphW = width - offsetX, graphH = height - offsetY; - float graphX = x + offsetX, graphY = y + offsetY, graphW = width - offsetX, graphH = height - offsetY; - float spacing = graphW / (values.length - 1); + float left = (x-graphX)/spacing, right = (x + width - graphX)/spacing; - int selcol = Rect.contains(x, y, width, height, mouse.x, mouse.y) ? Mathf.round((mouse.x - graphX) / spacing) : -1; + //int radius = Mathf.ceil(graphW / spacing / 2f); + + from = (int)left - 1; + to = (int)right + 1; + + if(lastFrom != from || lastTo != to){ + rebuild(); + } + + lastFrom = from; + lastTo = to; + + if(!clipBegin(x + offsetX, y + offsetY, graphW, graphH)) return; + + int selcol = Rect.contains(x, y, width, height, mouse.x, mouse.y) ? Mathf.round((mouse.x - graphX - (from * spacing)) / spacing) : -1; + if(selcol + from <= -1) selcol = -1; if(mode == Mode.counts){ for(UnitType type : used.orderedItems()){ Draw.color(color(type)); Draw.alpha(parentAlpha); - Lines.beginLine(); + beginLine(); for(int i = 0; i < values.length; i++){ int val = values[i][type.id]; - float cx = graphX + i * spacing, cy = graphY + val * graphH / maxY; - Lines.linePoint(cx, cy); + float cx = graphX + (i+from) * spacing, cy = graphY + val * graphH / maxY; + linePoint(cx, cy); } - Lines.endLine(); + endLine(); } }else if(mode == Mode.totals){ - Lines.beginLine(); + beginLine(); Draw.color(Pal.accent); for(int i = 0; i < values.length; i++){ @@ -83,13 +146,13 @@ public class WaveGraph extends Table{ sum += values[i][type.id]; } - float cx = graphX + i * spacing, cy = graphY + sum * graphH / maxY; - Lines.linePoint(cx, cy); + float cx = graphX + (i+from) * spacing, cy = graphY + sum * graphH / maxY; + linePoint(cx, cy); } - Lines.endLine(); + endLine(); }else if(mode == Mode.health){ - Lines.beginLine(); + beginLine(); Draw.color(Pal.health); for(int i = 0; i < values.length; i++){ @@ -98,17 +161,17 @@ public class WaveGraph extends Table{ sum += (type.health) * values[i][type.id]; } - float cx = graphX + i * spacing, cy = graphY + sum * graphH / maxY; - Lines.linePoint(cx, cy); + float cx = graphX + (i+from) * spacing, cy = graphY + sum * graphH / maxY; + linePoint(cx, cy); } - Lines.endLine(); + endLine(); } if(selcol >= 0 && selcol < values.length){ Draw.color(1f, 0f, 0f, 0.2f); - Fill.crect(selcol * spacing + graphX - spacing/2f, graphY, spacing, graphH); + Fill.crect((selcol+from) * spacing + graphX - spacing/2f, graphY, spacing, graphH); Draw.color(); font.getData().setScale(1.5f); for(UnitType type : used.orderedItems()){ @@ -118,10 +181,12 @@ public class WaveGraph extends Table{ } } float pad = Scl.scl(5f); - font.draw(countStr, selcol * spacing + graphX - spacing/2f + pad, graphY + graphH - pad); + font.draw(countStr, (selcol+from) * spacing + graphX - spacing/2f + pad, graphY + graphH - pad); font.getData().setScale(1f); } + clipEnd(); + //how many numbers can fit here float totalMarks = Mathf.clamp(maxY, 1, 10); @@ -131,7 +196,7 @@ public class WaveGraph extends Table{ Draw.alpha(0.1f); for(int i = 0; i < maxY; i += markSpace){ - float cy = graphY + i * graphH / maxY, cx = graphX; + float cy = graphY + i * graphH / maxY, cx = offsetX + x; Lines.line(cx, cy, cx + graphW, cy); @@ -145,9 +210,11 @@ public class WaveGraph extends Table{ font.setColor(Color.lightGray); for(int i = 0; i < values.length; i++){ - float cy = y + fh, cx = graphX + graphW / (values.length - 1) * i; + float cy = y + fh, cx = graphX + spacing * (i + from); - Lines.line(cx, cy, cx, cy + len); + if(cx >= x + offsetX && cx <= x + offsetX + graphW){ + Lines.line(cx, cy, cx, cy + len); + } if(i == selcol){ font.draw("" + (i + from + 1), cx, cy - Scl.scl(2f), Align.center); } @@ -177,6 +244,28 @@ public class WaveGraph extends Table{ }).growX(); } + private void clampZoom(){ + zoom = Mathf.clamp(zoom, 0.5f / Scl.scl(1f), 40f / Scl.scl(1f)); + } + + private void linePoint(float x, float y){ + points.add(x, y); + } + + private void beginLine(){ + points.clear(); + } + + private void endLine(){ + var items = points.items; + for(int i = 0; i < points.size - 2; i += 2){ + Lines.line(items[i], items[i + 1], items[i + 2], items[i + 3], false); + Fill.circle(items[i], items[i + 1], Lines.getStroke()/2f); + } + Fill.circle(items[points.size - 2], items[points.size - 1], Lines.getStroke()); + points.clear(); + } + public void rebuild(){ values = new int[to - from + 1][Vars.content.units().size]; used.clear(); @@ -237,6 +326,8 @@ public class WaveGraph extends Table{ } }).scrollY(false); + colors.act(0.000001f); + for(UnitType type : hidden){ used.remove(type); } diff --git a/core/src/mindustry/editor/WaveInfoDialog.java b/core/src/mindustry/editor/WaveInfoDialog.java index e99008e54e..818a31844a 100644 --- a/core/src/mindustry/editor/WaveInfoDialog.java +++ b/core/src/mindustry/editor/WaveInfoDialog.java @@ -6,7 +6,6 @@ import arc.graphics.*; import arc.input.*; import arc.math.*; import arc.math.geom.*; -import arc.scene.*; import arc.scene.event.*; import arc.scene.style.*; import arc.scene.ui.*; @@ -28,7 +27,6 @@ import static mindustry.Vars.*; import static mindustry.game.SpawnGroup.*; public class WaveInfoDialog extends BaseDialog{ - private int start = 0, displayed = 20; Seq groups = new Seq<>(); private @Nullable SpawnGroup expandedGroup; @@ -37,7 +35,6 @@ public class WaveInfoDialog extends BaseDialog{ private @Nullable UnitType filterType; private Sort sort = Sort.begin; private boolean reverseSort = false; - private float updateTimer, updatePeriod = 1f; private boolean checkedSpawns; private WaveGraph graph = new WaveGraph(); @@ -94,30 +91,6 @@ public class WaveInfoDialog extends BaseDialog{ dialog.show(); }).size(250f, 64f); - buttons.defaults().width(60f); - - buttons.button("<", () -> {}).update(t -> { - if(t.getClickListener().isPressed()){ - shift(-1); - } - }); - buttons.button(">", () -> {}).update(t -> { - if(t.getClickListener().isPressed()){ - shift(1); - } - }); - - buttons.button("-", () -> {}).update(t -> { - if(t.getClickListener().isPressed()){ - view(-1); - } - }); - buttons.button("+", () -> {}).update(t -> { - if(t.getClickListener().isPressed()){ - view(1); - } - }); - if(experimental){ buttons.button(Core.bundle.get("waves.random"), Icon.refresh, () -> { groups.clear(); @@ -127,26 +100,6 @@ public class WaveInfoDialog extends BaseDialog{ } } - void view(int amount){ - updateTimer += Time.delta; - if(updateTimer >= updatePeriod){ - displayed += amount; - if(displayed < 5) displayed = 5; - updateTimer = 0f; - updateWaves(); - } - } - - void shift(int amount){ - updateTimer += Time.delta; - if(updateTimer >= updatePeriod){ - start += amount; - if(start < 0) start = 0; - updateTimer = 0f; - updateWaves(); - } - } - void setup(){ groups = JsonIO.copy(state.rules.spawns.isEmpty() ? waves.get() : state.rules.spawns); if(groups == null) groups = new Seq<>(); @@ -157,7 +110,6 @@ public class WaveInfoDialog extends BaseDialog{ s.image(Icon.zoom).padRight(8); s.field(search < 0 ? "" : (search + 1) + "", TextFieldFilter.digitsOnly, text -> { search = groups.any() ? Strings.parseInt(text, 0) - 1 : -1; - start = Math.max(search - (displayed / 2) - (displayed % 2), 0); buildGroups(); }).growX().maxTextLength(8).get().setMessageText("@waves.search"); s.button(Icon.units, Styles.emptyi, () -> showUnits(type -> filterType = type, true)).size(46f).tooltip("@waves.filter") @@ -202,19 +154,6 @@ public class WaveInfoDialog extends BaseDialog{ cont.add(graph = new WaveGraph()).grow(); - graph.scrolled((scroll) -> { - view(Mathf.sign(scroll)); - }); - - graph.touchable = Touchable.enabled; - graph.addListener(new InputListener(){ - - @Override - public void enter(InputEvent event, float x, float y, int pointer, Element fromActor){ - graph.requestScroll(); - } - }); - buildGroups(); } @@ -507,8 +446,6 @@ public class WaveInfoDialog extends BaseDialog{ void updateWaves(){ graph.groups = groups; - graph.from = start; - graph.to = start + displayed; graph.rebuild(); } } \ No newline at end of file