Merge branch 'sbv2'

This commit is contained in:
yugecin 2016-12-25 15:46:50 +01:00
commit eb1b3f3601
12 changed files with 930 additions and 2 deletions

View File

@ -72,6 +72,7 @@ import org.newdawn.slick.state.transition.EmptyTransition;
import org.newdawn.slick.state.transition.FadeInTransition; import org.newdawn.slick.state.transition.FadeInTransition;
import yugecin.opsudance.*; import yugecin.opsudance.*;
import yugecin.opsudance.objects.curves.FakeCombinedCurve; import yugecin.opsudance.objects.curves.FakeCombinedCurve;
import yugecin.opsudance.sbv2.MoveStoryboard;
import yugecin.opsudance.ui.SBOverlay; import yugecin.opsudance.ui.SBOverlay;
/** /**
@ -313,6 +314,7 @@ public class Game extends BasicGameState {
private final int state; private final int state;
private final Cursor mirrorCursor; private final Cursor mirrorCursor;
private MoveStoryboard msb;
private SBOverlay sbOverlay; private SBOverlay sbOverlay;
private FakeCombinedCurve knorkesliders; private FakeCombinedCurve knorkesliders;
@ -363,7 +365,8 @@ public class Game extends BasicGameState {
@Override @Override
public void init(GameContainer container, StateBasedGame game) public void init(GameContainer container, StateBasedGame game)
throws SlickException { throws SlickException {
this.sbOverlay = new SBOverlay(this, container); this.msb = new MoveStoryboard(container);
this.sbOverlay = new SBOverlay(this, msb, container);
this.container = container; this.container = container;
this.game = game; this.game = game;
input = container.getInput(); 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 // set mouse coordinates
autoMousePosition.set(autoPoint.x, autoPoint.y); autoMousePosition.set(autoPoint.x, autoPoint.y);
} }

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -0,0 +1,178 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
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 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;
import yugecin.opsudance.sbv2.movers.LinearStoryboardMover;
import yugecin.opsudance.sbv2.movers.QuadraticStoryboardMover;
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 SimpleButton btnAnimLin;
private final SimpleButton btnAnimCir;
private final SimpleButton btnAnimCub;
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);
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 {
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);
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);
}
}
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 (moves[objectIndex].getAmountOfMovers() == 0) {
moves[objectIndex] = null;
}
}
if (objectIndex == 0) {
return;
}
if (btnAddLinear.isHovered()) {
getCurrentMoveOrCreateNew().add(new LinearStoryboardMover());
}
if (btnAddQuadratic.isHovered()) {
getCurrentMoveOrCreateNew().add(new QuadraticStoryboardMover());
}
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() {
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, width);
}
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);
}
}
public void setGameObjects(GameObject[] gameObjects) {
this.gameObjects = gameObjects;
this.moves = new StoryboardMove[gameObjects.length];
}
public void setIndex(int objectIndex) {
this.objectIndex = objectIndex;
}
}

View File

@ -0,0 +1,36 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
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);
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);
}

View File

@ -0,0 +1,232 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
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;
import yugecin.opsudance.sbv2.movers.StoryboardMover;
import java.util.ArrayList;
import java.util.List;
public class StoryboardMoveImpl implements StoryboardMove {
private static final int POINTSIZE = 6;
private int screenWidth;
private Vec2f start;
private Vec2f end;
private List<StoryboardMover> movers;
private List<Vec2f> midPoints;
private StoryboardMover nextMover;
private Vec2f currentPoint;
private StoryboardMover prevMover;
private float totalLength;
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;
movers = new ArrayList<>();
midPoints = new ArrayList<>();
recalculateDelay = 700;
}
@Override
public void setAnimationEquation(AnimationEquation animationEquation) {
this.animationEquation = animationEquation;
}
@Override
public int getAmountOfMovers() {
return movers.size();
}
@Override
public void add(StoryboardMover mover) {
mover.end = end;
if (movers.size() == 0) {
mover.setInitialStart(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.setInitialStart(mid);
}
mover.recalculateLength();
totalLength += mover.getLength();
movers.add(mover);
recalculateTimes();
}
@Override
public float[] getPointAt(float t) {
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;
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) {
for (StoryboardMover mover : movers) {
mover.update(delta, x, y);
}
if (currentPoint != null) {
moveCurrentPoint(x, y);
recalculateDelay -= delta;
if (recalculateDelay < 0) {
recalculateDelay = 700;
recalculateLengths();
recalculateTimes();
}
}
}
@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);
return;
}
i++;
}
}
@Override
public void mouseReleased(int x, int y) {
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();
return;
}
}
for(StoryboardMover mover : movers) {
float prevLen = mover.getLength();
if (mover.mouseReleased(x, y)) {
mover.recalculateLength();
totalLength += mover.getLength() - prevLen;
recalculateTimes();
}
}
} else {
moveCurrentPoint(x, y);
recalculateLengths();
recalculateTimes();
currentPoint = null;
}
recalculateDelay = 700;
}
@Override
public void recalculateTimes() {
for (StoryboardMover mover : movers) {
mover.timeLengthPercentOfTotalTime = mover.getLength() / totalLength;
}
}
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;
prevMover.end = currentPoint;
nextMover.start = currentPoint;
}
@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;
RenderUtils.fillCenteredRect(g, screenWidth - 20, y - dif / 2, 5);
}
g.setColor(Color.cyan);
for (Vec2f point : midPoints) {
RenderUtils.fillCenteredRect(g, point.x, point.y, POINTSIZE);
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@ -0,0 +1,94 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
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;
import yugecin.opsudance.render.RenderUtils;
public abstract class StoryboardMover {
public static final float CALC_DRAW_INTERVAL = 0.05f;
protected float length;
public Vec2f start;
public Vec2f end;
private final Color renderColor;
public float timeLengthPercentOfTotalTime;
public StoryboardMover(Color renderColor) {
this.renderColor = renderColor;
}
public abstract float[] getPointAt(float t);
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) {
float[] p = getPointAt(t);
RenderUtils.fillCenteredRect(g, p[0], p[1], 1);
}
}
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;
}
}
}

View File

@ -0,0 +1,94 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
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;
public abstract class StoryboardMultipointMover extends StoryboardMover {
private static final int POINTSIZE = 6;
private List<Vec2f> 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(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) {
RenderUtils.fillCenteredRect(g, point.x, point.y, POINTSIZE);
}
super.render(g);
}
}

View File

@ -28,6 +28,7 @@ import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics; import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input; import org.newdawn.slick.Input;
import yugecin.opsudance.ObjectColorOverrides; import yugecin.opsudance.ObjectColorOverrides;
import yugecin.opsudance.sbv2.MoveStoryboard;
import yugecin.opsudance.ui.OptionsOverlay.OptionTab; import yugecin.opsudance.ui.OptionsOverlay.OptionTab;
import java.util.*; import java.util.*;
@ -109,6 +110,7 @@ public class SBOverlay implements OptionsOverlay.Parent {
private int index; private int index;
private final Game game; private final Game game;
private final MoveStoryboard msb;
private final OptionsOverlay overlay; private final OptionsOverlay overlay;
static { 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.game = game;
this.msb = msb;
initialOptions = new HashMap<>(); initialOptions = new HashMap<>();
overlay = new OptionsOverlay(this, options, 2, container); overlay = new OptionsOverlay(this, options, 2, container);
this.width = container.getWidth(); this.width = container.getWidth();
@ -131,6 +134,7 @@ public class SBOverlay implements OptionsOverlay.Parent {
if (!Options.isEnableSB() || hide) { if (!Options.isEnableSB() || hide) {
return; return;
} }
msb.render(g);
int lh = Fonts.SMALL.getLineHeight(); 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 + lh, "save position: ctrl+s, load position: ctrl+l", Color.cyan);
Fonts.SMALL.drawString(10, height - 50, "speed: C " + (speed / 10f) + " V", 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) { if (Options.isEnableSB() && menu) {
overlay.update(delta, mouseX, mouseY); overlay.update(delta, mouseX, mouseY);
} }
msb.update(delta, mouseX, mouseY);
} }
public boolean keyPressed(int key, char c) { public boolean keyPressed(int key, char c) {
@ -234,6 +239,7 @@ public class SBOverlay implements OptionsOverlay.Parent {
public void setGameObjects(GameObject[] gameObjects) { public void setGameObjects(GameObject[] gameObjects) {
if (this.gameObjects.length != gameObjects.length) { if (this.gameObjects.length != gameObjects.length) {
optionsMap = new HashMap[gameObjects.length]; optionsMap = new HashMap[gameObjects.length];
msb.setGameObjects(gameObjects);
} }
if (optionsMap.length > 0) { if (optionsMap.length > 0) {
// copy all current settings in first obj map // 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) { public boolean mousePressed(int button, int x, int y) {
msb.mousePressed(x, y);
if (!menu) { if (!menu) {
return false; return false;
} }
@ -270,6 +277,7 @@ public class SBOverlay implements OptionsOverlay.Parent {
if (index >= optionsMap.length) { if (index >= optionsMap.length) {
return; return;
} }
msb.setIndex(index);
for (; this.index <= index; this.index++) { for (; this.index <= index; this.index++) {
HashMap options = optionsMap[this.index]; HashMap options = optionsMap[this.index];
if (options == null) { if (options == null) {
@ -289,6 +297,7 @@ public class SBOverlay implements OptionsOverlay.Parent {
overlay.mouseReleased(button, x, y); overlay.mouseReleased(button, x, y);
return true; return true;
} }
msb.mouseReleased(x, y);
if (x > 10 || index >= optionsMap.length || optionsMap[index] == null) { if (x > 10 || index >= optionsMap.length || optionsMap[index] == null) {
return false; return false;
} }
@ -348,6 +357,10 @@ public class SBOverlay implements OptionsOverlay.Parent {
} }
} }
public float[] getPoint(int trackPosition) {
return msb.getPoint(trackPosition);
}
@Override @Override
public void onLeave() { public void onLeave() {
menu = false; menu = false;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}