Kinectic Scrolling

for SongNodes, Scores, Download Results, Download Info
This commit is contained in:
fd
2015-07-01 19:45:13 -04:00
parent 495a7e7f8b
commit 0562c66531
6 changed files with 482 additions and 207 deletions

View File

@@ -0,0 +1,155 @@
package itdelatrisu.opsu.ui;
/**
* Drag to scroll based on:
* http://ariya.ofilabs.com/2013/11/javascript-kinetic-scrolling-part-2.html
*
* @author fluddokt (https://github.com/fluddokt)
*/
public class KinecticScrolling {
/** The moving averaging constant */
final static private float AVG_CONST = 0.2f;
final static private float ONE_MINUS_AVG_CONST = 1 - AVG_CONST;
/** The constant used to determine how fast the target position will be reach. */
final static private int TIME_CONST = 200;
/** The constant used to determine how much of the velocity will be used to launch to the target. */
final static private float AMPLITUDE_CONST = 0.25f;
/** The current position. */
float position;
/** The offset to scroll to the target position. */
float amplitude;
/** The current target to scroll to. */
float target;
/** The total amount of time since the mouse button was released. */
float totalDelta;
/** The maximum and minimum value the position can reach. */
float max = Float.MAX_VALUE;
float min = -Float.MAX_VALUE;
/** Whether the mouse is currently pressed or not */
boolean pressed = false;
/** The change in position since the last update */
float deltaPosition;
/** The moving average of the velocity. */
float avgVelocity;
/**
* Returns the current Position.
* @return the position.
*/
public float getPosition() {
return position;
}
/**
* Updates the scrolling.
* @param delta the elapsed time since the last update
*/
public void update(float delta) {
if (!pressed) {
totalDelta += delta;
position = target + (float) (-amplitude * Math.exp(-totalDelta / TIME_CONST));
} else {
avgVelocity = (ONE_MINUS_AVG_CONST * avgVelocity + AVG_CONST * (deltaPosition * 1000f / delta));
position += deltaPosition;
target = position ;
deltaPosition = 0;
}
if (position > max) {
amplitude = 0;
target = position = max;
}
if (position < min) {
amplitude = 0;
target = position = min;
}
}
/**
* Scrolls to the position.
* @param newPosition the position to scroll to.
*/
public void scrollToPosition(float newPosition) {
amplitude = newPosition - position;
target = newPosition;
totalDelta = 0;
}
/**
* Scrolls to an offset from target.
* @param offset the offset from the target to scroll to.
*/
public void scrollOffset(float offset) {
scrollToPosition(target + offset);
}
/**
* Sets the position.
* @param newPosition the position to be set
*/
public void setPosition(float newPosition) {
pressed();
release();
target = newPosition;
position = target;
}
/**
* Set the position relative to an offset.
* @param offset the offset from the position.
*/
public void addOffset(float offset) {
setPosition(position + offset);
}
/**
* Call this when the mouse button has been pressed.
*/
public void pressed() {
if (pressed)
return;
pressed = true;
avgVelocity = 0;
}
/**
* Call this when the mouse button has been released.
*/
public void release() {
if (!pressed)
return;
pressed = false;
amplitude = AMPLITUDE_CONST * avgVelocity;
target = Math.round(target + amplitude);
totalDelta = 0;
}
/**
* Call this when the mouse has been dragged.
* @param distance the amount that the mouse has been dragged
*/
public void dragged(float distance) {
deltaPosition += distance;
}
/**
* Set the minimum and maximum bound.
* @param min the minimum bound
* @param max the maximum bound
*/
public void setMinMax(float min, float max) {
this.min = min;
this.max = max;
}
}

View File

@@ -318,28 +318,25 @@ public class UI {
/**
* Draws a scroll bar.
* @param g the graphics context
* @param unitIndex the unit index
* @param totalUnits the total number of units
* @param maxShown the maximum number of units shown at one time
* @param unitBaseX the base x coordinate of the units
* @param unitBaseY the base y coordinate of the units
* @param position the position in the virtual area
* @param totalLength the total length of the virtual area
* @param lengthShown the length of the virtual area shown
* @param unitBaseX the base x coordinate
* @param unitBaseY the base y coordinate
* @param unitWidth the width of a unit
* @param unitHeight the height of a unit
* @param unitOffsetY the y offset between units
* @param scrollAreaHeight the height of the scroll area
* @param bgColor the scroll bar area background color (null if none)
* @param scrollbarColor the scroll bar color
* @param right whether or not to place the scroll bar on the right side of the unit
*/
public static void drawScrollbar(
Graphics g, int unitIndex, int totalUnits, int maxShown,
float unitBaseX, float unitBaseY, float unitWidth, float unitHeight, float unitOffsetY,
Graphics g, float position, float totalLength, float lengthShown,
float unitBaseX, float unitBaseY, float unitWidth, float scrollAreaHeight,
Color bgColor, Color scrollbarColor, boolean right
) {
float scrollbarWidth = container.getWidth() * 0.00347f;
float heightRatio = (float) (2.6701f * Math.exp(-0.81 * Math.log(totalUnits)));
float scrollbarHeight = container.getHeight() * heightRatio;
float scrollAreaHeight = unitHeight + unitOffsetY * (maxShown - 1);
float offsetY = (scrollAreaHeight - scrollbarHeight) * ((float) unitIndex / (totalUnits - maxShown));
float scrollbarHeight = scrollAreaHeight * lengthShown / totalLength;
float offsetY = (scrollAreaHeight - scrollbarHeight) * (position / (totalLength - lengthShown));
float scrollbarX = unitBaseX + unitWidth - ((right) ? scrollbarWidth : 0);
if (bgColor != null) {
g.setColor(bgColor);