Merge pull request #134 from Bigpet/snakeslider
Snaking sliders implementation.
This commit is contained in:
commit
daf3a2aad3
|
@ -907,7 +907,7 @@ public class GameData {
|
||||||
float oldColorAlpha = hitResult.color.a;
|
float oldColorAlpha = hitResult.color.a;
|
||||||
Colors.WHITE_FADE.a = alpha;
|
Colors.WHITE_FADE.a = alpha;
|
||||||
hitResult.color.a = alpha;
|
hitResult.color.a = alpha;
|
||||||
hitResult.curve.draw(hitResult.color);
|
hitResult.curve.draw(hitResult.color,1.0f);
|
||||||
Colors.WHITE_FADE.a = oldWhiteAlpha;
|
Colors.WHITE_FADE.a = oldWhiteAlpha;
|
||||||
hitResult.color.a = oldColorAlpha;
|
hitResult.color.a = oldColorAlpha;
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,6 +417,7 @@ public class Options {
|
||||||
BACKGROUND_DIM ("Background Dim", "DimLevel", "Percentage to dim the background image during gameplay.", 50, 0, 100),
|
BACKGROUND_DIM ("Background Dim", "DimLevel", "Percentage to dim the background image during gameplay.", 50, 0, 100),
|
||||||
FORCE_DEFAULT_PLAYFIELD ("Force Default Playfield", "ForceDefaultPlayfield", "Override the song background with the default playfield background.", false),
|
FORCE_DEFAULT_PLAYFIELD ("Force Default Playfield", "ForceDefaultPlayfield", "Override the song background with the default playfield background.", false),
|
||||||
IGNORE_BEATMAP_SKINS ("Ignore All Beatmap Skins", "IgnoreBeatmapSkins", "Never use skin element overrides provided by beatmaps.", false),
|
IGNORE_BEATMAP_SKINS ("Ignore All Beatmap Skins", "IgnoreBeatmapSkins", "Never use skin element overrides provided by beatmaps.", false),
|
||||||
|
SNAKING_SLIDERS ("Snaking sliders", "SnakingSliders", "Sliders gradually snake out from their starting point.", true),
|
||||||
SHOW_HIT_LIGHTING ("Show Hit Lighting", "HitLighting", "Adds an effect behind hit explosions.", true),
|
SHOW_HIT_LIGHTING ("Show Hit Lighting", "HitLighting", "Adds an effect behind hit explosions.", true),
|
||||||
SHOW_COMBO_BURSTS ("Show Combo Bursts", "ComboBurst", "A character image is displayed at combo milestones.", true),
|
SHOW_COMBO_BURSTS ("Show Combo Bursts", "ComboBurst", "A character image is displayed at combo milestones.", true),
|
||||||
SHOW_PERFECT_HIT ("Show Perfect Hits", "PerfectHit", "Whether to show perfect hit result bursts (300s, slider ticks).", true),
|
SHOW_PERFECT_HIT ("Show Perfect Hits", "PerfectHit", "Whether to show perfect hit result bursts (300s, slider ticks).", true),
|
||||||
|
@ -941,6 +942,12 @@ public class Options {
|
||||||
*/
|
*/
|
||||||
public static boolean isBeatmapSkinIgnored() { return GameOption.IGNORE_BEATMAP_SKINS.getBooleanValue(); }
|
public static boolean isBeatmapSkinIgnored() { return GameOption.IGNORE_BEATMAP_SKINS.getBooleanValue(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not sliders should snake in or just appear fully at once.
|
||||||
|
* @return true if sliders should snake in
|
||||||
|
*/
|
||||||
|
public static boolean isSliderSnaking() { return GameOption.SNAKING_SLIDERS.getBooleanValue(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the fixed circle size override, if any.
|
* Returns the fixed circle size override, if any.
|
||||||
* @return the CS value (0, 10], 0f if disabled
|
* @return the CS value (0, 10], 0f if disabled
|
||||||
|
|
|
@ -30,6 +30,7 @@ import itdelatrisu.opsu.objects.curves.Curve;
|
||||||
import itdelatrisu.opsu.objects.curves.Vec2f;
|
import itdelatrisu.opsu.objects.curves.Vec2f;
|
||||||
import itdelatrisu.opsu.states.Game;
|
import itdelatrisu.opsu.states.Game;
|
||||||
import itdelatrisu.opsu.ui.Colors;
|
import itdelatrisu.opsu.ui.Colors;
|
||||||
|
import itdelatrisu.opsu.ui.animations.AnimationEquation;
|
||||||
|
|
||||||
import org.newdawn.slick.Color;
|
import org.newdawn.slick.Color;
|
||||||
import org.newdawn.slick.GameContainer;
|
import org.newdawn.slick.GameContainer;
|
||||||
|
@ -179,20 +180,27 @@ public class Slider implements GameObject {
|
||||||
float approachScale = 1 + scale * 3;
|
float approachScale = 1 + scale * 3;
|
||||||
float fadeinScale = (timeDiff - approachTime + fadeInTime) / (float) fadeInTime;
|
float fadeinScale = (timeDiff - approachTime + fadeInTime) / (float) fadeInTime;
|
||||||
float alpha = Utils.clamp(1 - fadeinScale, 0, 1);
|
float alpha = Utils.clamp(1 - fadeinScale, 0, 1);
|
||||||
|
float decorationsAlpha = Utils.clamp(-2.0f * fadeinScale, 0, 1);
|
||||||
boolean overlayAboveNumber = Options.getSkin().isHitCircleOverlayAboveNumber();
|
boolean overlayAboveNumber = Options.getSkin().isHitCircleOverlayAboveNumber();
|
||||||
|
|
||||||
float oldAlpha = Colors.WHITE_FADE.a;
|
float oldAlpha = Colors.WHITE_FADE.a;
|
||||||
Colors.WHITE_FADE.a = color.a = alpha;
|
Colors.WHITE_FADE.a = color.a = alpha;
|
||||||
Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage();
|
Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage();
|
||||||
Image hitCircle = GameImage.HITCIRCLE.getImage();
|
Image hitCircle = GameImage.HITCIRCLE.getImage();
|
||||||
Vec2f endPos = curve.pointAt(1);
|
Vec2f endPos = curve.pointAt(1);
|
||||||
|
|
||||||
curve.draw(color);
|
float curveInterval;
|
||||||
|
if(Options.isSliderSnaking()){
|
||||||
|
curveInterval = alpha;
|
||||||
|
} else {
|
||||||
|
curveInterval = 1.0f;
|
||||||
|
}
|
||||||
|
curve.draw(color,curveInterval);
|
||||||
color.a = alpha;
|
color.a = alpha;
|
||||||
|
|
||||||
// end circle
|
// end circle
|
||||||
hitCircle.drawCentered(endPos.x, endPos.y, color);
|
Vec2f endCircPos = curve.pointAt(curveInterval);
|
||||||
hitCircleOverlay.drawCentered(endPos.x, endPos.y, Colors.WHITE_FADE);
|
hitCircle.drawCentered(endCircPos.x, endCircPos.y, color);
|
||||||
|
hitCircleOverlay.drawCentered(endCircPos.x, endCircPos.y, Colors.WHITE_FADE);
|
||||||
|
|
||||||
// start circle
|
// start circle
|
||||||
hitCircle.drawCentered(x, y, color);
|
hitCircle.drawCentered(x, y, color);
|
||||||
|
@ -201,10 +209,13 @@ public class Slider implements GameObject {
|
||||||
|
|
||||||
// ticks
|
// ticks
|
||||||
if (ticksT != null) {
|
if (ticksT != null) {
|
||||||
Image tick = GameImage.SLIDER_TICK.getImage();
|
float tickScale = 0.5f + 0.5f*AnimationEquation.OUT_BACK.calc(decorationsAlpha);
|
||||||
|
Image tick = GameImage.SLIDER_TICK.getImage().getScaledCopy(tickScale);
|
||||||
for (int i = 0; i < ticksT.length; i++) {
|
for (int i = 0; i < ticksT.length; i++) {
|
||||||
Vec2f c = curve.pointAt(ticksT[i]);
|
Vec2f c = curve.pointAt(ticksT[i]);
|
||||||
|
Colors.WHITE_FADE.a = decorationsAlpha;
|
||||||
tick.drawCentered(c.x , c.y , Colors.WHITE_FADE);
|
tick.drawCentered(c.x , c.y , Colors.WHITE_FADE);
|
||||||
|
Colors.WHITE_FADE.a = alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GameMod.HIDDEN.isActive()) {
|
if (GameMod.HIDDEN.isActive()) {
|
||||||
|
@ -224,16 +235,23 @@ public class Slider implements GameObject {
|
||||||
hitCircleOverlay.drawCentered(x, y, Colors.WHITE_FADE);
|
hitCircleOverlay.drawCentered(x, y, Colors.WHITE_FADE);
|
||||||
|
|
||||||
// repeats
|
// repeats
|
||||||
|
if (curveInterval == 1.0f) {
|
||||||
for (int tcurRepeat = currentRepeats; tcurRepeat <= currentRepeats + 1; tcurRepeat++) {
|
for (int tcurRepeat = currentRepeats; tcurRepeat <= currentRepeats + 1; tcurRepeat++) {
|
||||||
if (hitObject.getRepeatCount() - 1 > tcurRepeat) {
|
if (hitObject.getRepeatCount() - 1 > tcurRepeat) {
|
||||||
Image arrow = GameImage.REVERSEARROW.getImage();
|
Image arrow = GameImage.REVERSEARROW.getImage();
|
||||||
if (tcurRepeat != currentRepeats) {
|
if (tcurRepeat != currentRepeats) {
|
||||||
if (sliderTime == 0)
|
if (sliderTime == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
float t = Math.max(getT(trackPosition, true), 0);
|
float t = Math.max(getT(trackPosition, true), 0);
|
||||||
arrow.setAlpha((float) (t - Math.floor(t)));
|
arrow.setAlpha((float) (t - Math.floor(t)));
|
||||||
} else
|
} else {
|
||||||
|
if(Options.isSliderSnaking()){
|
||||||
|
arrow.setAlpha(decorationsAlpha);
|
||||||
|
} else {
|
||||||
arrow.setAlpha(1f);
|
arrow.setAlpha(1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (tcurRepeat % 2 == 0) {
|
if (tcurRepeat % 2 == 0) {
|
||||||
// last circle
|
// last circle
|
||||||
arrow.setRotation(curve.getEndAngle());
|
arrow.setRotation(curve.getEndAngle());
|
||||||
|
@ -245,6 +263,7 @@ public class Slider implements GameObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (timeDiff >= 0) {
|
if (timeDiff >= 0) {
|
||||||
// approach circle
|
// approach circle
|
||||||
|
|
|
@ -20,6 +20,7 @@ package itdelatrisu.opsu.objects.curves;
|
||||||
|
|
||||||
import itdelatrisu.opsu.GameImage;
|
import itdelatrisu.opsu.GameImage;
|
||||||
import itdelatrisu.opsu.Options;
|
import itdelatrisu.opsu.Options;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
import itdelatrisu.opsu.beatmap.HitObject;
|
import itdelatrisu.opsu.beatmap.HitObject;
|
||||||
import itdelatrisu.opsu.render.CurveRenderState;
|
import itdelatrisu.opsu.render.CurveRenderState;
|
||||||
import itdelatrisu.opsu.skins.Skin;
|
import itdelatrisu.opsu.skins.Skin;
|
||||||
|
@ -111,28 +112,31 @@ public abstract class Curve {
|
||||||
public abstract Vec2f pointAt(float t);
|
public abstract Vec2f pointAt(float t);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the full curve to the graphics context.
|
* Draws the curve in the range [0, t] (where the full range is [0, 1]) to the graphics context.
|
||||||
* @param color the color filter
|
* @param color the color filter
|
||||||
|
* @param t set the curve interval to [0, t]
|
||||||
*/
|
*/
|
||||||
public void draw(Color color) {
|
public void draw(Color color, float t) {
|
||||||
if (curve == null)
|
if (curve == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
t = Utils.clamp(t, 0.0f, 1.0f);
|
||||||
// peppysliders
|
// peppysliders
|
||||||
if (Options.getSkin().getSliderStyle() == Skin.STYLE_PEPPYSLIDER || !mmsliderSupported) {
|
if (Options.getSkin().getSliderStyle() == Skin.STYLE_PEPPYSLIDER || !mmsliderSupported) {
|
||||||
|
int drawUpTo = (int)(curve.length*t);
|
||||||
Image hitCircle = GameImage.HITCIRCLE.getImage();
|
Image hitCircle = GameImage.HITCIRCLE.getImage();
|
||||||
Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage();
|
Image hitCircleOverlay = GameImage.HITCIRCLE_OVERLAY.getImage();
|
||||||
for (int i = 0; i < curve.length; i++)
|
for (int i = 0; i < drawUpTo; i++)
|
||||||
hitCircleOverlay.drawCentered(curve[i].x, curve[i].y, Colors.WHITE_FADE);
|
hitCircleOverlay.drawCentered(curve[i].x, curve[i].y, Colors.WHITE_FADE);
|
||||||
for (int i = 0; i < curve.length; i++)
|
for (int i = 0; i < drawUpTo; i++)
|
||||||
hitCircle.drawCentered(curve[i].x, curve[i].y, color);
|
hitCircle.drawCentered(curve[i].x, curve[i].y, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mmsliders
|
// mmsliders
|
||||||
else {
|
else {
|
||||||
if (renderState == null)
|
if (renderState == null)
|
||||||
renderState = new CurveRenderState(hitObject);
|
renderState = new CurveRenderState(hitObject,curve);
|
||||||
renderState.draw(color, borderColor, curve);
|
renderState.draw(color, borderColor, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
package itdelatrisu.opsu.render;
|
package itdelatrisu.opsu.render;
|
||||||
|
|
||||||
import itdelatrisu.opsu.GameImage;
|
import itdelatrisu.opsu.GameImage;
|
||||||
|
import itdelatrisu.opsu.Utils;
|
||||||
import itdelatrisu.opsu.beatmap.HitObject;
|
import itdelatrisu.opsu.beatmap.HitObject;
|
||||||
import itdelatrisu.opsu.objects.curves.Vec2f;
|
import itdelatrisu.opsu.objects.curves.Vec2f;
|
||||||
import itdelatrisu.opsu.ui.Colors;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
|
@ -59,6 +59,12 @@ public class CurveRenderState {
|
||||||
/** The HitObject associated with the curve to be drawn. */
|
/** The HitObject associated with the curve to be drawn. */
|
||||||
protected HitObject hitObject;
|
protected HitObject hitObject;
|
||||||
|
|
||||||
|
/** the points along the curve to be drawn */
|
||||||
|
protected Vec2f[] curve;
|
||||||
|
|
||||||
|
/** The point to which the curve has last been rendered into the texture (as an index into {@code curve}) */
|
||||||
|
private int lastPointDrawn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the width and height of the container that Curves get drawn into.
|
* Set the width and height of the container that Curves get drawn into.
|
||||||
* Should be called before any curves are drawn.
|
* Should be called before any curves are drawn.
|
||||||
|
@ -74,11 +80,12 @@ public class CurveRenderState {
|
||||||
scale = (int) (circleDiameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480)
|
scale = (int) (circleDiameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480)
|
||||||
//scale = scale * 118 / 128; //for curves exactly as big as the sliderball
|
//scale = scale * 118 / 128; //for curves exactly as big as the sliderball
|
||||||
FrameBufferCache.init(width, height);
|
FrameBufferCache.init(width, height);
|
||||||
|
NewCurveStyleState.initUnitCone();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undo the static state. Static state setup caused by calls to
|
* Undo the static state. Static state setup caused by calls to
|
||||||
* {@link #draw(org.newdawn.slick.Color, org.newdawn.slick.Color, itdelatrisu.opsu.objects.curves.Vec2f[])}
|
* {@link #draw(org.newdawn.slick.Color, org.newdawn.slick.Color, float)}
|
||||||
* are undone.
|
* are undone.
|
||||||
*/
|
*/
|
||||||
public static void shutdown() {
|
public static void shutdown() {
|
||||||
|
@ -89,10 +96,12 @@ public class CurveRenderState {
|
||||||
/**
|
/**
|
||||||
* Creates an object to hold the render state that's necessary to draw a curve.
|
* Creates an object to hold the render state that's necessary to draw a curve.
|
||||||
* @param hitObject the HitObject that represents this curve, just used as a unique ID
|
* @param hitObject the HitObject that represents this curve, just used as a unique ID
|
||||||
|
* @param curve the points along the curve to be drawn
|
||||||
*/
|
*/
|
||||||
public CurveRenderState(HitObject hitObject) {
|
public CurveRenderState(HitObject hitObject, Vec2f[] curve) {
|
||||||
fbo = null;
|
fbo = null;
|
||||||
this.hitObject = hitObject;
|
this.hitObject = hitObject;
|
||||||
|
this.curve = curve;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,9 +110,10 @@ public class CurveRenderState {
|
||||||
* runs it just draws the cached copy to the screen.
|
* runs it just draws the cached copy to the screen.
|
||||||
* @param color tint of the curve
|
* @param color tint of the curve
|
||||||
* @param borderColor the curve border color
|
* @param borderColor the curve border color
|
||||||
* @param curve the points along the curve to be drawn
|
* @param t the point up to which the curve should be drawn (in the interval [0, 1])
|
||||||
*/
|
*/
|
||||||
public void draw(Color color, Color borderColor, Vec2f[] curve) {
|
public void draw(Color color, Color borderColor, float t) {
|
||||||
|
t = Utils.clamp(t, 0.0f, 1.0f);
|
||||||
float alpha = color.a;
|
float alpha = color.a;
|
||||||
|
|
||||||
// if this curve hasn't been drawn, draw it and cache the result
|
// if this curve hasn't been drawn, draw it and cache the result
|
||||||
|
@ -113,26 +123,40 @@ public class CurveRenderState {
|
||||||
if (mapping == null)
|
if (mapping == null)
|
||||||
mapping = cache.insert(hitObject);
|
mapping = cache.insert(hitObject);
|
||||||
fbo = mapping;
|
fbo = mapping;
|
||||||
|
createVertexBuffer(fbo.getVbo());
|
||||||
|
//write impossible value to make sure the fbo is cleared
|
||||||
|
lastPointDrawn = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int drawUpTo = (int) (t * curve.length);
|
||||||
|
|
||||||
|
if (lastPointDrawn != drawUpTo) {
|
||||||
|
|
||||||
|
if (drawUpTo == lastPointDrawn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int oldFb = GL11.glGetInteger(EXTFramebufferObject.GL_FRAMEBUFFER_BINDING_EXT);
|
int oldFb = GL11.glGetInteger(EXTFramebufferObject.GL_FRAMEBUFFER_BINDING_EXT);
|
||||||
int oldTex = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
int oldTex = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||||
|
|
||||||
//glGetInteger requires a buffer of size 16, even though just 4
|
//glGetInteger requires a buffer of size 16, even though just 4
|
||||||
//values are returned in this specific case
|
//values are returned in this specific case
|
||||||
IntBuffer oldViewport = BufferUtils.createIntBuffer(16);
|
IntBuffer oldViewport = BufferUtils.createIntBuffer(16);
|
||||||
GL11.glGetInteger(GL11.GL_VIEWPORT, oldViewport);
|
GL11.glGetInteger(GL11.GL_VIEWPORT, oldViewport);
|
||||||
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbo.getID());
|
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fbo.getID());
|
||||||
GL11.glViewport(0, 0, fbo.width, fbo.height);
|
GL11.glViewport(0, 0, fbo.width, fbo.height);
|
||||||
|
if (lastPointDrawn <= 0 || lastPointDrawn > drawUpTo) {
|
||||||
|
lastPointDrawn = 0;
|
||||||
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||||
Colors.WHITE_FADE.a = 1.0f;
|
}
|
||||||
this.draw_curve(color, borderColor, curve);
|
|
||||||
|
this.renderCurve(color, borderColor, lastPointDrawn, drawUpTo);
|
||||||
|
lastPointDrawn = drawUpTo;
|
||||||
color.a = 1f;
|
color.a = 1f;
|
||||||
|
|
||||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, oldTex);
|
GL11.glBindTexture(GL11.GL_TEXTURE_2D, oldTex);
|
||||||
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, oldFb);
|
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, oldFb);
|
||||||
GL11.glViewport(oldViewport.get(0), oldViewport.get(1), oldViewport.get(2), oldViewport.get(3));
|
GL11.glViewport(oldViewport.get(0), oldViewport.get(1), oldViewport.get(2), oldViewport.get(3));
|
||||||
Colors.WHITE_FADE.a = alpha;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw a fullscreen quad with the texture that contains the curve
|
// draw a fullscreen quad with the texture that contains the curve
|
||||||
|
@ -180,7 +204,7 @@ public class CurveRenderState {
|
||||||
* Backup the current state of the relevant OpenGL state and change it to
|
* Backup the current state of the relevant OpenGL state and change it to
|
||||||
* what's needed to draw the curve.
|
* what's needed to draw the curve.
|
||||||
*/
|
*/
|
||||||
private RenderState startRender() {
|
private RenderState saveRenderState() {
|
||||||
RenderState state = new RenderState();
|
RenderState state = new RenderState();
|
||||||
state.smoothedPoly = GL11.glGetBoolean(GL11.GL_POLYGON_SMOOTH);
|
state.smoothedPoly = GL11.glGetBoolean(GL11.GL_POLYGON_SMOOTH);
|
||||||
state.blendEnabled = GL11.glGetBoolean(GL11.GL_BLEND);
|
state.blendEnabled = GL11.glGetBoolean(GL11.GL_BLEND);
|
||||||
|
@ -219,7 +243,7 @@ public class CurveRenderState {
|
||||||
* Restore the old OpenGL state that's backed up in {@code state}.
|
* Restore the old OpenGL state that's backed up in {@code state}.
|
||||||
* @param state the old state to restore
|
* @param state the old state to restore
|
||||||
*/
|
*/
|
||||||
private void endRender(RenderState state) {
|
private void restoreRenderState(RenderState state) {
|
||||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||||
GL11.glPopMatrix();
|
GL11.glPopMatrix();
|
||||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||||
|
@ -241,24 +265,18 @@ public class CurveRenderState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do the actual drawing of the curve into the currently bound framebuffer.
|
* Write the vertices and (with position and texture coordinates) for the full
|
||||||
* @param color the color of the curve
|
* curve into the OpenGL buffer with the ID specified by {@code bufferID}
|
||||||
* @param borderColor the curve border color
|
* @param bufferID the buffer ID for the OpenGL buffer the vertices should be written into
|
||||||
* @param curve the points along the curve
|
|
||||||
*/
|
*/
|
||||||
private void draw_curve(Color color, Color borderColor, Vec2f[] curve) {
|
private void createVertexBuffer(int bufferID)
|
||||||
staticState.initGradient();
|
{
|
||||||
RenderState state = startRender();
|
int arrayBufferBinding = GL11.glGetInteger(GL15.GL_ARRAY_BUFFER_BINDING);
|
||||||
int vtx_buf;
|
|
||||||
// the size is: floatsize * (position + texture coordinates) * (number of cones) * (vertices in a cone)
|
|
||||||
FloatBuffer buff = BufferUtils.createByteBuffer(4 * (4 + 2) * (2 * curve.length - 1) * (NewCurveStyleState.DIVIDES + 2)).asFloatBuffer();
|
FloatBuffer buff = BufferUtils.createByteBuffer(4 * (4 + 2) * (2 * curve.length - 1) * (NewCurveStyleState.DIVIDES + 2)).asFloatBuffer();
|
||||||
staticState.initShaderProgram();
|
|
||||||
vtx_buf = GL15.glGenBuffers();
|
|
||||||
for (int i = 0; i < curve.length; ++i) {
|
for (int i = 0; i < curve.length; ++i) {
|
||||||
float x = curve[i].x;
|
float x = curve[i].x;
|
||||||
float y = curve[i].y;
|
float y = curve[i].y;
|
||||||
//if (i == 0 || i == curve.length - 1){
|
fillCone(buff, x, y);
|
||||||
fillCone(buff, x, y, NewCurveStyleState.DIVIDES);
|
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
float last_x = curve[i - 1].x;
|
float last_x = curve[i - 1].x;
|
||||||
float last_y = curve[i - 1].y;
|
float last_y = curve[i - 1].y;
|
||||||
|
@ -266,12 +284,25 @@ public class CurveRenderState {
|
||||||
double diff_y = y - last_y;
|
double diff_y = y - last_y;
|
||||||
x = (float) (x - diff_x / 2);
|
x = (float) (x - diff_x / 2);
|
||||||
y = (float) (y - diff_y / 2);
|
y = (float) (y - diff_y / 2);
|
||||||
fillCone(buff, x, y, NewCurveStyleState.DIVIDES);
|
fillCone(buff, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buff.flip();
|
buff.flip();
|
||||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vtx_buf);
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferID);
|
||||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buff, GL15.GL_STATIC_DRAW);
|
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buff, GL15.GL_STATIC_DRAW);
|
||||||
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, arrayBufferBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the actual drawing of the curve into the currently bound framebuffer.
|
||||||
|
* @param color the color of the curve
|
||||||
|
* @param borderColor the curve border color
|
||||||
|
*/
|
||||||
|
private void renderCurve(Color color, Color borderColor, int from, int to) {
|
||||||
|
staticState.initGradient();
|
||||||
|
RenderState state = saveRenderState();
|
||||||
|
staticState.initShaderProgram();
|
||||||
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, fbo.getVbo());
|
||||||
GL20.glUseProgram(staticState.program);
|
GL20.glUseProgram(staticState.program);
|
||||||
GL20.glEnableVertexAttribArray(staticState.attribLoc);
|
GL20.glEnableVertexAttribArray(staticState.attribLoc);
|
||||||
GL20.glEnableVertexAttribArray(staticState.texCoordLoc);
|
GL20.glEnableVertexAttribArray(staticState.texCoordLoc);
|
||||||
|
@ -282,63 +313,37 @@ public class CurveRenderState {
|
||||||
//2*4 is for skipping the first 2 floats (u,v)
|
//2*4 is for skipping the first 2 floats (u,v)
|
||||||
GL20.glVertexAttribPointer(staticState.attribLoc, 4, GL11.GL_FLOAT, false, 6 * 4, 2 * 4);
|
GL20.glVertexAttribPointer(staticState.attribLoc, 4, GL11.GL_FLOAT, false, 6 * 4, 2 * 4);
|
||||||
GL20.glVertexAttribPointer(staticState.texCoordLoc, 2, GL11.GL_FLOAT, false, 6 * 4, 0);
|
GL20.glVertexAttribPointer(staticState.texCoordLoc, 2, GL11.GL_FLOAT, false, 6 * 4, 0);
|
||||||
for (int i = 0; i < curve.length * 2 - 1; ++i)
|
for (int i = from*2; i < to * 2 - 1; ++i)
|
||||||
GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, i * (NewCurveStyleState.DIVIDES + 2), NewCurveStyleState.DIVIDES + 2);
|
GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, i * (NewCurveStyleState.DIVIDES + 2), NewCurveStyleState.DIVIDES + 2);
|
||||||
|
GL11.glFlush();
|
||||||
GL20.glDisableVertexAttribArray(staticState.texCoordLoc);
|
GL20.glDisableVertexAttribArray(staticState.texCoordLoc);
|
||||||
GL20.glDisableVertexAttribArray(staticState.attribLoc);
|
GL20.glDisableVertexAttribArray(staticState.attribLoc);
|
||||||
GL15.glDeleteBuffers(vtx_buf);
|
restoreRenderState(state);
|
||||||
endRender(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill {@code buff} with the texture coordinates and positions for a cone
|
* Fill {@code buff} with the texture coordinates and positions for a cone
|
||||||
* with {@code DIVIDES} ground corners that has its center at the coordinates
|
* that has its center at the coordinates {@code (x1,y1)}.
|
||||||
* {@code (x1,y1)}.
|
|
||||||
* @param buff the buffer to be filled
|
* @param buff the buffer to be filled
|
||||||
* @param x1 x-coordinate of the cone
|
* @param x1 x-coordinate of the cone
|
||||||
* @param y1 y-coordinate of the cone
|
* @param y1 y-coordinate of the cone
|
||||||
* @param DIVIDES the base of the cone is a regular polygon with this many sides
|
|
||||||
*/
|
*/
|
||||||
protected void fillCone(FloatBuffer buff, float x1, float y1, final int DIVIDES) {
|
protected void fillCone(FloatBuffer buff, float x1, float y1) {
|
||||||
float divx = containerWidth / 2.0f;
|
float divx = containerWidth / 2.0f;
|
||||||
float divy = containerHeight / 2.0f;
|
float divy = containerHeight / 2.0f;
|
||||||
float offx = -1.0f;
|
float offx = -1.0f;
|
||||||
float offy = 1.0f;
|
float offy = 1.0f;
|
||||||
float x, y;
|
|
||||||
float radius = scale / 2;
|
float radius = scale / 2;
|
||||||
buff.put(1.0f);
|
|
||||||
buff.put(0.5f);
|
for(int i = 0; i<NewCurveStyleState.unitCone.length/6; ++i)
|
||||||
//GL11.glTexCoord2d(1.0, 0.5);
|
{
|
||||||
x = offx + x1 / divx;
|
buff.put(NewCurveStyleState.unitCone[i*6+0]);
|
||||||
y = offy - y1 / divy;
|
buff.put(NewCurveStyleState.unitCone[i*6+1]);
|
||||||
buff.put(x);
|
buff.put(offx + (x1 + radius * NewCurveStyleState.unitCone[i*6+2])/divx);
|
||||||
buff.put(y);
|
buff.put(offy - (y1 + radius * NewCurveStyleState.unitCone[i*6+3])/divy);
|
||||||
buff.put(0f);
|
buff.put(NewCurveStyleState.unitCone[i*6+4]);
|
||||||
buff.put(1f);
|
buff.put(NewCurveStyleState.unitCone[i*6+5]);
|
||||||
//GL11.glVertex4f(x, y, 0.0f, 1.0f);
|
|
||||||
for (int j = 0; j < DIVIDES; ++j) {
|
|
||||||
double phase = j * (float) Math.PI * 2 / DIVIDES;
|
|
||||||
buff.put(0.0f);
|
|
||||||
buff.put(0.5f);
|
|
||||||
//GL11.glTexCoord2d(0.0, 0.5);
|
|
||||||
x = (x1 + radius * (float) Math.sin(phase)) / divx;
|
|
||||||
y = (y1 + radius * (float) Math.cos(phase)) / divy;
|
|
||||||
buff.put((offx + x));
|
|
||||||
buff.put((offy - y));
|
|
||||||
buff.put(1f);
|
|
||||||
buff.put(1f);
|
|
||||||
//GL11.glVertex4f(x + 90 * (float) Math.sin(phase), y + 90 * (float) Math.cos(phase), 1.0f, 1.0f);
|
|
||||||
}
|
}
|
||||||
buff.put(0.0f);
|
|
||||||
buff.put(0.5f);
|
|
||||||
//GL11.glTexCoord2d(0.0, 0.5);
|
|
||||||
x = (x1 + radius * (float) Math.sin(0.0)) / divx;
|
|
||||||
y = (y1 + radius * (float) Math.cos(0.0)) / divy;
|
|
||||||
buff.put((offx + x));
|
|
||||||
buff.put((offy - y));
|
|
||||||
buff.put(1f);
|
|
||||||
buff.put(1f);
|
|
||||||
//GL11.glVertex4f(x + 90 * (float) Math.sin(0.0), y + 90 * (float) Math.cos(0.0), 1.0f, 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -354,6 +359,13 @@ public class CurveRenderState {
|
||||||
*/
|
*/
|
||||||
protected static final int DIVIDES = 30;
|
protected static final int DIVIDES = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array to hold the dummy vertex data (texture coordinates and position)
|
||||||
|
* of a cone with DIVIDES vertices at its base, that is centered around
|
||||||
|
* (0,0) and has a radius of 1 (so that it can be translated and scaled easily).
|
||||||
|
*/
|
||||||
|
protected static float[] unitCone = new float[(DIVIDES+2)*6];
|
||||||
|
|
||||||
/** OpenGL shader program ID used to draw and recolor the curve. */
|
/** OpenGL shader program ID used to draw and recolor the curve. */
|
||||||
protected int program = 0;
|
protected int program = 0;
|
||||||
|
|
||||||
|
@ -398,6 +410,47 @@ public class CurveRenderState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the data into {@code unitCone} if it hasn't already been initialized.
|
||||||
|
*/
|
||||||
|
public static void initUnitCone() {
|
||||||
|
int index = 0;
|
||||||
|
//check if initialization has already happened
|
||||||
|
if (unitCone[0] == 0.0f) {
|
||||||
|
|
||||||
|
//tip of the cone
|
||||||
|
//vec2 texture coordinates
|
||||||
|
unitCone[index++] = 1.0f;
|
||||||
|
unitCone[index++] = 0.5f;
|
||||||
|
|
||||||
|
//vec4 position
|
||||||
|
unitCone[index++] = 0.0f;
|
||||||
|
unitCone[index++] = 0.0f;
|
||||||
|
unitCone[index++] = 0.0f;
|
||||||
|
unitCone[index++] = 1.0f;
|
||||||
|
for (int j = 0; j < NewCurveStyleState.DIVIDES; ++j) {
|
||||||
|
double phase = j * (float) Math.PI * 2 / NewCurveStyleState.DIVIDES;
|
||||||
|
//vec2 texture coordinates
|
||||||
|
unitCone[index++] = 0.0f;
|
||||||
|
unitCone[index++] = 0.5f;
|
||||||
|
//vec4 positon
|
||||||
|
unitCone[index++] = (float) Math.sin(phase);
|
||||||
|
unitCone[index++] = (float) Math.cos(phase);
|
||||||
|
unitCone[index++] = 1.0f;
|
||||||
|
unitCone[index++] = 1.0f;
|
||||||
|
}
|
||||||
|
//vec2 texture coordinates
|
||||||
|
unitCone[index++] = 0.0f;
|
||||||
|
unitCone[index++] = 0.5f;
|
||||||
|
//vec4 positon
|
||||||
|
unitCone[index++] = (float) Math.sin(0.0f);
|
||||||
|
unitCone[index++] = (float) Math.cos(0.0f);
|
||||||
|
unitCone[index++] = 1.0f;
|
||||||
|
unitCone[index++] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles and links the shader program for the new style curve objects
|
* Compiles and links the shader program for the new style curve objects
|
||||||
* if it hasn't already been compiled and linked.
|
* if it hasn't already been compiled and linked.
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.lwjgl.opengl.EXTFramebufferObject;
|
import org.lwjgl.opengl.EXTFramebufferObject;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a rendertarget. For now this maps to an OpenGL FBO via LWJGL.
|
* Represents a rendertarget. For now this maps to an OpenGL FBO via LWJGL.
|
||||||
|
@ -31,6 +32,9 @@ public class Rendertarget {
|
||||||
/** The dimensions. */
|
/** The dimensions. */
|
||||||
public final int width, height;
|
public final int width, height;
|
||||||
|
|
||||||
|
/** ID of the vertex buffer associated with this rendertarget*/
|
||||||
|
private final int vboID;
|
||||||
|
|
||||||
/** The FBO ID. */
|
/** The FBO ID. */
|
||||||
private final int fboID;
|
private final int fboID;
|
||||||
|
|
||||||
|
@ -49,6 +53,7 @@ public class Rendertarget {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
fboID = EXTFramebufferObject.glGenFramebuffersEXT();
|
fboID = EXTFramebufferObject.glGenFramebuffersEXT();
|
||||||
|
vboID = GL15.glGenBuffers();
|
||||||
textureID = GL11.glGenTextures();
|
textureID = GL11.glGenTextures();
|
||||||
depthBufferID = EXTFramebufferObject.glGenRenderbuffersEXT();
|
depthBufferID = EXTFramebufferObject.glGenRenderbuffersEXT();
|
||||||
}
|
}
|
||||||
|
@ -60,19 +65,27 @@ public class Rendertarget {
|
||||||
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fboID);
|
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fboID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the FBO ID.
|
* Get the ID of the VBO associated with this Rendertarget.
|
||||||
|
* @return OpenGL buffer ID for the VBO
|
||||||
|
*/
|
||||||
|
public int getVbo() {
|
||||||
|
return vboID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the FBO ID.
|
||||||
|
* @return the OpenGL FBO ID
|
||||||
*/
|
*/
|
||||||
// NOTE: use judiciously, try to avoid if possible and consider adding a
|
|
||||||
// method to this class if you find yourself calling this repeatedly.
|
|
||||||
public int getID() {
|
public int getID() {
|
||||||
return fboID;
|
return fboID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the texture ID.
|
* Get the texture ID of the texture this rendertarget renders into.
|
||||||
|
* @return the OpenGL texture ID
|
||||||
*/
|
*/
|
||||||
// NOTE: try not to use, could be moved into separate class.
|
|
||||||
public int getTextureID() {
|
public int getTextureID() {
|
||||||
return textureID;
|
return textureID;
|
||||||
}
|
}
|
||||||
|
@ -89,6 +102,7 @@ public class Rendertarget {
|
||||||
* and a renderbuffer that it renders the depth to.
|
* and a renderbuffer that it renders the depth to.
|
||||||
* @param width the width
|
* @param width the width
|
||||||
* @param height the height
|
* @param height the height
|
||||||
|
* @return the newly created Rendertarget instance
|
||||||
*/
|
*/
|
||||||
public static Rendertarget createRTTFramebuffer(int width, int height) {
|
public static Rendertarget createRTTFramebuffer(int width, int height) {
|
||||||
int old_framebuffer = GL11.glGetInteger(EXTFramebufferObject.GL_FRAMEBUFFER_BINDING_EXT);
|
int old_framebuffer = GL11.glGetInteger(EXTFramebufferObject.GL_FRAMEBUFFER_BINDING_EXT);
|
||||||
|
@ -122,5 +136,6 @@ public class Rendertarget {
|
||||||
EXTFramebufferObject.glDeleteFramebuffersEXT(fboID);
|
EXTFramebufferObject.glDeleteFramebuffersEXT(fboID);
|
||||||
EXTFramebufferObject.glDeleteRenderbuffersEXT(depthBufferID);
|
EXTFramebufferObject.glDeleteRenderbuffersEXT(depthBufferID);
|
||||||
GL11.glDeleteTextures(textureID);
|
GL11.glDeleteTextures(textureID);
|
||||||
|
GL15.glDeleteBuffers(vboID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ public class OptionsMenu extends BasicGameState {
|
||||||
GameOption.BACKGROUND_DIM,
|
GameOption.BACKGROUND_DIM,
|
||||||
GameOption.FORCE_DEFAULT_PLAYFIELD,
|
GameOption.FORCE_DEFAULT_PLAYFIELD,
|
||||||
GameOption.IGNORE_BEATMAP_SKINS,
|
GameOption.IGNORE_BEATMAP_SKINS,
|
||||||
|
GameOption.SNAKING_SLIDERS,
|
||||||
GameOption.SHOW_HIT_LIGHTING,
|
GameOption.SHOW_HIT_LIGHTING,
|
||||||
GameOption.SHOW_COMBO_BURSTS,
|
GameOption.SHOW_COMBO_BURSTS,
|
||||||
GameOption.SHOW_PERFECT_HIT,
|
GameOption.SHOW_PERFECT_HIT,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user