import com.badlogic.gdx.graphics.g2d.NinePatch;\r
import com.badlogic.gdx.graphics.g2d.SpriteBatch;\r
import com.badlogic.gdx.graphics.g2d.TextureRegion;\r
+import com.badlogic.gdx.math.Interpolation;\r
import com.badlogic.gdx.math.MathUtils;\r
import com.badlogic.gdx.scenes.scene2d.InputEvent;\r
import com.badlogic.gdx.scenes.scene2d.InputListener;\r
public class Slider extends Widget {\r
private SliderStyle style;\r
private float min, max, stepSize;\r
- private float value;\r
+ private float value, animateFromValue;\r
private float sliderPos;\r
- private boolean vertical;\r
+ private final boolean vertical;\r
int draggingPointer = -1;\r
+ private float animateDuration, animateTime;\r
+ private Interpolation animateInterpolation = Interpolation.linear;\r
\r
public Slider (float min, float max, float stepSize, boolean vertical, Skin skin) {\r
this(min, max, stepSize, vertical, skin.get("default-" + (vertical ? "vertical" : "horizontal"), SliderStyle.class));\r
return style;\r
}\r
\r
+ public void act (float delta) {\r
+ super.act(delta);\r
+ animateTime -= delta;\r
+ }\r
+\r
@Override\r
public void draw (SpriteBatch batch, float parentAlpha) {\r
final Drawable knob = style.knob;\r
float y = getY();\r
float width = getWidth();\r
float height = getHeight();\r
+ float knobHeight = knob == null ? 0 : knob.getMinHeight();\r
+ float knobWidth = knob == null ? 0 : knob.getMinWidth();\r
+ float value = getVisualValue();\r
\r
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);\r
\r
bg.draw(batch, x + (int)((width - bg.getMinWidth()) * 0.5f), y, bg.getMinWidth(), height);\r
\r
float sliderPosHeight = height - (bg.getTopHeight() + bg.getBottomHeight());\r
- //this check is used for avoiding division by zero\r
- if(min != max) {\r
- sliderPos = (value - min) / (max - min) * (sliderPosHeight - knob.getMinHeight());\r
+ if(min!=max){\r
+ sliderPos = (value - min) / (max - min) * (sliderPosHeight - knobHeight);\r
sliderPos = Math.max(0, sliderPos);\r
- sliderPos = Math.min(sliderPosHeight - knob.getMinHeight(), sliderPos) + bg.getBottomHeight();\r
+ sliderPos = Math.min(sliderPosHeight - knobHeight, sliderPos) + bg.getBottomHeight();\r
}\r
- float knobHeightHalf = knob.getMinHeight() * 0.5f;\r
+ float knobHeightHalf = knobHeight * 0.5f;\r
if (knobBefore != null) {\r
knobBefore.draw(batch, x + (int)((width - knobBefore.getMinWidth()) * 0.5f), y, knobBefore.getMinWidth(),\r
(int)(sliderPos + knobHeightHalf));\r
knobAfter.draw(batch, x + (int)((width - knobAfter.getMinWidth()) * 0.5f), y + (int)(sliderPos + knobHeightHalf),\r
knobAfter.getMinWidth(), height - (int)(sliderPos + knobHeightHalf));\r
}\r
- knob.draw(batch, x + (int)((width - knob.getMinWidth()) * 0.5f), (int)(y + sliderPos), knob.getMinWidth(),\r
- knob.getMinHeight());\r
+ if (knob != null) knob.draw(batch, x + (int)((width - knobWidth) * 0.5f), (int)(y + sliderPos), knobWidth, knobHeight);\r
} else {\r
bg.draw(batch, x, y + (int)((height - bg.getMinHeight()) * 0.5f), width, bg.getMinHeight());\r
\r
float sliderPosWidth = width - (bg.getLeftWidth() + bg.getRightWidth());\r
- //this check is used for avoiding division by zero\r
- if(min != max) {\r
- sliderPos = (value - min) / (max - min) * (sliderPosWidth - knob.getMinWidth());\r
+ if(min!=max){\r
+ sliderPos = (value - min) / (max - min) * (sliderPosWidth - knobWidth);\r
sliderPos = Math.max(0, sliderPos);\r
- sliderPos = Math.min(sliderPosWidth - knob.getMinWidth(), sliderPos) + bg.getLeftWidth();\r
- } \r
- float knobHeightHalf = knob.getMinHeight() * 0.5f;\r
+ sliderPos = Math.min(sliderPosWidth - knobWidth, sliderPos) + bg.getLeftWidth();\r
+ }\r
+ float knobHeightHalf = knobHeight * 0.5f;\r
if (knobBefore != null) {\r
knobBefore.draw(batch, x, y + (int)((height - knobBefore.getMinHeight()) * 0.5f), (int)(sliderPos + knobHeightHalf),\r
knobBefore.getMinHeight());\r
knobAfter.draw(batch, x + (int)(sliderPos + knobHeightHalf), y + (int)((height - knobAfter.getMinHeight()) * 0.5f),\r
width - (int)(sliderPos + knobHeightHalf), knobAfter.getMinHeight());\r
}\r
- knob.draw(batch, (int)(x + sliderPos), (int)(y + (height - knob.getMinHeight()) * 0.5f), knob.getMinWidth(),\r
- knob.getMinHeight());\r
+ if (knob != null)\r
+ knob.draw(batch, (int)(x + sliderPos), (int)(y + (height - knobHeight) * 0.5f), knobWidth, knobHeight);\r
}\r
}\r
\r
\r
if (vertical) {\r
float height = getHeight() - bg.getTopHeight() - bg.getBottomHeight();\r
- sliderPos = y - bg.getBottomHeight() - knob.getMinHeight() * 0.5f;\r
+ float knobHeight = knob == null ? 0 : knob.getMinHeight();\r
+ sliderPos = y - bg.getBottomHeight() - knobHeight * 0.5f;\r
sliderPos = Math.max(0, sliderPos);\r
- sliderPos = Math.min(height - knob.getMinHeight(), sliderPos);\r
- value = min + (max - min) * (sliderPos / (height - knob.getMinHeight()));\r
+ sliderPos = Math.min(height - knobHeight, sliderPos);\r
+ value = min + (max - min) * (sliderPos / (height - knobHeight));\r
} else {\r
float width = getWidth() - bg.getLeftWidth() - bg.getRightWidth();\r
- sliderPos = x - bg.getLeftWidth() - knob.getMinWidth() * 0.5f;\r
+ float knobWidth = knob == null ? 0 : knob.getMinWidth();\r
+ sliderPos = x - bg.getLeftWidth() - knobWidth * 0.5f;\r
sliderPos = Math.max(0, sliderPos);\r
- sliderPos = Math.min(width - knob.getMinWidth(), sliderPos);\r
- value = min + (max - min) * (sliderPos / (width - knob.getMinWidth()));\r
+ sliderPos = Math.min(width - knobWidth, sliderPos);\r
+ value = min + (max - min) * (sliderPos / (width - knobWidth));\r
}\r
\r
float oldValue = value;\r
return value;\r
}\r
\r
+ /** If {@link #setAnimateDuration(float) animating} the slider value, this returns the value current displayed. */\r
+ public float getVisualValue () {\r
+ if (animateTime > 0) return animateInterpolation.apply(animateFromValue, value, animateTime / animateDuration);\r
+ return value;\r
+ }\r
+\r
/** Sets the slider position, rounded to the nearest step size and clamped to the minumum and maximim values. */\r
public void setValue (float value) {\r
if (value < min || value > max) throw new IllegalArgumentException("value must be >= min and <= max: " + value);\r
if (value == oldValue) return;\r
this.value = value;\r
ChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);\r
- if (fire(changeEvent)) this.value = oldValue;\r
+ if (fire(changeEvent))\r
+ this.value = oldValue;\r
+ else if (animateDuration > 0) {\r
+ animateTime = animateDuration;\r
+ animateFromValue = getVisualValue();\r
+ }\r
Pools.free(changeEvent);\r
}\r
\r
\r
public float getPrefWidth () {\r
if (vertical)\r
- return Math.max(style.knob.getMinWidth(), style.background.getMinWidth());\r
+ return Math.max(style.knob == null ? 0 : style.knob.getMinWidth(), style.background.getMinWidth());\r
else\r
return 140;\r
}\r
if (vertical)\r
return 140;\r
else\r
- return Math.max(style.knob.getMinHeight(), style.background.getMinHeight());\r
+ return Math.max(style.knob == null ? 0 : style.knob.getMinHeight(), style.background.getMinHeight());\r
}\r
\r
public float getMinValue () {\r
return this.stepSize;\r
}\r
\r
+ /** If > 0, changes to the slider value via {@link #setValue(float)} will happen over this duration in seconds. */\r
+ public void setAnimateDuration (float duration) {\r
+ this.animateDuration = duration;\r
+ }\r
+\r
+ /** Sets the interpolation to use for {@link #setAnimateDuration(float)}. */\r
+ public void setAnimateInterpolation (Interpolation animateInterpolation) {\r
+ if (animateInterpolation == null) throw new IllegalArgumentException("animateInterpolation cannot be null.");\r
+ this.animateInterpolation = animateInterpolation;\r
+ }\r
+\r
/** The style for a slider, see {@link Slider}.\r
* @author mzechner\r
* @author Nathan Sweet */\r
static public class SliderStyle {\r
/** The slider background, stretched only in one direction. */\r
public Drawable background;\r
- /** Centered on the background. */\r
+ /** Optional, centered on the background. */\r
public Drawable knob;\r
/** Optional. */\r
public Drawable knobBefore, knobAfter;\r
this.knob = style.knob;\r
}\r
}\r
-}
\ No newline at end of file
+}\r