Skip to content

Instantly share code, notes, and snippets.

@JoeCreates
Created October 12, 2014 10:01
Show Gist options
  • Select an option

  • Save JoeCreates/636a75d475d2c3ccbd88 to your computer and use it in GitHub Desktop.

Select an option

Save JoeCreates/636a75d475d2c3ccbd88 to your computer and use it in GitHub Desktop.
FlxSlider touch support
package flixel.addons.ui;
import flixel.FlxObject;
import flixel.input.FlxPointer;
import flixel.input.mouse.FlxMouse;
#if !(FLX_NO_MOUSE || FLX_NO_TOUCH)
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.group.FlxSpriteGroup;
import flixel.text.FlxText;
import flixel.util.FlxDestroyUtil;
import flixel.math.FlxMath;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
import flixel.util.FlxSpriteUtil;
import flixel.input.touch.FlxTouch;
import flixel.util.FlxColor;
/**
* A slider GUI element for float and integer manipulation.
* @author Gama11
*/
class FlxSlider extends FlxSpriteGroup
{
/**
* The horizontal line in the background.
*/
public var body:FlxSprite;
/**
* The dragable handle - loadGraphic() to change its graphic.
*/
public var handle:FlxSprite;
/**
* Sprite representing clickable/touchable area of the slider
*/
public var inputArea:FlxSprite;
/**
* The text under the left border - equals minValue by default.
*/
public var minLabel:FlxText;
/**
* The text under the right border - equals maxValue by default.
*/
public var maxLabel:FlxText;
/**
* A text above the slider that displays its name.
*/
public var nameLabel:FlxText;
/**
* A text under the slider that displays the current value.
*/
public var valueLabel:FlxText;
/**
* Stores the current value of the variable - updated each frame.
*/
public var value:Float;
/**
* Mininum value the variable can be changed to.
*/
public var minValue:Float;
/**
* Maximum value the variable can be changed to.
*/
public var maxValue:Float;
/**
* How many decimals the variable can have at max. Default is zero,
* or "only whole numbers".
*/
public var decimals:Int = 0;
/**
* Sound that's played whenever the slider is clicked.
*/
public var clickSound:String;
/**
* Sound that's played whenever the slider is hovered over.
*/
public var hoverSound:String;
/**
* The alpha value the slider uses when it's hovered over. 1 to turn the effect off.
*/
public var hoverAlpha:Float = 0.5;
/**
* A function to be called when the slider was used.
* The current relativePos is passed as an argument.
*/
public var callback:Float->Void = null;
/**
* Whether the slider sets the variable it tracks. Can be useful to deactivate this in conjunction with callbacks.
*/
public var setVariable:Bool = true;
/**
* The expected position of the handle based on the current variable value.
*/
public var expectedPos(get, never):Float;
/**
* The position of the handle relative to the slider / max value.
*/
public var relativePos(get, never):Float;
/**
* Stores the variable the slider controls.
*/
public var varString(default, set):String;
/**
* The pointer input (e.g. mouse/touch) currently sliding this slider
*/
public var activeInput:FlxPointer;
/**
* The width of the slider.
*/
private var _width:Int;
/**
* The height of the slider - make sure to call createSlider() if you
* want to change this.
*/
private var _height:Int;
/**
* The thickness of the slider - make sure to call createSlider() if you
* want to change this.
*/
private var _thickness:Int;
/**
* The color of the slider - make sure to call createSlider() if you
* want to change this.
*/
private var _color:FlxColor;
/**
* The color of the handle - make sure to call createSlider() if you
* want to change this.
*/
private var _handleColor:FlxColor;
/**
* Stores a reference to parent object.
*/
private var _object:Dynamic;
/**
* Helper var for callbacks.
*/
private var _lastPos:Float;
/**
* Creates a new FlxSlider.
*
* @param Object Reference to the parent object of the variable
* @param VarString Variable that the slider controls
* @param X x Position
* @param Y y Position
* @param MinValue Mininum value the variable can be changed to
* @param MaxValue Maximum value the variable can be changed to
* @param Width Width of the slider
* @param Height Height of the slider
* @param Thickness Thickness of the slider
* @param Color Color of the slider background and all texts except for valueText showing the current value
* @param HandleColor Color of the slider handle and the valueText showing the current value
*/
public function new(Object:Dynamic, VarString:String, X:Float = 0, Y:Float = 0, MinValue:Float = 0, MaxValue:Float = 10, Width:Int = 100, Height:Int = 15, Thickness:Int = 3, Color:Int = 0xFF000000, HandleColor:Int = 0xFF828282)
{
super();
if (MinValue == MaxValue)
{
FlxG.log.error("FlxSlider: MinValue and MaxValue can't be the same (" + MinValue + ")");
}
// Determine the amount of decimals to show
decimals = FlxMath.getDecimals(MinValue);
if (FlxMath.getDecimals(MaxValue) > decimals)
{
decimals = FlxMath.getDecimals(MaxValue);
}
decimals ++;
// Assign all those constructor vars
minValue = MinValue;
maxValue = MaxValue;
_object = Object;
varString = VarString;
_width = Width;
_height = Height;
_thickness = Thickness;
_color = Color;
_handleColor = HandleColor;
offset.set(7, 18);
// Create the slider
createSlider();
x = X;
y = Y;
// Set initial value variable
if (Reflect.getProperty(_object, varString) != null)
{
value = Reflect.getProperty(_object, varString);
}
}
/**
* Initially creates the slider with all its objects.
*/
private function createSlider():Void
{
scrollFactor.set();
createBody();
createHandle();
nameLabel = new FlxText(0, 0, _width, varString);
nameLabel.alignment = "center";
nameLabel.color = _color;
var textOffset:Float = _height + offset.y + 3;
valueLabel = new FlxText(offset.x, textOffset, _width);
valueLabel.alignment = "center";
valueLabel.color = _handleColor;
minLabel = new FlxText( -50 + offset.x, textOffset, 100, Std.string(minValue));
minLabel.alignment = "center";
minLabel.color = _color;
maxLabel = new FlxText(_width - 50 + offset.x, textOffset, 100, Std.string(maxValue));
maxLabel.alignment = "center";
maxLabel.color = _color;
inputArea = new FlxSprite(offset.x, offset.y);
var inputAreaKey:String = "slider:inputAreaW=" + _width + "H=" + _height + "C=" + _color.toHexString() + "T=" + _thickness;
inputArea.makeGraphic(_width, _height, FlxColor.TRANSPARENT, false, inputAreaKey);
// Add all the objects
add(body);
add(handle);
add(nameLabel);
add(valueLabel);
add(minLabel);
add(maxLabel);
add(inputArea);
}
override public function update(elapsed:Float):Void
{
// Clear active input if no longer pressed
if (Std.is(activeInput, FlxMouse))
{
var mouse:FlxMouse = cast activeInput;
if (!mouse.pressed)
{
activeInput = null;
}
}
else if (Std.is(activeInput, FlxTouch))
{
var touch:FlxTouch = cast activeInput;
if (!touch.pressed)
{
activeInput = null;
}
}
// Check for new input
checkInput();
// Mouse hover
if (FlxMath.pointInCoordinates(FlxG.mouse.x, FlxG.mouse.y,
inputArea.x, inputArea.y, inputArea.width, inputArea.height))
{
if (!FlxMath.pointInCoordinates(FlxG.mouse._lastX, FlxG.mouse._lastY,
inputArea.x, inputArea.y, inputArea.width, inputArea.height))
{
#if !FLX_NO_SOUND_SYSTEM
if (hoverSound != null)
{
FlxG.sound.play(hoverSound);
}
#end
if (hoverAlpha != 1)
{
alpha = hoverAlpha;
}
}
}
else
{
if (hoverAlpha != 1)
{
alpha = 1;
}
}
if (activeInput != null)
{
handle.x = activeInput.x - handle.width / 2;
updateValue();
}
// Update the value variable
if (Reflect.getProperty(_object, varString) != null)
{
value = Reflect.getProperty(_object, varString);
}
// Changes to value from outside update the handle pos
if (handle.x != expectedPos)
{
handle.x = expectedPos;
}
// Finally, update the valueLabel
valueLabel.text = Std.string(FlxMath.roundDecimal(value, decimals));
super.update(elapsed);
}
public function playClick():Void
{
#if !FLX_NO_SOUND_SYSTEM
if (clickSound != null)
{
FlxG.sound.play(clickSound);
}
#end
}
/**
* Function that is called whenever the slider is used to either update the variable tracked or call the Callback function.
*/
private function updateValue():Void
{
if (_lastPos != relativePos)
{
if ((setVariable) && (varString != null))
{
Reflect.setProperty(_object, varString, (relativePos * (maxValue - minValue)) + minValue);
}
_lastPos = relativePos;
if (callback != null) {
callback(relativePos);
}
}
}
/**
* Handy function for changing the textfields.
*
* @param Name Text of nameLabel - null to hide
* @param Value Whether to show the valueText or not
* @param Min Text of minLabel - null to hide
* @param Max Text of maxLabel - null to hide
* @param Size Size to use for the texts
*/
public function setTexts(Name:String, Value:Bool = true, ?Min:String, ?Max:String, Size:Int = 8):Void
{
if (Name == null)
{
nameLabel.visible = false;
}
else
{
nameLabel.text = Name;
nameLabel.visible = true;
}
if (Min == null)
{
minLabel.visible = false;
}
else
{
minLabel.text = Min;
minLabel.visible = true;
}
if (Max == null)
{
maxLabel.visible = false;
}
else
{
maxLabel.text = Max;
maxLabel.visible = true;
}
if (!Value)
{
valueLabel.visible = false;
}
else
{
valueLabel.visible = true;
}
nameLabel.size = Size;
valueLabel.size = Size;
minLabel.size = Size;
maxLabel.size = Size;
}
/**
* Checks for new input
*/
private function checkInput():Void
{
if (activeInput == null)
{
for (touch in FlxG.touches.list)
{
if (touch.justPressed &&
FlxMath.pointInCoordinates(touch.x, touch.y,
inputArea.x, inputArea.y, inputArea.width, inputArea.height))
{
activeInput = touch;
playClick();
return;
}
}
if (FlxG.mouse.justPressed &&
FlxMath.pointInCoordinates(FlxG.mouse.x, FlxG.mouse.y,
inputArea.x, inputArea.y, inputArea.width, inputArea.height))
{
activeInput = FlxG.mouse;
playClick();
}
}
}
/**
* Cleaning up memory.
*/
override public function destroy():Void
{
body = FlxDestroyUtil.destroy(body);
handle = FlxDestroyUtil.destroy(handle);
minLabel = FlxDestroyUtil.destroy(minLabel);
maxLabel = FlxDestroyUtil.destroy(maxLabel);
nameLabel = FlxDestroyUtil.destroy(nameLabel);
valueLabel = FlxDestroyUtil.destroy(valueLabel);
inputArea = FlxDestroyUtil.destroy(inputArea);
super.destroy();
}
/**
* Create the body of the slider
*/
private function createBody():Void
{
body = new FlxSprite(offset.x, offset.y);
var colorKey:String = "slider:W=" + _width + "H=" + _height + "C=" + _color.toHexString() + "T=" + _thickness;
body.makeGraphic(_width, _height, 0, false, colorKey);
FlxSpriteUtil.drawLine(body, 0, _height / 2, _width, _height / 2, { color:_color, thickness:_thickness });
}
/**
* Create the handle
*/
private function createHandle():Void
{
handle = new FlxSprite(offset.x, offset.y);
handle.makeGraphic(_thickness, _height, _handleColor);
handle.x = expectedPos;
}
private function get_expectedPos():Float
{
var pos:Float = x + offset.x + ((_width - handle.width) * ((value - minValue) / (maxValue - minValue)));
return FlxMath.bound(pos, x + offset.x, x + offset.x + _width);
}
private function get_relativePos():Float
{
var pos:Float = (handle.x - x - offset.x) / (_width - handle.width);
return FlxMath.bound(pos, 0, 1);
}
private function set_varString(Value:String):String
{
try
{
var prop:Dynamic = Reflect.getProperty(_object, Value);
varString = Value;
}
catch (e:Dynamic)
{
FlxG.log.error("Could not create FlxSlider - '" + Value + "' is not a valid field of '" + _object + "'");
varString = null;
}
return Value;
}
}
#end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment