diff --git a/src/itdelatrisu/opsu/Utils.java b/src/itdelatrisu/opsu/Utils.java index 7dd46fbf..3043131f 100644 --- a/src/itdelatrisu/opsu/Utils.java +++ b/src/itdelatrisu/opsu/Utils.java @@ -661,4 +661,13 @@ public class Utils { }; } + public static class Pair { + public F first; + public S second; + public Pair(F first, S second) { + this.first = first; + this.second = second; + } + } + } diff --git a/src/itdelatrisu/opsu/objects/Slider.java b/src/itdelatrisu/opsu/objects/Slider.java index fbd8e698..eea5d0a4 100644 --- a/src/itdelatrisu/opsu/objects/Slider.java +++ b/src/itdelatrisu/opsu/objects/Slider.java @@ -466,13 +466,14 @@ public class Slider extends GameObject { int curvelen = curve.getCurvePoints().length; if (Options.isMergingSliders()) { if (Options.isShrinkingSliders() && curveIntervalFrom > 0) { - if (repeats % 2 == 0) { - game.spliceSliderCurve(baseSliderFrom + (int) ((1d - curveIntervalFrom) * curvelen) - 1, baseSliderFrom + curvelen); + if (hitObject.getRepeatCount() % 2 == 0) { + game.addMergedSliderPointsToRender(baseSliderFrom, baseSliderFrom + (int) ((1d - curveIntervalFrom) * curvelen)); } else { - game.setSlidercurveFrom(baseSliderFrom + (int) (curveIntervalFrom * curvelen) + 1); + game.addMergedSliderPointsToRender(baseSliderFrom + (int) (curveIntervalFrom * curvelen) + 1, baseSliderFrom + (int) (curveIntervalTo * curve.getCurvePoints().length)); } + } else { + game.addMergedSliderPointsToRender(baseSliderFrom, baseSliderFrom + (int) (curveIntervalTo * curve.getCurvePoints().length)); } - game.setSlidercurveTo(baseSliderFrom + (int) (curveIntervalTo * curve.getCurvePoints().length)); } else { if (Options.isShrinkingSliders() && curveIntervalFrom > 0 && repeats % 2 == 0) { if (Options.isFallbackSliders()) { @@ -687,9 +688,6 @@ public class Slider extends GameObject { // calculate and send slider result hitResult(); - if (Options.isMergingSliders()) { - game.setSlidercurveFrom(baseSliderFrom + curve.getCurvePoints().length + 1); - } return true; } diff --git a/src/itdelatrisu/opsu/objects/curves/Curve.java b/src/itdelatrisu/opsu/objects/curves/Curve.java index 18f54f62..7ab8ccd3 100644 --- a/src/itdelatrisu/opsu/objects/curves/Curve.java +++ b/src/itdelatrisu/opsu/objects/curves/Curve.java @@ -20,7 +20,6 @@ package itdelatrisu.opsu.objects.curves; import itdelatrisu.opsu.GameImage; import itdelatrisu.opsu.Options; -import itdelatrisu.opsu.Utils; import itdelatrisu.opsu.beatmap.HitObject; import itdelatrisu.opsu.render.CurveRenderState; import itdelatrisu.opsu.skins.Skin; @@ -31,7 +30,6 @@ import org.lwjgl.opengl.GLContext; import org.newdawn.slick.Color; import org.newdawn.slick.Image; import org.newdawn.slick.util.Log; -import yugecin.opsudance.objects.curves.FakeCombinedCurve; /** * Representation of a curve. @@ -43,7 +41,7 @@ public abstract class Curve { protected static float CURVE_POINTS_SEPERATION = 2.5f; /** The curve border color. */ - private static Color borderColor; + protected static Color borderColor; /** Whether mmsliders are supported. */ private static boolean mmsliderSupported = false; @@ -58,7 +56,7 @@ public abstract class Curve { protected float[] sliderX, sliderY; /** Per-curve render-state used for the new style curve renders. */ - private CurveRenderState renderState; + protected CurveRenderState renderState; /** Points along the curve (set by inherited classes). */ public Vec2f[] curve; @@ -150,14 +148,14 @@ public abstract class Curve { // mmsliders else { if (renderState == null) - renderState = new CurveRenderState(hitObject, curve, this instanceof FakeCombinedCurve); + renderState = new CurveRenderState(hitObject, curve, false); renderState.draw(color, borderColor, from, to); } } public void splice(int from, int to) { if (renderState == null) - renderState = new CurveRenderState(hitObject, curve, this instanceof FakeCombinedCurve); + renderState = new CurveRenderState(hitObject, curve, false); renderState.splice(from, to); } diff --git a/src/itdelatrisu/opsu/render/CurveRenderState.java b/src/itdelatrisu/opsu/render/CurveRenderState.java index f2d7e3cb..9670680d 100644 --- a/src/itdelatrisu/opsu/render/CurveRenderState.java +++ b/src/itdelatrisu/opsu/render/CurveRenderState.java @@ -26,6 +26,7 @@ import itdelatrisu.opsu.objects.curves.Vec2f; import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; +import java.util.LinkedList; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.EXTFramebufferObject; @@ -69,6 +70,8 @@ public class CurveRenderState { private int spliceFrom; private int spliceTo; + protected LinkedList> pointsToRender; + private final int mirrors; /** @@ -138,6 +141,14 @@ public class CurveRenderState { lastPointDrawn = -1; // force redraw } + public void draw(Color color, Color borderColor, LinkedList> pointsToRender) { + lastPointDrawn = -1; + firstPointDrawn = -1; + this.pointsToRender = pointsToRender; + draw(color, borderColor, 0, curve.length); + this.pointsToRender = null; + } + /** * Draw a curve to the screen that's tinted with `color`. The first time * this is called this caches the image result of the curve and on subsequent @@ -348,7 +359,11 @@ public class CurveRenderState { max = 1; } for (int i = 0; i < max; i++) { - renderCurve(from, to, i); + if (pointsToRender == null) { + renderCurve(from, to, i); + } else { + renderCurve(i); + } } GL11.glFlush(); GL20.glDisableVertexAttribArray(staticState.texCoordLoc); @@ -370,6 +385,15 @@ public class CurveRenderState { } } + private void renderCurve(int mirror) { + for (Utils.Pair point : pointsToRender) { + for (int i = point.first * 2; i < point.second * 2 - 1; ++i) { + final int index = i + curve.length * 2 * mirror; + GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, index * (NewCurveStyleState.DIVIDES + 2), NewCurveStyleState.DIVIDES + 2); + } + } + } + /** * Fill {@code buff} with the texture coordinates and positions for a cone * that has its center at the coordinates {@code (x1,y1)}. diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index b73ed03e..6fa5d414 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -382,17 +382,6 @@ public class Game extends ComplexOpsuState { if (objectIndex > 0) { objectIndex--; } - if (Options.isMergingSliders()) { - int obj = objectIndex; - while (obj < gameObjects.length) { - if (gameObjects[obj] instanceof Slider) { - slidercurveFrom = slidercurveTo = ((Slider) gameObjects[obj]).baseSliderFrom; - break; - } - obj++; - } - spliceSliderCurve(-1, -1); - } Dancer.instance.setObjectIndex(objectIndex); storyboardOverlay.updateIndex(objectIndex); lastReplayTime = beatmap.objects[objectIndex].getTime(); @@ -1680,9 +1669,6 @@ public class Game extends ComplexOpsuState { } } - slidercurveFrom = 0; - slidercurveTo = 0; - Dancer.instance.setGameObjects(gameObjects); storyboardOverlay.setGameObjects(gameObjects); if (!skippedToCheckpoint) { @@ -1738,19 +1724,8 @@ public class Game extends ComplexOpsuState { GameMod.loadModState(previousMods); } - private int slidercurveFrom; - private int slidercurveTo; - - public void setSlidercurveFrom(int slidercurveFrom) { - this.slidercurveFrom = Math.max(slidercurveFrom, this.slidercurveFrom); - } - - public void setSlidercurveTo(int slidercurveTo) { - this.slidercurveTo = Math.max(slidercurveTo, this.slidercurveTo); - } - - public void spliceSliderCurve(int from, int to) { - this.knorkesliders.splice(from, to); + public void addMergedSliderPointsToRender(int from, int to) { + knorkesliders.addRange(from, to); } /** @@ -1767,7 +1742,8 @@ public class Game extends ComplexOpsuState { } if (Options.isMergingSliders() && knorkesliders != null) { - knorkesliders.draw(Color.white, this.slidercurveFrom, this.slidercurveTo); + knorkesliders.draw(Color.white); + knorkesliders.initForFrame(); /* if (Options.isMirror()) { g.pushTransform(); diff --git a/src/yugecin/opsudance/objects/curves/FakeCombinedCurve.java b/src/yugecin/opsudance/objects/curves/FakeCombinedCurve.java index 788c3886..79239640 100644 --- a/src/yugecin/opsudance/objects/curves/FakeCombinedCurve.java +++ b/src/yugecin/opsudance/objects/curves/FakeCombinedCurve.java @@ -17,15 +17,38 @@ */ package yugecin.opsudance.objects.curves; +import itdelatrisu.opsu.Utils; import itdelatrisu.opsu.beatmap.HitObject; import itdelatrisu.opsu.objects.curves.Curve; import itdelatrisu.opsu.objects.curves.Vec2f; +import itdelatrisu.opsu.render.CurveRenderState; +import org.newdawn.slick.Color; + +import java.util.LinkedList; public class FakeCombinedCurve extends Curve { + private LinkedList> pointsToRender; + public FakeCombinedCurve(Vec2f[] points) { super(new HitObject(0, 0, 0), false); this.curve = points; + pointsToRender = new LinkedList<>(); + } + + public void initForFrame() { + pointsToRender.clear(); + } + + public void addRange(int from, int to) { + pointsToRender.add(new Utils.Pair<>(from, to)); + } + + @Override + public void draw(Color color) { + if (renderState == null) + renderState = new CurveRenderState(hitObject, curve, true); + renderState.draw(color, borderColor, pointsToRender); } @Override