Created
October 12, 2014 10:01
-
-
Save JoeCreates/636a75d475d2c3ccbd88 to your computer and use it in GitHub Desktop.
FlxSlider touch support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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