Shader tm
This commit is contained in:
parent
02448503c7
commit
9a3ecc06aa
15
res/sh_Cursor.vertex
Normal file
15
res/sh_Cursor.vertex
Normal file
|
@ -0,0 +1,15 @@
|
|||
attribute vec4 m_Position;
|
||||
attribute vec2 m_TexCoord;
|
||||
attribute float m_Time;
|
||||
|
||||
varying vec4 v_Color;
|
||||
varying vec2 v_TexCoord;
|
||||
|
||||
uniform float g_FadeClock;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = m_Position;
|
||||
v_Color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
v_TexCoord = m_TexCoord;
|
||||
}
|
13
res/sh_Texture.frag
Normal file
13
res/sh_Texture.frag
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
varying vec4 v_Color;
|
||||
varying vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2D m_Sampler;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);//v_Color * texture2D(m_Sampler, v_TexCoord);
|
||||
}
|
92
src/com/osufx/sunpy/PropertyCollection.java
Normal file
92
src/com/osufx/sunpy/PropertyCollection.java
Normal file
|
@ -0,0 +1,92 @@
|
|||
package com.osufx.sunpy;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class PropertyCollection {
|
||||
private HashMap<String, ShaderProperty> properties = new HashMap<>();
|
||||
private Shader owner;
|
||||
|
||||
private boolean changed = false;
|
||||
|
||||
public PropertyCollection(Shader owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
this.changed = true;
|
||||
this.properties.clear();
|
||||
}
|
||||
|
||||
public void Add(ShaderProperty prop) {
|
||||
this.properties.put(prop.Name, prop);
|
||||
}
|
||||
|
||||
public void Replace(ShaderProperty prop) {
|
||||
this.properties.replace(prop.Name, prop);
|
||||
}
|
||||
|
||||
public void Replace(String key, Object value) {
|
||||
if (!this.properties.containsKey(key))
|
||||
return;
|
||||
|
||||
ShaderProperty prop = this.properties.get(key);
|
||||
|
||||
if (value.getClass() != prop.Type){
|
||||
System.out.println(String.format("%s variable %s does not take value type %s", this.owner.name, key, value.getClass()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop.Value != null && prop.Value == value)
|
||||
return;
|
||||
|
||||
prop.Value = value;
|
||||
}
|
||||
|
||||
public void Remove(String key) {
|
||||
this.properties.remove(key);
|
||||
}
|
||||
|
||||
public void Set() {
|
||||
if (!this.changed)
|
||||
return;
|
||||
|
||||
for (ShaderProperty prop : this.properties.values()) {
|
||||
prop.Set();
|
||||
}
|
||||
|
||||
this.changed = false;
|
||||
}
|
||||
|
||||
public ShaderProperty get(String propName) {
|
||||
if (!this.properties.containsKey(propName))
|
||||
return null;
|
||||
return this.properties.get(propName);
|
||||
}
|
||||
|
||||
public void set(String propName, Object value) {
|
||||
if (!this.owner.loaded)
|
||||
return;
|
||||
|
||||
if (!this.properties.containsKey(propName)) {
|
||||
System.out.println(String.format("Property %s does not exist!", propName));
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderProperty prop = this.properties.get(propName);
|
||||
|
||||
if (value.getClass() != prop.Type){
|
||||
System.out.println(String.format("%s variable %s does not take value type %s", this.owner.name, propName, value.getClass()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop.Value != null && prop.Value == value)
|
||||
return;
|
||||
|
||||
prop.Value = value;
|
||||
|
||||
if (this.owner.started)
|
||||
prop.Set();
|
||||
else
|
||||
this.changed = true;
|
||||
}
|
||||
}
|
204
src/com/osufx/sunpy/Shader.java
Normal file
204
src/com/osufx/sunpy/Shader.java
Normal file
|
@ -0,0 +1,204 @@
|
|||
package com.osufx.sunpy;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.newdawn.slick.util.Log;
|
||||
import org.newdawn.slick.util.ResourceLoader;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.*;
|
||||
|
||||
public class Shader {
|
||||
public String name;
|
||||
public int programId = -1;
|
||||
public boolean loaded = false;
|
||||
public boolean started = false;
|
||||
|
||||
public PropertyCollection Properties;
|
||||
|
||||
public static HashMap<String, Object> globalProperties = new HashMap<>();
|
||||
public static List<Shader> loadedShaders = new ArrayList<>();
|
||||
public static int currentShader = 0;
|
||||
|
||||
private HashMap<String, Integer> attribLoc = new HashMap<>();
|
||||
private static final String[] attribs = new String[] {
|
||||
"m_Position",
|
||||
"m_Color",
|
||||
"m_TexCoord",
|
||||
"m_Time",
|
||||
"m_Direction"
|
||||
};
|
||||
|
||||
private HashMap<Integer, String> shaderParts = new HashMap<>();
|
||||
private int previousShader;
|
||||
|
||||
public Shader(String vertexShader, String fragmentShader) {
|
||||
String vertexString;
|
||||
String fragmentString;
|
||||
|
||||
try {
|
||||
InputStream vertexStream = ResourceLoader.getResourceAsStream(vertexShader);
|
||||
vertexString = convertStreamToString(vertexStream);
|
||||
|
||||
InputStream fragmentStream = ResourceLoader.getResourceAsStream(fragmentShader);
|
||||
fragmentString = convertStreamToString(fragmentStream);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
this.name = String.format("%s/%s", vertexShader, fragmentShader);
|
||||
this.Properties = new PropertyCollection(this);
|
||||
|
||||
this.programId = GL20.glCreateProgram();
|
||||
|
||||
this.shaderParts.put(GL20.glCreateShader(GL20.GL_VERTEX_SHADER), vertexString);
|
||||
this.shaderParts.put(GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER), fragmentString);
|
||||
this.CompileParts();
|
||||
this.Compile();
|
||||
}
|
||||
|
||||
public Shader(String shader, final int shaderType) {
|
||||
if (shaderType != GL20.GL_FRAGMENT_SHADER && shaderType != GL20.GL_VERTEX_SHADER){
|
||||
System.out.println("Invalid shader type");
|
||||
return;
|
||||
}
|
||||
|
||||
String shaderString;
|
||||
|
||||
try {
|
||||
InputStream shaderStream = ResourceLoader.getResourceAsStream(shader);
|
||||
shaderString = convertStreamToString(shaderStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
this.name = String.format("%s/%s",
|
||||
shaderType == GL20.GL_FRAGMENT_SHADER ? "Fragment" : "Vertex",
|
||||
shader);
|
||||
this.Properties = new PropertyCollection(this);
|
||||
|
||||
this.programId = GL20.glCreateProgram();
|
||||
|
||||
this.shaderParts.put(GL20.glCreateShader(shaderType), shaderString);
|
||||
this.CompileParts();
|
||||
this.Compile();
|
||||
}
|
||||
|
||||
public void CompileParts() {
|
||||
for (Map.Entry<Integer, String> entry : this.shaderParts.entrySet()) {
|
||||
int handle = entry.getKey();
|
||||
String source = entry.getValue();
|
||||
|
||||
GL20.glShaderSource(handle, source);
|
||||
GL20.glCompileShader(handle);
|
||||
|
||||
int res = GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS);
|
||||
if (res != GL11.GL_TRUE) {
|
||||
String error = GL20.glGetShaderInfoLog(handle, 1024);
|
||||
Log.error("Shader compilation failed.", new Exception(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Compile() {
|
||||
this.Properties.Clear();
|
||||
|
||||
for (int handler : this.shaderParts.keySet()) {
|
||||
GL20.glAttachShader(this.programId, handler);
|
||||
}
|
||||
|
||||
GL20.glLinkProgram(this.programId);
|
||||
|
||||
int res = GL20.glGetProgrami(this.programId, GL20.GL_LINK_STATUS);
|
||||
if (res != GL11.GL_TRUE) {
|
||||
String error = GL20.glGetProgramInfoLog(this.programId, 1024);
|
||||
Log.error("Program linking failed.", new Exception(error));
|
||||
}
|
||||
|
||||
for (int handler : this.shaderParts.keySet()) {
|
||||
GL20.glDeleteShader(handler);
|
||||
}
|
||||
|
||||
for (int i = 0; i < attribs.length; i++) {
|
||||
int attrib = GL20.glGetAttribLocation(this.programId, attribs[i]);
|
||||
this.attribLoc.put(attribs[i], attrib);
|
||||
//GL20.glBindAttribLocation(this.programId, i, attribLoc[i]);
|
||||
}
|
||||
|
||||
/*for (int handler : this.shaderParts.keySet()) {
|
||||
GL20.glDetachShader(this.programId, handler);
|
||||
}*/
|
||||
|
||||
this.loaded = res == GL11.GL_TRUE;
|
||||
|
||||
if (this.loaded) {
|
||||
int uniCount = GL20.glGetProgrami(this.programId, GL20.GL_ACTIVE_UNIFORMS);
|
||||
|
||||
for (int i = 0; i < uniCount; i++) {
|
||||
IntBuffer length = BufferUtils.createIntBuffer(1);
|
||||
IntBuffer size = BufferUtils.createIntBuffer(1);
|
||||
IntBuffer type = BufferUtils.createIntBuffer(1);
|
||||
ByteBuffer name = ByteBuffer.allocateDirect(64);
|
||||
|
||||
GL20.glGetActiveUniform(this.programId, i, length, size, type, name);
|
||||
|
||||
|
||||
byte[] buf = new byte[length.get(0)];
|
||||
|
||||
name.get(buf, 0, buf.length);
|
||||
String propName = new String(buf);
|
||||
int propLocation = GL20.glGetUniformLocation(programId, propName);
|
||||
|
||||
UniformType propUniformType = UniformType.map.get(type.get(0));
|
||||
Class propType = ShaderProperty.ConvertType(propUniformType.name());
|
||||
|
||||
System.out.println(String.format("propName:%s PropUniformType:%s PropType:%s", propName, propUniformType, propType));
|
||||
|
||||
this.Properties.Add(new ShaderProperty(
|
||||
propName,
|
||||
propLocation,
|
||||
propType,
|
||||
propUniformType
|
||||
));
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Object> entry : globalProperties.entrySet()) {
|
||||
this.Properties.Replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
loadedShaders.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Begin(){
|
||||
if (this.started || !this.loaded)
|
||||
return;
|
||||
|
||||
GL20.glUseProgram(this.programId);
|
||||
this.previousShader = currentShader;
|
||||
currentShader = this.programId;
|
||||
|
||||
this.started = true;
|
||||
}
|
||||
|
||||
public void End() {
|
||||
if (!this.started)
|
||||
return;
|
||||
|
||||
GL20.glUseProgram(this.previousShader);
|
||||
currentShader = this.previousShader;
|
||||
|
||||
this.started = false;
|
||||
}
|
||||
|
||||
static String convertStreamToString(InputStream is) {
|
||||
Scanner s = new Scanner(is).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
}
|
133
src/com/osufx/sunpy/ShaderProperty.java
Normal file
133
src/com/osufx/sunpy/ShaderProperty.java
Normal file
|
@ -0,0 +1,133 @@
|
|||
package com.osufx.sunpy;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
public class ShaderProperty {
|
||||
public String Name;
|
||||
public int Location;
|
||||
|
||||
public Class Type;
|
||||
public UniformType ActiveUniformType;
|
||||
|
||||
public Object Value;
|
||||
|
||||
public ShaderProperty(String Name, int Location, Class Type, UniformType ActiveUniformType) {
|
||||
this.Name = Name;
|
||||
this.Location = Location;
|
||||
this.Type = Type;
|
||||
this.ActiveUniformType = ActiveUniformType;
|
||||
}
|
||||
|
||||
public void Set() {
|
||||
if (Value == null)
|
||||
return;
|
||||
|
||||
switch (this.ActiveUniformType) {
|
||||
case Bool:
|
||||
GL20.glUniform1(this.Location, IntBuffer.wrap( new int[]{ (boolean)Value ? 1 : 0 } ));
|
||||
break;
|
||||
case Int:
|
||||
GL20.glUniform1(this.Location, IntBuffer.wrap( new int[]{ (int)Value } ));
|
||||
break;
|
||||
case Float:
|
||||
GL20.glUniform1(this.Location, FloatBuffer.wrap( new float[]{ (float)Value } ));
|
||||
break;
|
||||
case BoolVec2:
|
||||
GL20.glUniform2(this.Location, IntBuffer.wrap( boolArrayToIntArray( (boolean[])Value ) ));
|
||||
break;
|
||||
case IntVec2:
|
||||
GL20.glUniform2(this.Location, IntBuffer.wrap( (int[])Value ));
|
||||
break;
|
||||
case FloatVec2:
|
||||
GL20.glUniform2(this.Location, FloatBuffer.wrap( (float[])Value ));
|
||||
break;
|
||||
case FloatMat2:
|
||||
GL20.glUniformMatrix2(this.Location, false, FloatBuffer.wrap( (float[])Value ));
|
||||
break;
|
||||
case BoolVec3:
|
||||
GL20.glUniform3(this.Location, IntBuffer.wrap( boolArrayToIntArray( (boolean[])Value ) ));
|
||||
break;
|
||||
case IntVec3:
|
||||
GL20.glUniform3(this.Location, IntBuffer.wrap( (int[])Value ));
|
||||
break;
|
||||
case FloatVec3:
|
||||
GL20.glUniform3(this.Location, FloatBuffer.wrap( (float[])Value ));
|
||||
break;
|
||||
case FloatMat3:
|
||||
GL20.glUniformMatrix3(this.Location, false, FloatBuffer.wrap( (float[])Value ));
|
||||
break;
|
||||
case BoolVec4:
|
||||
GL20.glUniform4(this.Location, IntBuffer.wrap( boolArrayToIntArray( (boolean[])Value ) ));
|
||||
break;
|
||||
case IntVec4:
|
||||
GL20.glUniform4(this.Location, IntBuffer.wrap( (int[])Value ));
|
||||
break;
|
||||
case FloatVec4:
|
||||
GL20.glUniform4(this.Location, FloatBuffer.wrap( (float[])Value ));
|
||||
break;
|
||||
case FloatMat4:
|
||||
GL20.glUniformMatrix4(this.Location, false, FloatBuffer.wrap( (float[])Value ));
|
||||
break;
|
||||
case Sampler2D:
|
||||
GL20.glUniform1(this.Location, BufferUtils.createIntBuffer(1).put((int) Value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static Class ConvertType(String type) {
|
||||
switch (type) {
|
||||
default:
|
||||
//throw new Exception(String.format("Uniform type %s is not supported.", type));
|
||||
System.out.println(String.format("Uniform type %s is not supported.", type));
|
||||
return null;
|
||||
case "Bool":
|
||||
return Boolean.class;
|
||||
case "Int":
|
||||
return Integer.class;
|
||||
case "Float":
|
||||
return Float.class;
|
||||
case "BoolVec2":
|
||||
return boolean[].class;
|
||||
case "IntVec2":
|
||||
return int[].class;
|
||||
case "FloatVec2":
|
||||
return float[].class;
|
||||
case "BoolVec3":
|
||||
return boolean[].class;
|
||||
case "IntVec3":
|
||||
return int[].class;
|
||||
case "FloatVec3":
|
||||
return float[].class;
|
||||
case "BoolVec4":
|
||||
return boolean[].class;
|
||||
case "IntVec4":
|
||||
return int[].class;
|
||||
case "FloatVec4":
|
||||
return float[].class;
|
||||
case "FloatMat2":
|
||||
return float[].class;
|
||||
case "FloatMat3":
|
||||
return float[].class;
|
||||
case "FloatMat4":
|
||||
return float[].class;
|
||||
case "Sampler2D":
|
||||
case "SamplerCube":
|
||||
return Integer.class;
|
||||
}
|
||||
}
|
||||
|
||||
/*public static Type ConvertType(int type) {
|
||||
(UniformType)24;
|
||||
}*/
|
||||
|
||||
public static int[] boolArrayToIntArray(boolean[] array) {
|
||||
int[] value = new int[array.length];
|
||||
for (int i = 0; i < array.length; i++)
|
||||
value[i] = array[i] ? 1 : 0;
|
||||
return value;
|
||||
}
|
||||
}
|
39
src/com/osufx/sunpy/UniformType.java
Normal file
39
src/com/osufx/sunpy/UniformType.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
package com.osufx.sunpy;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public enum UniformType {
|
||||
Int(GL11.GL_INT),
|
||||
Float(GL11.GL_FLOAT),
|
||||
FloatVec2(GL20.GL_FLOAT_VEC2),
|
||||
FloatVec3(GL20.GL_FLOAT_VEC3),
|
||||
FloatVec4(GL20.GL_FLOAT_VEC4),
|
||||
IntVec2(GL20.GL_INT_VEC2),
|
||||
IntVec3(GL20.GL_INT_VEC3),
|
||||
IntVec4(GL20.GL_INT_VEC4),
|
||||
Bool(GL20.GL_BOOL),
|
||||
BoolVec2(GL20.GL_BOOL_VEC2),
|
||||
BoolVec3(GL20.GL_BOOL_VEC3),
|
||||
BoolVec4(GL20.GL_BOOL_VEC4),
|
||||
FloatMat2(GL20.GL_FLOAT_MAT2),
|
||||
FloatMat3(GL20.GL_FLOAT_MAT3),
|
||||
FloatMat4(GL20.GL_FLOAT_MAT4),
|
||||
Sampler2D(GL20.GL_SAMPLER_2D),
|
||||
SamplerCube(GL20.GL_SAMPLER_CUBE);
|
||||
|
||||
private final int glIndex;
|
||||
|
||||
public static HashMap<Integer, UniformType> map = new HashMap<>();
|
||||
static {
|
||||
for (UniformType v : UniformType.values()) {
|
||||
map.put(v.glIndex, v);
|
||||
}
|
||||
}
|
||||
|
||||
UniformType(int glIndex) {
|
||||
this.glIndex = glIndex;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
package itdelatrisu.opsu.render;
|
||||
|
||||
import com.osufx.sunpy.Shader;
|
||||
import itdelatrisu.opsu.GameImage;
|
||||
import itdelatrisu.opsu.Utils;
|
||||
import itdelatrisu.opsu.beatmap.HitObject;
|
||||
|
@ -248,7 +249,7 @@ public class CurveRenderState {
|
|||
GL11.glTexParameteri(GL11.GL_TEXTURE_1D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_1D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
|
||||
|
||||
GL20.glUseProgram(0);
|
||||
GL20.glUseProgram(Shader.currentShader);
|
||||
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glPushMatrix();
|
||||
|
|
|
@ -307,7 +307,7 @@ public class Game extends ComplexOpsuState {
|
|||
MUSICBAR_HOVER = new Color(12, 9, 10, 0.35f),
|
||||
MUSICBAR_FILL = new Color(255, 255, 255, 0.75f);
|
||||
|
||||
private final Cursor mirrorCursor;
|
||||
private Cursor mirrorCursor;
|
||||
private final MoveStoryboard moveStoryboardOverlay;
|
||||
private final StoryboardOverlay storyboardOverlay;
|
||||
private final OptionsOverlay optionsOverlay;
|
||||
|
@ -318,7 +318,7 @@ public class Game extends ComplexOpsuState {
|
|||
|
||||
public Game() {
|
||||
super();
|
||||
mirrorCursor = new Cursor(true);
|
||||
//mirrorCursor = new Cursor(true);
|
||||
this.moveStoryboardOverlay = new MoveStoryboard();
|
||||
this.optionsOverlay = new OptionsOverlay(OptionGroups.storyboardOptions);
|
||||
this.storyboardOverlay = new StoryboardOverlay(moveStoryboardOverlay, optionsOverlay, this);
|
||||
|
@ -1501,6 +1501,7 @@ public class Game extends ComplexOpsuState {
|
|||
|
||||
super.enter();
|
||||
|
||||
/*
|
||||
File replaydir = new File("d:/Users/Robin/games/osu/osr-stuff-master/xi/");
|
||||
if (!replaydir.exists()) {
|
||||
bubNotifs.sendf(Colors.BUB_RED, "replay folder '%s' does not exist", replaydir.getAbsolutePath());
|
||||
|
@ -1577,7 +1578,7 @@ public class Game extends ComplexOpsuState {
|
|||
replayidx++;
|
||||
}
|
||||
|
||||
displayContainer.drawCursor = false;
|
||||
displayContainer.drawCursor = false;*/
|
||||
|
||||
isInGame = true;
|
||||
if (!skippedToCheckpoint) {
|
||||
|
|
|
@ -18,18 +18,34 @@
|
|||
|
||||
package itdelatrisu.opsu.ui;
|
||||
|
||||
import com.osufx.sunpy.Shader;
|
||||
import itdelatrisu.opsu.GameImage;
|
||||
import itdelatrisu.opsu.Utils;
|
||||
import itdelatrisu.opsu.render.Rendertarget;
|
||||
import itdelatrisu.opsu.ui.animations.AnimationEquation;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.EXTFramebufferObject;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.newdawn.slick.*;
|
||||
import org.newdawn.slick.opengl.Texture;
|
||||
import org.newdawn.slick.opengl.TextureImpl;
|
||||
|
||||
import yugecin.opsudance.Dancer;
|
||||
import yugecin.opsudance.ReplayPlayback;
|
||||
import yugecin.opsudance.skinning.SkinService;
|
||||
|
||||
import static yugecin.opsudance.options.Options.*;
|
||||
import static itdelatrisu.opsu.GameImage.CURSOR;
|
||||
import static itdelatrisu.opsu.GameImage.CURSOR_MIDDLE;
|
||||
import static itdelatrisu.opsu.GameImage.CURSOR_TRAIL;
|
||||
import static yugecin.opsudance.core.InstanceContainer.*;
|
||||
|
||||
/**
|
||||
|
@ -55,8 +71,7 @@ public class Cursor {
|
|||
/** The time it takes for the cursor to scale, in milliseconds. */
|
||||
private static final float CURSOR_SCALE_TIME = 125;
|
||||
|
||||
/** Stores all previous cursor locations to display a trail. */
|
||||
private LinkedList<Point> trail = new LinkedList<>();
|
||||
private TrailList trail = new TrailList();
|
||||
|
||||
private boolean newStyle;
|
||||
|
||||
|
@ -70,6 +85,10 @@ public class Cursor {
|
|||
|
||||
private Color filter;
|
||||
|
||||
private Rendertarget fbo;
|
||||
|
||||
private Shader cursorTrailShader;
|
||||
|
||||
public Cursor() {
|
||||
this(false);
|
||||
}
|
||||
|
@ -77,6 +96,9 @@ public class Cursor {
|
|||
public Cursor(boolean isMirrored) {
|
||||
resetLocations(0, 0);
|
||||
this.isMirrored = isMirrored;
|
||||
this.lastPosition = new Point(width2, 0);
|
||||
this.filter = new Color(255,255,255);
|
||||
this.cursorTrailShader = new Shader("sh_Cursor.vertex", "sh_Texture.frag");
|
||||
}
|
||||
|
||||
public Cursor(Color filter) {
|
||||
|
@ -89,6 +111,10 @@ public class Cursor {
|
|||
* @param mousePressed whether or not the mouse button is pressed
|
||||
*/
|
||||
public void draw(boolean mousePressed) {
|
||||
if (fbo == null) {
|
||||
this.fbo = Rendertarget.createRTTFramebuffer(width, height);
|
||||
}
|
||||
/*
|
||||
if (OPTION_DISABLE_CURSOR.state) {
|
||||
return;
|
||||
}
|
||||
|
@ -168,6 +194,78 @@ public class Cursor {
|
|||
if (hasMiddle) {
|
||||
cursorMiddle.drawCentered(lastPosition.x, lastPosition.y, OPTION_DANCE_CURSOR_ONLY_COLOR_TRAIL.state ? Color.white : filter);
|
||||
}
|
||||
*/
|
||||
final Image img = CURSOR_TRAIL.getImage();
|
||||
final Texture txt = img.getTexture();
|
||||
|
||||
final float trailw2 = img.getWidth() * OPTION_CURSOR_SIZE.val / 100f / 2f;
|
||||
final float trailh2 = img.getHeight() * OPTION_CURSOR_SIZE.val / 100f / 2f;
|
||||
float txtw = txt.getWidth();
|
||||
float txth = txt.getHeight();
|
||||
|
||||
/*
|
||||
// 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);
|
||||
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);
|
||||
GL11.glClearColor(0f, 0f, 0f, 0f);
|
||||
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||
*/
|
||||
//txt.bind();
|
||||
Color.white.bind();
|
||||
TextureImpl.unbind();
|
||||
cursorTrailShader.Begin();
|
||||
GL11.glBegin(GL11.GL_QUADS);
|
||||
|
||||
//GL11.glBindTexture(GL11.GL_TEXTURE_2D, );
|
||||
//cursorTrailShader.Properties.set("m_Sampler", txt.getTextureID());
|
||||
//cursorTrailShader.Properties.set("g_FadeClock", 0.4f);
|
||||
float alpha = 0f;
|
||||
float alphaIncrease = .4f / trail.size;
|
||||
for (Trailpart p : trail) {
|
||||
//alpha += alphaIncrease;
|
||||
GL11.glColor4f(filter.r, filter.g, filter.b, alpha);
|
||||
//GL11.glTexCoord2f(0f, 0f);
|
||||
GL11.glVertex3f(p.x - trailw2, p.y - trailh2, 0f);
|
||||
//GL11.glTexCoord2f(txtw, 0);
|
||||
GL11.glVertex3f(p.x + trailw2, p.y - trailh2, 0f);
|
||||
//GL11.glTexCoord2f(txtw, txth);
|
||||
GL11.glVertex3f(p.x + trailw2, p.y + trailh2, 0f);
|
||||
//GL11.glTexCoord2f(0f, txth);
|
||||
GL11.glVertex3f(p.x - trailw2, p.y + trailh2, 0f);
|
||||
break;
|
||||
}
|
||||
//GL11.glEnd();
|
||||
GL11.glEnd();
|
||||
cursorTrailShader.End();
|
||||
|
||||
/*
|
||||
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));
|
||||
|
||||
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.getScaledImage(OPTION_CURSOR_SIZE.val / 100f).drawCentered(lastPosition.x, lastPosition.y, filter);
|
||||
//CURSOR_MIDDLE.getScaledImage(OPTION_CURSOR_SIZE.val / 100f).drawCentered(lastPosition.x, lastPosition.y, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,34 +274,22 @@ public class Cursor {
|
|||
* @param mouseY y coordinate to set position to
|
||||
*/
|
||||
public void setCursorPosition(int delta, int mouseX, int mouseY) {
|
||||
// TODO: use an image buffer
|
||||
int removeCount = 0;
|
||||
float FPSmod = Math.max(1000 / Math.max(delta, 1), 1) / 30f; // TODO
|
||||
if (newStyle) {
|
||||
// new style: add all points between cursor movements
|
||||
if ((lastPosition.x == 0 && lastPosition.y == 0) || !addCursorPoints(lastPosition.x, lastPosition.y, mouseX, mouseY)) {
|
||||
trail.add(new Point(mouseX, mouseY));
|
||||
}
|
||||
nowtime = System.currentTimeMillis();
|
||||
|
||||
addCursorPoints(lastPosition.x, lastPosition.y, mouseX, mouseY);
|
||||
lastPosition.move(mouseX, mouseY);
|
||||
|
||||
removeCount = (int) (trail.size() / (6 * FPSmod)) + 1;
|
||||
} else {
|
||||
// old style: sample one point at a time
|
||||
trail.add(new Point(mouseX, mouseY));
|
||||
|
||||
int max = (int) (10 * FPSmod);
|
||||
if (trail.size() > max)
|
||||
removeCount = trail.size() - max;
|
||||
int removecount = 0;
|
||||
TrailNode newfirst = trail.first;
|
||||
while (newfirst != null && newfirst.value.time < nowtime - 175) {
|
||||
newfirst = newfirst.next;
|
||||
removecount++;
|
||||
}
|
||||
|
||||
int cursortraillength = OPTION_DANCE_CURSOR_TRAIL_OVERRIDE.val;
|
||||
if (cursortraillength > 20) {
|
||||
removeCount = trail.size() - cursortraillength;
|
||||
trail.first = newfirst;
|
||||
if (newfirst == null) {
|
||||
trail.last = null;
|
||||
}
|
||||
|
||||
// remove points from the lists
|
||||
for (int i = 0; i < removeCount && !trail.isEmpty(); i++)
|
||||
trail.remove();
|
||||
trail.size -= removecount;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,8 +297,8 @@ public class Cursor {
|
|||
* @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
|
||||
boolean added = false;
|
||||
int d = 0;
|
||||
int dy = Math.abs(y2 - y1);
|
||||
int dx = Math.abs(x2 - x1);
|
||||
|
@ -222,16 +308,11 @@ public class Cursor {
|
|||
int ix = x1 < x2 ? 1 : -1; // increment direction
|
||||
int iy = y1 < y2 ? 1 : -1;
|
||||
|
||||
int k = 5; // sample size
|
||||
if (dy <= dx) {
|
||||
for (int i = 0; ; i++) {
|
||||
if (i == k) {
|
||||
trail.add(new Point(x1, y1));
|
||||
added = true;
|
||||
i = 0;
|
||||
}
|
||||
for (;;) {
|
||||
if (x1 == x2)
|
||||
break;
|
||||
trail.add(new Trailpart(x1, y1));
|
||||
x1 += ix;
|
||||
d += dy2;
|
||||
if (d > dx) {
|
||||
|
@ -240,14 +321,10 @@ public class Cursor {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; ; i++) {
|
||||
if (i == k) {
|
||||
trail.add(new Point(x1, y1));
|
||||
added = true;
|
||||
i = 0;
|
||||
}
|
||||
for (;;) {
|
||||
if (y1 == y2)
|
||||
break;
|
||||
trail.add(new Trailpart(x1, y1));
|
||||
y1 += iy;
|
||||
d += dx2;
|
||||
if (d > dy) {
|
||||
|
@ -256,7 +333,64 @@ public class Cursor {
|
|||
}
|
||||
}
|
||||
}
|
||||
return added;
|
||||
return trail.size != size;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -289,11 +423,7 @@ public class Cursor {
|
|||
* Resets all cursor location data.
|
||||
*/
|
||||
public void resetLocations(int mouseX, int mouseY) {
|
||||
trail.clear();
|
||||
lastPosition = new Point(mouseX, mouseY);
|
||||
for (int i = 0; i < 50; i++) {
|
||||
trail.add(new Point(lastPosition));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -92,7 +92,7 @@ public class DisplayContainer implements ErrorDumpable, SkinChangedListener {
|
|||
|
||||
private long exitconfirmation;
|
||||
|
||||
public final Cursor cursor;
|
||||
public Cursor cursor;
|
||||
public boolean drawCursor;
|
||||
|
||||
private final List<ResolutionChangedListener> resolutionChangedListeners;
|
||||
|
@ -106,8 +106,6 @@ public class DisplayContainer implements ErrorDumpable, SkinChangedListener {
|
|||
public DisplayContainer()
|
||||
{
|
||||
this.resolutionChangedListeners = new ArrayList<>();
|
||||
this.cursor = new Cursor();
|
||||
drawCursor = true;
|
||||
|
||||
skinservice.addSkinChangedListener(this);
|
||||
|
||||
|
@ -271,6 +269,8 @@ public class DisplayContainer implements ErrorDumpable, SkinChangedListener {
|
|||
glVersion = GL11.glGetString(GL11.GL_VERSION);
|
||||
glVendor = GL11.glGetString(GL11.GL_VENDOR);
|
||||
GLHelper.hideNativeCursor();
|
||||
this.cursor = new Cursor();
|
||||
drawCursor = true;
|
||||
}
|
||||
|
||||
// TODO: move this elsewhere
|
||||
|
|
|
@ -35,6 +35,7 @@ public class Entrypoint {
|
|||
try {
|
||||
InstanceContainer.kickstart();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
JOptionPane.showMessageDialog(null, e.getMessage(), "Cannot start " + PROJECT_NAME, JOptionPane.ERROR_MESSAGE);
|
||||
// TODO replace with errorhandler
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user