Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add Start Menu

  • Loading branch information...
commit c1cf8a56593cf0766b5ed51083757e027758a4bb 1 parent 8007b2d
@TomK32 TomK32 authored
View
32 game.lua
@@ -0,0 +1,32 @@
+
+game = {
+ graphics = {
+ fullscreen = false,
+ mode = { height = love.graphics.getHeight(), width = love.graphics.getWidth() }
+ },
+ fonts = {},
+}
+
+function game:createFonts(offset)
+ self.fonts = {
+ lineHeight = (10 + offset) * 1.7,
+ small = love.graphics.newFont(10 + offset),
+ regular = love.graphics.newFont(14 + offset),
+ large = love.graphics.newFont(24 + offset),
+ very_large = love.graphics.newFont(48 + offset)
+ }
+end
+
+function game:setMode(mode)
+ self.graphics.mode = mode
+ love.graphics.setMode(mode.width, mode.height)
+ if self.graphics.mode.height < 600 then
+ self:createFonts(-2)
+ else
+ self:createFonts(0)
+ end
+end
+
+
+function game:start()
+end
View
15 game_states/game_state.lua
@@ -0,0 +1,15 @@
+
+GameState = class("GameState")
+function GameState:initialize(game, name)
+ self.name = name
+ self.game = game
+end
+
+function GameState:update(dt)
+end
+
+function GameState:draw()
+end
+
+function GameState:keypressed(key)
+end
View
15 game_states/start_menu.lua
@@ -0,0 +1,15 @@
+require 'views/start_menu_view'
+
+StartMenu = class("Menu", GameState)
+
+function StartMenu:initialize()
+ self.view = StartMenuView()
+end
+
+function StartMenu:update(dt)
+ self.view:update(dt)
+end
+
+function StartMenu:draw()
+ self.view:draw()
+end
View
160 lib/quickie/README.md
@@ -0,0 +1,160 @@
+# QUICKIE
+
+Quickie is an [immediate mode gui][IMGUI] library for [L&Ouml;VE][LOVE]. Initial inspiration came from the article [Sol on Immediate Mode GUIs (IMGUI)][Sol]. You should check it out to understand how Quickie works.
+
+
+# Example
+
+ local gui = require "Quickie"
+
+ -- lazy font loading
+ local fonts = setmetatable({}, {__index = function(t,k)
+ local f = love.graphics.newFont(k)
+ rawset(t, k, f)
+ return f
+ end })
+
+ function love.load()
+ love.graphics.setBackgroundColor(17,17,17)
+ love.graphics.setFont(fonts[12])
+
+ -- group defaults
+ gui.group.default.size[1] = 150
+ gui.group.default.size[2] = 25
+ gui.group.default.spacing = 5
+ end
+
+ local menu_open = {
+ main = false,
+ right = false,
+ foo = false,
+ demo = false
+ }
+ local check1 = {checked = false, label = "Checkbox"}
+ local check2 = {checked = false, label = "Another one"}
+ local input = {text = ""}
+ local slider = {value = .5}
+ local slider2d = {value = {.5,.5}}
+ function love.update(dt)
+ gui.group.push{grow = "down", pos = {5,5}}
+ if gui.Button{text = "Menu"} then
+ menu_open.main = not menu_open.main
+ end
+
+ if menu_open.main then
+ gui.group.push{grow = "right"}
+ if gui.Button{text = "Group stacking"} then
+ menu_open.right = not menu_open.right
+ end
+
+ if menu_open.right then
+ gui.group.push{grow = "up"}
+ if gui.Button{text = "Foo"} then
+ menu_open.foo = not menu_open.foo
+ end
+ if menu_open.foo then
+ gui.Button{text = "???"}
+ end
+ gui.group.pop{}
+
+ gui.Button{text = "Bar"}
+ gui.Button{text = "Baz"}
+ end
+ gui.group.pop{}
+
+ if gui.Button{text = "Widget demo"} then
+ menu_open.demo = not menu_open.open
+ end
+
+ end
+ gui.group.pop{}
+
+ if menu_open.demo then
+ gui.group.push{grow = "down", pos = {200, 80}}
+
+ love.graphics.setFont(fonts[20])
+ gui.Label{text = "Widgets"}
+ love.graphics.setFont(fonts[12])
+ gui.group.push{grow = "right"}
+ gui.Button{text = "Button"}
+ gui.Button{text = "Tight Button", size = {"tight"}}
+ gui.Button{text = "Tight² Button", size = {"tight", "tight"}}
+ gui.group.pop{}
+
+ gui.group.push{grow = "right"}
+ gui.Button{text = "", size = {2}}
+ gui.Label{text = "Tight Label", size = {"tight"}}
+ gui.Button{text = "", size = {2}}
+ gui.Label{text = "Center Label", align = "center"}
+ gui.Button{text = "", size = {2}}
+ gui.Label{text = "Another Label"}
+ gui.Button{text = "", size = {2}}
+ gui.group.pop{}
+
+ gui.group.push{grow = "right"}
+ gui.Checkbox{info = check1, size = {"tight"}}
+ gui.Checkbox{info = check2}
+ gui.group.pop{}
+
+ gui.group.push{grow = "right"}
+ gui.Label{text = "Input", size = {70}}
+ gui.Input{info = input, size = {300}}
+ gui.group.pop{}
+
+ gui.group.push{grow = "right"}
+ gui.Label{text = "Slider", size = {70}}
+ gui.Slider{info = slider}
+ gui.Label{text = ("Value: %.2f"):format(slider.value), size = {70}}
+ gui.group.pop{}
+
+ gui.Label{text = "2D Slider", pos = {nil,10}}
+ gui.Slider2D{info = slider2d, size = {250, 250}}
+ gui.Label{text = ("Value: %.2f, %.2f"):format(slider2d.value[1], slider2d.value[2])}
+
+ end
+ end
+
+ function love.draw()
+ gui.core.draw()
+ end
+
+ function love.keypressed(key, code)
+ gui.keyboard.pressed(key, code)
+ end
+
+
+# Documentation
+
+To be done...
+
+
+# License
+
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+[LOVE]: http://love2d.org
+[IMGUI]: http://www.mollyrocket.com/forums/viewforum.php?f=10
+[Sol]: http://sol.gfxile.net/imgui/
View
77 lib/quickie/button.lua
@@ -0,0 +1,77 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+local BASE = (...):match("(.-)[^%.]+$")
+local core = require(BASE .. 'core')
+local group = require(BASE .. 'group')
+local mouse = require(BASE .. 'mouse')
+local keyboard = require(BASE .. 'keyboard')
+
+-- the widget
+-- {text = text, pos = {x, y}, size={w, h}, widgetHit=widgetHit, draw=draw}
+return function(w)
+ assert(type(w) == "table" and w.text, "Invalid argument")
+
+ -- if tight fit requested, compute the size according to text size
+ -- have a 2px margin around the text
+ local tight = w.size and (w.size[1] == 'tight' or w.size[2] == 'tight')
+ if tight then
+ local f = assert(love.graphics.getFont())
+ if w.size[1] == 'tight' then
+ w.size[1] = f:getWidth(w.text) + 4
+ end
+ if w.size[2] == 'tight' then
+ w.size[2] = f:getHeight(w.text) + 4
+ end
+ end
+
+ -- Generate unique identifier for gui state update and querying.
+ local id = core.generateID()
+
+ -- group.getRect determines the position and size of the widget according
+ -- to the currently active group. Both arguments may be omitted.
+ local pos, size = group.getRect(w.pos, w.size)
+
+ -- mouse.updateWidget(id, {x,y}, {w,h}, widgetHit) updates the state for this widget.
+ -- widgetHit may be nil, in which case mouse.widgetHit will be used.
+ -- The widget mouse-state can be:
+ -- hot (mouse over widget),
+ -- active (mouse pressed on widget) or
+ -- normal (mouse not on widget and not pressed on widget).
+ mouse.updateWidget(id, pos, size, w.widgetHit)
+
+ -- keyboard.makeCyclable makes the item focus on tab or whatever binding is
+ -- in place (see core.keyboard.cycle). Cycle order is determied by the
+ -- order you call the widget functions.
+ keyboard.makeCyclable(id)
+
+ -- core.registerDraw(id, drawfunction, drawfunction-arguments...)
+ -- shows widget when core.draw() is called.
+ core.registerDraw(id, w.draw or core.style.Button,
+ w.text, pos[1],pos[2], size[1],size[2])
+
+ return mouse.releasedOn(id) or (keyboard.key == 'return' and keyboard.hasFocus(id))
+end
+
View
68 lib/quickie/checkbox.lua
@@ -0,0 +1,68 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+local BASE = (...):match("(.-)[^%.]+$")
+local core = require(BASE .. 'core')
+local group = require(BASE .. 'group')
+local mouse = require(BASE .. 'mouse')
+local keyboard = require(BASE .. 'keyboard')
+
+-- {info = {checked = status, label = "", algin = "left"}, pos = {x, y}, size={w, h}, widgetHit=widgetHit, draw=draw}
+return function(w)
+ assert(type(w) == "table")
+ w.info.label = w.info.label or ""
+
+ local tight = w.size and (w.size[1] == 'tight' or w.size[2] == 'tight')
+ if tight then
+ local f = assert(love.graphics.getFont())
+ if w.size[1] == 'tight' then
+ w.size[1] = f:getWidth(w.info.label)
+ end
+ if w.size[2] == 'tight' then
+ w.size[2] = f:getHeight(w.info.label)
+ end
+ -- account for the checkbox
+ local bw = math.min(w.size[1] or group.size[1], w.size[2] or group.size[2])
+ w.size[1] = w.size[1] + bw + 4
+ end
+
+ local id = core.generateID()
+ local pos, size = group.getRect(w.pos, w.size)
+
+ mouse.updateWidget(id, pos, size, w.widgetHit)
+ keyboard.makeCyclable(id)
+
+ local checked = w.info.checked
+ local key = keyboard.key
+ if mouse.releasedOn(id) or ((key == 'return' or key == ' ') and keyboard.hasFocus(id)) then
+ w.info.checked = not w.info.checked
+ end
+
+ core.registerDraw(id, w.draw or core.style.Checkbox,
+ w.info.checked, w.info.label, w.info.align or 'left', pos[1], pos[2], size[1], size[2])
+
+ return w.info.checked ~= checked
+end
+
View
134 lib/quickie/core.lua
@@ -0,0 +1,134 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+local BASE = (...):match("(.-)[^%.]+$")
+local group = require(BASE .. 'group')
+local mouse = require(BASE .. 'mouse')
+local keyboard = require(BASE .. 'keyboard')
+
+--
+-- Helper functions
+--
+
+-- evaluates all arguments
+local function strictAnd(...)
+ local n = select("#", ...)
+ local ret = true
+ for i = 1,n do ret = select(i, ...) and ret end
+ return ret
+end
+
+local function strictOr(...)
+ local n = select("#", ...)
+ local ret = false
+ for i = 1,n do ret = select(i, ...) or ret end
+ return ret
+end
+
+-- allow packed nil
+local function save_pack(...)
+ return {n = select('#', ...), ...}
+end
+
+local function save_unpack(t, i)
+ i = i or 1
+ if i >= t.n then return t[i] end
+ return t[i], save_unpack(t, i+1)
+end
+
+--
+-- Widget ID
+--
+local maxid = 0
+local function generateID()
+ maxid = maxid + 1
+ return maxid
+end
+
+--
+-- Drawing / Frame update
+--
+local draw_items = {n = 0}
+local function registerDraw(id, f, ...)
+ assert(type(f) == 'function' or (getmetatable(f) or {}).__call,
+ 'Drawing function is not a callable type!')
+
+ local font = love.graphics.getFont()
+
+ local state = 'normal'
+ if mouse.isHot(id) or keyboard.hasFocus(id) then
+ state = mouse.isActive(id) and 'active' or 'hot'
+ end
+ local rest = save_pack(...)
+ draw_items.n = draw_items.n + 1
+ draw_items[draw_items.n] = function()
+ if font then love.graphics.setFont(font) end
+ f(state, save_unpack(rest))
+ end
+end
+
+-- actually update-and-draw
+local function draw()
+ keyboard.endFrame()
+ mouse.endFrame()
+ group.endFrame()
+
+ -- save graphics state
+ local c = {love.graphics.getColor()}
+ local f = love.graphics.getFont()
+ local lw = love.graphics.getLineWidth()
+ local ls = love.graphics.getLineStyle()
+
+ for i = 1,draw_items.n do draw_items[i]() end
+
+ -- restore graphics state
+ love.graphics.setLine(lw, ls)
+ if f then love.graphics.setFont(f) end
+ love.graphics.setColor(c)
+
+ draw_items.n = 0
+ maxid = 0
+
+ group.beginFrame()
+ mouse.beginFrame()
+ keyboard.beginFrame()
+end
+
+--
+-- The Module
+--
+return {
+ generateID = generateID,
+
+ style = require((...):match("(.-)[^%.]+$") .. 'style-default'),
+ registerDraw = registerDraw,
+ draw = draw,
+
+ strictAnd = strictAnd,
+ strictOr = strictOr,
+ save_pack = save_pack,
+ save_unpack = save_unpack,
+}
View
143 lib/quickie/group.lua
@@ -0,0 +1,143 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+local stack = {n = 0}
+local default = {
+ pos = {0,0},
+ grow = {0,0},
+ spacing = 2,
+ size = {100, 30},
+ upper_left = {0,0},
+ lower_right = {0,0},
+}
+local current = default
+
+local Grow = {
+ none = { 0, 0},
+ up = { 0, -1},
+ down = { 0, 1},
+ left = {-1, 0},
+ right = { 1, 0}
+}
+
+-- {grow = grow, spacing = spacing, size = size, pos = pos}
+local function push(info)
+ local grow = info.grow or "none"
+ local spacing = info.spacing or default.spacing
+
+ local size = {
+ info.size and info.size[1] or current.size[1],
+ info.size and info.size[2] or current.size[2]
+ }
+
+ local pos = {current.pos[1], current.pos[2]}
+ if info.pos then
+ pos[1] = pos[1] + (info.pos[1] or 0)
+ pos[2] = pos[2] + (info.pos[2] or 0)
+ end
+
+ assert(size, "Size neither specified nor derivable from parent group.")
+ assert(pos, "Position neither specified nor derivable from parent group.")
+ grow = assert(Grow[grow], "Invalid grow: " .. tostring(grow))
+
+ current = {
+ pos = pos,
+ grow = grow,
+ size = size,
+ spacing = spacing,
+ upper_left = { math.huge, math.huge},
+ lower_right = {-math.huge, -math.huge},
+ }
+ stack.n = stack.n + 1
+ stack[stack.n] = current
+end
+
+local function advance(pos, size)
+ current.upper_left[1] = math.min(current.upper_left[1], pos[1])
+ current.upper_left[2] = math.min(current.upper_left[2], pos[2])
+ current.lower_right[1] = math.max(current.lower_right[1], pos[1] + size[1])
+ current.lower_right[2] = math.max(current.lower_right[2], pos[2] + size[2])
+
+ if current.grow[1] ~= 0 then
+ current.pos[1] = pos[1] + current.grow[1] * (size[1] + current.spacing)
+ end
+ if current.grow[2] ~= 0 then
+ current.pos[2] = pos[2] + current.grow[2] * (size[2] + current.spacing)
+ end
+ return pos, size
+end
+
+local function getRect(pos, size)
+ pos = {pos and pos[1] or 0, pos and pos[2] or 0}
+ size = {size and size[1] or current.size[1], size and size[2] or current.size[2]}
+
+ -- growing left/up: update current position to account for differnt size
+ if current.grow[1] < 0 and current.size[1] ~= size[1] then
+ current.pos[1] = current.pos[1] + (current.size[1] - size[1])
+ end
+ if current.grow[2] < 0 and current.size[2] ~= size[2] then
+ current.pos[2] = current.pos[2] - (current.size[2] - size[2])
+ end
+
+ pos[1] = pos[1] + current.pos[1]
+ pos[2] = pos[2] + current.pos[2]
+
+ return advance(pos, size)
+end
+
+local function pop()
+ assert(stack.n > 0, "Group stack is empty.")
+ stack.n = stack.n - 1
+ local child = current
+ current = stack[stack.n] or default
+
+ local size = {
+ child.lower_right[1] - math.max(child.upper_left[1], current.pos[1]),
+ child.lower_right[2] - math.max(child.upper_left[2], current.pos[2])
+ }
+ advance(current.pos, size)
+end
+
+local function beginFrame()
+ current = default
+ stack.n = 0
+end
+
+local function endFrame()
+ -- future use?
+end
+
+return setmetatable({
+ push = push,
+ pop = pop,
+ getRect = getRect,
+ advance = advance,
+ beginFrame = beginFrame,
+ endFrame = endFrame,
+ default = default,
+}, {__index = function(_,k)
+ return ({size = current.size, pos = current.pos})[k]
+end})
View
41 lib/quickie/init.lua
@@ -0,0 +1,41 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+local BASE = (...) .. '.'
+assert(not BASE:match('%.init%.$'), "Invalid require path `"..(...).."' (drop the `.init').")
+
+return {
+ core = require(BASE .. 'core'),
+ group = require(BASE .. 'group'),
+ mouse = require(BASE .. 'mouse'),
+ keyboard = require(BASE .. 'keyboard'),
+ Button = require(BASE .. 'button'),
+ Slider = require(BASE .. 'slider'),
+ Slider2D = require(BASE .. 'slider2d'),
+ Label = require(BASE .. 'label'),
+ Input = require(BASE .. 'input'),
+ Checkbox = require(BASE .. 'checkbox')
+}
View
79 lib/quickie/input.lua
@@ -0,0 +1,79 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+local BASE = (...):match("(.-)[^%.]+$")
+local core = require(BASE .. 'core')
+local group = require(BASE .. 'group')
+local mouse = require(BASE .. 'mouse')
+local keyboard = require(BASE .. 'keyboard')
+
+-- {info = {text = "", cursor = text:len()}, pos = {x, y}, size={w, h}, widgetHit=widgetHit, draw=draw}
+return function(w)
+ assert(type(w) == "table" and type(w.info) == "table", "Invalid argument")
+ w.info.text = w.info.text or ""
+ w.info.cursor = math.min(w.info.cursor or w.info.text:len(), w.info.text:len())
+
+ local id = core.generateID()
+ local pos, size = group.getRect(w.pos, w.size)
+ mouse.updateWidget(id, pos, size, w.widgetHit)
+ keyboard.makeCyclable(id)
+ if mouse.isActive(id) then keyboard.setFocus(id) end
+
+ local changed = false
+ if not keyboard.hasFocus(id) then
+ --[[nothing]]
+ -- editing
+ elseif keyboard.key == 'backspace' then
+ w.info.text = w.info.text:sub(1,w.info.cursor-1) .. w.info.text:sub(w.info.cursor+1)
+ w.info.cursor = math.max(0, w.info.cursor-1)
+ changed = true
+ elseif keyboard.key == 'delete' then
+ w.info.text = w.info.text:sub(1,w.info.cursor) .. w.info.text:sub(w.info.cursor+2)
+ w.info.cursor = math.min(w.info.text:len(), w.info.cursor)
+ changed = true
+ -- movement
+ elseif keyboard.key == 'left' then
+ w.info.cursor = math.max(0, w.info.cursor-1)
+ elseif keyboard.key == 'right' then
+ w.info.cursor = math.min(w.info.text:len(), w.info.cursor+1)
+ elseif keyboard.key == 'home' then
+ w.info.cursor = 0
+ elseif keyboard.key == 'end' then
+ w.info.cursor = w.info.text:len()
+ -- info
+ elseif keyboard.code >= 32 and keyboard.code < 127 then
+ local left = w.info.text:sub(1,w.info.cursor)
+ local right = w.info.text:sub(w.info.cursor+1)
+ w.info.text = table.concat{left, string.char(keyboard.code), right}
+ w.info.cursor = w.info.cursor + 1
+ changed = true
+ end
+
+ core.registerDraw(id, w.draw or core.style.Input,
+ w.info.text, w.info.cursor, pos[1],pos[2], size[1],size[2])
+
+ return changed
+end
View
91 lib/quickie/keyboard.lua
@@ -0,0 +1,91 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+local key,code = nil, -1
+local focus, lastwidget
+local NO_WIDGET = {}
+
+local cycle = {
+ -- binding = {key = key, modifier1, modifier2, ...} XXX: modifiers are OR-ed!
+ prev = {key = 'tab', 'lshift', 'rshift'},
+ next = {key = 'tab'},
+}
+
+local function pressed(...) key, code = ... end
+local function setFocus(id) focus = id end
+local function disable() focus = NO_WIDGET end
+local function clearFocus() focus = nil end
+local function hasFocus(id) return id == focus end
+
+local function tryGrab(id)
+ if not focus then
+ setFocus(id)
+ end
+end
+
+local function isBindingDown(bind)
+ local modifiersDown = #bind == 0 or love.keyboard.isDown(unpack(bind))
+ return key == bind.key and modifiersDown
+end
+
+local function makeCyclable(id)
+ tryGrab(id)
+ if hasFocus(id) then
+ if isBindingDown(cycle.prev) then
+ setFocus(lastwidget)
+ key = nil
+ elseif isBindingDown(cycle.next) then
+ setFocus(nil)
+ key = nil
+ end
+ end
+ lastwidget = id
+end
+
+local function beginFrame()
+ -- for future use?
+end
+
+local function endFrame()
+ key, code = nil, -1
+end
+
+return setmetatable({
+ cycle = cycle,
+ pressed = pressed,
+ tryGrab = tryGrab,
+ isBindingDown = isBindingDown,
+ setFocus = setFocus,
+ clearFocus = clearFocus,
+ hasFocus = hasFocus,
+ makeCyclable = makeCyclable,
+
+ disable = disable,
+ enable = clearFocus,
+
+ beginFrame = beginFrame,
+ endFrame = endFrame,
+}, {__index = function(_,k) return ({key = key, code = code})[k] end})
View
61 lib/quickie/label.lua
@@ -0,0 +1,61 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+local BASE = (...):match("(.-)[^%.]+$")
+local core = require(BASE .. 'core')
+local group = require(BASE .. 'group')
+local mouse = require(BASE .. 'mouse')
+local keyboard = require(BASE .. 'keyboard')
+
+-- {text = text, align = align, pos = {x, y}, size={w, h}, widgetHit=widgetHit, draw=draw}
+return function(w)
+ assert(type(w) == "table" and w.text, "Invalid argument")
+ w.align = w.align or 'left'
+
+ local tight = w.size and (w.size[1] == 'tight' or w.size[2] == 'tight')
+ if tight then
+ local f = assert(love.graphics.getFont())
+ if w.size[1] == 'tight' then
+ w.size[1] = f:getWidth(w.text)
+ end
+ if w.size[2] == 'tight' then
+ w.size[2] = f:getHeight(w.text)
+ end
+ end
+
+ local id = core.generateID()
+ local pos, size = group.getRect(w.pos, w.size)
+
+ if keyboard.hasFocus(id) then
+ keyboard.clearFocus()
+ end
+
+ core.registerDraw(id, w.draw or core.style.Label,
+ w.text, w.align, pos[1],pos[2], size[1],size[2])
+
+ return mouse.releasedOn(id)
+end
+
View
102 lib/quickie/mouse.lua
@@ -0,0 +1,102 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+local _M -- holds the module. needed to make widgetHit overridable
+
+local x,y = 0,0
+local down = false
+local hot, active = nil, nil
+local NO_WIDGET = {}
+
+local function widgetHit(mouse, pos, size)
+ return mouse[1] >= pos[1] and mouse[1] <= pos[1] + size[1] and
+ mouse[2] >= pos[2] and mouse[2] <= pos[2] + size[2]
+end
+
+local function setHot(id) hot = id end
+local function setActive(id) active = id end
+local function isHot(id) return id == hot end
+local function isActive(id) return id == active end
+
+local function updateWidget(id, pos, size, hit)
+ hit = hit or _M.widgetHit
+
+ if hit({x,y}, pos, size) then
+ setHot(id)
+ if not active and down then
+ setActive(id)
+ end
+ end
+end
+
+local function releasedOn(id)
+ return not down and isHot(id) and isActive(id)
+end
+
+local function beginFrame()
+ hot = nil
+ x,y = love.mouse.getPosition()
+ down = love.mouse.isDown('l')
+end
+
+local function endFrame()
+ if not down then -- released
+ setActive(nil)
+ elseif not active then -- clicked outside
+ setActive(NO_WIDGET)
+ end
+end
+
+local function disable()
+ --_M.beginFrame = nothing
+ --_M.endFrame = nothing
+ --_M.isHot = isHot,
+ --_M.isActive = isActive,
+ _M.updateWidget = function() end
+end
+
+local function enable()
+ _M.updateWidget = updateWidget
+end
+
+_M = {
+ widgetHit = widgetHit,
+ setHot = setHot,
+ setActive = setActive,
+ isHot = isHot,
+ isActive = isActive,
+ updateWidget = updateWidget,
+ releasedOn = releasedOn,
+
+ beginFrame = beginFrame,
+ endFrame = endFrame,
+
+ disable = disable,
+ enable = enable,
+}
+
+-- metatable provides getters to x, y and down
+return setmetatable(_M, {__index = function(_,k) return ({x = x, y = y, down = down})[k] end})
View
79 lib/quickie/slider.lua
@@ -0,0 +1,79 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+local BASE = (...):match("(.-)[^%.]+$")
+local core = require(BASE .. 'core')
+local group = require(BASE .. 'group')
+local mouse = require(BASE .. 'mouse')
+local keyboard = require(BASE .. 'keyboard')
+
+-- {info = {value = v, min = 0, max = 1, step = (max-min)/20}, vertical = boolean, pos = {x, y}, size={w, h}, widgetHit=widgetHit, draw=draw}
+return function(w)
+ assert(type(w) == 'table' and type(w.info) == "table" and w.info.value, "Invalid argument.")
+ w.info.min = w.info.min or 0
+ w.info.max = w.info.max or math.max(w.info.value, 1)
+ w.info.step = w.info.step or (w.info.max - w.info.min) / 20
+ local fraction = (w.info.value - w.info.min) / (w.info.max - w.info.min)
+
+ local id = core.generateID()
+ local pos, size = group.getRect(w.pos, w.info.size)
+
+ mouse.updateWidget(id, pos, size, w.widgetHit)
+ keyboard.makeCyclable(id)
+
+ -- mouse update
+ local changed = false
+ if mouse.isActive(id) then
+ keyboard.setFocus(id)
+ if w.vertical then
+ fraction = math.min(1, math.max(0, (pos[2] - mouse.y + size[2]) / size[2]))
+ else
+ fraction = math.min(1, math.max(0, (mouse.x - pos[1]) / size[1]))
+ end
+ local v = fraction * (w.info.max - w.info.min) + w.info.min
+ if v ~= w.info.value then
+ w.info.value = v
+ changed = true
+ end
+ end
+
+ -- keyboard update
+ if keyboard.hasFocus(id) then
+ local keys = w.vertical and {'up', 'down'} or {'right', 'left'}
+ if keyboard.key == keys[1] then
+ w.info.value = math.min(w.info.max, w.info.value + w.info.step)
+ changed = true
+ elseif keyboard.key == keys[2] then
+ w.info.value = math.max(w.info.min, w.info.value - w.info.step)
+ changed = true
+ end
+ end
+
+ core.registerDraw(id, w.draw or core.style.Slider,
+ fraction, w.vertical, pos[1],pos[2], size[1],size[2])
+
+ return changed
+end
View
99 lib/quickie/slider2d.lua
@@ -0,0 +1,99 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+local BASE = (...):match("(.-)[^%.]+$")
+local core = require(BASE .. 'core')
+local group = require(BASE .. 'group')
+local mouse = require(BASE .. 'mouse')
+local keyboard = require(BASE .. 'keyboard')
+
+-- {info = {value = {x,y}, min = {0,0}, max = {1,1}, step = (max-min)/20}, pos = {x, y}, size={w, h}, widgetHit=widgetHit, draw=draw}
+return function(w)
+ assert(type(w) == 'table' and type(w.info) == "table" and w.info.value, "Invalid argument.")
+ w.info.min = {
+ w.info.min and w.info.min[1] or 0,
+ w.info.min and w.info.min[2] or 0,
+ }
+ w.info.max = {
+ w.info.max and w.info.max[1] or math.max(1, w.info.value[1]),
+ w.info.max and w.info.max[2] or math.max(1, w.info.value[2]),
+ }
+ w.info.step = {
+ w.info.step and w.info.step[1] or (w.info.max[1] - w.info.min[1]) / 20,
+ w.info.step and w.info.step[2] or (w.info.max[2] - w.info.min[2]) / 20,
+ }
+
+ local fraction = {
+ (w.info.value[1] - w.info.min[1]) / (w.info.max[1] - w.info.min[1]),
+ (w.info.value[2] - w.info.min[2]) / (w.info.max[2] - w.info.min[2]),
+ }
+
+ local id = core.generateID()
+ local pos, size = group.getRect(w.pos, w.size)
+
+ mouse.updateWidget(id, pos, size, w.widgetHit)
+ keyboard.makeCyclable(id)
+
+ -- update value
+ local changed = false
+ if mouse.isActive(id) then
+ keyboard.setFocus(id)
+ fraction = {
+ math.min(1, math.max(0, (mouse.x - pos[1]) / size[1])),
+ math.min(1, math.max(0, (mouse.y - pos[2]) / size[2])),
+ }
+ local v = {
+ fraction[1] * (w.info.max[1] - w.info.min[1]) + w.info.min[1],
+ fraction[2] * (w.info.max[2] - w.info.min[2]) + w.info.min[2],
+ }
+ if v[1] ~= w.info.value[1] or v[2] ~= w.info.value[2] then
+ w.info.value = v
+ changed = true
+ end
+ end
+
+ if keyboard.hasFocus(id) then
+ if keyboard.key == 'down' then
+ w.info.value[2] = math.min(w.info.max[2], w.info.value[2] + w.info.step.y)
+ changed = true
+ elseif keyboard.key == 'up' then
+ w.info.value[2] = math.max(w.info.min[2], w.info.value[2] - w.info.step.y)
+ changed = true
+ end
+ if keyboard.key == 'right' then
+ w.info.value[1] = math.min(w.info.max[1], w.info.value[1] + w.info.step.x)
+ changed = true
+ elseif keyboard.key == 'left' then
+ w.info.value[1] = math.max(w.info.min[1], w.info.value[1] - w.info.step.x)
+ changed = true
+ end
+ end
+
+ core.registerDraw(id, w.draw or core.style.Slider2D,
+ fraction, pos[1],pos[2], size[1],size[2])
+
+ return changed
+end
View
179 lib/quickie/style-default.lua
@@ -0,0 +1,179 @@
+--[[
+Copyright (c) 2012 Matthias Richter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Except as contained in this notice, the name(s) of the above copyright holders
+shall not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+]]--
+
+-- default style
+local color = {
+-- normal = {bg = {180,180,180}, fg = {48,48,48}, border={100,100,100}},
+-- hot = {bg = {215,215,215}, fg = {52,65,160}, border={100,100,100}},
+-- active = {bg = {230,230,230}, fg = {69,84,201}, border={100,100,100}}
+ normal = {bg = {78,78,78}, fg = {200,200,200}, border={20,20,20}},
+ hot = {bg = {98,98,98}, fg = {229,101,84}, border={30,30,30}},
+ active = {bg = {88,88,88}, fg = {149,81,64}, border={10,10,10}}
+}
+
+-- box drawing
+local gradient = {}
+function gradient:set(from, to)
+ local id = love.image.newImageData(1,2)
+ id:setPixel(0,0, to,to/2,to,255)
+ id:setPixel(0,1, from,from/2,from,255)
+ gradient.img = love.graphics.newImage(id)
+ gradient.img:setFilter('linear', 'linear')
+end
+gradient:set(200,255)
+
+local function box(x,y,w,h, bg, border, flip)
+ love.graphics.setLine(1, 'rough')
+
+ love.graphics.setColor(bg)
+ local sy = flip and -h/2 or h/2
+ love.graphics.draw(gradient.img, x,y+h/2, 0,w,sy, 0,1)
+ love.graphics.setColor(border)
+ love.graphics.rectangle('line', x,y,w,h)
+end
+
+-- load default font
+if not love.graphics.getFont() then
+ love.graphics.setFont(love.graphics.newFont(12))
+end
+
+local function Button(state, title, x,y,w,h)
+ local c = color[state]
+ box(x,y,w,h, c.bg, c.border, state == 'active')
+ local f = assert(love.graphics.getFont())
+ x,y = x + (w-f:getWidth(title))/2, y + (h-f:getHeight(title))/2
+ love.graphics.setColor(c.fg)
+ love.graphics.print(title, x,y)
+end
+
+local function Label(state, text, align, x,y,w,h)
+ local c = color[state]
+ love.graphics.setColor(c.fg)
+ local f = assert(love.graphics.getFont())
+ y = y + (h - f:getHeight(text))/2
+ if align == 'center' then
+ x = x + (w - f:getWidth(text))/2
+ elseif align == 'right' then
+ x = x + w - f:getWidth(text)
+ end
+ love.graphics.print(text, x,y)
+end
+
+local function Slider(state, fraction, vertical, x,y,w,h)
+ local c = color[state]
+
+ love.graphics.setLineWidth(2)
+ love.graphics.setColor(c.border)
+ love.graphics.line(x,y+h/2-1,x+w,y+h/2-1)
+ love.graphics.line(x,y+h/2+1,x+w,y+h/2+1)
+ love.graphics.setColor(c.bg)
+ love.graphics.line(x,y+h/2,x+w,y+h/2)
+
+ if vertical then
+ y = math.floor(y + h * fraction - 5)
+ h = 10
+ else
+ x = math.floor(x + w * fraction - 5)
+ w = 10
+ end
+ box(x,y,w,h, c.bg,c.border)
+end
+
+local function Slider2D(state, fraction, x,y,w,h)
+ local c = color[state]
+ box(x,y,w,h, c.bg, c.border)
+
+ -- draw quadrants
+ love.graphics.setLine(1, 'rough')
+ love.graphics.setColor(c.fg[1], c.fg[2], c.fg[3], math.min(127,c.fg[4] or 255))
+ love.graphics.line(x+w/2,y, x+w/2,y+h)
+ love.graphics.line(x,y+h/2, x+w,y+h/2)
+
+ -- draw cursor
+ local xx = math.ceil(x + fraction[1] * w)
+ local yy = math.ceil(y + fraction[2] * h)
+ love.graphics.setColor(c.fg)
+ love.graphics.line(xx-3,yy,xx+2,yy)
+ love.graphics.line(xx,yy-3,xx,yy+2)
+end
+
+local function Input(state, text, cursor, x,y,w,h)
+ local c = color[state]
+ box(x,y,w,h, c.bg, c.border, state ~= 'active')
+
+ local f = love.graphics.getFont()
+ local th = f:getHeight(text)
+ local cursorPos = x + 2 + f:getWidth(text:sub(1,cursor))
+
+ love.graphics.setLine(1, 'rough')
+ love.graphics.setColor(color.normal.fg)
+ love.graphics.print(text, x+2,y+(h-th)/2)
+ love.graphics.setColor(color.active.fg)
+ love.graphics.line(cursorPos, y+4, cursorPos, y+h-4)
+end
+
+local function Checkbox(state, checked, label, align, x,y,w,h)
+ local c = color[state]
+ local bw, bx, by = math.min(w,h)*.7, x, y
+ by = y + (h-bw)/2
+
+ local f = assert(love.graphics.getFont())
+ local tw,th = f:getWidth(label), f:getHeight(label)
+ local tx, ty = x, y + (h-th)/2
+ if align == 'left' then
+ -- [ ] LABEL
+ bx, tx = x, x+bw+4
+ else
+ -- LABEL [ ]
+ tx, bx = x, x+4+tw
+ end
+
+ box(bx,by,bw,bw, c.bg, c.border)
+
+ if checked then
+ bx,by = bx+bw*.25, by+bw*.25
+ bw = bw * .5
+ love.graphics.setColor(color.active.fg)
+ box(bx,by,bw,bw, color.hot.fg, {0,0,0,0}, true)
+ end
+
+ love.graphics.setColor(c.fg)
+ love.graphics.print(label, tx, ty)
+end
+
+
+-- the style
+return {
+ color = color,
+ gradient = gradient,
+
+ Button = Button,
+ Label = Label,
+ Slider = Slider,
+ Slider2D = Slider2D,
+ Input = Input,
+ Checkbox = Checkbox,
+}
View
34 main.lua
@@ -6,39 +6,29 @@
-- (C) 2012-2013 Thomas R. Koll
require 'lib/middleclass'
-
-game = {
- graphics = {
- fullscreen = false,
- mode = { height = love.graphics.getHeight(), width = love.graphics.getWidth() }
- },
- fonts = {},
-}
-
-function game.createFonts(offset)
- return {
- lineHeight = (10 + offset) * 1.7,
- small = love.graphics.newFont(10 + offset),
- regular = love.graphics.newFont(14 + offset),
- large = love.graphics.newFont(24 + offset),
- very_large = love.graphics.newFont(48 + offset)
- }
-end
+require 'game'
+require 'views/view'
+require 'game_states/game_state'
+require 'game_states/start_menu'
function love.load()
- game.fonts = game.createFonts(0)
+ game:createFonts(0)
+ game.current_state = StartMenu()
end
function love.draw()
-
+ if not game.current_state then return end
+ game.current_state:draw()
end
-
function love.keypressed(key)
+ if not game.current_state then return end
+ game.current_state:keypressed(key)
end
function love.update(dt)
-
+ if not game.current_state then return end
+ game.current_state:update(dt)
end
View
61 views/start_menu_view.lua
@@ -0,0 +1,61 @@
+
+gui = require 'lib/quickie'
+
+StartMenuView = class("MenuView", View)
+
+gui.core.style.color.normal.bg = {80,180,80}
+
+function StartMenuView:draw()
+ gui.core.draw()
+ local x = 250
+ local y = 50
+ if game.graphics.mode.width < 800 then
+ x = 130
+ y = 20
+ end
+
+ love.graphics.push()
+ love.graphics.setFont(game.fonts.regular)
+ love.graphics.setColor(255,255,255,200)
+ love.graphics.print('Rogue Beach, CA', x, y)
+ love.graphics.setColor(255,200, 10, 255)
+ love.graphics.print('Rogue Beach, CA', x-1, y-1)
+
+ love.graphics.pop()
+end
+
+function StartMenuView:update(dt)
+ local x = 100
+ local y = 50
+ if game.graphics.mode.width < 800 then
+ x = 10
+ y = 20
+ end
+
+ gui.group.push({grow = "down", pos = {x, y}})
+ -- start the game
+ if gui.Button({text = 'Start'}) then
+ game:start()
+ end
+ gui.group.push({grow = "down", pos = {0, 20}})
+
+ -- fullscreen toggle
+ if game.graphics.mode.fullscreen then
+ text = 'Windowed'
+ else
+ text = 'Fullscreen'
+ end
+ if gui.Button({text = text}) then
+ game.graphics.fullscreen = not game.graphics.fullscreen
+ love.graphics.setMode(love.graphics.getWidth(), love.graphics.getHeight(), game.graphics.fullscreen)
+ end
+
+ -- screen resolutions
+ modes = love.graphics.getModes()
+ table.sort(modes, function(a, b) return a.width*a.height > b.width*b.height end) -- sort from smallest to largest
+ for i, mode in ipairs(modes) do
+ if gui.Button({text = mode.width .. 'x' .. mode.height}) then
+ game:setMode(mode)
+ end
+ end
+end
View
26 views/view.lua
@@ -0,0 +1,26 @@
+
+View = class("View")
+View:include({
+ display = {x = 0, y = 0, width = 200, height = 100},
+ focus = nil,
+
+ draw = function(self, ...)
+ love.graphics.push()
+ love.graphics.translate(self.display.x, self.display.y)
+ self:drawContent(...)
+ love.graphics.pop()
+ end
+})
+
+function View:setDisplay(display)
+ self.display = display
+ if display.align then
+ if display.align.x == 'center' then
+ display.x = love.graphics.getWidth() / 2 - display.width / 2
+ end
+ if display.align.y == 'center' then
+ display.y = love.graphics.getHeight() / 2 - display.height / 2
+ end
+ end
+end
+
Please sign in to comment.
Something went wrong with that request. Please try again.