Difference between revisions of "UI Buttons"

From GiderosMobile
m
m (update to uddp)
Line 757: Line 757:
  
 
=== Button with Text and/or Images UDDP ===
 
=== Button with Text and/or Images UDDP ===
'''This button has it all :-)'''
+
'''This button is the most complete :-)'''
 
<source lang="lua">
 
<source lang="lua">
 
--[[
 
--[[
Line 763: Line 763:
 
This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php
 
This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php
 
github: mokalux
 
github: mokalux
 +
v 0.1.2: 2020-03-29 added nine patch
 +
v 0.1.1: 2020-03-28 added pixel
 
v 0.1.0: 2020-03-28 init (based on the initial gideros generic button class)
 
v 0.1.0: 2020-03-28 init (based on the initial gideros generic button class)
 
]]
 
]]
 
--[[
 
--[[
 
-- SAMPLES
 
-- SAMPLES
local button = ButtonTextUDDP.new({
+
-- BUTTON QUIT
imgup="gfx/ui/btn_01_up.png", imgdown="gfx/ui/btn_01_down.png",
+
local mybtn03 = ButtonTextUDDP.new({
text="BUTTON 1", textcolorup=0x0, textcolordown=0xffff00,
+
imgup="gfx/ui/btn_01_up.png", imgdown="gfx/ui/btn_01_down.png",imgdisabled="gfx/ui/btn_01_disabled.png",
 +
text="QUIT", font="fonts/KenPixel Blocks.ttf", fontsize=32, textcolorup=0xffffff, textcolordown=0x0,
 
})
 
})
local button2 = ButtonTextUDDP.new({
+
mybtn03:setPosition(128, 128)
imgup="gfx/ui/btn_02_up.png", imgdown="gfx/ui/btn_02_down.png", imgdisabled="gfx/ui/btn_02_disabled.png",
+
stage:addChild(mybtn03)
text="BUTTON 2", textcolorup=0x0, textcolordown=0xffff00, font = "fonts/Kenney Future Narrow.ttf", fontsize = 10,
+
mybtn03:addEventListener("clicked", function()
nohover=true,
+
-- application:exit()
})
 
button:addEventListener("clicked", function()
 
button2:setDisabled(not button2:isDisabled())
 
end)
 
button2:addEventListener("click", function()
 
-- your code here
 
 
end)
 
end)
 
+
mybtn03:setDisabled(true)
local button3 = ButtonTextUDDP.new({
 
pixelcolorup = "0xffddff", pixelcolordown = "0xff0000",
 
text = "BUTTON 3",
 
})
 
button:setPosition(2.25 * 64, 2 * 32)
 
button2:setPosition(2.25 * 64, 4.5 * 32)
 
button3:setPosition(2.25 * 64, 7 * 32)
 
stage:addChild(button)
 
stage:addChild(button2)
 
stage:addChild(button3)
 
 
]]
 
]]
 
ButtonTextUDDP = Core.class(Sprite)
 
ButtonTextUDDP = Core.class(Sprite)
Line 803: Line 790:
 
self.params.imgdown = xparams.imgdown or self.params.imgup -- img down path
 
self.params.imgdown = xparams.imgdown or self.params.imgup -- img down path
 
self.params.imgdisabled = xparams.imgdisabled or self.params.imgup -- img disabled path
 
self.params.imgdisabled = xparams.imgdisabled or self.params.imgup -- img disabled path
self.params.imgscalex = xparams.imgscalex or nil -- number or nil = autoscale
+
self.params.imagealpha = xparams.imagealpha or 1 -- number
self.params.imgscaley = xparams.imgscaley or nil -- number or nil = autoscale
+
self.params.imgscalex = xparams.imgscalex or 1 -- number
 +
self.params.imgscaley = xparams.imgscaley or 1 -- number
 +
self.params.imagepaddingx = xparams.imagepaddingx or nil -- number (nil = auto, the image width)
 +
self.params.imagepaddingy = xparams.imagepaddingy or nil -- number (nil = auto, the image height)
 
-- pixel?
 
-- pixel?
 
self.params.pixelcolorup = xparams.pixelcolorup or nil -- color
 
self.params.pixelcolorup = xparams.pixelcolorup or nil -- color
 
self.params.pixelcolordown = xparams.pixelcolordown or self.params.pixelcolorup -- color
 
self.params.pixelcolordown = xparams.pixelcolordown or self.params.pixelcolorup -- color
 
self.params.pixelcolordisabled = xparams.pixelcolordisabled or 0x555555 -- color
 
self.params.pixelcolordisabled = xparams.pixelcolordisabled or 0x555555 -- color
self.params.pixelscalex = xparams.pixelscalex or nil -- number or nil = autoscale
+
self.params.pixelalpha = xparams.pixelalpha or 1 -- number
self.params.pixelscaley = xparams.pixelscaley or nil -- number or nil = autoscale
+
self.params.pixelscalex = xparams.pixelscalex or 1 -- number
 +
self.params.pixelscaley = xparams.pixelscaley or 1 -- number
 +
self.params.pixelpaddingx = xparams.pixelpaddingx or 12 -- number
 +
self.params.pixelpaddingy = xparams.pixelpaddingy or 12 -- number
 
-- text?
 
-- text?
 
self.params.text = xparams.text or nil -- string
 
self.params.text = xparams.text or nil -- string
Line 820: Line 813:
 
self.params.textscalex = xparams.textscalex or 1 -- number
 
self.params.textscalex = xparams.textscalex or 1 -- number
 
self.params.textscaley = xparams.textscaley or self.params.textscalex -- number
 
self.params.textscaley = xparams.textscaley or self.params.textscalex -- number
self.params.nohover = xparams.nohover or nil -- boolean
+
-- EXTRAS
-- let's go
+
self.params.isautoscale = xparams.isautoscale or 1 -- number (default 1 = true)
 +
self.params.hover = xparams.hover or 1 -- number (default 1 = true)
 +
self.params.defaultpadding = xparams.defaultpadding or 12 -- number
 +
-- LET'S GO!
 
self.sprite = Sprite.new()
 
self.sprite = Sprite.new()
 
self.sprite:setAnchorPoint(0.5,0.5)
 
self.sprite:setAnchorPoint(0.5,0.5)
 
self:addChild(self.sprite)
 
self:addChild(self.sprite)
-- button has up state image?
+
-- button has images/pixel/text?
if self.params.imgup ~= nil then
+
if self.params.imgup ~= nil then self.hasbmpup = true else self.hasbmpup = false end
self.bmpup = Bitmap.new(Texture.new(self.params.imgup))
+
if self.params.imgdown ~= nil then self.hasbmpdown = true else self.hasbmpdown = false end
self.bmpup:setAnchorPoint(0.5, 0.5)
+
if self.params.imgdisabled ~= nil then self.hasbmpdisabled = true else self.hasbmpdisabled = false end
self.bmpupwidth = self.bmpup:getWidth()
+
if self.params.pixelcolorup ~= nil then self.haspixel = true else self.haspixel = false end
self.bmpupheight = self.bmpup:getHeight()
+
if self.params.text ~= nil then self.hastext = true else self.hastext = false end
self.sprite:addChild(self.bmpup)
+
-- EXTRAS
self.hasbmpup = true
+
if self.params.isautoscale == 0 then self.params.isautoscale = false else self.params.isautoscale = true end
else
+
if self.params.hover == 0 then self.params.hover = false else self.params.hover = true end
self.hasbmpup = false
 
end
 
-- button has down state image?
 
if self.params.imgdown ~= nil then
 
self.bmpdown = Bitmap.new(Texture.new(self.params.imgdown))
 
self.bmpdown:setAnchorPoint(0.5, 0.5)
 
self.bmpdownwidth = self.bmpdown:getWidth()
 
self.bmpdownheight = self.bmpdown:getHeight()
 
self.sprite:addChild(self.bmpdown)
 
self.hasbmpdown = true
 
else
 
self.hasbmpdown = false
 
end
 
-- button has disabled state image?
 
if self.params.imgdisabled ~= nil then
 
self.bmpdisabled = Bitmap.new(Texture.new(self.params.imgdisabled))
 
self.bmpdisabled:setAnchorPoint(0.5, 0.5)
 
self.bmpdisabledwidth = self.bmpdown:getWidth()
 
self.bmpdisabledheight = self.bmpdown:getHeight()
 
self.sprite:addChild(self.bmpdisabled)
 
self.hasbmpdisabled = true
 
else
 
self.hasbmpdisabled = false
 
end
 
-- button has pixel?
 
if self.params.pixelcolorup ~= nil then
 
self.pixel = Pixel.new(self.params.pixelcolor, 1, 48, 48)
 
self.pixel:setAnchorPoint(0.5, 0.5)
 
self.pixel:setScale(self.params.pixelscalex or 1, self.params.pixelscaley or 1)
 
self.pixelwidth, self.pixelheight = self.pixel:getSize()
 
self.sprite:addChild(self.pixel)
 
self.haspixel = true
 
else
 
self.haspixel = false
 
end
 
-- button has text?
 
if self.params.text ~= nil then
 
self:setText(self.params.text)
 
self.hastext = true
 
else
 
self.hastext = false
 
end
 
 
-- warnings
 
-- warnings
 
if not self.hasbmpup and not self.hasbmpdown and not self.hasbmpdisabled and not self.haspixel and not self.hastext then
 
if not self.hasbmpup and not self.hasbmpdown and not self.hasbmpdisabled and not self.haspixel and not self.hastext then
 
print("*** WARNING: BUTTON NEEDS AT LEAST A TEXTURE, A PIXEL OR SOME TEXT! ***")
 
print("*** WARNING: BUTTON NEEDS AT LEAST A TEXTURE, A PIXEL OR SOME TEXT! ***")
 +
else
 +
self:setButton()
 
end
 
end
 
-- update visual state
 
-- update visual state
Line 889: Line 845:
 
self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)
 
self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)
 
self:addEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
 
self:addEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
if self.params.nohover then
+
if not self.params.hover then
 
-- print("*** no mouse hover effect ***")
 
-- print("*** no mouse hover effect ***")
 
self:removeEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
 
self:removeEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
Line 901: Line 857:
  
 
-- FUNCTIONS
 
-- FUNCTIONS
function ButtonTextUDDP:setText(xtext)
+
function ButtonTextUDDP:setButton()
if self.params.font ~= nil then
+
local textwidth, textheight
-- self.font = TTFont.new(self.params.font, self.params.fontsize, "", true, 1) -- , filtering, outline (number)
+
local bmps = {}
self.font = TTFont.new(self.params.font, self.params.fontsize, "")
+
-- text
 +
if self.hastext then
 +
local font
 +
if self.params.font ~= nil then
 +
-- font = TTFont.new(self.params.font, self.params.fontsize, "", true, 1) -- , filtering, outline (number)
 +
font = TTFont.new(self.params.font, self.params.fontsize, "")
 +
end
 +
if self.text ~= nil then
 +
self.text:setButton(self.params.text)
 +
else
 +
self.text = TextField.new(font, self.params.text, self.params.text)
 +
end
 +
self.text:setAnchorPoint(0.5, 0.5)
 +
self.text:setScale(self.params.textscalex, self.params.textscaley)
 +
self.text:setTextColor(self.params.textcolorup)
 +
textwidth, textheight = self.text:getWidth(), self.text:getHeight()
 
end
 
end
if self.text ~= nil then
+
-- first add pixels
self.text:setText(xtext)
+
if self.haspixel then
else
+
if self.params.isautoscale and self.hastext then
self.text = TextField.new(self.font, xtext, xtext)
+
self.pixel = Pixel.new(
 +
self.params.pixelcolor, self.params.pixelalpha,
 +
textwidth + self.params.pixelpaddingx,
 +
textheight + self.params.pixelpaddingy)
 +
else
 +
self.pixel = Pixel.new(
 +
self.params.pixelcolor, self.params.pixelalpha,
 +
self.params.pixelpaddingx,
 +
self.params.pixelpaddingy)
 +
end
 +
self.pixel:setAnchorPoint(0.5, 0.5)
 +
self.pixel:setScale(self.params.pixelscalex, self.params.pixelscaley)
 +
self.sprite:addChild(self.pixel)
 
end
 
end
self.text:setAnchorPoint(0.5, 0.5)
+
-- then images
self.text:setScale(self.params.textscalex, self.params.textscaley)
 
self.text:setTextColor(self.params.textcolorup)
 
self.textwidth = self.text:getWidth()
 
self.textheight = self.text:getHeight()
 
self.sprite:addChild(self.text)
 
-- has image
 
 
if self.hasbmpup then
 
if self.hasbmpup then
-- scale image
+
local texup = Texture.new(self.params.imgup)
local sx, sy = 1, 1
+
if self.params.isautoscale and self.hastext then
if self.bmpupwidth < self.textwidth then
+
self.bmpup = Pixel.new(texup,
sx = self.params.imgscalex or (self.textwidth/self.bmpupwidth * 1.25)
+
textwidth + (self.params.imagepaddingx or self.params.defaultpadding),
sy = self.params.imgscaley or (self.textheight/self.bmpupheight * 2)
+
textheight + (self.params.imagepaddingy or self.params.defaultpadding))
 +
else
 +
self.bmpup = Pixel.new(texup, self.params.imagepaddingx, self.params.imagepaddingy)
 
end
 
end
self.bmpup:setScale(sx, sy)
+
bmps[self.bmpup] = 1
 
end
 
end
 
if self.hasbmpdown then
 
if self.hasbmpdown then
local sx, sy = 1, 1
+
local texdown = Texture.new(self.params.imgdown)
if self.bmpdownwidth < self.textwidth then
+
if self.params.isautoscale and self.hastext then
sx = self.params.imgscalex or (self.textwidth/self.bmpdownwidth * 1.25)
+
self.bmpdown = Pixel.new(texdown,
sy = self.params.imgscaley or (self.textheight/self.bmpdownheight * 2)
+
textwidth + (self.params.imagepaddingx or self.params.defaultpadding),
 +
textheight + (self.params.imagepaddingy or self.params.defaultpadding))
 +
else
 +
self.bmpdown = Pixel.new(texdown, self.params.imagepaddingx, self.params.imagepaddingy)
 
end
 
end
self.bmpdown:setScale(sx, sy)
+
bmps[self.bmpdown] = 2
 
end
 
end
 
if self.hasbmpdisabled then
 
if self.hasbmpdisabled then
local sx, sy = 1, 1
+
local texdisabled = Texture.new(self.params.imgdisabled)
if self.bmpdisabledwidth < self.textwidth then
+
if self.params.isautoscale and self.hastext then
sx = self.params.imgscalex or (self.textwidth/self.bmpdisabledwidth * 1.25)
+
self.bmpdisabled = Pixel.new(texdisabled,
sy = self.params.imgscaley or (self.textheight/self.bmpdisabledheight * 2)
+
textwidth + (self.params.imagepaddingx or self.params.defaultpadding),
 +
textheight + (self.params.imagepaddingy or self.params.defaultpadding))
 +
else
 +
self.bmpdisabled = Pixel.new(texdisabled, self.params.imagepaddingx, self.params.imagepaddingy)
 
end
 
end
self.bmpdisabled:setScale(sx, sy)
+
bmps[self.bmpdisabled] = 3
 
end
 
end
-- has pixel
+
-- image batch
if self.haspixel then
+
for k, _ in pairs(bmps) do
local sx, sy = 1, 1
+
k:setAnchorPoint(0.5, 0.5)
if self.pixelwidth < self.textwidth then
+
k:setAlpha(self.params.imagealpha)
sx = self.textwidth/self.pixelwidth * 1.25
+
local split = 9 -- magik number
sy = self.textheight/self.pixelheight * 2
+
k:setNinePatch(math.floor(k:getWidth()/split), math.floor(k:getWidth()/split),
end
+
math.floor(k:getHeight()/split), math.floor(k:getHeight()/split))
self.pixel:setScale(sx, sy)
+
self.sprite:addChild(k)
 
end
 
end
 +
-- finally add text on top of all
 +
if self.hastext then self.sprite:addChild(self.text) end
 
end
 
end
  
function ButtonTextUDDP:setTextColor(xcolor)
+
--function ButtonTextUDDP:setTextColor(xcolor)
self.text:setTextColor(xcolor or 0x0)
+
-- self.text:setTextColor(xcolor or 0x0)
end
+
--end
  
 
-- VISUAL STATE
 
-- VISUAL STATE
Line 984: Line 971:
  
 
function ButtonTextUDDP:setDisabled(xdisabled)
 
function ButtonTextUDDP:setDisabled(xdisabled)
if self.disabled == xdisabled then
+
if self.disabled == xdisabled then return end
return
 
end
 
 
self.disabled = xdisabled
 
self.disabled = xdisabled
 
self.focus = false
 
self.focus = false
Line 1,032: Line 1,017:
 
if self:hitTestPoint(e.x, e.y) then
 
if self:hitTestPoint(e.x, e.y) then
 
self.focus = true
 
self.focus = true
self:updateVisualState(true)
 
 
else
 
else
 
self.focus = false
 
self.focus = false
self:updateVisualState(false)
 
 
end
 
end
 +
self:updateVisualState(self.focus)
 
end
 
end
 
-- touch
 
-- touch

Revision as of 05:59, 30 March 2020

Here you will find various resources to help you create buttons in Gideros Studio.

note:You may have to provide your own assets (fonts, gfx, …).

Simple Button

--[[
A generic button class

This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php
(C) 2010 - 2011 Gideros Mobile 
]]
--[[
-- USAGE
-- clickable button (arrow button)
local arrow = Texture.new("gfx/arrow_right.png")
local arrow_pressed = Texture.new("gfx/arrow_right_down.png")
local button = Button.new(Bitmap.new(arrow), Bitmap.new(arrow_pressed))
button:addEventListener("click", function()
	-- your code here
end)
]]

Button = Core.class(Sprite)

function Button:init(upState, downState) -- upstate and downstate are bitmaps
	self.upState = upState
	self.downState = downState
		
	self.focus = false

	-- set the visual state as "up"
	self:updateVisualState(false)

	-- register to all mouse and touch events
	self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
	self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
	self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)

	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
end

function Button:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		self:updateVisualState(true)
		event:stopPropagation()
	end
end

function Button:onMouseMove(event)
	if self.focus then
		if not self:hitTestPoint(event.x, event.y) then	
			self.focus = false
			self:updateVisualState(false)
		end
		event:stopPropagation()
	end
end

function Button:onMouseUp(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		self:dispatchEvent(Event.new("click"))	-- button is clicked, dispatch "click" event
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function Button:onTouchesBegin(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function Button:onTouchesMove(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function Button:onTouchesEnd(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if touches are cancelled, reset the state of the button
function Button:onTouchesCancel(event)
	if self.focus then
		self.focus = false;
		self:updateVisualState(false)
		event:stopPropagation()
	end
end

-- if state is true show downState else show upState
function Button:updateVisualState(state)
	if state then
		if self:contains(self.upState) then
			self:removeChild(self.upState)
		end
		
		if not self:contains(self.downState) then
			self:addChild(self.downState)
		end
	else
		if self:contains(self.downState) then
			self:removeChild(self.downState)
		end
		
		if not self:contains(self.upState) then
			self:addChild(self.upState)
		end
	end
end


Button with an Up, Down and Disabled state (UDD)

--[[
A generic button class with an up, down and disabled state (UDD)

This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php
(C) 2010 - 2011 Gideros Mobile
]]
--[[
--usage
local button = ButtonUDD.new(
	Bitmap.new(Texture.new("gfx/button-up.png")), -- up state
	Bitmap.new(Texture.new("gfx/button-down.png")), -- down state
	Bitmap.new(Texture.new("gfx/button-disabled.png")) -- disabled state
)
button:setPosition(70, 130)
stage:addChild(button)
local function onRecord()
--	play:setDisabled(true)
--	record:removeFromParent()
--	stage:addChild(recordStop)
--	microphone:start()
end
button:addEventListener(Event.CLICK, onRecord)
]]

Event.CLICK = "click"

ButtonUDD = Core.class(Sprite)

function ButtonUDD:init(upState, downState, disabledState)
	self.upState = upState
	self.downState = downState
	self.disabledState = disabledState or upState

	self.focus = false
	self.disabled = false

	-- set the visual state as "up"
	self:updateVisualState(false)

	-- register to all mouse and touch events
	self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
	self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
	self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)

	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
end

function ButtonUDD:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		self:updateVisualState(true)
		event:stopPropagation()
	end
end

function ButtonUDD:onMouseMove(event)
	if self.focus then
		if not self:hitTestPoint(event.x, event.y) then
			self.focus = false
			self:updateVisualState(false)
		end
		event:stopPropagation()
	end
end

function ButtonUDD:onMouseUp(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		if not self.disabled then
			self:dispatchEvent(Event.new(Event.CLICK))	-- button is clicked, dispatch "click" event
		end
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function ButtonUDD:onTouchesBegin(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function ButtonUDD:onTouchesMove(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function ButtonUDD:onTouchesEnd(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if touches are cancelled, reset the state of the button
function ButtonUDD:onTouchesCancel(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
	end
end

-- if state is true show downState else show upState
function ButtonUDD:updateVisualState(state)
	self.upState:removeFromParent()
	self.downState:removeFromParent()
	self.disabledState:removeFromParent()

	if self.disabled then
		self:addChild(self.disabledState)
	else
		if state then
			self:addChild(self.downState)
		else
			self:addChild(self.upState)
		end
	end
end

function ButtonUDD:setDisabled(disabled)
	if self.disabled == disabled then
		return
	end

	self.disabled = disabled
	self.focus = false
	self:updateVisualState(false)
end

function ButtonUDD:isDisabled()
	return self.disabled
end


Button with Text and/or Images

--[[
A Button class with text and/or image
This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php
github: mokalux
v 0.1.1: 2020-03-07 added optional mouse hover effect params (mouse hover effect default is true)
v 0.1.0: 2020-03-02 init (based on the initial gideros generic button class)
]]
--[[
-- sample usage
	local button = ButtonText.new(
		{
			text="01", textscalex=4, textcolorup=0x0, textcolordown=0xffff00,
			imgdown="gfx/ui/Blue.png", nohover=true,
		}
	)
	button:setPosition(128, 128)
	self:addChild(button)
	button:addEventListener("click", function() 
		-- your code here
	end)
]]
ButtonText = Core.class(Sprite)

function ButtonText:init(xparams)
	-- the params
	self.params = xparams or {}
	self.params.imgup = xparams.imgup or nil -- img up path
	self.params.imgdown = xparams.imgdown or self.params.imgup -- img down path
	self.params.imgscalex = xparams.imgscalex or nil -- number or nil = autoscale
	self.params.imgscaley = xparams.imgscaley or nil -- number or nil = autoscale
	self.params.text = xparams.text or nil -- string
	self.params.font = xparams.font or nil -- ttf font path
	self.params.fontsize = xparams.fontsize or 16 -- number
	self.params.textcolorup = xparams.textcolorup or 0x0 -- color
	self.params.textcolordown = xparams.textcolordown or self.params.textcolorup -- color
	self.params.textscalex = xparams.textscalex or 1 -- number
	self.params.textscaley = xparams.textscaley or self.params.textscalex -- number
	self.params.nohover = xparams.nohover or nil -- boolean
	-- let's go
	self.sprite = Sprite.new()
	self.sprite:setAnchorPoint(0.5,0.5)
	self:addChild(self.sprite)
	-- button has up state image?
	if self.params.imgup ~= nil then
		self.bmpup = Bitmap.new(Texture.new(self.params.imgup))
		self.bmpup:setAnchorPoint(0.5, 0.5)
		self.bmpupwidth = self.bmpup:getWidth()
		self.bmpupheight = self.bmpup:getHeight()
		self.sprite:addChild(self.bmpup)
		self.hasbmpup = true
	else
		self.hasbmpup = false
	end
	-- button has down state image?
	if self.params.imgdown ~= nil then
		self.bmpdown = Bitmap.new(Texture.new(self.params.imgdown))
		self.bmpdown:setAnchorPoint(0.5, 0.5)
		self.bmpdownwidth = self.bmpdown:getWidth()
		self.bmpdownheight = self.bmpdown:getHeight()
		self.sprite:addChild(self.bmpdown)
		self.hasbmpdown = true
	else
		self.hasbmpdown = false
	end
	-- button has text?
	if self.params.text ~= nil then
		self:setText(self.params.text)
		self.hastext = true
	else
		self.hastext = false
	end
	-- warnings
	if not self.hasbmpup and not self.hasbmpdown and not self.hastext then
		print("*** WARNING: BUTTONTEXT NEEDS AT LEAST SOME TEXT OR SOME BITMAPS! ***")
	end
	-- update visual state
	self.focus = false
	self:updateVisualState(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)
	self:addEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
	if self.params.nohover then
--		print("*** no mouse hover effect ***")
		self:removeEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
	end
	-- mobile
	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
end

-- FUNCTIONS
function ButtonText:setText(xtext)
	if self.params.font ~= nil then
		self.font = TTFont.new(self.params.font, self.params.fontsize)
	end
	if self.text ~= nil then
		self.text:setText(xtext)
	else
		self.text = TextField.new(self.font, xtext, xtext)
	end
	self.text:setAnchorPoint(0.5, 0.5)
	self.text:setScale(self.params.textscalex, self.params.textscaley)
	self.text:setTextColor(self.params.textcolorup)
	self.textwidth = self.text:getWidth()
	self.textheight = self.text:getHeight()
	self.sprite:addChild(self.text)
	-- scale image
	if self.hasbmpup then
		local sx, sy = 1, 1
		if self.bmpupwidth < self.textwidth then
			sx = self.params.imgscalex or (self.textwidth/self.bmpupwidth * 1.25)
			sy = self.params.imgscaley or (self.textheight/self.bmpupheight * 2)
		end
		self.bmpup:setScale(sx, sy)
	end
	if self.hasbmpdown then
		local sx, sy = 1, 1
		if self.bmpdownwidth < self.textwidth then
			sx = self.params.imgscalex or (self.textwidth/self.bmpdownwidth * 1.25)
			sy = self.params.imgscaley or (self.textheight/self.bmpdownheight * 2)
		end
		self.bmpdown:setScale(sx, sy)
	end
end

function ButtonText:setTextColor(xcolor)
	self.text:setTextColor(xcolor or 0x0)
end

-- VISUAL STATE
function ButtonText:updateVisualState(xisdown)
	if xisdown then
		if self.params.imgup ~= nil then self.bmpup:setVisible(false) end
		if self.params.imgdown ~= nil then self.bmpdown:setVisible(true) end
		if self.params.text ~= nil then self.text:setTextColor(self.params.textcolordown) end
	else
		if self.params.imgup ~= nil then self.bmpup:setVisible(true) end
		if self.params.imgdown ~= nil then self.bmpdown:setVisible(false) end
		if self.params.text ~= nil then self.text:setTextColor(self.params.textcolorup) end
	end
end

-- BUTTON LISTENERS
-- mouse
function ButtonText:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		self:updateVisualState(true)
		event:stopPropagation()
	end
end
function ButtonText:onMouseMove(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		self:updateVisualState(true)
		event:stopPropagation()
	end
	if not self:hitTestPoint(event.x, event.y) then
		self.focus = false
		self:updateVisualState(false)
--		event:stopPropagation() -- you may want to comment this line
	end
end
function ButtonText:onMouseUp(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		self:dispatchEvent(Event.new("click"))
		event:stopPropagation()
	end
end
function ButtonText:onMouseHover(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		self:updateVisualState(true)
	else
		self.focus = false
		self:updateVisualState(false)
	end
end
-- mobile
function ButtonText:onTouchesBegin(event)
	if self.focus then
		event:stopPropagation()
	end
end
function ButtonText:onTouchesMove(event)
	if self.focus then
		event:stopPropagation()
	end
end
function ButtonText:onTouchesEnd(event)
	if self.focus then
		event:stopPropagation()
	end
end
function ButtonText:onTouchesCancel(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		event:stopPropagation()
	end
end


Button with Text and/or Images UDD

This button has it all (almost) :-)

--[[
A Button class with text and/or image with Up state, Down state, Disabled state (UDD)
This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php
github: mokalux
v 0.1.0: 2020-03-09 init (based on the initial gideros generic button class)
]]
--[[
-- sample usage
	local button = ButtonTextUDD.new(
		{
			text="01", textscalex=4, textcolorup=0x0, textcolordown=0xffff00,
			imgdown="gfx/ui/Blue.png",
			nohover=false,
		}
	)
	button:setPosition(64, 2 * 16)
	stage:addChild(button)

	local button2 = ButtonTextUDD.new(
		{
			text="02 CAN DO", textscalex=4, textcolorup=0x0, textcolordown=0xffff00,
			imgup="gfx/ui/blue (2).png", imgdown="gfx/ui/Blue.png", imgdisabled="gfx/ui/blocker2.png",
			nohover=true,
		}
	)
	button2:setPosition(64, 4 * 16)
	stage:addChild(button2)

	button:addEventListener("clicked", function()
		button2:setDisabled(not button2:isDisabled())
	end)
	button2:addEventListener("click", function()
		-- your code here
	end)
]]
ButtonTextUDD = Core.class(Sprite)

function ButtonTextUDD:init(xparams)
	-- the params
	self.params = xparams or {}
	self.params.imgup = xparams.imgup or nil -- img up path
	self.params.imgdown = xparams.imgdown or self.params.imgup -- img down path
	self.params.imgdisabled = xparams.imgdisabled or self.params.imgup -- img disabled path
	self.params.imgscalex = xparams.imgscalex or nil -- number or nil = autoscale
	self.params.imgscaley = xparams.imgscaley or nil -- number or nil = autoscale
	self.params.text = xparams.text or nil -- string
	self.params.font = xparams.font or nil -- ttf font path
	self.params.fontsize = xparams.fontsize or 16 -- number
	self.params.textcolorup = xparams.textcolorup or 0x0 -- color
	self.params.textcolordown = xparams.textcolordown or self.params.textcolorup -- color
	self.params.textcolordisabled = xparams.textcolordisabled or 0x555555 -- color
	self.params.textscalex = xparams.textscalex or 1 -- number
	self.params.textscaley = xparams.textscaley or self.params.textscalex -- number
	self.params.nohover = xparams.nohover or nil -- boolean
	-- let's go
	self.sprite = Sprite.new()
	self.sprite:setAnchorPoint(0.5,0.5)
	self:addChild(self.sprite)
	-- button has up state image?
	if self.params.imgup ~= nil then
		self.bmpup = Bitmap.new(Texture.new(self.params.imgup))
		self.bmpup:setAnchorPoint(0.5, 0.5)
		self.bmpupwidth = self.bmpup:getWidth()
		self.bmpupheight = self.bmpup:getHeight()
		self.sprite:addChild(self.bmpup)
		self.hasbmpup = true
	else
		self.hasbmpup = false
	end
	-- button has down state image?
	if self.params.imgdown ~= nil then
		self.bmpdown = Bitmap.new(Texture.new(self.params.imgdown))
		self.bmpdown:setAnchorPoint(0.5, 0.5)
		self.bmpdownwidth = self.bmpdown:getWidth()
		self.bmpdownheight = self.bmpdown:getHeight()
		self.sprite:addChild(self.bmpdown)
		self.hasbmpdown = true
	else
		self.hasbmpdown = false
	end
	-- button has disabled state image?
	if self.params.imgdisabled ~= nil then
		self.bmpdisabled = Bitmap.new(Texture.new(self.params.imgdisabled))
		self.bmpdisabled:setAnchorPoint(0.5, 0.5)
		self.bmpdisabledwidth = self.bmpdown:getWidth()
		self.bmpdisabledheight = self.bmpdown:getHeight()
		self.sprite:addChild(self.bmpdisabled)
		self.hasbmpdisabled = true
	else
		self.hasbmpdisabled = false
	end
	-- button has text?
	if self.params.text ~= nil then
		self:setText(self.params.text)
		self.hastext = true
	else
		self.hastext = false
	end
	-- warnings
	if not self.hasbmpup and not self.hasbmpdown and not self.hasbmpdisabled and not self.hastext then
		print("*** WARNING: BUTTONTEXT NEEDS AT LEAST SOME TEXT OR SOME BITMAPS! ***")
	end
	-- update visual state
	self.focus = false
	self.disabled = false
	self:updateVisualState(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)
	self:addEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
	if self.params.nohover then
		print("*** no mouse hover effect ***")
		self:removeEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
	end
	-- mobile
	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
end

-- FUNCTIONS
function ButtonTextUDD:setText(xtext)
	if self.params.font ~= nil then
		self.font = TTFont.new(self.params.font, self.params.fontsize)
	end
	if self.text ~= nil then
		self.text:setText(xtext)
	else
		self.text = TextField.new(self.font, xtext, xtext)
	end
	self.text:setAnchorPoint(0.5, 0.5)
	self.text:setScale(self.params.textscalex, self.params.textscaley)
	self.text:setTextColor(self.params.textcolorup)
	self.textwidth = self.text:getWidth()
	self.textheight = self.text:getHeight()
	self.sprite:addChild(self.text)
	-- scale image
	if self.hasbmpup then
		local sx, sy = 1, 1
		if self.bmpupwidth < self.textwidth then
			sx = self.params.imgscalex or (self.textwidth/self.bmpupwidth * 1.25)
			sy = self.params.imgscaley or (self.textheight/self.bmpupheight * 2)
		end
		self.bmpup:setScale(sx, sy)
	end
	if self.hasbmpdown then
		local sx, sy = 1, 1
		if self.bmpdownwidth < self.textwidth then
			sx = self.params.imgscalex or (self.textwidth/self.bmpdownwidth * 1.25)
			sy = self.params.imgscaley or (self.textheight/self.bmpdownheight * 2)
		end
		self.bmpdown:setScale(sx, sy)
	end
	if self.hasbmpdisabled then
		local sx, sy = 1, 1
		if self.bmpdisabledwidth < self.textwidth then
			sx = self.params.imgscalex or (self.textwidth/self.bmpdisabledwidth * 1.25)
			sy = self.params.imgscaley or (self.textheight/self.bmpdisabledheight * 2)
		end
		self.bmpdisabled:setScale(sx, sy)
	end
end

function ButtonTextUDD:setTextColor(xcolor)
	self.text:setTextColor(xcolor or 0x0)
end

-- VISUAL STATE
function ButtonTextUDD:updateVisualState(xstate)
	if self.disabled then -- button disabled state
		if self.params.imgup ~= nil then self.bmpup:setVisible(false) end
		if self.params.imgdown ~= nil then self.bmpdown:setVisible(false) end
		if self.params.imgdisabled ~= nil then self.bmpdisabled:setVisible(true) end
		if self.params.text ~= nil then self.text:setTextColor(self.params.textcolordisabled) end
	else
		if xstate then -- button down state
			if self.params.imgup ~= nil then self.bmpup:setVisible(false) end
			if self.params.imgdown ~= nil then self.bmpdown:setVisible(true) end
			if self.params.imgdisabled ~= nil then self.bmpdisabled:setVisible(false) end
			if self.params.text ~= nil then self.text:setTextColor(self.params.textcolordown) end
		else -- button up state
			if self.params.imgup ~= nil then self.bmpup:setVisible(true) end
			if self.params.imgdown ~= nil then self.bmpdown:setVisible(false) end
			if self.params.imgdisabled ~= nil then self.bmpdisabled:setVisible(false) end
			if self.params.text ~= nil then self.text:setTextColor(self.params.textcolorup) end
		end
	end
end

function ButtonTextUDD:setDisabled(xdisabled)
	if self.disabled == xdisabled then
		return
	end
	self.disabled = xdisabled
	self.focus = false
	self:updateVisualState(false)
end

function ButtonTextUDD:isDisabled()
	return self.disabled
end

-- BUTTON LISTENERS
-- mouse
function ButtonTextUDD:onMouseDown(e)
	if self:hitTestPoint(e.x, e.y) then
		self.focus = true
		self:updateVisualState(true)
		e:stopPropagation()
	end
end
function ButtonTextUDD:onMouseMove(e)
	if self:hitTestPoint(e.x, e.y) then
		self.focus = true
		self:updateVisualState(true)
		e:stopPropagation()
	end
	if self.focus then
		if not self:hitTestPoint(e.x, e.y) then
			self.focus = false
			self:updateVisualState(false)
--			e:stopPropagation() -- you may want to comment this line
		end
	end
end
function ButtonTextUDD:onMouseUp(e)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		if not self.disabled then
			self:dispatchEvent(Event.new("clicked"))	-- button is clicked, dispatch "click" event
		end
		e:stopPropagation()
	end
end
function ButtonTextUDD:onMouseHover(e)
	if self:hitTestPoint(e.x, e.y) then
		self.focus = true
		self:updateVisualState(true)
	else
		self.focus = false
		self:updateVisualState(false)
	end
end
-- touch
function ButtonTextUDD:onTouchesBegin(e)
	if self.focus then
		e:stopPropagation()
	end
end
function ButtonTextUDD:onTouchesMove(e)
	if self.focus then
		e:stopPropagation()
	end
end
function ButtonTextUDD:onTouchesEnd(e)
	if self.focus then
		e:stopPropagation()
	end
end
function ButtonTextUDD:onTouchesCancel(e)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		e:stopPropagation()
	end
end


Button with Text and/or Images UDDP

This button is the most complete :-)

--[[
A Button class with text and/or image/pixel with Up state, Down state, Disabled state (UDD)
This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php
github: mokalux
v 0.1.2: 2020-03-29 added nine patch
v 0.1.1: 2020-03-28 added pixel
v 0.1.0: 2020-03-28 init (based on the initial gideros generic button class)
]]
--[[
-- SAMPLES
-- BUTTON QUIT
local mybtn03 = ButtonTextUDDP.new({
	imgup="gfx/ui/btn_01_up.png", imgdown="gfx/ui/btn_01_down.png",imgdisabled="gfx/ui/btn_01_disabled.png",
	text="QUIT", font="fonts/KenPixel Blocks.ttf", fontsize=32, textcolorup=0xffffff, textcolordown=0x0,
})
mybtn03:setPosition(128, 128)
stage:addChild(mybtn03)
mybtn03:addEventListener("clicked", function()
--		application:exit()
end)
mybtn03:setDisabled(true)
]]
ButtonTextUDDP = Core.class(Sprite)

function ButtonTextUDDP:init(xparams)
	-- the params
	self.params = xparams or {}
	-- textures?
	self.params.imgup = xparams.imgup or nil -- img up path
	self.params.imgdown = xparams.imgdown or self.params.imgup -- img down path
	self.params.imgdisabled = xparams.imgdisabled or self.params.imgup -- img disabled path
	self.params.imagealpha = xparams.imagealpha or 1 -- number
	self.params.imgscalex = xparams.imgscalex or 1 -- number
	self.params.imgscaley = xparams.imgscaley or 1 -- number
	self.params.imagepaddingx = xparams.imagepaddingx or nil -- number (nil = auto, the image width)
	self.params.imagepaddingy = xparams.imagepaddingy or nil -- number (nil = auto, the image height)
	-- pixel?
	self.params.pixelcolorup = xparams.pixelcolorup or nil -- color
	self.params.pixelcolordown = xparams.pixelcolordown or self.params.pixelcolorup -- color
	self.params.pixelcolordisabled = xparams.pixelcolordisabled or 0x555555 -- color
	self.params.pixelalpha = xparams.pixelalpha or 1 -- number
	self.params.pixelscalex = xparams.pixelscalex or 1 -- number
	self.params.pixelscaley = xparams.pixelscaley or 1 -- number
	self.params.pixelpaddingx = xparams.pixelpaddingx or 12 -- number
	self.params.pixelpaddingy = xparams.pixelpaddingy or 12 -- number
	-- text?
	self.params.text = xparams.text or nil -- string
	self.params.font = xparams.font or nil -- ttf font path
	self.params.fontsize = xparams.fontsize or 16 -- number
	self.params.textcolorup = xparams.textcolorup or 0x0 -- color
	self.params.textcolordown = xparams.textcolordown or self.params.textcolorup -- color
	self.params.textcolordisabled = xparams.textcolordisabled or 0x777777 -- color
	self.params.textscalex = xparams.textscalex or 1 -- number
	self.params.textscaley = xparams.textscaley or self.params.textscalex -- number
	-- EXTRAS
	self.params.isautoscale = xparams.isautoscale or 1 -- number (default 1 = true)
	self.params.hover = xparams.hover or 1 -- number (default 1 = true)
	self.params.defaultpadding = xparams.defaultpadding or 12 -- number
	-- LET'S GO!
	self.sprite = Sprite.new()
	self.sprite:setAnchorPoint(0.5,0.5)
	self:addChild(self.sprite)
	-- button has images/pixel/text?
	if self.params.imgup ~= nil then self.hasbmpup = true else self.hasbmpup = false end
	if self.params.imgdown ~= nil then self.hasbmpdown = true else self.hasbmpdown = false end
	if self.params.imgdisabled ~= nil then self.hasbmpdisabled = true else self.hasbmpdisabled = false end
	if self.params.pixelcolorup ~= nil then self.haspixel = true else self.haspixel = false end
	if self.params.text ~= nil then self.hastext = true else self.hastext = false end
	-- EXTRAS
	if self.params.isautoscale == 0 then self.params.isautoscale = false else self.params.isautoscale = true end
	if self.params.hover == 0 then self.params.hover = false else self.params.hover = true end
	-- warnings
	if not self.hasbmpup and not self.hasbmpdown and not self.hasbmpdisabled and not self.haspixel and not self.hastext then
		print("*** WARNING: BUTTON NEEDS AT LEAST A TEXTURE, A PIXEL OR SOME TEXT! ***")
	else
		self:setButton()
	end
	-- update visual state
	self.focus = false
	self.disabled = false
	self:updateVisualState(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)
	self:addEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
	if not self.params.hover then
--		print("*** no mouse hover effect ***")
		self:removeEventListener(Event.MOUSE_HOVER, self.onMouseHover, self)
	end
	-- mobile
	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
end

-- FUNCTIONS
function ButtonTextUDDP:setButton()
	local textwidth, textheight
	local bmps = {}
	-- text
	if self.hastext then
		local font
		if self.params.font ~= nil then
	--		font = TTFont.new(self.params.font, self.params.fontsize, "", true, 1) -- , filtering, outline (number)
			font = TTFont.new(self.params.font, self.params.fontsize, "")
		end
		if self.text ~= nil then
			self.text:setButton(self.params.text)
		else
			self.text = TextField.new(font, self.params.text, self.params.text)
		end
		self.text:setAnchorPoint(0.5, 0.5)
		self.text:setScale(self.params.textscalex, self.params.textscaley)
		self.text:setTextColor(self.params.textcolorup)
		textwidth, textheight = self.text:getWidth(), self.text:getHeight()
	end
	-- first add pixels
	if self.haspixel then
		if self.params.isautoscale and self.hastext then
			self.pixel = Pixel.new(
				self.params.pixelcolor, self.params.pixelalpha,
				textwidth + self.params.pixelpaddingx,
				textheight + self.params.pixelpaddingy)
		else
			self.pixel = Pixel.new(
				self.params.pixelcolor, self.params.pixelalpha,
				self.params.pixelpaddingx,
				self.params.pixelpaddingy)
		end
		self.pixel:setAnchorPoint(0.5, 0.5)
		self.pixel:setScale(self.params.pixelscalex, self.params.pixelscaley)
		self.sprite:addChild(self.pixel)
	end
	-- then images
	if self.hasbmpup then
		local texup = Texture.new(self.params.imgup)
		if self.params.isautoscale and self.hastext then
			self.bmpup = Pixel.new(texup,
				textwidth + (self.params.imagepaddingx or self.params.defaultpadding),
				textheight + (self.params.imagepaddingy or self.params.defaultpadding))
		else
			self.bmpup = Pixel.new(texup, self.params.imagepaddingx, self.params.imagepaddingy)
		end
		bmps[self.bmpup] = 1
	end
	if self.hasbmpdown then
		local texdown = Texture.new(self.params.imgdown)
		if self.params.isautoscale and self.hastext then
			self.bmpdown = Pixel.new(texdown,
				textwidth + (self.params.imagepaddingx or self.params.defaultpadding),
				textheight + (self.params.imagepaddingy or self.params.defaultpadding))
		else
			self.bmpdown = Pixel.new(texdown, self.params.imagepaddingx, self.params.imagepaddingy)
		end
		bmps[self.bmpdown] = 2
	end
	if self.hasbmpdisabled then
		local texdisabled = Texture.new(self.params.imgdisabled)
		if self.params.isautoscale and self.hastext then
			self.bmpdisabled = Pixel.new(texdisabled,
				textwidth + (self.params.imagepaddingx or self.params.defaultpadding),
				textheight + (self.params.imagepaddingy or self.params.defaultpadding))
		else
			self.bmpdisabled = Pixel.new(texdisabled, self.params.imagepaddingx, self.params.imagepaddingy)
		end
		bmps[self.bmpdisabled] = 3
	end
	-- image batch
	for k, _ in pairs(bmps) do
		k:setAnchorPoint(0.5, 0.5)
		k:setAlpha(self.params.imagealpha)
		local split = 9 -- magik number
		k:setNinePatch(math.floor(k:getWidth()/split), math.floor(k:getWidth()/split),
			math.floor(k:getHeight()/split), math.floor(k:getHeight()/split))
		self.sprite:addChild(k)
	end
	-- finally add text on top of all
	if self.hastext then self.sprite:addChild(self.text) end
end

--function ButtonTextUDDP:setTextColor(xcolor)
--	self.text:setTextColor(xcolor or 0x0)
--end

-- VISUAL STATE
function ButtonTextUDDP:updateVisualState(xstate)
	if self.disabled then -- button disabled state
		if self.params.imgup ~= nil then self.bmpup:setVisible(false) end
		if self.params.imgdown ~= nil then self.bmpdown:setVisible(false) end
		if self.params.imgdisabled ~= nil then self.bmpdisabled:setVisible(true) end
		if self.params.pixelcolorup ~= nil then self.pixel:setColor(self.params.pixelcolordisabled) end
		if self.params.text ~= nil then self.text:setTextColor(self.params.textcolordisabled) end
	else
		if xstate then -- button down state
			if self.params.imgup ~= nil then self.bmpup:setVisible(false) end
			if self.params.imgdown ~= nil then self.bmpdown:setVisible(true) end
			if self.params.imgdisabled ~= nil then self.bmpdisabled:setVisible(false) end
			if self.params.pixelcolorup ~= nil then self.pixel:setColor(self.params.pixelcolordown) end
			if self.params.text ~= nil then self.text:setTextColor(self.params.textcolordown) end
		else -- button up state
			if self.params.imgup ~= nil then self.bmpup:setVisible(true) end
			if self.params.imgdown ~= nil then self.bmpdown:setVisible(false) end
			if self.params.imgdisabled ~= nil then self.bmpdisabled:setVisible(false) end
			if self.params.pixelcolorup ~= nil then self.pixel:setColor(self.params.pixelcolorup) end
			if self.params.text ~= nil then self.text:setTextColor(self.params.textcolorup) end
		end
	end
end

function ButtonTextUDDP:setDisabled(xdisabled)
	if self.disabled == xdisabled then return end
	self.disabled = xdisabled
	self.focus = false
	self:updateVisualState(false)
end

function ButtonTextUDDP:isDisabled()
	return self.disabled
end

-- BUTTON LISTENERS
-- mouse
function ButtonTextUDDP:onMouseDown(e)
	if self:hitTestPoint(e.x, e.y) then
		self.focus = true
		self:updateVisualState(true)
		e:stopPropagation()
	end
end
function ButtonTextUDDP:onMouseMove(e)
	if self:hitTestPoint(e.x, e.y) then
		self.focus = true
		self:updateVisualState(true)
		e:stopPropagation()
	end
	if self.focus then
		if not self:hitTestPoint(e.x, e.y) then
			self.focus = false
			self:updateVisualState(false)
--			e:stopPropagation() -- you may want to comment this line
		end
	end
end
function ButtonTextUDDP:onMouseUp(e)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		if not self.disabled then
			self:dispatchEvent(Event.new("clicked"))	-- button is clicked, dispatch "click" event
		end
		e:stopPropagation()
	end
end
function ButtonTextUDDP:onMouseHover(e)
	if self:hitTestPoint(e.x, e.y) then
		self.focus = true
	else
		self.focus = false
	end
	self:updateVisualState(self.focus)
end
-- touch
function ButtonTextUDDP:onTouchesBegin(e)
	if self.focus then
		e:stopPropagation()
	end
end
function ButtonTextUDDP:onTouchesMove(e)
	if self.focus then
		e:stopPropagation()
	end
end
function ButtonTextUDDP:onTouchesEnd(e)
	if self.focus then
		e:stopPropagation()
	end
end
function ButtonTextUDDP:onTouchesCancel(e)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		e:stopPropagation()
	end
end


Toggle Button

--[[
ToggleButton v1.0
 
v1.0 - 19.3.2013
Initial release
 
Free to modify and use!
Matjaž Bravc
]]
--[[
-- USAGE
local btntoggle = ToggleButton.new(Bitmap.new(Texture.new("gfx/off.png", true)), Bitmap.new(Texture.new("gfx/on.png", true)))
stage:addChild(btntoggle)
btntoggle:addEventListener("click", function()
	print(btntoggle:isPressed())
end)
]]

ToggleButton = Core.class(Sprite)

function ToggleButton:init(upState, downState)
	self.upState = upState
	self.downState = downState

	self.pressed = false
	self.focus = false

	self:updateVisualState(self.pressed)

	self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
	self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
	self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)

	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
end

function ToggleButton:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		event:stopPropagation()
	end
end

function ToggleButton:onMouseMove(event)
	if self.focus then
		if not self:hitTestPoint(event.x, event.y) then
			self.focus = false
		end
		event:stopPropagation()
	end
end

function ToggleButton:onMouseUp(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(not self.pressed)
		self:dispatchEvent(Event.new("click"))
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function ToggleButton:onTouchesBegin(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function ToggleButton:onTouchesMove(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function ToggleButton:onTouchesEnd(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if touches are cancelled, reset the state of the button
function ToggleButton:onTouchesCancel(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(false) -- XXX
		event:stopPropagation()
	end
end

-- if state is true show downState else show upState
function ToggleButton:updateVisualState(state)
	self.pressed = state

	-- Modification to allow single state buttons (checkboxes etc)
	if not self.downState then
		if not self:contains(self.upState) then
			self:addChild(self.upState)
		end
		return
	end

	if self.pressed then
		if self:contains(self.upState) then
			self:removeChild(self.upState)
		end
		if not self:contains(self.downState) then
			self:addChild(self.downState)
		end
	else
		if self:contains(self.downState) then
			self:removeChild(self.downState)
		end
		if not self:contains(self.upState) then
			self:addChild(self.upState)
		end
	end
end

function ToggleButton:setPressed(xbool)
	self:updateVisualState(xbool)
end

function ToggleButton:isPressed()
	return self.pressed
end

Template:Welcome!