Fix #17: Support multiple instances
This commit is contained in:
parent
f77ab8e5e8
commit
aca8a297bb
14 changed files with 385 additions and 244 deletions
15
button.lua
15
button.lua
|
@ -1,9 +1,8 @@
|
|||
-- This file is part of SUIT, copyright (c) 2016 Matthias Richter
|
||||
|
||||
local BASE = (...):match('(.-)[^%.]+$')
|
||||
local core = require(BASE .. 'core')
|
||||
|
||||
return function(text, ...)
|
||||
return function(core, text, ...)
|
||||
local opt, x,y,w,h = core.getOptionsAndSize(...)
|
||||
opt.id = opt.id or text
|
||||
opt.font = opt.font or love.graphics.getFont()
|
||||
|
@ -11,14 +10,14 @@ return function(text, ...)
|
|||
w = w or opt.font:getWidth(text) + 4
|
||||
h = h or opt.font:getHeight() + 4
|
||||
|
||||
core.registerHitbox(opt.id, x,y,w,h)
|
||||
core.registerDraw(core.theme.Button, text, opt, x,y,w,h)
|
||||
opt.state = core:registerHitbox(opt.id, x,y,w,h)
|
||||
core:registerDraw(core.theme.Button, text, opt, x,y,w,h)
|
||||
|
||||
return {
|
||||
id = opt.id,
|
||||
hit = core.mouseReleasedOn(opt.id),
|
||||
hovered = core.isHot(opt.id),
|
||||
entered = core.isHot(opt.id) and not core.wasHot(opt.id),
|
||||
left = not core.isHot(opt.id) and core.wasHot(opt.id)
|
||||
hit = core:mouseReleasedOn(opt.id),
|
||||
hovered = core:isHovered(opt.id),
|
||||
entered = core:isHovered(opt.id) and not core:wasHovered(opt.id),
|
||||
left = not core:isHovered(opt.id) and core:wasHovered(opt.id)
|
||||
}
|
||||
end
|
||||
|
|
15
checkbox.lua
15
checkbox.lua
|
@ -1,9 +1,8 @@
|
|||
-- This file is part of SUIT, copyright (c) 2016 Matthias Richter
|
||||
|
||||
local BASE = (...):match('(.-)[^%.]+$')
|
||||
local core = require(BASE .. 'core')
|
||||
|
||||
return function(checkbox, ...)
|
||||
return function(core, checkbox, ...)
|
||||
local opt, x,y,w,h = core.getOptionsAndSize(...)
|
||||
opt.id = opt.id or checkbox
|
||||
opt.font = opt.font or love.graphics.getFont()
|
||||
|
@ -11,18 +10,18 @@ return function(checkbox, ...)
|
|||
w = w or (opt.font:getWidth(checkbox.text) + opt.font:getHeight() + 4)
|
||||
h = h or opt.font:getHeight() + 4
|
||||
|
||||
core.registerHitbox(opt.id, x,y,w,h)
|
||||
local hit = core.mouseReleasedOn(opt.id)
|
||||
opt.state = core:registerHitbox(opt.id, x,y,w,h)
|
||||
local hit = core:mouseReleasedOn(opt.id)
|
||||
if hit then
|
||||
checkbox.checked = not checkbox.checked
|
||||
end
|
||||
core.registerDraw(core.theme.Checkbox, checkbox, opt, x,y,w,h)
|
||||
core:registerDraw(core.theme.Checkbox, checkbox, opt, x,y,w,h)
|
||||
|
||||
return {
|
||||
id = opt.id,
|
||||
hit = hit,
|
||||
hovered = core.isHot(opt.id),
|
||||
entered = core.isHot(opt.id) and not core.wasHot(opt.id),
|
||||
left = not core.isHot(opt.id) and core.wasHot(opt.id)
|
||||
hovered = core:isHovered(opt.id),
|
||||
entered = core:isHovered(opt.id) and not core:wasHovered(opt.id),
|
||||
left = not core:isHovered(opt.id) and core:wasHovered(opt.id)
|
||||
}
|
||||
end
|
||||
|
|
191
core.lua
191
core.lua
|
@ -1,10 +1,34 @@
|
|||
-- This file is part of SUIT, copyright (c) 2016 Matthias Richter
|
||||
|
||||
local NONE = {}
|
||||
local BASE = (...):match('(.-)[^%.]+$')
|
||||
local theme = require(BASE..'theme')
|
||||
local default_theme = require(BASE..'theme')
|
||||
|
||||
local suit = {}
|
||||
suit.__index = suit
|
||||
|
||||
function suit.new(theme)
|
||||
return setmetatable({
|
||||
-- TODO: deep copy/copy on write? better to let user handle => documentation?
|
||||
theme = theme or default_theme,
|
||||
mouse_x = 0, mouse_y = 0,
|
||||
mouse_button_down = false,
|
||||
|
||||
draw_queue = {n = 0},
|
||||
|
||||
Button = require(BASE.."button"),
|
||||
ImageButton = require(BASE.."imagebutton"),
|
||||
Label = require(BASE.."label"),
|
||||
Checkbox = require(BASE.."checkbox"),
|
||||
Input = require(BASE.."input"),
|
||||
Slider = require(BASE.."slider"),
|
||||
|
||||
layout = require(BASE.."layout").new(),
|
||||
}, suit)
|
||||
end
|
||||
|
||||
-- helper
|
||||
local function getOptionsAndSize(opt, ...)
|
||||
function suit.getOptionsAndSize(opt, ...)
|
||||
if type(opt) == "table" then
|
||||
return opt, ...
|
||||
end
|
||||
|
@ -12,75 +36,83 @@ local function getOptionsAndSize(opt, ...)
|
|||
end
|
||||
|
||||
-- gui state
|
||||
local hot, hot_last, active
|
||||
local NONE = {}
|
||||
|
||||
local function anyHot()
|
||||
return hot ~= nil
|
||||
function suit:anyHovered()
|
||||
return self.hovered ~= nil
|
||||
end
|
||||
|
||||
local function isHot(id)
|
||||
return id == hot
|
||||
function suit:isHovered(id)
|
||||
return id == self.hovered
|
||||
end
|
||||
|
||||
local function wasHot(id)
|
||||
return id == hot_last
|
||||
function suit:wasHovered(id)
|
||||
return id == self.hovered_last
|
||||
end
|
||||
|
||||
local function isActive(id)
|
||||
return id == active
|
||||
function suit:isActive(id)
|
||||
return id == self.active
|
||||
end
|
||||
|
||||
function suit:getStateName(id)
|
||||
if self:isActive(id) then
|
||||
return "active"
|
||||
elseif self:isHovered(id) then
|
||||
return "hovered"
|
||||
end
|
||||
return "normal"
|
||||
end
|
||||
|
||||
-- mouse handling
|
||||
local mouse_x, mouse_y, mouse_button_down = 0,0, false
|
||||
local function mouseInRect(x,y,w,h)
|
||||
return not (mouse_x < x or mouse_y < y or mouse_x > x+w or mouse_y > y+h)
|
||||
function suit:mouseInRect(x,y,w,h)
|
||||
return self.mouse_x >= x and self.mouse_y >= y and
|
||||
self.mouse_x <= x+w and self.mouse_y > y+h
|
||||
end
|
||||
|
||||
local function registerMouseHit(id, ul_x, ul_y, hit)
|
||||
if hit(mouse_x - ul_x, mouse_y - ul_y) then
|
||||
hot = id
|
||||
if active == nil and mouse_button_down then
|
||||
active = id
|
||||
function suit:registerMouseHit(id, ul_x, ul_y, hit)
|
||||
if hit(self.mouse_x - ul_x, self.mouse_y - ul_y) then
|
||||
self.hovered = id
|
||||
if self.active == nil and self.mouse_button_down then
|
||||
self.active = id
|
||||
end
|
||||
end
|
||||
return self:getStateName(id)
|
||||
end
|
||||
|
||||
local function registerHitbox(id, x,y,w,h)
|
||||
return registerMouseHit(id, x,y, function(x,y)
|
||||
function suit:registerHitbox(id, x,y,w,h)
|
||||
return self:registerMouseHit(id, x,y, function(x,y)
|
||||
return x >= 0 and x <= w and y >= 0 and y <= h
|
||||
end)
|
||||
end
|
||||
|
||||
local function mouseReleasedOn(id)
|
||||
return not mouse_button_down and isActive(id) and isHot(id)
|
||||
function suit:mouseReleasedOn(id)
|
||||
return not self.mouse_button_down and self:isActive(id) and self:isHovered(id)
|
||||
end
|
||||
|
||||
local function updateMouse(x, y, button_down)
|
||||
mouse_x, mouse_y, mouse_button_down = x,y, button_down
|
||||
function suit:updateMouse(x, y, button_down)
|
||||
self.mouse_x, self.mouse_y = x,y
|
||||
if button_down ~= nil then
|
||||
self.mouse_button_down = button_down
|
||||
end
|
||||
end
|
||||
|
||||
local function getMousePosition()
|
||||
return mouse_x, mouse_y
|
||||
function suit:getMousePosition()
|
||||
return self.mouse_x, self.mouse_y
|
||||
end
|
||||
|
||||
-- keyboard handling
|
||||
local key_down, textchar, keyboardFocus
|
||||
local function getPressedKey()
|
||||
return key_down, textchar
|
||||
function suit:getPressedKey()
|
||||
return self.key_down, self.textchar
|
||||
end
|
||||
|
||||
local function keypressed(key)
|
||||
key_down = key
|
||||
function suit:keypressed(key)
|
||||
self.key_down = key
|
||||
end
|
||||
|
||||
local function textinput(char)
|
||||
textchar = char
|
||||
function suit:textinput(char)
|
||||
self.textchar = char
|
||||
end
|
||||
|
||||
local function grabKeyboardFocus(id)
|
||||
if isActive(id) then
|
||||
keyboardFocus = id
|
||||
function suit:grabKeyboardFocus(id)
|
||||
if self:isActive(id) then
|
||||
if love.system.getOS() == "Android" or love.system.getOS() == "iOS" then
|
||||
if id == NONE then
|
||||
love.keyboard.setTextInput( false )
|
||||
|
@ -88,81 +120,52 @@ local function grabKeyboardFocus(id)
|
|||
love.keyboard.setTextInput( true )
|
||||
end
|
||||
end
|
||||
self.keyboardFocus = id
|
||||
end
|
||||
return self:hasKeyboardFocus(id)
|
||||
end
|
||||
|
||||
local function hasKeyboardFocus(id)
|
||||
return keyboardFocus == id
|
||||
function suit:hasKeyboardFocus(id)
|
||||
return self.keyboardFocus == id
|
||||
end
|
||||
|
||||
local function keyPressedOn(id, key)
|
||||
return hasKeyboardFocus(id) and key_down == key
|
||||
function suit:keyPressedOn(id, key)
|
||||
return self:hasKeyboardFocus(id) and self.key_down == key
|
||||
end
|
||||
|
||||
-- state update
|
||||
local function enterFrame()
|
||||
hot_last, hot = hot, nil
|
||||
updateMouse(love.mouse.getX(), love.mouse.getY(), love.mouse.isDown(1))
|
||||
key_down, textchar = nil, ""
|
||||
grabKeyboardFocus(NONE)
|
||||
function suit:enterFrame()
|
||||
self.hovered_last, self.hovered = self.hovered, nil
|
||||
self:updateMouse(love.mouse.getX(), love.mouse.getY(), love.mouse.isDown(1))
|
||||
self.key_down, self.textchar = nil, ""
|
||||
self:grabKeyboardFocus(NONE)
|
||||
end
|
||||
|
||||
local function exitFrame()
|
||||
if not mouse_button_down then
|
||||
active = nil
|
||||
elseif active == nil then
|
||||
active = NONE
|
||||
function suit:exitFrame()
|
||||
if not self.mouse_button_down then
|
||||
self.active = nil
|
||||
elseif self.active == nil then
|
||||
self.active = NONE
|
||||
end
|
||||
end
|
||||
|
||||
-- draw
|
||||
local draw_queue = {n = 0}
|
||||
|
||||
local function registerDraw(f, ...)
|
||||
function suit:registerDraw(f, ...)
|
||||
local args = {...}
|
||||
local nargs = select('#', ...)
|
||||
draw_queue.n = draw_queue.n + 1
|
||||
draw_queue[draw_queue.n] = function()
|
||||
self.draw_queue.n = self.draw_queue.n + 1
|
||||
self.draw_queue[self.draw_queue.n] = function()
|
||||
f(unpack(args, 1, nargs))
|
||||
end
|
||||
end
|
||||
|
||||
local function draw()
|
||||
exitFrame()
|
||||
for i = 1,draw_queue.n do
|
||||
draw_queue[i]()
|
||||
function suit:draw()
|
||||
self:exitFrame()
|
||||
for i = 1,self.draw_queue.n do
|
||||
self.draw_queue[i]()
|
||||
end
|
||||
draw_queue.n = 0
|
||||
enterFrame()
|
||||
self.draw_queue.n = 0
|
||||
self:enterFrame()
|
||||
end
|
||||
|
||||
local module = {
|
||||
getOptionsAndSize = getOptionsAndSize,
|
||||
|
||||
anyHot = anyHot,
|
||||
isHot = isHot,
|
||||
wasHot = wasHot,
|
||||
isActive = isActive,
|
||||
|
||||
mouseInRect = mouseInRect,
|
||||
registerHitbox = registerHitbox,
|
||||
registerMouseHit = registerMouseHit,
|
||||
mouseReleasedOn = mouseReleasedOn,
|
||||
updateMouse = updateMouse,
|
||||
getMousePosition = getMousePosition,
|
||||
|
||||
getPressedKey = getPressedKey,
|
||||
keypressed = keypressed,
|
||||
textinput = textinput,
|
||||
grabKeyboardFocus = grabKeyboardFocus,
|
||||
hasKeyboardFocus = hasKeyboardFocus,
|
||||
keyPressedOn = keyPressedOn,
|
||||
|
||||
enterFrame = enterFrame,
|
||||
exitFrame = exitFrame,
|
||||
registerDraw = registerDraw,
|
||||
theme = theme,
|
||||
draw = draw,
|
||||
}
|
||||
theme.core = module
|
||||
return module
|
||||
return suit
|
||||
|
|
|
@ -76,23 +76,23 @@ Clears GUI state when exiting a frame.
|
|||
GUI State
|
||||
^^^^^^^^^
|
||||
|
||||
.. function:: anyHot()
|
||||
.. function:: anyHovered()
|
||||
|
||||
:returns: ``true`` if any widget is in the ``hot`` state.
|
||||
:returns: ``true`` if any widget is hovered by the mouse.
|
||||
|
||||
Checks if any widget is in the hot state
|
||||
Checks if any widget is hovered by the mouse.
|
||||
|
||||
.. function:: isHot(id)
|
||||
.. function:: isHovered(id)
|
||||
|
||||
:param mixed id: Identifier of the widget.
|
||||
:returns: ``true`` if the widget is in the ``hot`` state.
|
||||
:returns: ``true`` if the widget is hovered by the mouse.
|
||||
|
||||
Checks if the widget identified by ``id`` is hovered by the mouse.
|
||||
|
||||
.. function:: wasHot(id)
|
||||
.. function:: wasHovered(id)
|
||||
|
||||
:param mixed id: Identifier of the widget.
|
||||
:returns: ``true`` if the widget was in the ``hot`` state in the last frame.
|
||||
:returns: ``true`` if the widget was in the hovered by the mouse in the last frame.
|
||||
|
||||
Checks if the widget identified by ``id`` was hovered by the mouse in the last frame.
|
||||
|
||||
|
@ -121,7 +121,7 @@ Checks whether the mouse cursor is in the rectangle defined by ``x,y,w,h``.
|
|||
:param function hit: Function to perform the hit test.
|
||||
|
||||
Registers a hit-test defined by the function ``hit`` for the widget identified
|
||||
by ``id``. Sets the widget to ``hot`` if th hit-test returns ``true``. Sets the
|
||||
by ``id``. Sets the widget to ``hovered`` if th hit-test returns ``true``. Sets the
|
||||
widget to ``active`` if the hit-test returns ``true`` and the mouse button is
|
||||
pressed.
|
||||
|
||||
|
@ -186,3 +186,36 @@ Checks whether the widget identified by ``id`` currently has keyboard focus.
|
|||
Checks whether the key ``key`` was pressed while the widget identified by
|
||||
``id`` has keyboard focus.
|
||||
|
||||
|
||||
Instancing
|
||||
----------
|
||||
|
||||
.. function:: new()
|
||||
|
||||
:returns: Separate UI state.
|
||||
|
||||
Create a separate UI and layout state. Everything that happens in the new
|
||||
state will not affect any other state. You can use the new state like the
|
||||
"global" state ``suit``, but call functions with the colon syntax instead of
|
||||
the dot syntax, e.g.::
|
||||
|
||||
function love.load()
|
||||
dress = suit.new()
|
||||
end
|
||||
|
||||
function love.update()
|
||||
dress.layout:reset()
|
||||
dress:Label("Hello, World!", dress.layout:row(200,30))
|
||||
dress:Input(input, dress.layout:row())
|
||||
end
|
||||
|
||||
function love.draw()
|
||||
dress:draw()
|
||||
end
|
||||
|
||||
.. warning::
|
||||
|
||||
Unlike UI and layout state, the theme might be shared with other states.
|
||||
Changes in a shared theme will be shared across all themes.
|
||||
See the :ref:`Instance Theme <instance-theme>` subsection in the
|
||||
:doc:`gettingstarted` guide.
|
||||
|
|
|
@ -93,7 +93,7 @@ draw it in ``love.draw()``::
|
|||
end
|
||||
|
||||
function love.draw()
|
||||
suit.core.draw()
|
||||
suit.draw()
|
||||
end
|
||||
|
||||
This will produce this UI (after clicking the button):
|
||||
|
@ -159,11 +159,11 @@ and ``textinput`` events to SUIT::
|
|||
|
||||
-- forward keyboard events
|
||||
function love.textinput(t)
|
||||
suit.core.textinput(t)
|
||||
suit.textinput(t)
|
||||
end
|
||||
|
||||
function love.keypressed(key)
|
||||
suit.core.keypressed(key)
|
||||
suit.keypressed(key)
|
||||
end
|
||||
|
||||
.. image:: _static/keyboard.gif
|
||||
|
@ -193,33 +193,34 @@ The first example can be written as follows::
|
|||
function love.update(dt)
|
||||
-- put the layout origin at position (100,100)
|
||||
-- cells will grow down and to the right of the origin
|
||||
suit.layout.reset(100,100)
|
||||
-- note the colon syntax
|
||||
suit.layout:reset(100,100)
|
||||
|
||||
-- put 10 extra pixels between cells in each direction
|
||||
suit.layout.padding(10,10)
|
||||
suit.layout:padding(10,10)
|
||||
|
||||
-- construct a cell of size 300x30 px and put the button into it
|
||||
if suit.Button("Hello, World!", suit.layout.row(300,30)).hit then
|
||||
if suit.Button("Hello, World!", suit.layout:row(300,30)).hit then
|
||||
show_message = true
|
||||
end
|
||||
|
||||
-- add another cell below the first cell
|
||||
-- the size of the cell is the same as the first cell
|
||||
if show_message then
|
||||
suit.Label("How are you today?", suit.layout.row())
|
||||
suit.Label("How are you today?", suit.layout:row())
|
||||
end
|
||||
end
|
||||
|
||||
function love.draw()
|
||||
suit.core.draw()
|
||||
suit.draw()
|
||||
end
|
||||
|
||||
.. image:: _static/layout.gif
|
||||
|
||||
At the beginning of each frame, the layout origin (and some internal layout
|
||||
state) has to be reset. You can also define optional padding between cells.
|
||||
Cells are added using ``layout.row(w,h)`` (which puts the new cell below the
|
||||
old cell) and ``layout.col(w,h)`` (which puts the new cell to the right of the
|
||||
Cells are added using ``layout:row(w,h)`` (which puts the new cell below the
|
||||
old cell) and ``layout:col(w,h)`` (which puts the new cell to the right of the
|
||||
old cell). If omitted, the width and height of the new cell are copied from
|
||||
the old cell. There are also special identifiers that calculate the size from
|
||||
the sizes of all cells that were created since the last ``reset()``: ``max``,
|
||||
|
@ -235,31 +236,90 @@ Themeing
|
|||
|
||||
SUIT lets you customize how any widget (except :func:`ImageButton`) is drawn.
|
||||
Each widget (except, :func:`you know <ImageButton>`) is drawn by a function in
|
||||
the table ``suit.core.theme``. Conveniently, the name of the function
|
||||
the table ``suit.theme``. Conveniently, the name of the function
|
||||
responsible for drawing a widget is named after it, so, a button is drawn by
|
||||
the function ``suit.core.theme.Button``. If you want to change how a button is
|
||||
the function ``suit.theme.Button``. If you want to change how a button is
|
||||
drawn, simply overwrite the function. If you want to redecorate completely, it
|
||||
might be easiest to start from scratch and swap the whole table.
|
||||
|
||||
However, if you just don't like the colors, the default theme is open to change.
|
||||
It requires you to change the background (``bg``) and foreground (``fg``) color
|
||||
of three possible widget states: ``normal``, when nothing out of
|
||||
the ordinary happened, ``hover``, when the mouse hovers above a widget, and
|
||||
the ordinary happened, ``hovered``, when the mouse hovers above a widget, and
|
||||
``active``, when the mouse hovers above, and the mouse button is pressed (but
|
||||
not yet released) on the widget. The colors are saved in the table
|
||||
``suit.core.theme.color``. The default color scheme is this::
|
||||
``suit.theme.color``. The default color scheme is this::
|
||||
|
||||
suit.core.theme.color = {
|
||||
normal = {bg = { 66, 66, 66}, fg = {188,188,188}},
|
||||
hover = {bg = { 50,153,187}, fg = {255,255,255}},
|
||||
active = {bg = {255,153, 0}, fg = {225,225,225}}
|
||||
suit.theme.color = {
|
||||
normal = {bg = { 66, 66, 66}, fg = {188,188,188}},
|
||||
hovered = {bg = { 50,153,187}, fg = {255,255,255}},
|
||||
active = {bg = {255,153, 0}, fg = {225,225,225}}
|
||||
}
|
||||
|
||||
You can also do minimally invasive surgery::
|
||||
|
||||
function love.load()
|
||||
suit.core.theme.color.normal.fg = {255,255,255}
|
||||
suit.core.theme.color.hover = {bg = {200,230,255}, fg = {0,0,0}}
|
||||
suit.theme.color.normal.fg = {255,255,255}
|
||||
suit.theme.color.hovered = {bg = {200,230,255}, fg = {0,0,0}}
|
||||
end
|
||||
|
||||
|
||||
GUI Instances
|
||||
-------------
|
||||
|
||||
Sometimes you might feel the need to separate parts of the GUI. Maybe the
|
||||
widgets should have a different theme, maybe certain should always be drawn
|
||||
before or after other UI elements, or maybe you don't want the UI state to
|
||||
"leak" (e.g., from a stacked pause gamestate to the main gamestate).
|
||||
|
||||
For this reason, SUIT allows you to create GUI instances::
|
||||
|
||||
local dress = suit.new()
|
||||
|
||||
The IO and layout state of ``dress`` is totally contained in the instance and
|
||||
does not affect any other instances (including the "global" instance ``suit``).
|
||||
In particular, ``suit.draw()`` will not draw anything from ``dress``. Luckily,
|
||||
you can do that yourself::
|
||||
|
||||
dress:draw()
|
||||
|
||||
Notice that instances require that you use the colon syntax. This is true for
|
||||
every `core <core>` function as well as the widgets. To create a button, for
|
||||
example, you have to write::
|
||||
|
||||
dress:Button("Click?", dress.layout:row())
|
||||
|
||||
.. _instance-theme:
|
||||
|
||||
Instance Theme
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Unlike UI and layout state, themes **are** shared among instances. The reason
|
||||
is that the ``suit.theme`` and ``dress.theme`` are **references**, and point to
|
||||
the same table (unless you make either of them point somewhere else). Usually
|
||||
this is a feature, but please still consider this
|
||||
|
||||
.. warning::
|
||||
|
||||
Changes in a shared theme will be shared across GUI instances.
|
||||
|
||||
If this is an issue---for example because you only want to change the color
|
||||
scheme of an instance---you can either `deep-copy
|
||||
<http://hump.readthedocs.org/en/latest/class.html#class:clone>`_ the theme
|
||||
table or use some metatable magic::
|
||||
|
||||
dress.theme = setmetatable({}, {__index = suit.theme})
|
||||
|
||||
-- NOTE: you have to replace the whole color table. E.g., replacing only
|
||||
-- dress.theme.color.normal will also change suit.theme.color.normal!
|
||||
dress.theme.color = {
|
||||
normal = {bg = {188,188,188}, fg = { 66, 66, 66}},
|
||||
hovered = {bg = {255,255,255}, fg = { 50,153,187}},
|
||||
active = {bg = {255,255,255}, fg = {225,153, 0}}
|
||||
}
|
||||
|
||||
function dress.theme.Label(text, opt, x,y,w,h)
|
||||
-- draw the label in a fancier way
|
||||
end
|
||||
|
||||
.. [1] But it thinks you can handle that.
|
||||
|
|
|
@ -49,7 +49,7 @@ The following code will create this UI:
|
|||
-- generate some assets (below)
|
||||
function love.load()
|
||||
snd = generateClickySound()
|
||||
normal, hover, active = generateImageButton()
|
||||
normal, hovered, active = generateImageButton()
|
||||
smallerFont = love.graphics.newFont(10)
|
||||
end
|
||||
|
||||
|
@ -63,11 +63,11 @@ The following code will create this UI:
|
|||
-- put the layout origin at position (100,100)
|
||||
-- cells will grown down and to the right from this point
|
||||
-- also set cell padding to 20 pixels to the right and to the bottom
|
||||
suit.layout.reset(100,100, 20,20)
|
||||
suit.layout:reset(100,100, 20,20)
|
||||
|
||||
-- put a button at the layout origin
|
||||
-- the cell of the button has a size of 200 by 30 pixels
|
||||
state = suit.Button("Click?", suit.layout.row(200,30))
|
||||
state = suit.Button("Click?", suit.layout:row(200,30))
|
||||
|
||||
-- if the button was entered, play a sound
|
||||
if state.entered then love.audio.play(snd) end
|
||||
|
@ -78,67 +78,67 @@ The following code will create this UI:
|
|||
-- put an input box below the button
|
||||
-- the cell of the input box has the same size as the cell above
|
||||
-- if the input cell is submitted, print the text
|
||||
if suit.Input(input, suit.layout.row()).submitted then
|
||||
if suit.Input(input, suit.layout:row()).submitted then
|
||||
print(input.text)
|
||||
end
|
||||
|
||||
-- put a button below the input box
|
||||
-- the width of the cell will be the same as above, the height will be 40 px
|
||||
if suit.Button("Hover?", suit.layout.row(nil,40)).hovered then
|
||||
if suit.Button("Hover?", suit.layout:row(nil,40)).hovered then
|
||||
-- if the button is hovered, show two other buttons
|
||||
-- this will shift all other ui elements down
|
||||
|
||||
-- put a button below the previous button
|
||||
-- the cell height will be 30 px
|
||||
-- the label of the button will be aligned top left
|
||||
suit.Button("You can see", {align='left', valign='top'}, suit.layout.row(nil,30))
|
||||
suit.Button("You can see", {align='left', valign='top'}, suit.layout:row(nil,30))
|
||||
|
||||
-- put a button below the previous button
|
||||
-- the cell size will be the same as the one above
|
||||
-- the label will be aligned bottom right
|
||||
suit.Button("...but you can't touch!", {align='right', valign='bottom'},
|
||||
suit.layout.row())
|
||||
suit.layout:row())
|
||||
end
|
||||
|
||||
-- put a checkbox below the button
|
||||
-- the size will be the same as above
|
||||
-- (NOTE: height depends on whether "Hover?" is hovered)
|
||||
-- the label "Check?" will be aligned right
|
||||
suit.Checkbox(chk, {align='right'}, suit.layout.row())
|
||||
suit.Checkbox(chk, {align='right'}, suit.layout:row())
|
||||
|
||||
-- put a nested layout
|
||||
-- the size of the cell will be as big as the cell above or as big as the
|
||||
-- nested content, whichever is bigger
|
||||
suit.layout.push(suit.layout.row())
|
||||
suit.layout:push(suit.layout:row())
|
||||
|
||||
-- put a slider in the cell
|
||||
-- the inner cell will be 160 px wide and 20 px high
|
||||
suit.Slider(slider, suit.layout.col(160, 20))
|
||||
suit.Slider(slider, suit.layout:col(160, 20))
|
||||
|
||||
-- put a label that shows the slider value to the right of the slider
|
||||
-- the width of the label will be 40 px
|
||||
suit.Label(("%.02f"):format(slider.value), suit.layout.col(40))
|
||||
suit.Label(("%.02f"):format(slider.value), suit.layout:col(40))
|
||||
|
||||
-- close the nested layout
|
||||
suit.layout.pop()
|
||||
suit.layout:pop()
|
||||
|
||||
-- put an image button below the nested cell
|
||||
-- the size of the cell will be 200 by 100 px,
|
||||
-- but the image may be bigger or smaller
|
||||
-- the button shows the image `normal' when the mouse is outside the image
|
||||
-- or above a transparent pixel
|
||||
-- the button shows the image `hover` if the mouse is above an opaque pixel
|
||||
-- the button shows the image `hovered` if the mouse is above an opaque pixel
|
||||
-- of the image `normal'
|
||||
-- the button shows the image `active` if the mouse is above an opaque pixel
|
||||
-- of the image `normal' and the mouse button is pressed
|
||||
suit.ImageButton(normal, {hover = hover, active = active}, suit.layout.row(200,100))
|
||||
suit.ImageButton(normal, {hovered = hovered, active = active}, suit.layout:row(200,100))
|
||||
|
||||
-- if the checkbox is checked, display a precomputed layout
|
||||
if chk.checked then
|
||||
-- the precomputed layout will be 3 rows below each other
|
||||
-- the origin of the layout will be at (400,100)
|
||||
-- the minimal height of the layout will be 300 px
|
||||
rows = suit.layout.rows{pos = {400,100}, min_height = 300,
|
||||
rows = suit.layout:rows{pos = {400,100}, min_height = 300,
|
||||
{200, 30}, -- the first cell will measure 200 by 30 px
|
||||
{30, 'fill'}, -- the second cell will be 30 px wide and fill the
|
||||
-- remaining vertical space between the other cells
|
||||
|
@ -165,17 +165,17 @@ The following code will create this UI:
|
|||
|
||||
function love.draw()
|
||||
-- draw the gui
|
||||
suit.core.draw()
|
||||
suit.draw()
|
||||
end
|
||||
|
||||
function love.textinput(t)
|
||||
-- forward text input to SUIT
|
||||
suit.core.textinput(t)
|
||||
suit.textinput(t)
|
||||
end
|
||||
|
||||
function love.keypressed(key)
|
||||
-- forward keypressed to SUIT
|
||||
suit.core.keypressed(key)
|
||||
suit.keypressed(key)
|
||||
end
|
||||
|
||||
-- generate assets (see love.load)
|
||||
|
@ -203,11 +203,11 @@ The following code will create this UI:
|
|||
end
|
||||
end
|
||||
|
||||
local normal, hover, active = love.image.newImageData(200,100), love.image.newImageData(200,100), love.image.newImageData(200,100)
|
||||
local normal, hovered, active = love.image.newImageData(200,100), love.image.newImageData(200,100), love.image.newImageData(200,100)
|
||||
normal:mapPixel(metaballs(.48, 188,188,188))
|
||||
hover:mapPixel(metaballs(.46, 50,153,187))
|
||||
hovered:mapPixel(metaballs(.46, 50,153,187))
|
||||
active:mapPixel(metaballs(.43, 255,153,0))
|
||||
return love.graphics.newImage(normal), love.graphics.newImage(hover), love.graphics.newImage(active)
|
||||
return love.graphics.newImage(normal), love.graphics.newImage(hovered), love.graphics.newImage(active)
|
||||
end
|
||||
|
||||
Indices and tables
|
||||
|
|
|
@ -93,9 +93,9 @@ The specification is a table of tables, where each inner table follows the
|
|||
convention of :func:`row` and :func:`col`.
|
||||
The result is a layout definition object that can be used to access the cells.
|
||||
|
||||
There is almost only one reason to do so: You know the area of your layout in
|
||||
advance (say, the screen size), and want certain cells to dynamically fill the
|
||||
available space.
|
||||
There are almost only two reasons to do so: (1) You know the area of your
|
||||
layout in advance (say, the screen size), and want certain cells to dynamically
|
||||
fill the available space; (2) You want to animate the cells.
|
||||
|
||||
.. note::
|
||||
Unlike immediate mode layouts, predefined layouts **can not be nested**.
|
||||
|
@ -139,8 +139,7 @@ define the position (upper left corner) of the layout using the ``pos`` keyword:
|
|||
Layout Definition Objects
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Once constructed, the layout can be executed using a layout definition object
|
||||
in two ways:
|
||||
Once constructed, the cells can be accessed in two ways:
|
||||
|
||||
- Using iterators::
|
||||
|
||||
|
@ -154,6 +153,27 @@ in two ways:
|
|||
suit.Button("Button 3", definition.cell(3))
|
||||
suit.Button("Button 2", definition.cell(2))
|
||||
|
||||
There is actually a third way: Because layout definitions are just tables, you
|
||||
can access the cells directly::
|
||||
|
||||
local cell = definition[1]
|
||||
suit.Button("Button 1", cell[1], cell[2], cell[3], cell[4])
|
||||
-- or suit.Button("Button 1", unpack(cell))
|
||||
|
||||
This is especially useful if you want to animate the cells, for example with a
|
||||
`tween <http://hump.readthedocs.org/en/latest/timer.html#Timer.tween>`_::
|
||||
|
||||
for i,cell in ipairs(definition)
|
||||
local destination = {[2] = cell[2]} -- save cell y position
|
||||
cell[2] = -cell[4] -- move cell just outside of the screen
|
||||
|
||||
-- let the cells fall into the screen one after another
|
||||
timer.after(i / 10, function()
|
||||
timer.tween(0.7, cell, destination, 'bounce')
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
Constructors
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ theme.
|
|||
The argument ``normal`` defines the image of the normal state as well as the
|
||||
area of the widget: The button activates when the mouse is over a pixel with
|
||||
non-zero alpha value.
|
||||
You can provide additional ``hover`` and ``active`` images, but the widget area
|
||||
You can provide additional ``hovered`` and ``active`` images, but the widget area
|
||||
is always computed from the ``normal`` image.
|
||||
|
||||
Note that ``ImageButton`` does not recieve width and height parameters. As
|
||||
|
@ -52,11 +52,11 @@ such, it does not necessarily honor the cell size of a :doc:`layout`.
|
|||
``normal``
|
||||
Image for the normal state of the widget. Defaults to widget payload.
|
||||
|
||||
``hover``
|
||||
Image for the hot state of the widget. Defaults to ``normal`` if omitted.
|
||||
``hovered``
|
||||
Image for the hovered state of the widget. Defaults to ``normal`` if omitted.
|
||||
|
||||
``active``
|
||||
Image for the active state of the widget. Defaults to ``hover`` if omitted.
|
||||
Image for the active state of the widget. Defaults to ``hovered`` if omitted.
|
||||
|
||||
Mutable Widgets
|
||||
---------------
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
-- This file is part of SUIT, copyright (c) 2016 Matthias Richter
|
||||
|
||||
local BASE = (...):match('(.-)[^%.]+$')
|
||||
local core = require(BASE .. 'core')
|
||||
|
||||
return function(normal, ...)
|
||||
return function(core, normal, ...)
|
||||
local opt, x,y = core.getOptionsAndSize(...)
|
||||
opt.normal = normal or opt.normal or opt[1]
|
||||
opt.hover = opt.hover or opt[2] or opt.normal
|
||||
opt.active = opt.active or opt[3] or opt.hover
|
||||
opt.hovered = opt.hovered or opt[2] or opt.normal
|
||||
opt.active = opt.active or opt[3] or opt.hovered
|
||||
assert(opt.normal, "Need at least `normal' state image")
|
||||
opt.id = opt.id or opt.normal
|
||||
|
||||
core.registerMouseHit(opt.id, x,y, function(u,v)
|
||||
opt.state = core:registerMouseHit(opt.id, x,y, function(u,v)
|
||||
local id = opt.normal:getData()
|
||||
assert(id:typeOf("ImageData"), "Can only use uncompressed images")
|
||||
u, v = math.floor(u+.5), math.floor(v+.5)
|
||||
|
@ -23,20 +22,20 @@ return function(normal, ...)
|
|||
end)
|
||||
|
||||
local img = opt.normal
|
||||
if core.isActive(opt.id) then
|
||||
if core:isActive(opt.id) then
|
||||
img = opt.active
|
||||
elseif core.isHot(opt.id) then
|
||||
img = opt.hover
|
||||
elseif core:isHovered(opt.id) then
|
||||
img = opt.hovered
|
||||
end
|
||||
|
||||
core.registerDraw(love.graphics.setColor, 255,255,255)
|
||||
core.registerDraw(love.graphics.draw, img, x,y)
|
||||
core:registerDraw(love.graphics.setColor, 255,255,255)
|
||||
core:registerDraw(love.graphics.draw, img, x,y)
|
||||
|
||||
return {
|
||||
id = opt.id,
|
||||
hit = core.mouseReleasedOn(opt.id),
|
||||
hover = core.isHot(opt.id),
|
||||
entered = core.isHot(opt.id) and not core.wasHot(opt.id),
|
||||
left = not core.isHot(opt.id) and core.wasHot(opt.id)
|
||||
hit = core:mouseReleasedOn(opt.id),
|
||||
hovered = core:isHovered(opt.id),
|
||||
entered = core:isHovered(opt.id) and not core:wasHovered(opt.id),
|
||||
left = not core:isHovered(opt.id) and core:wasHovered(opt.id)
|
||||
}
|
||||
end
|
||||
|
|
66
init.lua
66
init.lua
|
@ -1,14 +1,58 @@
|
|||
-- This file is part of SUIT, copyright (c) 2016 Matthias Richter
|
||||
|
||||
local BASE = (...) .. '.'
|
||||
local BASE = (...) .. "."
|
||||
local suit = require(BASE .. "core")
|
||||
|
||||
return {
|
||||
core = require(BASE .. 'core'),
|
||||
layout = require(BASE .. 'layout'),
|
||||
Button = require(BASE .. 'button'),
|
||||
ImageButton = require(BASE .. 'imagebutton'),
|
||||
Slider = require(BASE .. 'slider'),
|
||||
Label = require(BASE .. 'label'),
|
||||
Input = require(BASE .. 'input'),
|
||||
Checkbox = require(BASE .. 'checkbox')
|
||||
}
|
||||
local instance = suit.new()
|
||||
return setmetatable({
|
||||
new = suit.new,
|
||||
getOptionsAndSize = suit.getOptionsAndSize,
|
||||
|
||||
-- core functions
|
||||
anyHovered = function(...) return instance:anyHovered(...) end,
|
||||
isHovered = function(...) return instance:isHovered(...) end,
|
||||
wasHovered = function(...) return instance:wasHovered(...) end,
|
||||
isActive = function(...) return instance:isActive(...) end,
|
||||
|
||||
mouseInRect = function(...) return instance:mouseInRect(...) end,
|
||||
registerHitbox = function(...) return instance:registerHitbox(...) end,
|
||||
registerMouseHit = function(...) return instance:registerMouseHit(...) end,
|
||||
mouseReleasedOn = function(...) return instance:mouseReleasedOn(...) end,
|
||||
updateMouse = function(...) return instance:updateMouse(...) end,
|
||||
getMousePosition = function(...) return instance:getMousePosition(...) end,
|
||||
|
||||
getPressedKey = function(...) return instance:getPressedKey(...) end,
|
||||
keypressed = function(...) return instance:keypressed(...) end,
|
||||
textinput = function(...) return instance:textinput(...) end,
|
||||
grabKeyboardFocus = function(...) return instance:grabKeyboardFocus(...) end,
|
||||
hasKeyboardFocus = function(...) return instance:hasKeyboardFocus(...) end,
|
||||
keyPressedOn = function(...) return instance:keyPressedOn(...) end,
|
||||
|
||||
enterFrame = function(...) return instance:enterFrame(...) end,
|
||||
exitFrame = function(...) return instance:exitFrame(...) end,
|
||||
registerDraw = function(...) return instance:registerDraw(...) end,
|
||||
draw = function(...) return instance:draw(...) end,
|
||||
|
||||
-- widgets
|
||||
Button = function(...) return instance:Button(...) end,
|
||||
ImageButton = function(...) return instance:ImageButton(...) end,
|
||||
Label = function(...) return instance:Label(...) end,
|
||||
Checkbox = function(...) return instance:Checkbox(...) end,
|
||||
Input = function(...) return instance:Input(...) end,
|
||||
Slider = function(...) return instance:Slider(...) end,
|
||||
|
||||
-- layout
|
||||
layout = instance.layout
|
||||
}, {
|
||||
-- theme
|
||||
__newindex = function(t, k, v)
|
||||
if k == "theme" then
|
||||
instance.theme = v
|
||||
else
|
||||
rawset(t, k, v)
|
||||
end
|
||||
end,
|
||||
__index = function(t, k)
|
||||
return k == "theme" and instance.theme or rawget(t, k)
|
||||
end,
|
||||
})
|
||||
|
|
23
input.lua
23
input.lua
|
@ -1,7 +1,6 @@
|
|||
-- This file is part of SUIT, copyright (c) 2016 Matthias Richter
|
||||
|
||||
local BASE = (...):match('(.-)[^%.]+$')
|
||||
local core = require(BASE .. 'core')
|
||||
local utf8 = require 'utf8'
|
||||
|
||||
local function split(str, pos)
|
||||
|
@ -9,7 +8,7 @@ local function split(str, pos)
|
|||
return str:sub(1, offset-1), str:sub(offset)
|
||||
end
|
||||
|
||||
return function(input, ...)
|
||||
return function(core, input, ...)
|
||||
local font = love.graphics.getFont()
|
||||
local opt, x,y,w,h = core.getOptionsAndSize(...)
|
||||
opt.id = opt.id or input
|
||||
|
@ -26,13 +25,11 @@ return function(input, ...)
|
|||
-- ...
|
||||
-- position 6: hello|
|
||||
|
||||
core.registerHitbox(opt.id, x,y,w,h)
|
||||
|
||||
core.grabKeyboardFocus(opt.id)
|
||||
opt.hasKeyboardFocus = core.hasKeyboardFocus(opt.id)
|
||||
opt.state = core:registerHitbox(opt.id, x,y,w,h)
|
||||
opt.hasKeyboardFocus = core:grabKeyboardFocus(opt.id)
|
||||
|
||||
if opt.hasKeyboardFocus then
|
||||
local keycode,char = core.getPressedKey()
|
||||
local keycode,char = core:getPressedKey()
|
||||
-- text input
|
||||
if char ~= "" then
|
||||
local a,b = split(input.text, input.cursor)
|
||||
|
@ -66,14 +63,14 @@ return function(input, ...)
|
|||
-- TODO
|
||||
end
|
||||
|
||||
core.registerDraw(core.theme.Input, input, opt, x,y,w,h)
|
||||
core:registerDraw(core.theme.Input, input, opt, x,y,w,h)
|
||||
|
||||
return {
|
||||
id = opt.id,
|
||||
hit = core.mouseReleasedOn(opt.id),
|
||||
submitted = core.keyPressedOn(opt.id, "return"),
|
||||
hovered = core.isHot(opt.id),
|
||||
entered = core.isHot(opt.id) and not core.wasHot(opt.id),
|
||||
left = not core.isHot(opt.id) and core.wasHot(opt.id)
|
||||
hit = core:mouseReleasedOn(opt.id),
|
||||
submitted = core:keyPressedOn(opt.id, "return"),
|
||||
hovered = core:isHovered(opt.id),
|
||||
entered = core:isHovered(opt.id) and not core:wasHovered(opt.id),
|
||||
left = not core:isHovered(opt.id) and core:wasHovered(opt.id)
|
||||
}
|
||||
end
|
||||
|
|
15
label.lua
15
label.lua
|
@ -1,9 +1,8 @@
|
|||
-- This file is part of SUIT, copyright (c) 2016 Matthias Richter
|
||||
|
||||
local BASE = (...):match('(.-)[^%.]+$')
|
||||
local core = require(BASE .. 'core')
|
||||
|
||||
return function(text, ...)
|
||||
return function(core, text, ...)
|
||||
local opt, x,y,w,h = core.getOptionsAndSize(...)
|
||||
opt.id = opt.id or text
|
||||
opt.font = opt.font or love.graphics.getFont()
|
||||
|
@ -11,14 +10,14 @@ return function(text, ...)
|
|||
w = w or opt.font:getWidth(text) + 4
|
||||
h = h or opt.font:getHeight() + 4
|
||||
|
||||
core.registerHitbox(opt.id, x,y,w,h)
|
||||
core.registerDraw(core.theme.Label, text, opt, x,y,w,h)
|
||||
opt.state = core:registerHitbox(opt.id, x,y,w,h)
|
||||
core:registerDraw(core.theme.Label, text, opt, x,y,w,h)
|
||||
|
||||
return {
|
||||
id = opt.id,
|
||||
hit = core.mouseReleasedOn(opt.id),
|
||||
hovered = core.isHot(opt.id),
|
||||
entered = core.isHot(opt.id) and not core.wasHot(opt.id),
|
||||
left = not core.isHot(opt.id) and core.wasHot(opt.id)
|
||||
hit = core:mouseReleasedOn(opt.id),
|
||||
hovered = core:isHovered(opt.id),
|
||||
entered = core:isHovered(opt.id) and not core:wasHovered(opt.id),
|
||||
left = not core:isHovered(opt.id) and core:wasHovered(opt.id)
|
||||
}
|
||||
end
|
||||
|
|
23
slider.lua
23
slider.lua
|
@ -1,9 +1,8 @@
|
|||
-- This file is part of SUIT, copyright (c) 2016 Matthias Richter
|
||||
|
||||
local BASE = (...):match('(.-)[^%.]+$')
|
||||
local core = require(BASE .. 'core')
|
||||
|
||||
return function(info, ...)
|
||||
return function(core, info, ...)
|
||||
local opt, x,y,w,h = core.getOptionsAndSize(...)
|
||||
|
||||
opt.id = opt.id or info
|
||||
|
@ -14,11 +13,11 @@ return function(info, ...)
|
|||
local fraction = (info.value - info.min) / (info.max - info.min)
|
||||
local value_changed = false
|
||||
|
||||
core.registerHitbox(opt.id, x,y,w,h)
|
||||
opt.state = core:registerHitbox(opt.id, x,y,w,h)
|
||||
|
||||
if core.isActive(opt.id) then
|
||||
if core:isActive(opt.id) then
|
||||
-- mouse update
|
||||
local mx,my = core.getMousePosition()
|
||||
local mx,my = core:getMousePosition()
|
||||
if opt.vertical then
|
||||
fraction = math.min(1, math.max(0, (y+h - my) / h))
|
||||
else
|
||||
|
@ -33,23 +32,23 @@ return function(info, ...)
|
|||
-- keyboard update
|
||||
local key_up = opt.vertical and 'up' or 'right'
|
||||
local key_down = opt.vertical and 'down' or 'left'
|
||||
if core.getPressedKey() == key_up then
|
||||
if core:getPressedKey() == key_up then
|
||||
info.value = math.min(info.max, info.value + info.step)
|
||||
value_changed = true
|
||||
elseif core.getPressedKey() == key_down then
|
||||
elseif core:getPressedKey() == key_down then
|
||||
info.value = math.max(info.min, info.value - info.step)
|
||||
value_changed = true
|
||||
end
|
||||
end
|
||||
|
||||
core.registerDraw(core.theme.Slider, fraction, opt, x,y,w,h)
|
||||
core:registerDraw(core.theme.Slider, fraction, opt, x,y,w,h)
|
||||
|
||||
return {
|
||||
id = opt.id,
|
||||
hit = core.mouseReleasedOn(opt.id),
|
||||
hit = core:mouseReleasedOn(opt.id),
|
||||
changed = value_changed,
|
||||
hovered = core.isHot(opt.id),
|
||||
entered = core.isHot(opt.id) and not core.wasHot(opt.id),
|
||||
left = not core.isHot(opt.id) and core.wasHot(opt.id)
|
||||
hovered = core:isHovered(opt.id),
|
||||
entered = core:isHovered(opt.id) and not core:wasHovered(opt.id),
|
||||
left = not core:isHovered(opt.id) and core:wasHovered(opt.id)
|
||||
}
|
||||
end
|
||||
|
|
25
theme.lua
25
theme.lua
|
@ -6,26 +6,16 @@ local theme = {}
|
|||
theme.cornerRadius = 4
|
||||
|
||||
theme.color = {
|
||||
normal = {bg = { 66, 66, 66}, fg = {188,188,188}},
|
||||
hover = {bg = { 50,153,187}, fg = {255,255,255}},
|
||||
active = {bg = {255,153, 0}, fg = {225,225,225}}
|
||||
normal = {bg = { 66, 66, 66}, fg = {188,188,188}},
|
||||
hovered = {bg = { 50,153,187}, fg = {255,255,255}},
|
||||
active = {bg = {255,153, 0}, fg = {225,225,225}}
|
||||
}
|
||||
|
||||
|
||||
-- HELPER
|
||||
function theme.getStateName(id)
|
||||
if theme.core.isActive(id) then
|
||||
return 'active'
|
||||
end
|
||||
if theme.core.isHot(id) then
|
||||
return 'hover'
|
||||
end
|
||||
return 'normal'
|
||||
end
|
||||
|
||||
function theme.getColorForState(opt)
|
||||
local s = theme.getStateName(opt.id)
|
||||
return (opt.color and opt.color[s]) or theme.color[s]
|
||||
local s = opt.state or "normal"
|
||||
return (opt.color and opt.color[opt.state]) or theme.color[s]
|
||||
end
|
||||
|
||||
function theme.drawBox(x,y,w,h, colors)
|
||||
|
@ -96,10 +86,9 @@ function theme.Slider(fraction, opt, x,y,w,h)
|
|||
|
||||
local c = theme.getColorForState(opt)
|
||||
theme.drawBox(x,y,w,h, c)
|
||||
love.graphics.setColor(c.fg)
|
||||
love.graphics.rectangle('fill', x,yb,wb,hb, theme.cornerRadius)
|
||||
theme.drawBox(x,yb,wb,hb, {bg=c.fg})
|
||||
|
||||
if theme.getStateName(opt.id) ~= "normal" then
|
||||
if opt.state ~= nil and opt.state ~= "normal" then
|
||||
love.graphics.setColor((opt.color and opt.color.active or {}).fg or theme.color.active.fg)
|
||||
if opt.vertical then
|
||||
love.graphics.circle('fill', x+wb/2, yb, r)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue