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.opengl.Display;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.newdawn.slick.Animation;
|
||||
import org.newdawn.slick.Color;
|
||||
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<>();
|
||||
float hueshift = 360f / files.length + 18f;
|
||||
float hue = 0;
|
||||
|
@ -1533,7 +1537,7 @@ public class Game extends ComplexOpsuState {
|
|||
for (ReplayPlayback r : replays) {
|
||||
Color c = new Color(java.awt.Color.getHSBColor((hue) / 360f, 1.0f, 1.0f).getRGB());
|
||||
r.color = c;
|
||||
r.cursor = new Cursor(c);
|
||||
r.cursor.filter = c;
|
||||
hue += hueshift;
|
||||
}
|
||||
|
||||
|
@ -1807,6 +1811,13 @@ public class Game extends ComplexOpsuState {
|
|||
|
||||
knorkesliders = null;
|
||||
|
||||
if (replays != null) {
|
||||
for (ReplayPlayback r : replays) {
|
||||
r.cursor.destroy();
|
||||
}
|
||||
replays.clear();
|
||||
}
|
||||
|
||||
Dancer.instance.setGameObjects(null);
|
||||
|
||||
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.replay.Replay;
|
||||
import itdelatrisu.opsu.replay.ReplayFrame;
|
||||
import itdelatrisu.opsu.ui.Cursor;
|
||||
import itdelatrisu.opsu.ui.Fonts;
|
||||
import itdelatrisu.opsu.ui.animations.AnimationEquation;
|
||||
import org.newdawn.slick.Color;
|
||||
|
@ -48,7 +47,7 @@ public class ReplayPlayback {
|
|||
private int frameIndex;
|
||||
public Color color;
|
||||
public Color originalcolor;
|
||||
public Cursor cursor;
|
||||
public final ReplayCursor cursor;
|
||||
private int keydelay[];
|
||||
public static final int SQSIZE = 15;
|
||||
public static final int UNITHEIGHT = SQSIZE + 5;
|
||||
|
@ -80,7 +79,7 @@ public class ReplayPlayback {
|
|||
this.originalcolor = new Color(color);
|
||||
Color cursorcolor = new Color(color);
|
||||
//cursorcolor.a = 0.5f;
|
||||
cursor = new Cursor(cursorcolor);
|
||||
cursor = new ReplayCursor(cursorcolor);
|
||||
keydelay = new int[4];
|
||||
this.player = replay.playerName;
|
||||
this.playerwidth = Fonts.SMALLBOLD.getWidth(this.player);
|
||||
|
@ -299,7 +298,7 @@ public class ReplayPlayback {
|
|||
y = height - y;
|
||||
}
|
||||
cursor.setCursorPosition(renderdelta, currentFrame.getScaledX(), y);
|
||||
cursor.draw(false);
|
||||
cursor.draw();
|
||||
}
|
||||
|
||||
private void processKeys() {
|
||||
|
@ -322,11 +321,11 @@ public class ReplayPlayback {
|
|||
public static class HitData {
|
||||
|
||||
int combobreaktime = -1;
|
||||
LinkedList<Integer> time300 = new LinkedList();
|
||||
LinkedList<Integer> time100 = new LinkedList();
|
||||
LinkedList<Integer> time50 = new LinkedList();
|
||||
LinkedList<AccData> acc = new LinkedList();
|
||||
LinkedList<ComboData> combo = new LinkedList();
|
||||
LinkedList<Integer> time300 = new LinkedList<>();
|
||||
LinkedList<Integer> time100 = new LinkedList<>();
|
||||
LinkedList<Integer> time50 = new LinkedList<>();
|
||||
LinkedList<AccData> acc = new LinkedList<>();
|
||||
LinkedList<ComboData> combo = new LinkedList<>();
|
||||
|
||||
public HitData(File file) {
|
||||
try (InputStream in = new FileInputStream(file)) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user