attempt to make a better cursortrail for replay stuff
This commit is contained in:
parent
5a268bc713
commit
ee14ac9b2d
|
@ -51,7 +51,6 @@ import java.util.*;
|
||||||
|
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
import org.lwjgl.opengl.Display;
|
import org.lwjgl.opengl.Display;
|
||||||
import org.lwjgl.opengl.GL11;
|
|
||||||
import org.newdawn.slick.Animation;
|
import org.newdawn.slick.Animation;
|
||||||
import org.newdawn.slick.Color;
|
import org.newdawn.slick.Color;
|
||||||
import org.newdawn.slick.Graphics;
|
import org.newdawn.slick.Graphics;
|
||||||
|
@ -1500,6 +1499,11 @@ public class Game extends ComplexOpsuState {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (replays != null) {
|
||||||
|
for (ReplayPlayback r : replays) {
|
||||||
|
r.cursor.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
replays = new LinkedList<>();
|
replays = new LinkedList<>();
|
||||||
float hueshift = 360f / files.length + 18f;
|
float hueshift = 360f / files.length + 18f;
|
||||||
float hue = 0;
|
float hue = 0;
|
||||||
|
@ -1533,7 +1537,7 @@ public class Game extends ComplexOpsuState {
|
||||||
for (ReplayPlayback r : replays) {
|
for (ReplayPlayback r : replays) {
|
||||||
Color c = new Color(java.awt.Color.getHSBColor((hue) / 360f, 1.0f, 1.0f).getRGB());
|
Color c = new Color(java.awt.Color.getHSBColor((hue) / 360f, 1.0f, 1.0f).getRGB());
|
||||||
r.color = c;
|
r.color = c;
|
||||||
r.cursor = new Cursor(c);
|
r.cursor.filter = c;
|
||||||
hue += hueshift;
|
hue += hueshift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1807,6 +1811,13 @@ public class Game extends ComplexOpsuState {
|
||||||
|
|
||||||
knorkesliders = null;
|
knorkesliders = null;
|
||||||
|
|
||||||
|
if (replays != null) {
|
||||||
|
for (ReplayPlayback r : replays) {
|
||||||
|
r.cursor.destroy();
|
||||||
|
}
|
||||||
|
replays.clear();
|
||||||
|
}
|
||||||
|
|
||||||
Dancer.instance.setGameObjects(null);
|
Dancer.instance.setGameObjects(null);
|
||||||
|
|
||||||
Cursor.lastObjColor = Color.white;
|
Cursor.lastObjColor = Color.white;
|
||||||
|
|
267
src/yugecin/opsudance/ReplayCursor.java
Normal file
267
src/yugecin/opsudance/ReplayCursor.java
Normal file
|
@ -0,0 +1,267 @@
|
||||||
|
/*
|
||||||
|
* opsu! - an open-source osu! client
|
||||||
|
* Copyright (C) 2014, 2015 Jeffrey Han
|
||||||
|
*
|
||||||
|
* opsu! 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! 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!. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package yugecin.opsudance;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.opengl.*;
|
||||||
|
import org.newdawn.slick.*;
|
||||||
|
import org.newdawn.slick.opengl.Texture;
|
||||||
|
|
||||||
|
import itdelatrisu.opsu.render.Rendertarget;
|
||||||
|
|
||||||
|
import static itdelatrisu.opsu.GameImage.*;
|
||||||
|
import static yugecin.opsudance.core.InstanceContainer.*;
|
||||||
|
|
||||||
|
public class ReplayCursor
|
||||||
|
{
|
||||||
|
private final Point lastPosition;
|
||||||
|
private TrailList trail = new TrailList();
|
||||||
|
|
||||||
|
public Color filter;
|
||||||
|
|
||||||
|
private Rendertarget fbo;
|
||||||
|
|
||||||
|
private static long nowtime;
|
||||||
|
|
||||||
|
public ReplayCursor(Color filter) {
|
||||||
|
this.filter = filter;
|
||||||
|
this.lastPosition = new Point(width2, 0);
|
||||||
|
this.fbo = Rendertarget.createRTTFramebuffer(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void draw()
|
||||||
|
{
|
||||||
|
nowtime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// stuff copied from CurveRenderState and stuff, I don't know what I'm doing
|
||||||
|
int oldFb = GL11.glGetInteger(EXTFramebufferObject.GL_FRAMEBUFFER_BINDING_EXT);
|
||||||
|
int oldTex = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||||
|
//glGetInteger requires a buffer of size 16, even though just 4
|
||||||
|
//values are returned in this specific case
|
||||||
|
IntBuffer oldViewport = BufferUtils.createIntBuffer(16);
|
||||||
|
GL11.glGetInteger(GL11.GL_VIEWPORT, oldViewport);
|
||||||
|
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbo.getID());
|
||||||
|
GL11.glViewport(0, 0, fbo.width, fbo.height);
|
||||||
|
// render
|
||||||
|
GL11.glClearColor(0f, 0f, 0f, 0f);
|
||||||
|
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||||
|
//GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
// render2
|
||||||
|
|
||||||
|
renderstuff();
|
||||||
|
|
||||||
|
//GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
|
||||||
|
GL11.glBindTexture(GL11.GL_TEXTURE_2D, oldTex);
|
||||||
|
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, oldFb);
|
||||||
|
GL11.glViewport(oldViewport.get(0), oldViewport.get(1), oldViewport.get(2), oldViewport.get(3));
|
||||||
|
|
||||||
|
//GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
|
||||||
|
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||||
|
GL11.glDisable(GL11.GL_TEXTURE_1D);
|
||||||
|
GL11.glBindTexture(GL11.GL_TEXTURE_2D, fbo.getTextureID());
|
||||||
|
GL11.glBegin(GL11.GL_QUADS);
|
||||||
|
GL11.glColor4f(1f, 1f, 1f, 1f);
|
||||||
|
GL11.glTexCoord2f(1f, 1f);
|
||||||
|
GL11.glVertex2i(fbo.width, 0);
|
||||||
|
GL11.glTexCoord2f(0f, 1f);
|
||||||
|
GL11.glVertex2i(0, 0);
|
||||||
|
GL11.glTexCoord2f(0f, 0f);
|
||||||
|
GL11.glVertex2i(0, fbo.height);
|
||||||
|
GL11.glTexCoord2f(1f, 0f);
|
||||||
|
GL11.glVertex2i(fbo.width, fbo.height);
|
||||||
|
GL11.glEnd();
|
||||||
|
GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
CURSOR.getImage().drawCentered(lastPosition.x, lastPosition.y, filter);
|
||||||
|
CURSOR_MIDDLE.getImage().drawCentered(lastPosition.x, lastPosition.y, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderstuff()
|
||||||
|
{
|
||||||
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, fbo.getVbo());
|
||||||
|
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||||
|
GL11.glEnable(GL11.GL_TEXTURE_1D);
|
||||||
|
|
||||||
|
final Image img = CURSOR_TRAIL.getImage();
|
||||||
|
final Texture txt = img.getTexture();
|
||||||
|
Color.white.bind();
|
||||||
|
txt.bind();
|
||||||
|
|
||||||
|
float alpha = 0f;
|
||||||
|
float alphaIncrease = .5f / trail.size;
|
||||||
|
float trailwidth2 = img.getWidth() / 2f;
|
||||||
|
float trailheight2 = img.getHeight() / 2f;
|
||||||
|
float txtwidth = txt.getWidth();
|
||||||
|
float txtheight = txt.getHeight();
|
||||||
|
GL11.glBegin(GL11.GL_QUADS);
|
||||||
|
final Point lastpoint = new Point(-1, -1);
|
||||||
|
for (Trailpart p : trail) {
|
||||||
|
alpha += alphaIncrease;
|
||||||
|
GL11.glColor4f(filter.r, filter.g, filter.b, alpha);
|
||||||
|
GL11.glTexCoord2f(0f, 0f);
|
||||||
|
GL11.glVertex3f(p.x - trailwidth2, p.y - trailheight2, 0f);
|
||||||
|
GL11.glTexCoord2f(txtwidth, 0);
|
||||||
|
GL11.glVertex3f(p.x + trailwidth2, p.y - trailheight2, 0f);
|
||||||
|
GL11.glTexCoord2f(txtwidth, txtheight);
|
||||||
|
GL11.glVertex3f(p.x + trailwidth2, p.y + trailheight2, 0f);
|
||||||
|
GL11.glTexCoord2f(0f, txtheight);
|
||||||
|
GL11.glVertex3f(p.x - trailwidth2, p.y + trailheight2, 0f);
|
||||||
|
lastpoint.x = p.x;
|
||||||
|
lastpoint.y = p.y;
|
||||||
|
}
|
||||||
|
GL11.glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cursor position to given point and updates trail.
|
||||||
|
* @param mouseX x coordinate to set position to
|
||||||
|
* @param mouseY y coordinate to set position to
|
||||||
|
*/
|
||||||
|
public void setCursorPosition(int delta, int mouseX, int mouseY) {
|
||||||
|
nowtime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
if ((lastPosition.x == 0 && lastPosition.y == 0) || !addCursorPoints(lastPosition.x, lastPosition.y, mouseX, mouseY)) {
|
||||||
|
//trail.add(new Trailpart(mouseX, mouseY));
|
||||||
|
}
|
||||||
|
lastPosition.move(mouseX, mouseY);
|
||||||
|
|
||||||
|
int removecount = 0;
|
||||||
|
TrailNode newfirst = trail.first;
|
||||||
|
while (newfirst != null && newfirst.value.time < nowtime - 400) {
|
||||||
|
newfirst = newfirst.next;
|
||||||
|
removecount++;
|
||||||
|
}
|
||||||
|
trail.first = newfirst;
|
||||||
|
if (newfirst == null) {
|
||||||
|
trail.last = null;
|
||||||
|
}
|
||||||
|
trail.size -= removecount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all points between (x1, y1) and (x2, y2) to the cursor point lists.
|
||||||
|
* @author http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#Java
|
||||||
|
*/
|
||||||
|
private boolean addCursorPoints(int x1, int y1, int x2, int y2) {
|
||||||
|
int size = trail.size;
|
||||||
|
// delta of exact value and rounded value of the dependent variable
|
||||||
|
int d = 0;
|
||||||
|
int dy = Math.abs(y2 - y1);
|
||||||
|
int dx = Math.abs(x2 - x1);
|
||||||
|
|
||||||
|
int dy2 = (dy << 1); // slope scaling factors to avoid floating
|
||||||
|
int dx2 = (dx << 1); // point
|
||||||
|
int ix = x1 < x2 ? 1 : -1; // increment direction
|
||||||
|
int iy = y1 < y2 ? 1 : -1;
|
||||||
|
|
||||||
|
if (dy <= dx) {
|
||||||
|
for (;;) {
|
||||||
|
if (x1 == x2)
|
||||||
|
break;
|
||||||
|
trail.add(new Trailpart(x1, y1));
|
||||||
|
x1 += ix;
|
||||||
|
d += dy2;
|
||||||
|
if (d > dx) {
|
||||||
|
y1 += iy;
|
||||||
|
d -= dx2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (;;) {
|
||||||
|
if (y1 == y2)
|
||||||
|
break;
|
||||||
|
trail.add(new Trailpart(x1, y1));
|
||||||
|
y1 += iy;
|
||||||
|
d += dx2;
|
||||||
|
if (d > dy) {
|
||||||
|
x1 += ix;
|
||||||
|
d -= dy2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return trail.size != size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
this.fbo.destroyRTT();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TrailList implements Iterable<Trailpart>
|
||||||
|
{
|
||||||
|
TrailNode first;
|
||||||
|
TrailNode last;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
public void add(Trailpart t)
|
||||||
|
{
|
||||||
|
if (last == null) {
|
||||||
|
last = first = new TrailNode(t);
|
||||||
|
} else {
|
||||||
|
TrailNode n = new TrailNode(t);
|
||||||
|
last.next = n;
|
||||||
|
last = n;
|
||||||
|
}
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Trailpart> iterator()
|
||||||
|
{
|
||||||
|
return new Iterator<Trailpart>() {
|
||||||
|
TrailNode node = first;
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return node != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trailpart next() {
|
||||||
|
Trailpart v = node.value;
|
||||||
|
node = node.next;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TrailNode
|
||||||
|
{
|
||||||
|
TrailNode next;
|
||||||
|
Trailpart value;
|
||||||
|
TrailNode(Trailpart t) {
|
||||||
|
value = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Trailpart {
|
||||||
|
int x, y;
|
||||||
|
long time;
|
||||||
|
Trailpart(int x, int y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.time = nowtime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,6 @@ package yugecin.opsudance;
|
||||||
import itdelatrisu.opsu.GameData;
|
import itdelatrisu.opsu.GameData;
|
||||||
import itdelatrisu.opsu.replay.Replay;
|
import itdelatrisu.opsu.replay.Replay;
|
||||||
import itdelatrisu.opsu.replay.ReplayFrame;
|
import itdelatrisu.opsu.replay.ReplayFrame;
|
||||||
import itdelatrisu.opsu.ui.Cursor;
|
|
||||||
import itdelatrisu.opsu.ui.Fonts;
|
import itdelatrisu.opsu.ui.Fonts;
|
||||||
import itdelatrisu.opsu.ui.animations.AnimationEquation;
|
import itdelatrisu.opsu.ui.animations.AnimationEquation;
|
||||||
import org.newdawn.slick.Color;
|
import org.newdawn.slick.Color;
|
||||||
|
@ -48,7 +47,7 @@ public class ReplayPlayback {
|
||||||
private int frameIndex;
|
private int frameIndex;
|
||||||
public Color color;
|
public Color color;
|
||||||
public Color originalcolor;
|
public Color originalcolor;
|
||||||
public Cursor cursor;
|
public final ReplayCursor cursor;
|
||||||
private int keydelay[];
|
private int keydelay[];
|
||||||
public static final int SQSIZE = 15;
|
public static final int SQSIZE = 15;
|
||||||
public static final int UNITHEIGHT = SQSIZE + 5;
|
public static final int UNITHEIGHT = SQSIZE + 5;
|
||||||
|
@ -80,7 +79,7 @@ public class ReplayPlayback {
|
||||||
this.originalcolor = new Color(color);
|
this.originalcolor = new Color(color);
|
||||||
Color cursorcolor = new Color(color);
|
Color cursorcolor = new Color(color);
|
||||||
//cursorcolor.a = 0.5f;
|
//cursorcolor.a = 0.5f;
|
||||||
cursor = new Cursor(cursorcolor);
|
cursor = new ReplayCursor(cursorcolor);
|
||||||
keydelay = new int[4];
|
keydelay = new int[4];
|
||||||
this.player = replay.playerName;
|
this.player = replay.playerName;
|
||||||
this.playerwidth = Fonts.SMALLBOLD.getWidth(this.player);
|
this.playerwidth = Fonts.SMALLBOLD.getWidth(this.player);
|
||||||
|
@ -299,7 +298,7 @@ public class ReplayPlayback {
|
||||||
y = height - y;
|
y = height - y;
|
||||||
}
|
}
|
||||||
cursor.setCursorPosition(renderdelta, currentFrame.getScaledX(), y);
|
cursor.setCursorPosition(renderdelta, currentFrame.getScaledX(), y);
|
||||||
cursor.draw(false);
|
cursor.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processKeys() {
|
private void processKeys() {
|
||||||
|
@ -322,11 +321,11 @@ public class ReplayPlayback {
|
||||||
public static class HitData {
|
public static class HitData {
|
||||||
|
|
||||||
int combobreaktime = -1;
|
int combobreaktime = -1;
|
||||||
LinkedList<Integer> time300 = new LinkedList();
|
LinkedList<Integer> time300 = new LinkedList<>();
|
||||||
LinkedList<Integer> time100 = new LinkedList();
|
LinkedList<Integer> time100 = new LinkedList<>();
|
||||||
LinkedList<Integer> time50 = new LinkedList();
|
LinkedList<Integer> time50 = new LinkedList<>();
|
||||||
LinkedList<AccData> acc = new LinkedList();
|
LinkedList<AccData> acc = new LinkedList<>();
|
||||||
LinkedList<ComboData> combo = new LinkedList();
|
LinkedList<ComboData> combo = new LinkedList<>();
|
||||||
|
|
||||||
public HitData(File file) {
|
public HitData(File file) {
|
||||||
try (InputStream in = new FileInputStream(file)) {
|
try (InputStream in = new FileInputStream(file)) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user