Last active
September 6, 2015 13:09
-
-
Save HyroVitalyProtago/055093e0ec4f511e8fb6 to your computer and use it in GitHub Desktop.
Btn is a simple and lite button library for Codea
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
automatically created by Required (0.0.28) from HyroVitalyProtago | |
[email protected] | |
https://gist.github.com/7802bd00e7d56d480379 |
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
return (function() | |
local Btn = class() | |
-- todo | |
-- Advanced | |
-- size = "lg" | "sm" | "xs" | "default", | |
-- defined by width | height | width,height | fontSize | width,height,fontSize | |
-- width => fontSize max + height auto | |
-- height => fontSize max + width auto | |
-- width,height => fontSize max | |
-- fontSize => width,height auto | |
-- width,height,fontSize => width,height max, favorite fontSize (if too large => adjusted) | |
local styles = { | |
primary = { | |
background = color(39, 78, 191), | |
fill = color(220), | |
active = { | |
background = color(19, 58, 171) | |
} | |
}, | |
success = { | |
background = color(80, 210, 97), | |
fill = color(220), | |
active = { | |
background = color(60, 190, 77), | |
} | |
}, | |
info = { | |
background = color(79, 175, 208), | |
fill = color(220), | |
active = { | |
background = color(59, 155, 188), | |
} | |
}, | |
warning = { | |
background = color(207, 147, 40), | |
fill = color(220), | |
active = { | |
background = color(187, 127, 20), | |
} | |
}, | |
danger = { | |
background = color(180, 74, 57), | |
fill = color(220), | |
active = { | |
background = color(160, 54, 37), | |
} | |
}, | |
link = { | |
noBackground = true, | |
noStroke = true, | |
fill = color(46, 108, 152), | |
active = { | |
fill = color(6, 48, 92), | |
} | |
} | |
} | |
local default = setmetatable({ | |
mode = CENTER, | |
font = "HelveticaNeue-Light", | |
fontSize = 32, | |
fill = color(20), | |
background = color(220), | |
noBackground = false, | |
stroke = color(20), | |
noStroke = false, | |
strokeWidth = 2, | |
textWrapWidth = 0, | |
active = { | |
background = color(200) | |
}, | |
shape = "rect", | |
x = 0, | |
y = 0, | |
w = 200, | |
h = 50, | |
angle = 0, -- rotation | |
padding = { | |
h = 20, -- horizontal | |
v = 5 -- vertical | |
}, | |
onPress = function(self, touch) end, | |
onRelease = function(self, touch) end | |
}, { | |
__call = function(default,a,k) | |
return a[k] or (a.style and styles[a.style][k]) or (a.inherit and type(_G[k]) == "function" and _G[k]()) or default[k] | |
end | |
}) | |
local shapes = { | |
rect = rect, | |
circle = ellipse | |
} | |
local function backgroundContext(self) | |
stroke(self.stroke) | |
if self.noStroke then noStroke() else strokeWidth(self.strokeWidth) end | |
if self.noBackground then noFill() else fill(self.background) end | |
end | |
local function textContext(self) | |
font(self.font) | |
fontSize(self.fontSize) | |
fill(self.fill) | |
textWrapWidth(self.textWrapWidth) | |
end | |
local function getWidthAndHeightFromFontSize(self) | |
pushStyle() | |
textContext(self) | |
local w, h = textSize(self.text) | |
popStyle() | |
return w, h | |
end | |
local function adaptFontSize(self, valid) -- todo better | |
local w, h | |
local optimalFontSize = 0 | |
repeat | |
pushStyle() | |
self.fontSize = optimalFontSize | |
textContext(self) | |
w, h = textSize(self.text) | |
popStyle() | |
optimalFontSize = optimalFontSize + 1 | |
until not valid(optimalFontSize,w,h) | |
return w,h | |
end | |
local function draw(self) | |
backgroundContext(self) | |
rectMode(CENTER) | |
self.fshape(0, 0, self.w, self.h) | |
textContext(self) | |
text(self.text) | |
end | |
local function texture(s) | |
local t = image(s.w, s.h) | |
setContext(t) | |
pushMatrix() | |
translate(s.w*.5, s.h*.5) | |
pushStyle() | |
draw(s) | |
popStyle() | |
popMatrix() | |
setContext() | |
return t | |
end | |
local function meshBuild(w,h,t) | |
local m = mesh() | |
m:addRect(0,0,w,h) | |
m.texture = t | |
return m | |
end | |
local function decor(o,t) | |
return setmetatable(table.deepcopy(t),{ | |
__index = function(tbl,k) | |
return o[k] | |
end | |
}) | |
end | |
local function convertCoord(x,s) | |
return (math.type(x) == "float" and x*s) or (x < 0 and s-x) or x | |
end | |
function Btn:updateSize(args) | |
local h,v = self.padding.h*2, self.padding.v*2 | |
if args.w or args.h then | |
self.w = args.w or self.w | |
self.h = args.h or self.h | |
local nw, nh = adaptFontSize(self, function(ft,w,h) | |
return w <= (args.w and args.w - h or w) and | |
h <= (args.h and args.h - v or h) and | |
ft <= (args.fontSize or ft) | |
end) | |
self.w = not args.w and nw + h or self.w | |
self.h = not args.h and nh + v or self.h | |
else | |
self.w, self.h = getWidthAndHeightFromFontSize(self) | |
self.w = self.w + h | |
self.h = self.h + v | |
end | |
if self.shape == "circle" then | |
self.w = math.max(self.w, self.h) | |
self.h = self.w | |
end | |
self:updatePos() | |
self:updateMesh() | |
end | |
function Btn:updatePos() | |
self.realX, self.realY = convertCoord(self.x, WIDTH), convertCoord(self.y, HEIGHT) | |
local tmp = vec2(self.w*.5, self.h*.5) | |
self.ct = vec2(self.realX, self.realY) + (self.mode == CORNER and tmp or vec2(0,0)) -- center | |
self.bl = self.ct - tmp -- bottomLeft | |
self.tr = self.ct + tmp -- topRight | |
end | |
function Btn:updateMesh() | |
self.textures = { | |
default = texture(self), | |
active = texture(decor(self, self.active)) | |
} | |
self.mesh = meshBuild(self.w,self.h,self.textures[self.state]) | |
end | |
function Btn:init(txt, args) -- inherit | |
assert(txt and type(txt) == "string", "[Btn] first arg need to be a string") | |
args = args or {} | |
self.text = txt | |
self.state = "default" -- "default" or "active" | |
for k,_ in pairs(default) do | |
self[k] = default(args, k) | |
end | |
self.fshape = shapes[self.shape] or _G[default.shape] -- inherited | |
if self.shape == "circle" then | |
self.inBounds = function(self, p) -- override in bounds for circle | |
return self.ct:dist(vec2(p.x, p.y)) < self.w*.5 | |
end | |
end | |
self:updateSize(args) -- compute size | |
-- automaticaly called by updateSize | |
-- self:updatePos() -- pos: absolute, screen (width, height) | |
-- self:updateMesh() | |
end | |
function Btn:draw() | |
pushMatrix() | |
translate(self.ct.x, self.ct.y) | |
rotate(self.angle) | |
self.mesh:draw() | |
popMatrix() | |
end | |
function Btn:inBounds(p) | |
return p.x >= self.bl.x and p.x <= self.tr.x and p.y >= self.bl.y and p.y <= self.tr.y | |
end | |
function Btn:touched(t) | |
local touch = (vec2(t.x, t.y) - self.ct):rotate(-self.angle) + self.ct | |
if self:inBounds(touch) then | |
if not self:isActive() then self:onIn() end | |
if t.state == BEGAN then | |
self:pressed(touch) | |
elseif t.state == ENDED then | |
self:released(touch) | |
end | |
elseif self:isActive() then | |
self:onOut() | |
end | |
end | |
function Btn:changeState(state) | |
self.state = state | |
self.mesh.texture = self.textures[state] -- update texture | |
end | |
function Btn:clone() | |
return Btn(self.text, {}) -- todo | |
end | |
function Btn:isActive() return self.state == "active" end | |
function Btn:onIn() self:changeState("active") end | |
function Btn:onOut() self:changeState("default") end | |
function Btn:pressed(t) self:onPress(t) end | |
function Btn:released(t) self:onOut() self:onRelease(t) end | |
function Btn:orientationChanged(o) print("orientationChanged", o) end | |
return Btn | |
end) |
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
return (function() | |
local BtnGrp = class() | |
--[[ todo | |
size = "lg" | "sm" | "xs" | "default", | |
mode = CENTER, (UP, LEFT, RIGHT, BOTTOM, ...) | |
background = ..., | |
margin = 5, -- space between buttons | |
]]-- | |
local function convertCoord(x,s) | |
return (math.type(x) == "float" and x*s) or (x < 0 and s-x) or x | |
end | |
function BtnGrp:init(group, args) | |
assert(group and type(group) == "table", "[BtnGrp] first arg need to be a table") | |
args = args or {} | |
self.group = group | |
self.align = args.align or "vertical" | |
self.realX, self.realY = convertCoord(args.x or .5, WIDTH), convertCoord(args.y or .5, HEIGHT) | |
local maxWidth, maxHeight = 0, 0 | |
-- move buttons to the right place | |
local x, y = self.realX, self.realY | |
for _,btn in ipairs(self.group) do | |
maxWidth, maxHeight = math.max(maxWidth, btn.w), math.max(maxHeight, btn.h) | |
btn.x, btn.y = math.floor(x), math.floor(y) -- todo setPos | |
btn:updatePos() | |
x, y = x + (self.align == "horizontal" and btn.w or 0), y + (self.align == "vertical" and btn.h or 0) | |
end | |
-- right size based on bigger size | |
local newSize = { w = maxWidth, h = maxHeight } | |
for _,btn in ipairs(self.group) do | |
btn:updateSize(newSize) -- todo setSize | |
btn:updateMesh() | |
end | |
end | |
function BtnGrp:get(i) end -- todo | |
function BtnGrp:insert(btn) end -- todo | |
function BtnGrp:remove(btn) end -- todo | |
function BtnGrp:draw() | |
for _,btn in ipairs(self.group) do | |
btn:draw() | |
end | |
end | |
function BtnGrp:touched(t) | |
for _,btn in ipairs(self.group) do | |
btn:touched(t) | |
end | |
end | |
function BtnGrp:orientationChanged(o) | |
for _,btn in ipairs(self.group) do | |
btn:orientationChanged(o) | |
end | |
end | |
return BtnGrp | |
end) |
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
-- Btn | |
local btns, map = {} | |
function setup() | |
displayMode(FULLSCREEN) | |
required.path 'Btn' | |
local Btn = required.import 'Btn' | |
local BtnGrp = required.import 'BtnGrp' | |
local grp = {} | |
local styles = {"Default", "Primary", "Success", "Info", "Warning", "Danger", "Link"} | |
for _,v in pairs(styles) do | |
grp[#grp+1] = Btn(v, { | |
style = v ~= "Default" and v:lower() | |
}) | |
end | |
btns[#btns+1] = BtnGrp(grp, { | |
x = .85, | |
y = .3 | |
}) | |
local next_pos = (function(step) | |
local i = step | |
return function() | |
local tmp = i | |
i = i + step | |
return tmp | |
end | |
end) | |
local npl = next_pos(1/4) | |
-- Circle | |
btns[#btns+1] = Btn("GO", { | |
x = .15, | |
y = npl(), | |
shape = "circle", | |
background = color(0), | |
fill = color(220), | |
fontSize = 50, | |
active = { | |
background = color(255), | |
fill = color(0) | |
} | |
}) | |
-- Circle with utf-8 icon | |
btns[#btns+1] = Btn("\u{2654}", { | |
x = .15, | |
y = npl(), | |
shape = "circle", | |
background = color(0), | |
fill = color(220), | |
fontSize = 80, | |
active = { | |
background = color(255), | |
fill = color(0) | |
} | |
}) | |
-- Rect with utf-8 icon | |
btns[#btns+1] = Btn("\u{2663}", { | |
x = .15, | |
y = npl(), | |
fontSize = 80, | |
padding = { h=15, v=7 }, | |
active = { | |
background = color(255), | |
fill = color(0) | |
} | |
}) | |
-- with image | |
--[[ | |
btns[#btns+1] = Btn(readImage("Cargo Bot:Star Filled"), { | |
x = .15, | |
y = npl(), | |
shape = "circle", | |
background = color(0), | |
active = { | |
background = color(255), | |
fill = color(0) | |
} | |
}) | |
]]-- | |
local npl = next_pos(1/6) | |
-- width => fontSize max + height auto | |
btns[#btns+1] = Btn("Fixed width", { | |
x = .5, | |
y = npl(), | |
w = 100 | |
}) | |
-- height => fontSize max + width auto | |
btns[#btns+1] = Btn("Fixed height", { | |
x = .5, | |
y = npl(), | |
h = 75 | |
}) | |
-- width,height => fontSize max | |
btns[#btns+1] = Btn("Fixed width,height", { | |
x = .5, | |
y = npl(), | |
w = 400, | |
h = 50 | |
}) | |
-- fontSize => width,height auto | |
btns[#btns+1] = Btn("Fixed fontSize", { | |
x = .5, | |
y = npl(), | |
fontSize = 64 | |
}) | |
-- width,height,fontSize => width,height max, favorite fontSize (if too large => adjusted) | |
btns[#btns+1] = Btn("Fixed width,height,fontSize", { | |
x = .5, | |
y = npl(), | |
w = 400, | |
h = 80, | |
fontSize = 24 | |
}) | |
end | |
function draw() | |
background(200) | |
for _,v in pairs(btns) do v:draw() end | |
end | |
function touched(t) | |
for _,v in pairs(btns) do v:touched(t) end | |
end | |
function orientationChanged(o) | |
for _,v in pairs(btns) do v:orientationChanged(o) end | |
end |
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
{ | |
"author":"HyroVitalyProtago", | |
"id":"055093e0ec4f511e8fb6", | |
"description":"Btn is a simple and lite button library for Codea", | |
"version":"0.0.4", | |
"codea":"2.3.1", | |
"name":"Btn" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment