Difference between revisions of "UI Slider"

From GiderosMobile
(→‎Slider with Increments: fixed offset issue, final?)
(added another slider!)
Line 203: Line 203:
 
tfsfxvolume:setText("VOLUME: "..ev.value)
 
tfsfxvolume:setText("VOLUME: "..ev.value)
 
g_sfxvolume = ev.value
 
g_sfxvolume = ev.value
 +
end
 +
volumeslider:addEventListener("value_changed", onVolumeValueChanged)
 +
]]
 +
</source>
 +
 +
=== Slider with Text ===
 +
<source lang="lua">
 +
SliderText = Core.class(Sprite)
 +
 +
function SliderText: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
 +
-- parametrable slit and knob
 +
local slit = Pixel.new(params.slitcolor, params.slitalpha, params.slitw, params.slith)
 +
slit:setAnchorPoint(0, 0.5)
 +
local knob = Pixel.new(params.knobcolor, params.knobalpha, params.knobw, params.knobh)
 +
knob:setAnchorPoint(0.5, 0.5)
 +
-- text
 +
local textfield = TextField.new(params.font, params.text)
 +
textfield:setRotation(params.textrotation)
 +
textfield:setScale(params.textscale)
 +
textfield:setTextColor(params.textcolor)
 +
-- order
 +
self:addChild(slit)
 +
self:addChild(knob)
 +
self:addChild(textfield)
 +
-- positions
 +
textfield:setPosition(slit:getX() + params.textoffsetx, slit:getY() + params.textoffsety)
 +
-- class variables
 +
self.value = params.initialvalue
 +
self.maximum = params.maximum
 +
self.steps = params.steps
 +
self.width = slit:getWidth()
 +
self.knob = knob
 +
self.text = params.text
 +
self.textfield = textfield
 +
self.isFocus = false
 +
-- let's go!
 +
self.textfield:setText(self.text..self.value)
 +
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
 +
 +
-- events
 +
function SliderText:onMouseDown(event)
 +
if self:hitTestPoint(event.x, event.y) then
 +
local x, y = self:globalToLocal(event.x, event.y)
 +
self.isFocus = true
 +
self.knob:setX(self:setRange(x, self.steps))
 +
 +
self.value = self:round(self.maximum * self.knob:getX() / self.width)
 +
local e = Event.new("value_changed")
 +
e.value = self.value
 +
self:dispatchEvent(e)
 +
 +
self.textfield:setText(self.text..self.value)
 +
 +
event:stopPropagation()
 +
end
 +
end
 +
 +
function SliderText:onMouseMove(event)
 +
if self.isFocus then
 +
local x, y = self:globalToLocal(event.x, event.y)
 +
self.knob:setX(self:setRange(x, self.steps))
 +
 +
self.value = self:round(self.maximum * self.knob:getX() / self.width)
 +
local e = Event.new("value_changed")
 +
e.value = self.value
 +
self:dispatchEvent(e)
 +
 +
self.textfield:setText(self.text..self.value)
 +
 +
event:stopPropagation()
 +
end
 +
end
 +
 +
function SliderText:onMouseUp(event)
 +
if self.isFocus then
 +
self.isFocus = false
 +
event:stopPropagation()
 +
end
 +
end
 +
 +
-- functions
 +
function SliderText:setValue(xvalue)
 +
local value = math.floor(xvalue)
 +
-- check within a range of [0, max]
 +
if value < 0 then value = 0 end
 +
if value > self.maximum then value = self.maximum end
 +
local posX = self.width * value / self.maximum
 +
self.knob:setPosition(posX, 0)
 +
self.value = value
 +
end
 +
 +
function SliderText:setRange(x, xstep)
 +
for s = 0, self.width do
 +
if x <= 0 then
 +
return 0
 +
elseif x >= s * self.width / xstep and x <= (s + 1) * self.width / xstep then
 +
return s * self.width / xstep
 +
elseif x >= self.width then
 +
return self.width
 +
end
 +
end
 +
end
 +
 +
function SliderText:round(num)
 +
return num + (2^52 + 2^51) - (2^52 + 2^51)
 +
end
 +
 +
--[[
 +
---- usage
 +
application:setBackgroundColor(0x333333)
 +
local volumeslider = SliderText.new({
 +
initialvalue=10, maximum=20,
 +
slitcolor=0x330033, slitalpha=1, slitw=512 - 64 * 2, slith=48,
 +
knobcolor=0xff00ff, knobalpha=0.7, knobw=40, knobh=30,
 +
text="VOLUME: ", textscale=4, textoffsety=-40, textrotation=-10,
 +
})
 +
volumeslider:setPosition(64, 128)
 +
volumeslider:setRotation(45)
 +
stage:addChild(volumeslider)
 +
 +
function onVolumeValueChanged(ev)
 +
print(ev.value)
 
end
 
end
 
volumeslider:addEventListener("value_changed", onVolumeValueChanged)
 
volumeslider:addEventListener("value_changed", onVolumeValueChanged)
 
]]
 
]]
 
</source>
 
</source>

Revision as of 06:24, 31 August 2021

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
	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)

Slider with Increments

Slider2 = Core.class(Sprite)

function Slider2:init(xparams)
	local params = xparams or {}
	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
	-- parametrable slit and knob
	local slit = Pixel.new(params.slitcolor, params.slitalpha, params.slitw, params.slith)
	slit:setAnchorPoint(0, 0.5)
	local knob = Pixel.new(params.knobcolor, params.knobalpha, params.knobw, params.knobh)
	knob:setAnchorPoint(0.5, 0.5)
	-- order
	self.width = slit:getWidth()
	self:addChild(slit)
	self.knob = knob
	self:addChild(self.knob)
	-- class variables
	self.maximum = params.maximum
	self.steps = params.steps
	self.value = 0
	self.isFocus = false
	-- 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

-- events
function Slider2:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		local x, y = self:globalToLocal(event.x, event.y)
		self.isFocus = true
		self.knob:setX(self:setRange(x, self.steps))

		self.value = self:round(self.maximum * self.knob:getX() / self.width)
		local e = Event.new("value_changed")
		e.value = self.value
		self:dispatchEvent(e)

		event:stopPropagation()
	end
end

function Slider2:onMouseMove(event)
	if self.isFocus then
		local x, y = self:globalToLocal(event.x, event.y)
		self.knob:setX(self:setRange(x, self.steps))

		self.value = self:round(self.maximum * self.knob:getX() / self.width)
		local e = Event.new("value_changed")
		e.value = self.value
		self:dispatchEvent(e)

		event:stopPropagation()
	end
end

function Slider2:onMouseUp(event)
	if self.isFocus then
		self.isFocus = false
		event:stopPropagation()
	end
end

-- functions
function Slider2:setValue(value)
	local value = math.floor(value)
	-- check within a range of [0, max]
	if value < 0 then value = 0 end
	if value > self.maximum then value = self.maximum end
	posX = self.width * value / self.maximum
	self.knob:setPosition(posX, 0)
	self.value = value
end

function Slider2:setRange(x, xstep)
	for s = 0, self.width do
		if x <= 0 then
			return 0
		elseif x >= s * self.width / xstep and x <= (s + 1) * self.width / xstep then
			return s * self.width / xstep
		elseif x >= self.width then
			return self.width
		end
	end
end

function Slider2:round(num)
	return num + (2^52 + 2^51) - (2^52 + 2^51)
end

--[[
---- usage
-- bg
application:setBackgroundColor(0x333333)
-- a volume slider
local volumeslider = Slider2.new({
	maximum=20, steps=4,
	slitcolor=0x330033, slitalpha=1, slitw=512 - 64 * 2, slith=48,
	knobcolor=0xff00ff, knobalpha=0.7, knobw=40, knobh=30,
})
volumeslider:setValue(10)
tfsfxvolume = TextField.new(nil, "VOLUME: "..volumeslider.value)
tfsfxvolume:setScale(4)
tfsfxvolume:setTextColor(0xffffff)
-- positions
tfsfxvolume:setPosition(64, 128)
volumeslider:setPosition(64, 196)
-- order
stage:addChild(tfsfxvolume)
stage:addChild(volumeslider)
-- listeners
function onVolumeValueChanged(ev)
	tfsfxvolume:setText("VOLUME: "..ev.value)
	g_sfxvolume = ev.value
end
volumeslider:addEventListener("value_changed", onVolumeValueChanged)
]]

Slider with Text

SliderText = Core.class(Sprite)

function SliderText: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
	-- parametrable slit and knob
	local slit = Pixel.new(params.slitcolor, params.slitalpha, params.slitw, params.slith)
	slit:setAnchorPoint(0, 0.5)
	local knob = Pixel.new(params.knobcolor, params.knobalpha, params.knobw, params.knobh)
	knob:setAnchorPoint(0.5, 0.5)
	-- text
	local textfield = TextField.new(params.font, params.text)
	textfield:setRotation(params.textrotation)
	textfield:setScale(params.textscale)
	textfield:setTextColor(params.textcolor)
	-- order
	self:addChild(slit)
	self:addChild(knob)
	self:addChild(textfield)
	-- positions
	textfield:setPosition(slit:getX() + params.textoffsetx, slit:getY() + params.textoffsety)
	-- class variables
	self.value = params.initialvalue
	self.maximum = params.maximum
	self.steps = params.steps
	self.width = slit:getWidth()
	self.knob = knob
	self.text = params.text
	self.textfield = textfield
	self.isFocus = false
	-- let's go!
	self.textfield:setText(self.text..self.value)
	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

-- events
function SliderText:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		local x, y = self:globalToLocal(event.x, event.y)
		self.isFocus = true
		self.knob:setX(self:setRange(x, self.steps))

		self.value = self:round(self.maximum * self.knob:getX() / self.width)
		local e = Event.new("value_changed")
		e.value = self.value
		self:dispatchEvent(e)

		self.textfield:setText(self.text..self.value)

		event:stopPropagation()
	end
end

function SliderText:onMouseMove(event)
	if self.isFocus then
		local x, y = self:globalToLocal(event.x, event.y)
		self.knob:setX(self:setRange(x, self.steps))

		self.value = self:round(self.maximum * self.knob:getX() / self.width)
		local e = Event.new("value_changed")
		e.value = self.value
		self:dispatchEvent(e)

		self.textfield:setText(self.text..self.value)

		event:stopPropagation()
	end
end

function SliderText:onMouseUp(event)
	if self.isFocus then
		self.isFocus = false
		event:stopPropagation()
	end
end

-- functions
function SliderText:setValue(xvalue)
	local value = math.floor(xvalue)
	-- check within a range of [0, max]
	if value < 0 then value = 0 end
	if value > self.maximum then value = self.maximum end
	local posX = self.width * value / self.maximum
	self.knob:setPosition(posX, 0)
	self.value = value
end

function SliderText:setRange(x, xstep)
	for s = 0, self.width do
		if x <= 0 then
			return 0
		elseif x >= s * self.width / xstep and x <= (s + 1) * self.width / xstep then
			return s * self.width / xstep
		elseif x >= self.width then
			return self.width
		end
	end
end

function SliderText:round(num)
	return num + (2^52 + 2^51) - (2^52 + 2^51)
end

--[[
---- usage
application:setBackgroundColor(0x333333)
local volumeslider = SliderText.new({
	initialvalue=10, maximum=20,
	slitcolor=0x330033, slitalpha=1, slitw=512 - 64 * 2, slith=48,
	knobcolor=0xff00ff, knobalpha=0.7, knobw=40, knobh=30,
	text="VOLUME: ", textscale=4, textoffsety=-40, textrotation=-10,
})
volumeslider:setPosition(64, 128)
volumeslider:setRotation(45)
stage:addChild(volumeslider)

function onVolumeValueChanged(ev)
	print(ev.value)
end
volumeslider:addEventListener("value_changed", onVolumeValueChanged)
]]