UI Slider
From GiderosMobile
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Here you will find various resources to help you create sliders in Gideros Studio.
note: You may have to provide your own assets (fonts, gfx, …)
Slider
-- UI Slider class
Slider = Core.class(Sprite)
function Slider:init(slit, knob)
self.slit = slit
self.width = self.slit:getWidth()
self:addChild(self.slit)
self.knob = knob
self:addChild(self.knob)
self.value = 0
self.isFocus = false
self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)
end
function Slider:onMouseDown(event)
if self.knob:hitTestPoint(event.x, event.y) then
self.isFocus = true
self.x0 = event.x
event:stopPropagation()
end
end
function Slider:onMouseMove(event)
if self.isFocus then
local dx = event.x - self.x0
self.knob:setX(self.knob:getX() + dx)
self.x0 = event.x
-- keep the knob position within its range
if self.knob:getX() < 0 then self.knob:setX(0) end
if self.knob:getX() > self.width then self.knob:setX(self.width) end
self.value = math.floor(100 * self.knob:getX() / self.width)
event:stopPropagation()
end
end
function Slider:onMouseUp(event)
if self.isFocus then
self.isFocus = false
event:stopPropagation()
end
end
function Slider:setValue(value)
local value = math.floor(value)
-- check within a range of [0, 100]
if value < 0 then value = 0 end
if value > 100 then value = 100 end
local posX = self.width * value / 100
self.knob:setPosition(posX, 0)
self.value = value
end
function Slider:getValue()
return self.value
end
---- USAGE
--local slit = Bitmap.new(Texture.new("Images/slit.png"))
--slit:setAnchorPoint(0, 0.5)
--local knob = Bitmap.new(Texture.new("Images/knob.png"))
--knob:setAnchorPoint(0.5, 0.5)
--local myslider = Slider.new(slit, knob)
--stage:addChild(myslider)
--slider:setValue(75)
Another Slider
You can rotate it as well (0 and 90° work best)
--[[
-- ASlider
-- mokalux, cc0
-- Slith, Knob, steps, text, ...
v 0.0.1: 2024-04-23 my take on a ui slider
]]
-- Class
ASlider = Core.class(Sprite) -- integers only slider
local floor = math.floor
function ASlider:init(xparams)
local params = xparams or {}
params.initialvalue = xparams.initialvalue or 0
params.maximum = xparams.maximum or 100
params.steps = xparams.steps or params.maximum
params.slitcolor = xparams.slitcolor or 0x0
params.slitalpha = xparams.slitalpha or 1
params.slitw = xparams.slitw or 64
params.slith = xparams.slith or 64
params.knobcolor = xparams.knobcolor or 0xffffff
params.knobalpha = xparams.knobalpha or 1
params.knobw = xparams.knobw or 32
params.knobh = xparams.knobh or 32
params.text = xparams.text or nil
params.font = xparams.font or nil
params.textscale = xparams.textscale or 1
params.textcolor = xparams.textcolor or 0xffffff
params.textoffsetx = xparams.textoffsetx or 0
params.textoffsety = xparams.textoffsety or 0
params.textrotation = xparams.textrotation or 0
params.id = xparams.id or nil
-- slit and knob
self.slit = Pixel.new(params.slitcolor, params.slitalpha, params.slitw, params.slith)
self.slit:setAnchorPoint(0, 0.5)
self.knob = Pixel.new(params.knobcolor, params.knobalpha, params.knobw, params.knobh)
self.knob:setAnchorPoint(0.5, 0.5)
-- textfield
self.textfield = TextField.new(params.font, params.text or params.maximum) -- if no text then maximum
self.textfield:setRotation(params.textrotation)
self.textfield:setScale(params.textscale)
self.textfield:setTextColor(params.textcolor)
-- position
self.textfield:setPosition(self.slit:getX() + params.textoffsetx, self.slit:getY() + params.textoffsety)
-- order
self:addChild(self.slit)
self:addChild(self.knob)
self:addChild(self.textfield)
-- class variables
self.value = params.initialvalue
self.maximum = params.maximum
self.steps = params.steps
self.width = self.slit:getWidth()
self.text = params.text
self.isFocus = false
self.id = params.id
-- let's go!
self:setValue(self.value)
-- event listeners
self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)
end
-- helper function
function ASlider:setRange(x, xstep)
for s = 0, self.width do
if x <= 0 + (self.width / xstep)/2 then
return 0
elseif x >= s * self.width / xstep and x <= (s + 1) * self.width / xstep - (self.width / xstep)/2 then
return s * self.width / xstep
elseif x >= (s + 1) * self.width / xstep - (self.width / xstep)/2 and x <= (s + 1) * self.width / xstep then
return (s + 1) * self.width / xstep
elseif x >= self.width - (self.width / xstep)/2 then
return self.width
end
end
end
-- events
function ASlider:onMouseDown(event)
if self.slit:hitTestPoint(event.x, event.y) or self.knob:hitTestPoint(event.x, event.y) then
local function round(val, n)
if (n) then return floor( (val * 10^n)+0.5 ) / (10^n)
else return floor(val+0.5)
end
end
local x, _y = self:globalToLocal(event.x, event.y)
self.isFocus = true
self.knob:setX(self:setRange(x, self.steps))
self.value = round(self.maximum * self.knob:getX() / self.width, 3)
local e = Event.new("value_just_changed")
e.value = self.value
e.id = self.id
self:dispatchEvent(e)
event:stopPropagation()
end
end
function ASlider:onMouseMove(event)
if self.isFocus then
local function round(val, n)
if (n) then return floor( (val * 10^n)+0.5 ) / (10^n)
else return floor(val+0.5)
end
end
local x, _y = self:globalToLocal(event.x, event.y)
self.knob:setX(self:setRange(x, self.steps))
self.value = round(self.maximum * self.knob:getX() / self.width, 3)
local e = Event.new("value_changing")
e.value = self.value
e.id = self.id
self:dispatchEvent(e)
event:stopPropagation()
end
end
function ASlider:onMouseUp(event)
if self.isFocus then
self.isFocus = false
local e = Event.new("value_changed")
e.value = self.value
e.id = self.id
self:dispatchEvent(e)
event:stopPropagation()
end
end
-- function
function ASlider:setValue(xvalue)
-- check within range [0, max]
if xvalue < 0 then xvalue = 0 end
if xvalue > self.maximum then xvalue = self.maximum end
local posX = self.width * xvalue / self.maximum
self.knob:setPosition(posX, 0)
self.value = xvalue
if self.text then self.textfield:setText(self.text.."\e[color=#ddc]"..self.value.."\e[color]") -- value is themed ;-)
else self.textfield:setText("\e[color=#ddc]"..self.value.."\e[color]") -- value is themed ;-)
end
end
--[[
---- usage: a complete scene example
Options = Core.class(Sprite)
function Options:init()
-- bg
application:setBackgroundColor(0x232a35)
-- global var
g_bgmvolume = 10
g_difficulty = 1
-- SLIDERS
local slitcolor, knobcolor = 0x3a1d20, 0x8d595d
self.bgmvolumeslider = ASlider.new({
initialvalue=g_bgmvolume, maximum=100, --steps=2,
slitcolor=slitcolor, slitalpha=1, slitw=5*myappwidth/10, slith=24,
knobcolor=knobcolor, knobalpha=0.6, knobw=12, knobh=26,
text="BGM VOLUME: ", textscale=2, textoffsetx=-26*8, textoffsety=7,
id=1,
})
self.difficultyslider = ASlider.new({
initialvalue=g_difficulty, maximum=2, --steps=2,
slitcolor=slitcolor, slitalpha=1, slitw=5*myappwidth/10, slith=24,
knobcolor=knobcolor, knobalpha=0.6, knobw=12, knobh=26,
text="DIFFICULTY: ", textscale=2, textoffsetx=-26*8, textoffsety=7, textrotation=0,
id=3,
})
-- position
self.bgmvolumeslider:setPosition(29*8, 2.5*myappheight/10)
self.difficultyslider:setPosition(29*8, 4.5*myappheight/10)
-- order
self:addChild(self.bgmvolumeslider)
self:addChild(self.difficultyslider)
-- sliders listeners
self.bgmvolumeslider:addEventListener("value_just_changed", self.onValueJustChanged, self)
self.bgmvolumeslider:addEventListener("value_changing", self.onValueChanging, self)
self.bgmvolumeslider:addEventListener("value_changed", self.onValueChanged, self)
self.difficultyslider:addEventListener("value_just_changed", self.onValueJustChanged, self)
self.difficultyslider:addEventListener("value_changing", self.onValueChanging, self)
self.difficultyslider:addEventListener("value_changed", self.onValueChanged, self)
-- let's go!
self:difficulty(g_difficulty)
-- scenes listeners
self:addEventListener("enterBegin", self.onTransitionInBegin, self)
self:addEventListener("enterEnd", self.onTransitionInEnd, self)
self:addEventListener("exitBegin", self.onTransitionOutBegin, self)
self:addEventListener("exitEnd", self.onTransitionOutEnd, self)
end
-- sliders
function Options:difficulty(x)
if x >= 2 then self.difficultyslider.textfield:setText("DIFFICULTY: \e[color=#ddc]HARD\e[color]")
elseif x >= 1 then self.difficultyslider.textfield:setText("DIFFICULTY: \e[color=#ddc]MEDIUM\e[color]")
else self.difficultyslider.textfield:setText("DIFFICULTY: \e[color=#ddc]EASY\e[color]")
end
end
function Options:onValueJustChanged(e)
if e.id == 1 then
g_bgmvolume = e.value -- keep actual value, change in setVolume()
self.bgmvolumeslider:setValue(g_bgmvolume)
elseif e.id == 3 then
g_difficulty = e.value
self:difficulty(g_difficulty)
end
end
function Options:onValueChanging(e)
if e.id == 1 then -- bgm volume
g_bgmvolume = e.value -- keep actual value, change in setVolume()
self.bgmvolumeslider:setValue(g_bgmvolume)
elseif e.id == 3 then
self:difficulty(e.value)
end
end
function Options:onValueChanged(e)
if e.id == 1 then
g_bgmvolume = e.value -- keep actual value, change in setVolume()
local audio = Sound.new("audio/sfx/sfx_wpn_laser4.wav") -- feedback
local channel = audio:play()
channel:setVolume(g_bgmvolume)
self.bgmvolumeslider:setValue(g_bgmvolume)
elseif e.id == 3 then
g_difficulty = e.value
self:difficulty(g_difficulty)
end
-- mySavePrefs(g_configfilepath)
end
-- KEYS HANDLER
function Options:myKeysPressed()
self:addEventListener(Event.KEY_DOWN, function(e)
-- mobile and desktop
if e.keyCode == KeyCode.BACK or e.keyCode == KeyCode.ESC then self:back() end
end)
end
-- scene transitions
function Options:onTransitionInBegin() end
function Options:onTransitionInEnd() self:myKeysPressed() end
function Options:onTransitionOutBegin() self:removeAllListeners() end
function Options:onTransitionOutEnd() end
-- scenes navigation
function Options:back() scenemanager:changeScene("menu", 1, transitions[1], easings[2]) end