From 1803d714a5420c7dde05133e40d9e0368c296eeb Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 12:16:32 +0100 Subject: [PATCH 01/11] basic implementation of sbv2 --- src/itdelatrisu/opsu/states/Game.java | 11 +- .../opsudance/sbv2/StoryboardMove.java | 33 ++++ .../opsudance/sbv2/StoryboardMoveImpl.java | 146 ++++++++++++++++++ .../sbv2/movers/LinearStoryboardMover.java | 47 ++++++ .../sbv2/movers/StoryboardMover.java | 53 +++++++ src/yugecin/opsudance/ui/SBOverlay.java | 15 +- src/yugecin/opsudance/ui/SimpleButton.java | 72 +++++++++ 7 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 src/yugecin/opsudance/sbv2/StoryboardMove.java create mode 100644 src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java create mode 100644 src/yugecin/opsudance/sbv2/movers/LinearStoryboardMover.java create mode 100644 src/yugecin/opsudance/sbv2/movers/StoryboardMover.java create mode 100644 src/yugecin/opsudance/ui/SimpleButton.java diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index ada3cc92..56cab90a 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -72,6 +72,7 @@ import org.newdawn.slick.state.transition.EmptyTransition; import org.newdawn.slick.state.transition.FadeInTransition; import yugecin.opsudance.*; import yugecin.opsudance.objects.curves.FakeCombinedCurve; +import yugecin.opsudance.sbv2.MoveStoryboard; import yugecin.opsudance.ui.SBOverlay; /** @@ -313,6 +314,7 @@ public class Game extends BasicGameState { private final int state; private final Cursor mirrorCursor; + private MoveStoryboard msb; private SBOverlay sbOverlay; private FakeCombinedCurve knorkesliders; @@ -363,7 +365,8 @@ public class Game extends BasicGameState { @Override public void init(GameContainer container, StateBasedGame game) throws SlickException { - this.sbOverlay = new SBOverlay(this, container); + this.msb = new MoveStoryboard(container); + this.sbOverlay = new SBOverlay(this, msb, container); this.container = container; this.game = game; input = container.getInput(); @@ -470,6 +473,12 @@ public class Game extends BasicGameState { } } + float[] sbPosition = sbOverlay.getPoint(trackPosition); + if (sbPosition != null) { + autoPoint.x = sbPosition[0]; + autoPoint.y = sbPosition[1]; + } + // set mouse coordinates autoMousePosition.set(autoPoint.x, autoPoint.y); } diff --git a/src/yugecin/opsudance/sbv2/StoryboardMove.java b/src/yugecin/opsudance/sbv2/StoryboardMove.java new file mode 100644 index 00000000..8ef9c11a --- /dev/null +++ b/src/yugecin/opsudance/sbv2/StoryboardMove.java @@ -0,0 +1,33 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.sbv2; + +import org.newdawn.slick.Graphics; +import yugecin.opsudance.sbv2.movers.StoryboardMover; + +public interface StoryboardMove { + + void add(StoryboardMover mover); + float[] getPointAt(float t); + void update(int delta, int x, int y); + void mousePressed(int x, int y); + void mouseReleased(int x, int y); + void recalculateTimes(); + void render(Graphics g); + +} diff --git a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java new file mode 100644 index 00000000..a8613327 --- /dev/null +++ b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java @@ -0,0 +1,146 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.sbv2; + +import itdelatrisu.opsu.objects.curves.Vec2f; +import org.newdawn.slick.Color; +import org.newdawn.slick.Graphics; +import yugecin.opsudance.sbv2.movers.StoryboardMover; + +import java.util.ArrayList; +import java.util.List; + +public class StoryboardMoveImpl implements StoryboardMove { + + private static final int POINTSIZE = 3; + + private Vec2f start; + private Vec2f end; + private List movers; + private List midPoints; + + private StoryboardMover nextMover; + private Vec2f currentPoint; + private StoryboardMover prevMover; + + private float totalLength; + + public StoryboardMoveImpl(Vec2f start, Vec2f end) { + this.start = start; + this.end = end; + movers = new ArrayList<>(); + midPoints = new ArrayList<>(); + } + + @Override + public void add(StoryboardMover mover) { + mover.end = end; + if (movers.size() == 0) { + mover.start = start; + } else { + StoryboardMover lastMover = movers.get(movers.size() - 1); + Vec2f mid = new Vec2f( + (lastMover.start.x + lastMover.end.x) / 2f, + (lastMover.start.y + lastMover.end.y) / 2f + ); + midPoints.add(mid); + lastMover.end = mid; + totalLength -= lastMover.getLength(); + lastMover.recalculateLength(); + totalLength += lastMover.getLength(); + mover.start = mid; + } + movers.add(mover); + recalculateTimes(); + } + + @Override + public float[] getPointAt(float t) { + if (movers.size() == 0) { + return new float[] { end.x, end.y }; + } + float cumulativeTime = 0f; + for (StoryboardMover mover : movers) { + cumulativeTime += mover.timeLengthPercentOfTotalTime; + if (cumulativeTime > t) { + return mover.getPointAt((t - (cumulativeTime - mover.timeLengthPercentOfTotalTime)) / mover.timeLengthPercentOfTotalTime); + } + } + return new float[] { end.x, end.y }; + } + + @Override + public void update(int delta, int x, int y) { + if (currentPoint != null) { + moveCurrentPoint(x, y); + } + } + + @Override + public void mousePressed(int x, int y) { + int i = 0; + for (Vec2f point : midPoints) { + if (point.x - POINTSIZE <= x && x <= point.x + POINTSIZE && point.y - POINTSIZE <= y && y <= point.y + POINTSIZE) { + currentPoint = point; + prevMover = movers.get(i); + nextMover = movers.get(i + 1); + break; + } + i++; + } + } + + @Override + public void mouseReleased(int x, int y) { + if (currentPoint != null) { + moveCurrentPoint(x, y); + totalLength -= prevMover.getLength() + nextMover.getLength(); + prevMover.recalculateLength(); + nextMover.recalculateLength(); + totalLength += prevMover.getLength() + nextMover.getLength(); + currentPoint = null; + recalculateTimes(); + } + } + + @Override + public void recalculateTimes() { + for (StoryboardMover mover : movers) { + mover.timeLengthPercentOfTotalTime = mover.getLength() / totalLength; + } + } + + private void moveCurrentPoint(int x, int y) { + currentPoint.x = x; + currentPoint.y = y; + prevMover.end = currentPoint; + nextMover.start = currentPoint; + } + + @Override + public void render(Graphics g) { + for (StoryboardMover mover : movers) { + mover.render(g); + } + g.setColor(Color.cyan); + for (Vec2f point : midPoints) { + g.fillRect(point.x - POINTSIZE, point.y - POINTSIZE, POINTSIZE * 2 + 1, POINTSIZE * 2 + 1); + } + } + +} diff --git a/src/yugecin/opsudance/sbv2/movers/LinearStoryboardMover.java b/src/yugecin/opsudance/sbv2/movers/LinearStoryboardMover.java new file mode 100644 index 00000000..1742e06f --- /dev/null +++ b/src/yugecin/opsudance/sbv2/movers/LinearStoryboardMover.java @@ -0,0 +1,47 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.sbv2.movers; + +import itdelatrisu.opsu.Utils; +import org.newdawn.slick.Color; + +public class LinearStoryboardMover extends StoryboardMover { + + public LinearStoryboardMover() { + super(Color.red); + } + + @Override + public float[] getPointAt(float t) { + return new float[] { + Utils.lerp(start.x, end.x, t), + Utils.lerp(start.y, end.y, t), + }; + } + + @Override + public float getLength() { + return length; + } + + @Override + public void recalculateLength() { + length = Utils.distance(start.x, start.y, end.x, end.y); + } + +} diff --git a/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java b/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java new file mode 100644 index 00000000..b869614c --- /dev/null +++ b/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java @@ -0,0 +1,53 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.sbv2.movers; + +import itdelatrisu.opsu.objects.curves.Vec2f; +import org.newdawn.slick.Color; +import org.newdawn.slick.Graphics; + +public abstract class StoryboardMover { + + public static final float CALC_DRAW_INTERVAL = 0.05f; + + protected float length; + public Vec2f start; + public Vec2f end; + private Color renderColor; + public float timeLengthPercentOfTotalTime; + + public StoryboardMover(Color renderColor) { + this.renderColor = renderColor; + } + + public abstract float[] getPointAt(float t); + public abstract void recalculateLength(); + + public float getLength() { + return length; + } + + public void render(Graphics g) { + g.setColor(renderColor); + for (float t = 0; t <= 1f; t += StoryboardMover.CALC_DRAW_INTERVAL) { + float[] p = getPointAt(t); + g.fillRect(p[0] - 1, p[1] - 1, 3, 3); + } + } + +} diff --git a/src/yugecin/opsudance/ui/SBOverlay.java b/src/yugecin/opsudance/ui/SBOverlay.java index d7672f74..c3c4a9db 100644 --- a/src/yugecin/opsudance/ui/SBOverlay.java +++ b/src/yugecin/opsudance/ui/SBOverlay.java @@ -28,6 +28,7 @@ import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Input; import yugecin.opsudance.ObjectColorOverrides; +import yugecin.opsudance.sbv2.MoveStoryboard; import yugecin.opsudance.ui.OptionsOverlay.OptionTab; import java.util.*; @@ -109,6 +110,7 @@ public class SBOverlay implements OptionsOverlay.Parent { private int index; private final Game game; + private final MoveStoryboard msb; private final OptionsOverlay overlay; static { @@ -117,8 +119,9 @@ public class SBOverlay implements OptionsOverlay.Parent { } } - public SBOverlay(Game game, GameContainer container) { + public SBOverlay(Game game, MoveStoryboard msb, GameContainer container) { this.game = game; + this.msb = msb; initialOptions = new HashMap<>(); overlay = new OptionsOverlay(this, options, 2, container); this.width = container.getWidth(); @@ -131,6 +134,7 @@ public class SBOverlay implements OptionsOverlay.Parent { if (!Options.isEnableSB() || hide) { return; } + msb.render(g); int lh = Fonts.SMALL.getLineHeight(); Fonts.SMALL.drawString(10, height - 50 + lh, "save position: ctrl+s, load position: ctrl+l", Color.cyan); Fonts.SMALL.drawString(10, height - 50, "speed: C " + (speed / 10f) + " V", Color.cyan); @@ -163,6 +167,7 @@ public class SBOverlay implements OptionsOverlay.Parent { if (Options.isEnableSB() && menu) { overlay.update(delta, mouseX, mouseY); } + msb.update(delta, mouseX, mouseY); } public boolean keyPressed(int key, char c) { @@ -234,6 +239,7 @@ public class SBOverlay implements OptionsOverlay.Parent { public void setGameObjects(GameObject[] gameObjects) { if (this.gameObjects.length != gameObjects.length) { optionsMap = new HashMap[gameObjects.length]; + msb.setGameObjects(gameObjects); } if (optionsMap.length > 0) { // copy all current settings in first obj map @@ -246,6 +252,7 @@ public class SBOverlay implements OptionsOverlay.Parent { } public boolean mousePressed(int button, int x, int y) { + msb.mousePressed(x, y); if (!menu) { return false; } @@ -270,6 +277,7 @@ public class SBOverlay implements OptionsOverlay.Parent { if (index >= optionsMap.length) { return; } + msb.setIndex(index); for (; this.index <= index; this.index++) { HashMap options = optionsMap[this.index]; if (options == null) { @@ -289,6 +297,7 @@ public class SBOverlay implements OptionsOverlay.Parent { overlay.mouseReleased(button, x, y); return true; } + msb.mouseReleased(x, y); if (x > 10 || index >= optionsMap.length || optionsMap[index] == null) { return false; } @@ -348,6 +357,10 @@ public class SBOverlay implements OptionsOverlay.Parent { } } + public float[] getPoint(int trackPosition) { + return msb.getPoint(trackPosition); + } + @Override public void onLeave() { menu = false; diff --git a/src/yugecin/opsudance/ui/SimpleButton.java b/src/yugecin/opsudance/ui/SimpleButton.java new file mode 100644 index 00000000..a7c68d89 --- /dev/null +++ b/src/yugecin/opsudance/ui/SimpleButton.java @@ -0,0 +1,72 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.ui; + + +import org.newdawn.slick.Color; +import org.newdawn.slick.Font; +import org.newdawn.slick.Graphics; + +import java.awt.Rectangle; + +public class SimpleButton { + + private final Color bg; + private final Color fg; + private final Color border; + private final Color hoverBorder; + private final Font font; + private String text; + private int textY; + private Rectangle hitbox; + private boolean isHovered; + + public SimpleButton(int x, int y, int width, int height, Font font, String text, Color bg, Color fg, Color border, Color hoverBorder) { + this.bg = bg; + this.fg = fg; + this.border = border; + this.hoverBorder = hoverBorder; + this.hitbox = new Rectangle(x, y, width, height); + this.font = font; + this.text = text; + this.textY = y + (height - font.getLineHeight()) / 2; + } + + public void render(Graphics g) { + g.setLineWidth(2f); + g.setColor(bg); + g.fillRect(hitbox.x, hitbox.y, hitbox.width, hitbox.height); + g.setColor(fg); + font.drawString(hitbox.x + 20, textY, text); + if (isHovered) { + g.setColor(hoverBorder); + } else { + g.setColor(border); + } + g.drawRect(hitbox.x, hitbox.y, hitbox.width, hitbox.height); + } + + public void update(int x, int y) { + isHovered = hitbox.contains(x, y); + } + + public boolean isHovered() { + return isHovered; + } + +} From bf2e71e39b466f011d99b51d8360d58813a19b44 Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 12:35:33 +0100 Subject: [PATCH 02/11] fix wrong length calculation when adding first mover --- src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java index a8613327..7b064f5c 100644 --- a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java +++ b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java @@ -18,6 +18,7 @@ package yugecin.opsudance.sbv2; import itdelatrisu.opsu.objects.curves.Vec2f; +import itdelatrisu.opsu.ui.Fonts; import org.newdawn.slick.Color; import org.newdawn.slick.Graphics; import yugecin.opsudance.sbv2.movers.StoryboardMover; @@ -52,6 +53,8 @@ public class StoryboardMoveImpl implements StoryboardMove { mover.end = end; if (movers.size() == 0) { mover.start = start; + mover.recalculateLength(); + totalLength += mover.getLength(); } else { StoryboardMover lastMover = movers.get(movers.size() - 1); Vec2f mid = new Vec2f( From 414e20ec26fa919141a9a65ec3ce1242aa151c29 Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 12:41:40 +0100 Subject: [PATCH 03/11] recalculate length and times every x ms when moving --- .../opsudance/sbv2/StoryboardMoveImpl.java | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java index 7b064f5c..2c2ff027 100644 --- a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java +++ b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java @@ -41,11 +41,14 @@ public class StoryboardMoveImpl implements StoryboardMove { private float totalLength; + private int recalculateDelay; + public StoryboardMoveImpl(Vec2f start, Vec2f end) { this.start = start; this.end = end; movers = new ArrayList<>(); midPoints = new ArrayList<>(); + recalculateDelay = 700; } @Override @@ -91,6 +94,12 @@ public class StoryboardMoveImpl implements StoryboardMove { public void update(int delta, int x, int y) { if (currentPoint != null) { moveCurrentPoint(x, y); + recalculateDelay -= delta; + if (recalculateDelay < 0) { + recalculateDelay = 700; + recalculateLengths(); + recalculateTimes(); + } } } @@ -112,13 +121,10 @@ public class StoryboardMoveImpl implements StoryboardMove { public void mouseReleased(int x, int y) { if (currentPoint != null) { moveCurrentPoint(x, y); - totalLength -= prevMover.getLength() + nextMover.getLength(); - prevMover.recalculateLength(); - nextMover.recalculateLength(); - totalLength += prevMover.getLength() + nextMover.getLength(); + recalculateLengths(); currentPoint = null; - recalculateTimes(); } + recalculateDelay = 700; } @Override @@ -128,6 +134,14 @@ public class StoryboardMoveImpl implements StoryboardMove { } } + private void recalculateLengths() { + totalLength -= prevMover.getLength() + nextMover.getLength(); + prevMover.recalculateLength(); + nextMover.recalculateLength(); + totalLength += prevMover.getLength() + nextMover.getLength(); + recalculateTimes(); + } + private void moveCurrentPoint(int x, int y) { currentPoint.x = x; currentPoint.y = y; From ddaa8f5bccfd8519a7b481c07513a8d7a91d4c29 Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 12:42:09 +0100 Subject: [PATCH 04/11] add forgotten file (intellij plz, DMITRY PLZ) --- .../opsudance/sbv2/MoveStoryBoard.java | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 src/yugecin/opsudance/sbv2/MoveStoryBoard.java diff --git a/src/yugecin/opsudance/sbv2/MoveStoryBoard.java b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java new file mode 100644 index 00000000..7c6bbbef --- /dev/null +++ b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java @@ -0,0 +1,140 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.sbv2; + +import itdelatrisu.opsu.objects.GameObject; +import itdelatrisu.opsu.ui.Colors; +import itdelatrisu.opsu.ui.Fonts; +import itdelatrisu.opsu.ui.UI; +import org.newdawn.slick.GameContainer; +import org.newdawn.slick.Graphics; +import yugecin.opsudance.sbv2.movers.LinearStoryboardMover; +import yugecin.opsudance.ui.SimpleButton; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +public class MoveStoryboard { + + private final SimpleButton btnAddLinear; + private final SimpleButton btnAddQuadratic; + private final SimpleButton btnAddCubic; + + private final StoryboardMove dummyMove; + + private int width; + + private StoryboardMove[] moves; + + private GameObject[] gameObjects; + private int objectIndex; + + private int trackPosition; + + public MoveStoryboard(GameContainer container) { + this.width = container.getWidth(); + btnAddLinear = new SimpleButton(width - 205, 50, 200, 25, Fonts.SMALL, "add linear", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); + btnAddQuadratic = new SimpleButton(width - 205, 80, 200, 25, Fonts.SMALL, "add quadratic", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); + btnAddCubic = new SimpleButton(width - 205, 110, 200, 25, Fonts.SMALL, "add cubic", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); + dummyMove = (StoryboardMove) Proxy.newProxyInstance(StoryboardMove.class.getClassLoader(), new Class[]{StoryboardMove.class}, new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return null; + } + }); + } + + /** + * Get the point at the current time + * @param trackPosition current time in ms + * @return point calculated by the storyboardmover or null if there is no mover + */ + public float[] getPoint(int trackPosition) { + this.trackPosition = trackPosition; + if (moves[objectIndex] == null || objectIndex == 0) { + return null; + } + if (trackPosition < gameObjects[objectIndex - 1].getEndTime() || trackPosition > gameObjects[objectIndex].getTime()) { + return null; + } + float t = (float) (trackPosition - gameObjects[objectIndex - 1].getEndTime()) / (gameObjects[objectIndex].getTime() - gameObjects[objectIndex - 1].getEndTime()); + return moves[objectIndex].getPointAt(t); + } + + public void render(Graphics g) { + btnAddLinear.render(g); + btnAddQuadratic.render(g); + btnAddCubic.render(g); + if (moves[objectIndex] != null && objectIndex > 0 && trackPosition >= gameObjects[objectIndex - 1].getEndTime() && trackPosition < gameObjects[objectIndex].getTime()) { + moves[objectIndex].render(g, width); + } + } + + public void mousePressed(int x, int y) { + if (moves[objectIndex] != null) { + moves[objectIndex].mousePressed(x, y); + } + } + + public void mouseReleased(int x, int y) { + if (moves[objectIndex] != null) { + moves[objectIndex].mouseReleased(x, y); + } + if (objectIndex == 0) { + return; + } + if (btnAddLinear.isHovered()) { + getCurrentMoveOrCreateNew().add(new LinearStoryboardMover()); + } + if (btnAddQuadratic.isHovered()) { + } + if (btnAddCubic.isHovered()) { + } + } + + private StoryboardMove getCurrentMoveOrCreateNew() { + if (gameObjects[objectIndex].isSlider() && trackPosition > gameObjects[objectIndex].getTime() && trackPosition < gameObjects[objectIndex].getEndTime()) { + UI.sendBarNotification("wait until the slider ended"); + return dummyMove; + } + if (moves[objectIndex] == null) { + return moves[objectIndex] = new StoryboardMoveImpl(gameObjects[objectIndex - 1].end, gameObjects[objectIndex].start); + } + return moves[objectIndex]; + } + + public void update(int delta, int x, int y) { + btnAddLinear.update(x, y); + btnAddQuadratic.update(x, y); + btnAddCubic.update(x, y); + if (moves[objectIndex] != null) { + moves[objectIndex].update(delta, x, y); + } + } + + public void setGameObjects(GameObject[] gameObjects) { + this.gameObjects = gameObjects; + this.moves = new StoryboardMove[gameObjects.length]; + } + + public void setIndex(int objectIndex) { + this.objectIndex = objectIndex; + } + +} From 81431067d8143ddfe3c77acc2013419e0dfba772 Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 13:19:54 +0100 Subject: [PATCH 05/11] ability to remove movers --- .../opsudance/sbv2/MoveStoryBoard.java | 7 ++- .../opsudance/sbv2/StoryboardMove.java | 1 + .../opsudance/sbv2/StoryboardMoveImpl.java | 47 +++++++++++++++++-- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/yugecin/opsudance/sbv2/MoveStoryBoard.java b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java index 7c6bbbef..d4e7d682 100644 --- a/src/yugecin/opsudance/sbv2/MoveStoryBoard.java +++ b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java @@ -82,7 +82,7 @@ public class MoveStoryboard { btnAddQuadratic.render(g); btnAddCubic.render(g); if (moves[objectIndex] != null && objectIndex > 0 && trackPosition >= gameObjects[objectIndex - 1].getEndTime() && trackPosition < gameObjects[objectIndex].getTime()) { - moves[objectIndex].render(g, width); + moves[objectIndex].render(g); } } @@ -95,6 +95,9 @@ public class MoveStoryboard { public void mouseReleased(int x, int y) { if (moves[objectIndex] != null) { moves[objectIndex].mouseReleased(x, y); + if (moves[objectIndex].getAmountOfMovers() == 0) { + moves[objectIndex] = null; + } } if (objectIndex == 0) { return; @@ -114,7 +117,7 @@ public class MoveStoryboard { return dummyMove; } if (moves[objectIndex] == null) { - return moves[objectIndex] = new StoryboardMoveImpl(gameObjects[objectIndex - 1].end, gameObjects[objectIndex].start); + return moves[objectIndex] = new StoryboardMoveImpl(gameObjects[objectIndex - 1].end, gameObjects[objectIndex].start, width); } return moves[objectIndex]; } diff --git a/src/yugecin/opsudance/sbv2/StoryboardMove.java b/src/yugecin/opsudance/sbv2/StoryboardMove.java index 8ef9c11a..57d8c969 100644 --- a/src/yugecin/opsudance/sbv2/StoryboardMove.java +++ b/src/yugecin/opsudance/sbv2/StoryboardMove.java @@ -22,6 +22,7 @@ import yugecin.opsudance.sbv2.movers.StoryboardMover; public interface StoryboardMove { + int getAmountOfMovers(); void add(StoryboardMover mover); float[] getPointAt(float t); void update(int delta, int x, int y); diff --git a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java index 2c2ff027..f89b3bbf 100644 --- a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java +++ b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java @@ -28,7 +28,9 @@ import java.util.List; public class StoryboardMoveImpl implements StoryboardMove { - private static final int POINTSIZE = 3; + private static final int POINTSIZE = 6; + + private int screenWidth; private Vec2f start; private Vec2f end; @@ -43,14 +45,20 @@ public class StoryboardMoveImpl implements StoryboardMove { private int recalculateDelay; - public StoryboardMoveImpl(Vec2f start, Vec2f end) { + public StoryboardMoveImpl(Vec2f start, Vec2f end, int screenWidth) { this.start = start; this.end = end; + this.screenWidth = screenWidth; movers = new ArrayList<>(); midPoints = new ArrayList<>(); recalculateDelay = 700; } + @Override + public int getAmountOfMovers() { + return movers.size(); + } + @Override public void add(StoryboardMover mover) { mover.end = end; @@ -119,9 +127,34 @@ public class StoryboardMoveImpl implements StoryboardMove { @Override public void mouseReleased(int x, int y) { - if (currentPoint != null) { + int posY = 200; + if (currentPoint == null) { + for (int i = 0; i < movers.size(); i++) { + int dif = posY; + posY += Fonts.SMALL.getLineHeight() * 1.1f; + dif = posY - dif; + if (screenWidth - 20 <= x && x <= screenWidth - 10 && posY - dif / 2 - 5 <= y && y <= posY - dif / 2 + 5) { + if (movers.size() == 1) { + movers.clear(); + return; + } + StoryboardMover mover = movers.get(i); + if (i == movers.size() - 1) { + midPoints.remove(i - 1); + movers.get(i - 1).end = mover.end; + } else { + midPoints.remove(i); + movers.get(i + 1).start = mover.start; + } + movers.remove(i); + totalLength -= mover.getLength(); + recalculateTimes(); + } + } + } else { moveCurrentPoint(x, y); recalculateLengths(); + recalculateTimes(); currentPoint = null; } recalculateDelay = 700; @@ -151,8 +184,16 @@ public class StoryboardMoveImpl implements StoryboardMove { @Override public void render(Graphics g) { + g.setColor(Color.red); + int y = 200; for (StoryboardMover mover : movers) { mover.render(g); + String text = mover.toString(); + Fonts.SMALL.drawString(screenWidth - Fonts.SMALL.getWidth(text) - 30, y, text); + int dif = y; + y += Fonts.SMALL.getLineHeight() * 1.1f; + dif = y - dif; + g.fillRect(screenWidth - 20, y - dif / 2 - 5, 10, 10); } g.setColor(Color.cyan); for (Vec2f point : midPoints) { From 4d528089d2e934e895c9c8d29d4d5fae603e40eb Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 13:58:31 +0100 Subject: [PATCH 06/11] add multipoint storyboard mover --- .../opsudance/sbv2/MoveStoryBoard.java | 2 + .../opsudance/sbv2/StoryboardMoveImpl.java | 27 ++++-- .../sbv2/movers/StoryboardMover.java | 46 +++++++++- .../movers/StoryboardMultipointMover.java | 86 +++++++++++++++++++ 4 files changed, 153 insertions(+), 8 deletions(-) create mode 100644 src/yugecin/opsudance/sbv2/movers/StoryboardMultipointMover.java diff --git a/src/yugecin/opsudance/sbv2/MoveStoryBoard.java b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java index d4e7d682..aa3f36d7 100644 --- a/src/yugecin/opsudance/sbv2/MoveStoryBoard.java +++ b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java @@ -24,6 +24,7 @@ import itdelatrisu.opsu.ui.UI; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import yugecin.opsudance.sbv2.movers.LinearStoryboardMover; +import yugecin.opsudance.sbv2.movers.QuadraticStoryboardMover; import yugecin.opsudance.ui.SimpleButton; import java.lang.reflect.InvocationHandler; @@ -106,6 +107,7 @@ public class MoveStoryboard { getCurrentMoveOrCreateNew().add(new LinearStoryboardMover()); } if (btnAddQuadratic.isHovered()) { + getCurrentMoveOrCreateNew().add(new QuadraticStoryboardMover()); } if (btnAddCubic.isHovered()) { } diff --git a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java index f89b3bbf..5edefd8d 100644 --- a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java +++ b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java @@ -63,9 +63,7 @@ public class StoryboardMoveImpl implements StoryboardMove { public void add(StoryboardMover mover) { mover.end = end; if (movers.size() == 0) { - mover.start = start; - mover.recalculateLength(); - totalLength += mover.getLength(); + mover.setInitialStart(start); } else { StoryboardMover lastMover = movers.get(movers.size() - 1); Vec2f mid = new Vec2f( @@ -77,8 +75,10 @@ public class StoryboardMoveImpl implements StoryboardMove { totalLength -= lastMover.getLength(); lastMover.recalculateLength(); totalLength += lastMover.getLength(); - mover.start = mid; + mover.setInitialStart(mid); } + mover.recalculateLength(); + totalLength += mover.getLength(); movers.add(mover); recalculateTimes(); } @@ -100,6 +100,9 @@ public class StoryboardMoveImpl implements StoryboardMove { @Override public void update(int delta, int x, int y) { + for (StoryboardMover mover : movers) { + mover.update(delta, x, y); + } if (currentPoint != null) { moveCurrentPoint(x, y); recalculateDelay -= delta; @@ -114,12 +117,17 @@ public class StoryboardMoveImpl implements StoryboardMove { @Override public void mousePressed(int x, int y) { int i = 0; + for(StoryboardMover mover : movers) { + if (mover.mousePressed(x, y)) { + return; + } + } for (Vec2f point : midPoints) { if (point.x - POINTSIZE <= x && x <= point.x + POINTSIZE && point.y - POINTSIZE <= y && y <= point.y + POINTSIZE) { currentPoint = point; prevMover = movers.get(i); nextMover = movers.get(i + 1); - break; + return; } i++; } @@ -149,6 +157,15 @@ public class StoryboardMoveImpl implements StoryboardMove { movers.remove(i); totalLength -= mover.getLength(); recalculateTimes(); + return; + } + } + for(StoryboardMover mover : movers) { + float prevLen = mover.getLength(); + if (mover.mouseReleased(x, y)) { + mover.recalculateLength(); + totalLength += mover.getLength() - prevLen; + recalculateTimes(); } } } else { diff --git a/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java b/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java index b869614c..e3a2f72f 100644 --- a/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java +++ b/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java @@ -17,6 +17,7 @@ */ package yugecin.opsudance.sbv2.movers; +import itdelatrisu.opsu.Utils; import itdelatrisu.opsu.objects.curves.Vec2f; import org.newdawn.slick.Color; import org.newdawn.slick.Graphics; @@ -28,7 +29,7 @@ public abstract class StoryboardMover { protected float length; public Vec2f start; public Vec2f end; - private Color renderColor; + private final Color renderColor; public float timeLengthPercentOfTotalTime; public StoryboardMover(Color renderColor) { @@ -36,12 +37,41 @@ public abstract class StoryboardMover { } public abstract float[] getPointAt(float t); - public abstract void recalculateLength(); - public float getLength() { return length; } + /** + * Set the start position after just creating this mover + * @param start start position + */ + public void setInitialStart(Vec2f start) { + this.start = start; + } + + public void update(int delta, int x, int y) { + } + + /** + * + * @param x x pos of mouse + * @param y y pos of mouse + * @return true if mouse pressed something and consecutive checks should be ignored + */ + public boolean mousePressed(int x, int y) { + return false; + } + + /** + * + * @param x x pos of mouse + * @param y y pos of mouse + * @return true if mouse released something and length should be recalculated + */ + public boolean mouseReleased(int x, int y) { + return false; + } + public void render(Graphics g) { g.setColor(renderColor); for (float t = 0; t <= 1f; t += StoryboardMover.CALC_DRAW_INTERVAL) { @@ -50,4 +80,14 @@ public abstract class StoryboardMover { } } + public void recalculateLength() { + this.length = 0; + float[] lastPoint = new float[] { start.x, start.y }; + for (float t = StoryboardMover.CALC_DRAW_INTERVAL; t <= 1f; t += StoryboardMover.CALC_DRAW_INTERVAL) { + float[] p = getPointAt(t); + this.length += Utils.distance(lastPoint[0], lastPoint[1], p[0], p[1]); + lastPoint = p; + } + } + } diff --git a/src/yugecin/opsudance/sbv2/movers/StoryboardMultipointMover.java b/src/yugecin/opsudance/sbv2/movers/StoryboardMultipointMover.java new file mode 100644 index 00000000..d54388d4 --- /dev/null +++ b/src/yugecin/opsudance/sbv2/movers/StoryboardMultipointMover.java @@ -0,0 +1,86 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.sbv2.movers; + +import itdelatrisu.opsu.objects.curves.Vec2f; +import org.newdawn.slick.Color; +import org.newdawn.slick.Graphics; + +import java.util.ArrayList; +import java.util.List; + +public abstract class StoryboardMultipointMover extends StoryboardMover { + + private static final int POINTSIZE = 6; + + private List points; + private final Color pointColor; + + private Vec2f currentPoint; + + public StoryboardMultipointMover(Color renderColor, Color pointColor) { + super(renderColor); + this.pointColor = pointColor; + this.points = new ArrayList<>(); + } + + public void addPoint(Vec2f point) { + points.add(point); + } + + @Override + public void update(int delta, int x, int y) { + if (currentPoint != null) { + currentPoint.x = x; + currentPoint.y = y; + } + } + + @Override + public boolean mousePressed(int x, int y) { + for (Vec2f point : points) { + if (point.x - POINTSIZE <= x && x <= point.x + POINTSIZE && point.y - POINTSIZE <= y && y <= point.y + POINTSIZE) { + currentPoint = point; + return true; + } + } + return false; + } + + @Override + public boolean mouseReleased(int x, int y) { + if (currentPoint != null) { + currentPoint = null; + return true; + } + return false; + } + + protected Vec2f getPoint(int index) { + return points.get(index); + } + + @Override + public void render(Graphics g) { + g.setColor(pointColor); + for (Vec2f point : points) { + g.fillRect(point.x - POINTSIZE, point.y - POINTSIZE, POINTSIZE * 2 + 1, POINTSIZE * 2 + 1); + } + super.render(g); + } +} From a3928759407fba67b93e367932833bd8517c1b47 Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 14:18:50 +0100 Subject: [PATCH 07/11] renderutils --- src/yugecin/opsudance/render/RenderUtils.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/yugecin/opsudance/render/RenderUtils.java diff --git a/src/yugecin/opsudance/render/RenderUtils.java b/src/yugecin/opsudance/render/RenderUtils.java new file mode 100644 index 00000000..c78d9416 --- /dev/null +++ b/src/yugecin/opsudance/render/RenderUtils.java @@ -0,0 +1,54 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.render; + +import org.newdawn.slick.Graphics; + +public class RenderUtils { + + public static void drawDottedLine(Graphics g, float fromX, float fromY, float toX, float toY, int dotAmount, int dotRadius) { + float dx = (toX - fromX) / (dotAmount - 1); + float dy = (toY - fromY) / (dotAmount - 1); + for (; dotAmount > 0; dotAmount--) { + fillCenteredRect(g, fromX, fromY, dotRadius); + fromX += dx; + fromY += dy; + } + } + + public static void drawDottedLine(Graphics g, int fromX, int fromY, int toX, int toY, int dotAmount, int dotRadius) { + float dx = (float) (toX - fromX) / (dotAmount - 1); + float dy = (float) (toY - fromY) / (dotAmount - 1); + for (; dotAmount > 0; dotAmount--) { + fillCenteredRect(g, fromX, fromY, dotRadius); + fromX += dx; + fromY += dy; + } + } + + public static void fillCenteredRect(Graphics g, int x, int y, int radius) { + int totalLength = radius * 2 + 1; + g.fillRect(x - radius, y - radius, totalLength, totalLength); + } + + public static void fillCenteredRect(Graphics g, float x, float y, float radius) { + float totalLength = radius * 2f + 1f; + g.fillRect(x - radius, y - radius, totalLength, totalLength); + } + +} From c219f078fbd557dce1b4f464276d8486eacfc4ac Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 14:19:08 +0100 Subject: [PATCH 08/11] use renderutils --- src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java | 5 +++-- src/yugecin/opsudance/sbv2/movers/StoryboardMover.java | 3 ++- .../sbv2/movers/StoryboardMultipointMover.java | 10 +++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java index 5edefd8d..8ede9055 100644 --- a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java +++ b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java @@ -21,6 +21,7 @@ import itdelatrisu.opsu.objects.curves.Vec2f; import itdelatrisu.opsu.ui.Fonts; import org.newdawn.slick.Color; import org.newdawn.slick.Graphics; +import yugecin.opsudance.render.RenderUtils; import yugecin.opsudance.sbv2.movers.StoryboardMover; import java.util.ArrayList; @@ -210,11 +211,11 @@ public class StoryboardMoveImpl implements StoryboardMove { int dif = y; y += Fonts.SMALL.getLineHeight() * 1.1f; dif = y - dif; - g.fillRect(screenWidth - 20, y - dif / 2 - 5, 10, 10); + RenderUtils.fillCenteredRect(g, screenWidth - 20, y - dif / 2, 5); } g.setColor(Color.cyan); for (Vec2f point : midPoints) { - g.fillRect(point.x - POINTSIZE, point.y - POINTSIZE, POINTSIZE * 2 + 1, POINTSIZE * 2 + 1); + RenderUtils.fillCenteredRect(g, point.x, point.y, POINTSIZE); } } diff --git a/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java b/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java index e3a2f72f..b7653ee1 100644 --- a/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java +++ b/src/yugecin/opsudance/sbv2/movers/StoryboardMover.java @@ -21,6 +21,7 @@ import itdelatrisu.opsu.Utils; import itdelatrisu.opsu.objects.curves.Vec2f; import org.newdawn.slick.Color; import org.newdawn.slick.Graphics; +import yugecin.opsudance.render.RenderUtils; public abstract class StoryboardMover { @@ -76,7 +77,7 @@ public abstract class StoryboardMover { g.setColor(renderColor); for (float t = 0; t <= 1f; t += StoryboardMover.CALC_DRAW_INTERVAL) { float[] p = getPointAt(t); - g.fillRect(p[0] - 1, p[1] - 1, 3, 3); + RenderUtils.fillCenteredRect(g, p[0], p[1], 1); } } diff --git a/src/yugecin/opsudance/sbv2/movers/StoryboardMultipointMover.java b/src/yugecin/opsudance/sbv2/movers/StoryboardMultipointMover.java index d54388d4..687c60bb 100644 --- a/src/yugecin/opsudance/sbv2/movers/StoryboardMultipointMover.java +++ b/src/yugecin/opsudance/sbv2/movers/StoryboardMultipointMover.java @@ -20,6 +20,7 @@ package yugecin.opsudance.sbv2.movers; import itdelatrisu.opsu.objects.curves.Vec2f; import org.newdawn.slick.Color; import org.newdawn.slick.Graphics; +import yugecin.opsudance.render.RenderUtils; import java.util.ArrayList; import java.util.List; @@ -77,9 +78,16 @@ public abstract class StoryboardMultipointMover extends StoryboardMover { @Override public void render(Graphics g) { + g.setColor(Color.gray); + Vec2f lastPoint = start; + for (Vec2f point : points) { + RenderUtils.drawDottedLine(g, lastPoint.x, lastPoint.y, point.x, point.y, 20, 0); + lastPoint = point; + } + RenderUtils.drawDottedLine(g, lastPoint.x, lastPoint.y, end.x, end.y, 20, 0); g.setColor(pointColor); for (Vec2f point : points) { - g.fillRect(point.x - POINTSIZE, point.y - POINTSIZE, POINTSIZE * 2 + 1, POINTSIZE * 2 + 1); + RenderUtils.fillCenteredRect(g, point.x, point.y, POINTSIZE); } super.render(g); } From 7aafd590f699efcd53863e18c304240207ab64bb Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 14:19:22 +0100 Subject: [PATCH 09/11] QuadraticStoryboardMover --- .../sbv2/movers/QuadraticStoryboardMover.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/yugecin/opsudance/sbv2/movers/QuadraticStoryboardMover.java diff --git a/src/yugecin/opsudance/sbv2/movers/QuadraticStoryboardMover.java b/src/yugecin/opsudance/sbv2/movers/QuadraticStoryboardMover.java new file mode 100644 index 00000000..769f209b --- /dev/null +++ b/src/yugecin/opsudance/sbv2/movers/QuadraticStoryboardMover.java @@ -0,0 +1,49 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.sbv2.movers; + +import itdelatrisu.opsu.objects.curves.Vec2f; +import org.newdawn.slick.Color; + +public class QuadraticStoryboardMover extends StoryboardMultipointMover { + + public QuadraticStoryboardMover() { + super(Color.magenta, Color.blue); + } + + @Override + public void setInitialStart(Vec2f start) { + super.setInitialStart(start); + super.addPoint(new Vec2f((start.x + end.x) / 2, (start.y + end.y) / 2)); + } + + @Override + public float[] getPointAt(float t) { + float ct = 1f - t; + return new float[] { + ct * ct * start.x + ct * 2 * t * getPoint(0).x + t * t * end.x, + ct * ct * start.y + ct * 2 * t * getPoint(0).y + t * t * end.y, + }; + } + + @Override + public float getLength() { + return length; + } + +} From ce1dd5eba1eb2f7cb45e8578c214f52c1b24bb0c Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 14:23:10 +0100 Subject: [PATCH 10/11] CubicStoryboardMover --- .../opsudance/sbv2/MoveStoryBoard.java | 2 + .../sbv2/movers/CubicStoryboardMover.java | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/yugecin/opsudance/sbv2/movers/CubicStoryboardMover.java diff --git a/src/yugecin/opsudance/sbv2/MoveStoryBoard.java b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java index aa3f36d7..d02798a8 100644 --- a/src/yugecin/opsudance/sbv2/MoveStoryBoard.java +++ b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java @@ -23,6 +23,7 @@ import itdelatrisu.opsu.ui.Fonts; import itdelatrisu.opsu.ui.UI; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; +import yugecin.opsudance.sbv2.movers.CubicStoryboardMover; import yugecin.opsudance.sbv2.movers.LinearStoryboardMover; import yugecin.opsudance.sbv2.movers.QuadraticStoryboardMover; import yugecin.opsudance.ui.SimpleButton; @@ -110,6 +111,7 @@ public class MoveStoryboard { getCurrentMoveOrCreateNew().add(new QuadraticStoryboardMover()); } if (btnAddCubic.isHovered()) { + getCurrentMoveOrCreateNew().add(new CubicStoryboardMover()); } } diff --git a/src/yugecin/opsudance/sbv2/movers/CubicStoryboardMover.java b/src/yugecin/opsudance/sbv2/movers/CubicStoryboardMover.java new file mode 100644 index 00000000..d571f332 --- /dev/null +++ b/src/yugecin/opsudance/sbv2/movers/CubicStoryboardMover.java @@ -0,0 +1,50 @@ +/* + * opsu!dance - fork of opsu! with cursordance auto + * Copyright (C) 2016 yugecin + * + * opsu!dance is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * opsu!dance is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with opsu!dance. If not, see . + */ +package yugecin.opsudance.sbv2.movers; + +import itdelatrisu.opsu.objects.curves.Vec2f; +import org.newdawn.slick.Color; + +public class CubicStoryboardMover extends StoryboardMultipointMover { + + public CubicStoryboardMover() { + super(Color.green, Color.orange); + } + + @Override + public void setInitialStart(Vec2f start) { + super.setInitialStart(start); + super.addPoint(new Vec2f((start.x + end.x) / 3, (start.y + end.y) / 3)); + super.addPoint(new Vec2f((start.x + end.x) * 2 / 3, (start.y + end.y) * 2 / 3)); + } + + @Override + public float[] getPointAt(float t) { + float ct = 1f - t; + return new float[] { + ct * ct * ct * start.x + 3 * ct * ct * t * getPoint(0).x + 3 * ct * t * t * getPoint(1).x + t * t * t * end.x, + ct * ct * ct * start.y + 3 * ct * ct * t * getPoint(0).y + 3 * ct * t * t * getPoint(1).y + t * t * t * end.y, + }; + } + + @Override + public float getLength() { + return length; + } + +} From ad6ba664f97483340846187548004271a15dc4d4 Mon Sep 17 00:00:00 2001 From: yugecin Date: Sun, 25 Dec 2016 15:46:11 +0100 Subject: [PATCH 11/11] add animations to storyboardmovers --- .../opsudance/sbv2/MoveStoryBoard.java | 31 +++++++++++++++++++ .../opsudance/sbv2/StoryboardMove.java | 2 ++ .../opsudance/sbv2/StoryboardMoveImpl.java | 10 ++++++ 3 files changed, 43 insertions(+) diff --git a/src/yugecin/opsudance/sbv2/MoveStoryBoard.java b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java index d02798a8..4f6df0b8 100644 --- a/src/yugecin/opsudance/sbv2/MoveStoryBoard.java +++ b/src/yugecin/opsudance/sbv2/MoveStoryBoard.java @@ -21,6 +21,8 @@ import itdelatrisu.opsu.objects.GameObject; import itdelatrisu.opsu.ui.Colors; import itdelatrisu.opsu.ui.Fonts; import itdelatrisu.opsu.ui.UI; +import itdelatrisu.opsu.ui.animations.AnimationEquation; +import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import yugecin.opsudance.sbv2.movers.CubicStoryboardMover; @@ -38,6 +40,10 @@ public class MoveStoryboard { private final SimpleButton btnAddQuadratic; private final SimpleButton btnAddCubic; + private final SimpleButton btnAnimLin; + private final SimpleButton btnAnimCir; + private final SimpleButton btnAnimCub; + private final StoryboardMove dummyMove; private int width; @@ -54,6 +60,9 @@ public class MoveStoryboard { btnAddLinear = new SimpleButton(width - 205, 50, 200, 25, Fonts.SMALL, "add linear", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); btnAddQuadratic = new SimpleButton(width - 205, 80, 200, 25, Fonts.SMALL, "add quadratic", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); btnAddCubic = new SimpleButton(width - 205, 110, 200, 25, Fonts.SMALL, "add cubic", Colors.BLUE_BUTTON, Colors.WHITE_FADE, Colors.WHITE_FADE, Colors.ORANGE_BUTTON); + btnAnimLin = new SimpleButton(width - 250, 50, 40, 25, Fonts.SMALL, "lin", Color.blue, Color.white, Color.white, Color.orange); + btnAnimCir = new SimpleButton(width - 250, 80, 40, 25, Fonts.SMALL, "cir", Color.blue, Color.white, Color.white, Color.orange); + btnAnimCub = new SimpleButton(width - 250, 110, 40, 25, Fonts.SMALL, "cub", Color.blue, Color.white, Color.white, Color.orange); dummyMove = (StoryboardMove) Proxy.newProxyInstance(StoryboardMove.class.getClassLoader(), new Class[]{StoryboardMove.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { @@ -83,6 +92,9 @@ public class MoveStoryboard { btnAddLinear.render(g); btnAddQuadratic.render(g); btnAddCubic.render(g); + btnAnimLin.render(g); + btnAnimCir.render(g); + btnAnimCub.render(g); if (moves[objectIndex] != null && objectIndex > 0 && trackPosition >= gameObjects[objectIndex - 1].getEndTime() && trackPosition < gameObjects[objectIndex].getTime()) { moves[objectIndex].render(g); } @@ -113,6 +125,15 @@ public class MoveStoryboard { if (btnAddCubic.isHovered()) { getCurrentMoveOrCreateNew().add(new CubicStoryboardMover()); } + if (btnAnimLin.isHovered()) { + getCurrentMoveOrDummy().setAnimationEquation(AnimationEquation.LINEAR); + } + if (btnAnimCir.isHovered()) { + getCurrentMoveOrDummy().setAnimationEquation(AnimationEquation.IN_OUT_CIRC); + } + if (btnAnimCub.isHovered()) { + getCurrentMoveOrDummy().setAnimationEquation(AnimationEquation.IN_OUT_CUBIC); + } } private StoryboardMove getCurrentMoveOrCreateNew() { @@ -126,10 +147,20 @@ public class MoveStoryboard { return moves[objectIndex]; } + private StoryboardMove getCurrentMoveOrDummy() { + if (objectIndex < 0 || gameObjects.length <= objectIndex || moves[objectIndex] == null) { + return dummyMove; + } + return moves[objectIndex]; + } + public void update(int delta, int x, int y) { btnAddLinear.update(x, y); btnAddQuadratic.update(x, y); btnAddCubic.update(x, y); + btnAnimLin.update(x, y); + btnAnimCir.update(x, y); + btnAnimCub.update(x, y); if (moves[objectIndex] != null) { moves[objectIndex].update(delta, x, y); } diff --git a/src/yugecin/opsudance/sbv2/StoryboardMove.java b/src/yugecin/opsudance/sbv2/StoryboardMove.java index 57d8c969..94a11432 100644 --- a/src/yugecin/opsudance/sbv2/StoryboardMove.java +++ b/src/yugecin/opsudance/sbv2/StoryboardMove.java @@ -17,11 +17,13 @@ */ package yugecin.opsudance.sbv2; +import itdelatrisu.opsu.ui.animations.AnimationEquation; import org.newdawn.slick.Graphics; import yugecin.opsudance.sbv2.movers.StoryboardMover; public interface StoryboardMove { + void setAnimationEquation(AnimationEquation eq); int getAmountOfMovers(); void add(StoryboardMover mover); float[] getPointAt(float t); diff --git a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java index 8ede9055..e55e2058 100644 --- a/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java +++ b/src/yugecin/opsudance/sbv2/StoryboardMoveImpl.java @@ -19,6 +19,7 @@ package yugecin.opsudance.sbv2; import itdelatrisu.opsu.objects.curves.Vec2f; import itdelatrisu.opsu.ui.Fonts; +import itdelatrisu.opsu.ui.animations.AnimationEquation; import org.newdawn.slick.Color; import org.newdawn.slick.Graphics; import yugecin.opsudance.render.RenderUtils; @@ -46,7 +47,10 @@ public class StoryboardMoveImpl implements StoryboardMove { private int recalculateDelay; + private AnimationEquation animationEquation; + public StoryboardMoveImpl(Vec2f start, Vec2f end, int screenWidth) { + this.animationEquation = AnimationEquation.LINEAR; this.start = start; this.end = end; this.screenWidth = screenWidth; @@ -55,6 +59,11 @@ public class StoryboardMoveImpl implements StoryboardMove { recalculateDelay = 700; } + @Override + public void setAnimationEquation(AnimationEquation animationEquation) { + this.animationEquation = animationEquation; + } + @Override public int getAmountOfMovers() { return movers.size(); @@ -89,6 +98,7 @@ public class StoryboardMoveImpl implements StoryboardMove { if (movers.size() == 0) { return new float[] { end.x, end.y }; } + t = animationEquation.calc(t); float cumulativeTime = 0f; for (StoryboardMover mover : movers) { cumulativeTime += mover.timeLengthPercentOfTotalTime;