working on in app editor
This commit is contained in:
+1
-1
Submodule gui updated: 1a6ba8e09b...76abe31426
@@ -71,11 +71,11 @@ end)
|
|||||||
local loadLog = log:child("load")
|
local loadLog = log:child("load")
|
||||||
local old = multi.error
|
local old = multi.error
|
||||||
|
|
||||||
multi.error = function(self, err)
|
-- multi.error = function(self, err)
|
||||||
loadLog:error("Error: %s", err)
|
-- loadLog:error("Error: %s", err)
|
||||||
loadLog:error(debug.traceback())
|
-- loadLog:error(debug.traceback())
|
||||||
love.quit()
|
-- love.quit()
|
||||||
end
|
-- end
|
||||||
|
|
||||||
function readFileData(path)
|
function readFileData(path)
|
||||||
return io.open(path,"r"):read("*a")
|
return io.open(path,"r"):read("*a")
|
||||||
@@ -90,8 +90,358 @@ local picker = THREAD:newFunction(function()
|
|||||||
return nil, "No file selected." .. (err and (" (" .. err .. ")") or "")
|
return nil, "No file selected." .. (err and (" (" .. err .. ")") or "")
|
||||||
end
|
end
|
||||||
end, true)
|
end, true)
|
||||||
|
local nof = gui.noOf
|
||||||
|
function gui:newNumberPicker(x, y, w, h, sx, sy, sw, sh, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
opts.value = opts.value or 0
|
||||||
|
opts.inc = opts.inc or 1
|
||||||
|
opts.decimals = opts.decimals or 0 -- 0 = integers only
|
||||||
|
-- opts.min / opts.max / opts.onChange are optional, leave nil for "no limit"
|
||||||
|
|
||||||
|
local picker = self:newFrame(x, y, w, h, sx, sy, sw, sh)
|
||||||
|
picker:setRoundness(6, 6)
|
||||||
|
picker.active = false
|
||||||
|
|
||||||
|
|
||||||
|
local leftF = picker:newFrame(0, 0, 0, 0, 0, 0, .15, 1)
|
||||||
|
local left = leftF:newTextButton("-", 0, 0, 0, 0, 0, 0, 1, 1)
|
||||||
|
local rightF = picker:newFrame(0, 0, 0, 0, .85, 0, .15, 1)
|
||||||
|
local right = rightF:newTextButton("+", 0, 0, 0, 0, 0, 0, 1, 1)
|
||||||
|
local textbox = picker:newTextBox("", 0, 0, 0, 0, .15, 0, .7, 1)
|
||||||
|
|
||||||
|
textbox.blink = false
|
||||||
|
|
||||||
|
gui.apply({
|
||||||
|
scaleFont = {.45},
|
||||||
|
centerFont = {},
|
||||||
|
run = {function(self)
|
||||||
|
if self.text == "-" or self.text == "+" then
|
||||||
|
self:centerX(true)
|
||||||
|
self:centerY(true) -- also center vertically, not just horizontally
|
||||||
|
end
|
||||||
|
end},
|
||||||
|
align = gui.ALIGN_CENTER,
|
||||||
|
}, textbox, left, right)
|
||||||
|
|
||||||
|
gui.apply({
|
||||||
|
visibility = 0,
|
||||||
|
drawBorder = false, -- flat, no boxy outline around the arrows
|
||||||
|
}, left, right, leftF, rightF)
|
||||||
|
|
||||||
|
-- ---- value handling ----------------------------------------------
|
||||||
|
|
||||||
|
local function clamp(n)
|
||||||
|
if opts.min and n < opts.min then n = opts.min end
|
||||||
|
if opts.max and n > opts.max then n = opts.max end
|
||||||
|
return n
|
||||||
|
end
|
||||||
|
|
||||||
|
local function round(n)
|
||||||
|
if opts.decimals > 0 then
|
||||||
|
local mult = 10 ^ opts.decimals
|
||||||
|
return math.floor(n * mult + 0.5) / mult
|
||||||
|
end
|
||||||
|
return math.floor(n + 0.5)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function format(n)
|
||||||
|
if opts.decimals > 0 then
|
||||||
|
return string.format("%." .. opts.decimals .. "f", n)
|
||||||
|
end
|
||||||
|
return tostring(math.floor(n))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function updateButtons()
|
||||||
|
local canDec = (opts.min == nil) or (opts.value > opts.min)
|
||||||
|
local canInc = (opts.max == nil) or (opts.value < opts.max)
|
||||||
|
left.active, right.active = canDec, canInc
|
||||||
|
left.textColor = canDec and {0, 0, 0, 1} or {.6, .6, .6, 1}
|
||||||
|
right.textColor = canInc and {0, 0, 0, 1} or {.6, .6, .6, 1}
|
||||||
|
end
|
||||||
|
|
||||||
|
function picker:setValue(n, silent)
|
||||||
|
n = round(clamp(n))
|
||||||
|
opts.value = n
|
||||||
|
textbox.text = format(n)
|
||||||
|
textbox.cur_pos = #textbox.text
|
||||||
|
updateButtons()
|
||||||
|
if not silent and opts.onChange then opts.onChange(n) end
|
||||||
|
end
|
||||||
|
|
||||||
|
function picker:getValue()
|
||||||
|
return opts.value
|
||||||
|
end
|
||||||
|
|
||||||
|
picker:setValue(opts.value, true)
|
||||||
|
|
||||||
|
left:OnReleased(function() picker:setValue(opts.value - opts.inc) end)
|
||||||
|
right:OnReleased(function() picker:setValue(opts.value + opts.inc) end)
|
||||||
|
|
||||||
|
textbox:OnWheelMoved(function(_,dx, dy)
|
||||||
|
if dy > 0 then picker:setValue(opts.value + opts.inc)
|
||||||
|
elseif dy < 0 then picker:setValue(opts.value - opts.inc) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- ---- restrict typing to numbers only -------------------------------
|
||||||
|
|
||||||
|
local allowNegative = opts.min == nil or opts.min < 0
|
||||||
|
local allowDecimal = opts.decimals > 0
|
||||||
|
|
||||||
|
local function sanitize(s)
|
||||||
|
local out, seenDot = {}, false
|
||||||
|
for i = 1, #s do
|
||||||
|
local ch = s:sub(i, i)
|
||||||
|
if ch:match("%d") then
|
||||||
|
out[#out + 1] = ch
|
||||||
|
elseif ch == "-" and i == 1 and allowNegative then
|
||||||
|
out[#out + 1] = ch
|
||||||
|
elseif ch == "." and allowDecimal and not seenDot then
|
||||||
|
out[#out + 1] = ch
|
||||||
|
seenDot = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(out)
|
||||||
|
end
|
||||||
|
|
||||||
|
local tiRef = gui.Events.OnTextInputed(function(input)
|
||||||
|
if gui:getObjectFocus() ~= textbox then return end
|
||||||
|
local clean = sanitize(textbox.text)
|
||||||
|
if clean ~= textbox.text then
|
||||||
|
textbox.text = clean
|
||||||
|
textbox.cur_pos = math.min(textbox.cur_pos, #clean)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local kpRef = gui.Events.OnKeyPressed(function(key)
|
||||||
|
if gui:getObjectFocus() ~= textbox then return end
|
||||||
|
if key == "up" then picker:setValue(opts.value + opts.inc)
|
||||||
|
elseif key == "down" then picker:setValue(opts.value - opts.inc) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- re-normalize (round/clamp/reformat) whatever was typed once they
|
||||||
|
-- hit enter or click away, so "3." or "-" don't linger as invalid text
|
||||||
|
local function commit()
|
||||||
|
picker:setValue(tonumber(textbox.text) or opts.value)
|
||||||
|
end
|
||||||
|
textbox:OnReturn(commit)
|
||||||
|
textbox:OnPressedOuter(commit)
|
||||||
|
|
||||||
|
textbox:OnDestroy(function()
|
||||||
|
gui.Events.OnTextInputed:Unconnect(tiRef)
|
||||||
|
gui.Events.OnKeyPressed:Unconnect(kpRef)
|
||||||
|
end)
|
||||||
|
|
||||||
|
return picker
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---- HSV <-> RGB helpers ----
|
||||||
|
local function hsvToRgb(h, s, v)
|
||||||
|
local c = v * s
|
||||||
|
local x = c * (1 - math.abs((h / 60) % 2 - 1))
|
||||||
|
local m = v - c
|
||||||
|
local r, g, b
|
||||||
|
if h < 60 then r, g, b = c, x, 0
|
||||||
|
elseif h < 120 then r, g, b = x, c, 0
|
||||||
|
elseif h < 180 then r, g, b = 0, c, x
|
||||||
|
elseif h < 240 then r, g, b = 0, x, c
|
||||||
|
elseif h < 300 then r, g, b = x, 0, c
|
||||||
|
else r, g, b = c, 0, x end
|
||||||
|
return r + m, g + m, b + m
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rgbToHsv(r, g, b)
|
||||||
|
local max, min = math.max(r, g, b), math.min(r, g, b)
|
||||||
|
local d = max - min
|
||||||
|
local h = 0
|
||||||
|
if d ~= 0 then
|
||||||
|
if max == r then h = ((g - b) / d) % 6
|
||||||
|
elseif max == g then h = (b - r) / d + 2
|
||||||
|
else h = (r - g) / d + 4 end
|
||||||
|
h = h * 60
|
||||||
|
end
|
||||||
|
local s = (max == 0) and 0 or (d / max)
|
||||||
|
return h, s, max
|
||||||
|
end
|
||||||
|
|
||||||
|
local function clampNum(n, lo, hi) return math.max(lo, math.min(hi, n)) end
|
||||||
|
|
||||||
|
local function newCornerGradient(tl, tr, br, bl)
|
||||||
|
return love.graphics.newMesh({
|
||||||
|
{0, 0, 0, 0, tl[1], tl[2], tl[3], tl[4]},
|
||||||
|
{1, 0, 0, 0, tr[1], tr[2], tr[3], tr[4]},
|
||||||
|
{1, 1, 0, 0, br[1], br[2], br[3], br[4]},
|
||||||
|
{0, 1, 0, 0, bl[1], bl[2], bl[3], bl[4]},
|
||||||
|
}, "fan")
|
||||||
|
end
|
||||||
|
|
||||||
|
local _whiteFade, _blackFade
|
||||||
|
local function getFadeImages()
|
||||||
|
if not _whiteFade then
|
||||||
|
-- opaque white on the left fading to transparent on the right
|
||||||
|
_whiteFade = newCornerGradient(
|
||||||
|
{1,1,1,1}, {1,1,1,0}, {1,1,1,0}, {1,1,1,1}
|
||||||
|
)
|
||||||
|
-- transparent at top fading to opaque black at bottom
|
||||||
|
_blackFade = newCornerGradient(
|
||||||
|
{0,0,0,0}, {0,0,0,0}, {0,0,0,1}, {0,0,0,1}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return _whiteFade, _blackFade
|
||||||
|
end
|
||||||
|
|
||||||
|
function gui:newColorPicker(x, y, w, h, sx, sy, sw, sh, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local r0 = (opts.r or 255) / 255
|
||||||
|
local g0 = (opts.g or 0) / 255
|
||||||
|
local b0 = (opts.b or 0) / 255
|
||||||
|
|
||||||
|
local picker = self:newFrame(x, y, w, h, sx, sy, sw, sh)
|
||||||
|
picker.active = false -- container only; don't compete for focus with its children
|
||||||
|
picker.drawBorder = false
|
||||||
|
picker.visibility = 0
|
||||||
|
|
||||||
|
local hue, sat, val = rgbToHsv(r0, g0, b0)
|
||||||
|
local hueR, hueG, hueB = hsvToRgb(hue, 1, 1)
|
||||||
|
|
||||||
|
-- ---- Saturation/Value square ----
|
||||||
|
local svFrame = picker:newFrame(6, 6, -12, -12, 0, 0, .55, 1)
|
||||||
|
svFrame.drawBorder = false
|
||||||
|
svFrame.visibility = 0
|
||||||
|
|
||||||
|
local whiteFade, blackFade = getFadeImages()
|
||||||
|
svFrame.post = function(self)
|
||||||
|
local sx2, sy2, sw2, sh2 = self:getAbsolutes()
|
||||||
|
love.graphics.setColor(hueR, hueG, hueB, 1)
|
||||||
|
love.graphics.rectangle("fill", sx2, sy2, sw2, sh2)
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
love.graphics.draw(whiteFade, sx2, sy2, 0, sw2, sh2)
|
||||||
|
love.graphics.setColor(1, 1, 1, .95)
|
||||||
|
love.graphics.draw(blackFade, sx2, sy2, 0, sw2, sh2)
|
||||||
|
love.graphics.setColor(0, 0, 0, .4)
|
||||||
|
love.graphics.rectangle("line", sx2, sy2, sw2, sh2)
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local svThumb = svFrame:newFrame(0, 0, 0, 0)
|
||||||
|
svThumb:makeCircle(0, 0, 6)
|
||||||
|
svThumb.color = {1, 1, 1}
|
||||||
|
svThumb.borderColor = {0, 0, 0}
|
||||||
|
svThumb.drawBorder = true
|
||||||
|
|
||||||
|
-- ---- Hue strip ----
|
||||||
|
local hueSlider = picker:newFrame(0, 6, 0, -12, .57, 0, .10, 1)
|
||||||
|
-- applyGradient's "horizontal"/"vertical" naming is backwards from what
|
||||||
|
-- you'd expect visually (it names how colors are laid out in the source
|
||||||
|
-- image, not the on-screen direction) -- if this renders sideways for
|
||||||
|
-- you, just flip the string to "vertical".
|
||||||
|
hueSlider:applyGradient("horizontal",
|
||||||
|
{1, 0, 0, 1}, {1, 1, 0, 1}, {0, 1, 0, 1},
|
||||||
|
{0, 1, 1, 1}, {0, 0, 1, 1}, {1, 0, 1, 1}, {1, 0, 0, 1})
|
||||||
|
hueSlider.drawBorder = false
|
||||||
|
|
||||||
|
local hueThumb = hueSlider:newFrame(0, 0, 0, 4, 0, 0, 1, 0)
|
||||||
|
hueThumb.color = {1, 1, 1}
|
||||||
|
hueThumb.borderColor = {0, 0, 0}
|
||||||
|
hueThumb.drawBorder = true
|
||||||
|
|
||||||
|
-- ---- Preview + numeric fields ----
|
||||||
|
local preview = picker:newFrame(6, 6, -12, -6, .70, 0, .30, .20)
|
||||||
|
preview:setRoundness(4, 4)
|
||||||
|
|
||||||
|
local rPicker, gPicker, bPicker
|
||||||
|
|
||||||
|
local function refresh(fireChange)
|
||||||
|
local r, g, b = hsvToRgb(hue, sat, val)
|
||||||
|
hueR, hueG, hueB = hsvToRgb(hue, 1, 1)
|
||||||
|
|
||||||
|
preview.color = {r, g, b}
|
||||||
|
|
||||||
|
local _, _, sw2, sh2 = svFrame:getAbsolutes()
|
||||||
|
svThumb:rawSetDualDim(sat * sw2 - 12, (1 - val) * sh2 - 6)
|
||||||
|
|
||||||
|
local _, _, _, hh2 = hueSlider:getAbsolutes()
|
||||||
|
hueThumb:rawSetDualDim(nil, (hue / 360) * hh2 - 2)
|
||||||
|
|
||||||
|
local r255 = math.floor(r * 255 + .5)
|
||||||
|
local g255 = math.floor(g * 255 + .5)
|
||||||
|
local b255 = math.floor(b * 255 + .5)
|
||||||
|
if rPicker then
|
||||||
|
rPicker:setValue(r255, true)
|
||||||
|
gPicker:setValue(g255, true)
|
||||||
|
bPicker:setValue(b255, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
if fireChange ~= false and opts.onChange then
|
||||||
|
opts.onChange(r255, g255, b255)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function onRGBEdited()
|
||||||
|
local r = rPicker:getValue() / 255
|
||||||
|
local g = gPicker:getValue() / 255
|
||||||
|
local b = bPicker:getValue() / 255
|
||||||
|
hue, sat, val = rgbToHsv(r, g, b)
|
||||||
|
refresh(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
rPicker = picker:newNumberPicker(6, 0, -12, -6, .70, .26, .30, .20,
|
||||||
|
{value = math.floor(r0 * 255 + .5), min = 0, max = 255, onChange = onRGBEdited})
|
||||||
|
gPicker = picker:newNumberPicker(6, 0, -12, -6, .70, .52, .30, .20,
|
||||||
|
{value = math.floor(g0 * 255 + .5), min = 0, max = 255, onChange = onRGBEdited})
|
||||||
|
bPicker = picker:newNumberPicker(6, 0, -12, -6, .70, .78, .30, .20,
|
||||||
|
{value = math.floor(b0 * 255 + .5), min = 0, max = 255, onChange = onRGBEdited})
|
||||||
|
|
||||||
|
gui.apply({
|
||||||
|
scaleFont={.1}
|
||||||
|
},rPicker,gPicker,bPicker)
|
||||||
|
|
||||||
|
-- ---- drag interaction (same press/move/release pattern the built-in
|
||||||
|
-- textbox uses for its own text-selection dragging) ----
|
||||||
|
local function setSV(mx, my)
|
||||||
|
local sx2, sy2, sw2, sh2 = svFrame:getAbsolutes()
|
||||||
|
local lx = clampNum(mx - sx2, 0, sw2)
|
||||||
|
local ly = clampNum(my - sy2, 0, sh2)
|
||||||
|
sat = sw2 > 0 and (lx / sw2) or 0
|
||||||
|
val = sh2 > 0 and (1 - ly / sh2) or 0
|
||||||
|
refresh(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
local svDragging = false
|
||||||
|
svFrame:OnPressed(function(_, mx, my) svDragging = true; setSV(mx, my) end)
|
||||||
|
svFrame:OnMoved(function(_, mx, my) if svDragging then setSV(mx, my) end end)
|
||||||
|
svFrame:OnReleased(function() svDragging = false end)
|
||||||
|
svFrame:OnReleasedOuter(function() svDragging = false end)
|
||||||
|
|
||||||
|
local function setHue(mx, my)
|
||||||
|
local _, sy2, _, sh2 = hueSlider:getAbsolutes()
|
||||||
|
local ly = clampNum(my - sy2, 0, sh2)
|
||||||
|
hue = sh2 > 0 and (ly / sh2) * 360 or 0
|
||||||
|
refresh(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
local hueDragging = false
|
||||||
|
hueSlider:OnPressed(function(_, mx, my) hueDragging = true; setHue(mx, my) end)
|
||||||
|
hueSlider:OnMoved(function(_, mx, my) if hueDragging then setHue(mx, my) end end)
|
||||||
|
hueSlider:OnReleased(function() hueDragging = false end)
|
||||||
|
hueSlider:OnReleasedOuter(function() hueDragging = false end)
|
||||||
|
|
||||||
|
-- ---- public API ----
|
||||||
|
function picker:getColor()
|
||||||
|
local r, g, b = hsvToRgb(hue, sat, val)
|
||||||
|
return math.floor(r * 255 + .5), math.floor(g * 255 + .5), math.floor(b * 255 + .5)
|
||||||
|
end
|
||||||
|
|
||||||
|
function picker:setColor(r255, g255, b255)
|
||||||
|
hue, sat, val = rgbToHsv(r255 / 255, g255 / 255, b255 / 255)
|
||||||
|
refresh(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
refresh(false)
|
||||||
|
return picker
|
||||||
|
end
|
||||||
|
|
||||||
function love.load()
|
function love.load()
|
||||||
|
love.keyboard.setKeyRepeat(true)
|
||||||
-- local z = zip.new()
|
-- local z = zip.new()
|
||||||
-- z:add("main.lua",readFileData("main.lua"))
|
-- z:add("main.lua",readFileData("main.lua"))
|
||||||
-- z:add("package.bat",readFileData("package.bat"))
|
-- z:add("package.bat",readFileData("package.bat"))
|
||||||
@@ -105,6 +455,18 @@ function love.load()
|
|||||||
-- print("File selected",file)
|
-- print("File selected",file)
|
||||||
-- end).OnError(print)
|
-- end).OnError(print)
|
||||||
|
|
||||||
|
-- local numpicker = gui:newNumberPicker(0, 0, 200, 40, .5, .5, 0, 0, {
|
||||||
|
-- value = 1, inc = 1, min = 1, max = 4,
|
||||||
|
-- onChange = function(v) print("value is now", v) end,
|
||||||
|
-- })
|
||||||
|
|
||||||
|
local frame = gui:newFrame(0, 0, 500, 250, .5, .5, 0, 0)
|
||||||
|
local colorpicker = frame:newColorPicker(0, 0, 0, 0, 0, 0, 1, 1, {
|
||||||
|
r = 255, g = 100, b = 50,
|
||||||
|
onChange = function(r, g, b) print("color:", r, g, b) end,
|
||||||
|
})
|
||||||
|
|
||||||
|
--[[ -- bootstrap
|
||||||
loadLog:info("Starting Jeopardy Game")
|
loadLog:info("Starting Jeopardy Game")
|
||||||
loadLog:debug("Setting game identity to jeopardy")
|
loadLog:debug("Setting game identity to jeopardy")
|
||||||
for i,v in ipairs(color.listColors(showAllColors)) do
|
for i,v in ipairs(color.listColors(showAllColors)) do
|
||||||
@@ -129,6 +491,7 @@ function love.load()
|
|||||||
menu.init(bg)
|
menu.init(bg)
|
||||||
loadLog:debug("Displaying title menu")
|
loadLog:debug("Displaying title menu")
|
||||||
title:visible(true)
|
title:visible(true)
|
||||||
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.update(dt)
|
function love.update(dt)
|
||||||
|
|||||||
+44
-15
@@ -9,6 +9,14 @@ local menu = require("gui.core.menus")
|
|||||||
local transition = require("gui.core.transitions")
|
local transition = require("gui.core.transitions")
|
||||||
local logger = require("utils/logger")
|
local logger = require("utils/logger")
|
||||||
|
|
||||||
|
-- Constants
|
||||||
|
local IMAGE = "image"
|
||||||
|
local AUDIO = "audio"
|
||||||
|
local VIDEO = "video"
|
||||||
|
local TEXT = "text"
|
||||||
|
local LIST = "list"
|
||||||
|
local NUMBER = "number"
|
||||||
|
|
||||||
local timesup = love.audio.newSource("assets/sounds/timesup.mp3", "static")
|
local timesup = love.audio.newSource("assets/sounds/timesup.mp3", "static")
|
||||||
local double = love.audio.newSource("assets/sounds/double.mp3", "static")
|
local double = love.audio.newSource("assets/sounds/double.mp3", "static")
|
||||||
|
|
||||||
@@ -174,12 +182,12 @@ function LoadTemplate(name, path)
|
|||||||
ALIGN_LEFT = gui.ALIGN_LEFT,
|
ALIGN_LEFT = gui.ALIGN_LEFT,
|
||||||
ALIGN_RIGHT = gui.ALIGN_RIGHT,
|
ALIGN_RIGHT = gui.ALIGN_RIGHT,
|
||||||
ALIGN_JUSTIFY = gui.ALIGN_JUSTIFY,
|
ALIGN_JUSTIFY = gui.ALIGN_JUSTIFY,
|
||||||
IMAGE = "image",
|
IMAGE = IMAGE,
|
||||||
AUDIO = "audio",
|
AUDIO = AUDIO,
|
||||||
VIDEO = "video",
|
VIDEO = VIDEO,
|
||||||
TEXT = "text",
|
TEXT = TEXT,
|
||||||
LIST = "list",
|
LIST = LIST,
|
||||||
NUMBER = "number",
|
NUMBER = NUMBER,
|
||||||
-- Global vars
|
-- Global vars
|
||||||
color = color,
|
color = color,
|
||||||
error = multi.error,
|
error = multi.error,
|
||||||
@@ -265,13 +273,11 @@ function Menu(frame, path, deb)
|
|||||||
|
|
||||||
local scoreboard = ScoreBoard(frameRef, 0, 0, 0, 0, .06, .1, .170, .8)
|
local scoreboard = ScoreBoard(frameRef, 0, 0, 0, 0, .06, .1, .170, .8)
|
||||||
local properties = Properties(frameRef, 0, 0, 0, 0, .06, .1, .170, .8)
|
local properties = Properties(frameRef, 0, 0, 0, 0, .06, .1, .170, .8)
|
||||||
gui:setHotKey({"lctrl","q"})(function()
|
local function showProperties(b)
|
||||||
scoreboard.leaderboard.visible = not scoreboard.leaderboard.visible
|
properties.visible = b
|
||||||
end)
|
scoreboard.leaderboard.visible = not b
|
||||||
gui:setHotKey({"lctrl","e"})(function()
|
end
|
||||||
properties.visible = not properties.visible
|
showProperties(true)
|
||||||
end)
|
|
||||||
|
|
||||||
local qframe = frameRef:newFrame(0, 0, 0, 0, .24, .1, .70, .8)
|
local qframe = frameRef:newFrame(0, 0, 0, 0, .24, .1, .70, .8)
|
||||||
qframe.visibility = 0
|
qframe.visibility = 0
|
||||||
|
|
||||||
@@ -542,6 +548,7 @@ function Menu(frame, path, deb)
|
|||||||
end
|
end
|
||||||
self.textVisibility = 0
|
self.textVisibility = 0
|
||||||
local template = LoadTemplate(q.template, path)
|
local template = LoadTemplate(q.template, path)
|
||||||
|
if not template then boardLog:fatal("template returned nil. Likely an invalid template format. Did you return?") end
|
||||||
question.visible = true
|
question.visible = true
|
||||||
board.visible = false
|
board.visible = false
|
||||||
-- question.visibility = visibility
|
-- question.visibility = visibility
|
||||||
@@ -569,7 +576,7 @@ function Menu(frame, path, deb)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
local finished = false
|
local finished = false
|
||||||
template.index(question, q, function(ans, m)
|
local params = template.index(question, q, function(ans, m)
|
||||||
local m = m or 1
|
local m = m or 1
|
||||||
if finished then return end
|
if finished then return end
|
||||||
player = GetActivePlayer()
|
player = GetActivePlayer()
|
||||||
@@ -595,6 +602,7 @@ function Menu(frame, path, deb)
|
|||||||
self.text = ""
|
self.text = ""
|
||||||
end)
|
end)
|
||||||
boardUpdater:newThread("QuestionUpdater",function()
|
boardUpdater:newThread("QuestionUpdater",function()
|
||||||
|
if not template.update then return end
|
||||||
while true do
|
while true do
|
||||||
template.update(dt)
|
template.update(dt)
|
||||||
thread.sleep(.1)
|
thread.sleep(.1)
|
||||||
@@ -640,6 +648,9 @@ function love.filedropped(file)
|
|||||||
local data = file:read()
|
local data = file:read()
|
||||||
print("Load file? " .. file:getFilename())
|
print("Load file? " .. file:getFilename())
|
||||||
end
|
end
|
||||||
|
----------------
|
||||||
|
--- Sideboard
|
||||||
|
---
|
||||||
|
|
||||||
local C_BG_PANEL = color.scoreboard_panel_bg
|
local C_BG_PANEL = color.scoreboard_panel_bg
|
||||||
local C_BG_HEADER = color.scoreboard_header_bg
|
local C_BG_HEADER = color.scoreboard_header_bg
|
||||||
@@ -662,10 +673,28 @@ local PLAYER_HEIGHT = .05
|
|||||||
function Properties(frame, x, y, w, h, sx, sy, sw, sh)
|
function Properties(frame, x, y, w, h, sx, sy, sw, sh)
|
||||||
local prop = frame:newFrame(x, y, w, h, sx, sy, sw, sh)
|
local prop = frame:newFrame(x, y, w, h, sx, sy, sw, sh)
|
||||||
prop.color = C_BORDER_NRM
|
prop.color = C_BORDER_NRM
|
||||||
|
local header = prop:newTextLabel("PROPERTIES",0,0,0,0,0,0,1,LEADER_HEIGHT_SCALE)
|
||||||
|
header.borderColor = C_ACCENT
|
||||||
|
header.textColor = C_ACCENT
|
||||||
|
header.color = C_BG_HEADER
|
||||||
|
header.align = gui.ALIGN_CENTER
|
||||||
|
header:scaleFont(.7)
|
||||||
|
header:centerFont()
|
||||||
|
function prop:RenderAttributes(tab)
|
||||||
|
if tab == nil then
|
||||||
|
tab = {}
|
||||||
|
end
|
||||||
|
if not tab.title then -- make the first option
|
||||||
|
boardLog:fatal("Templates must define a title attribute")
|
||||||
|
end
|
||||||
|
if not tab.answer then -- append to the end
|
||||||
|
table.insert(tab,{answer=TEXT,description="The answer for the question"})
|
||||||
|
end
|
||||||
|
end
|
||||||
return prop
|
return prop
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- :newTextLabel(index,0,0,0,0,.015,.1,1/8,.8)
|
||||||
function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh)
|
function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh)
|
||||||
-- Config stuff
|
-- Config stuff
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ local plusLabel
|
|||||||
local function index(window, q, callback)
|
local function index(window, q, callback)
|
||||||
frame = window:newFrame(0,0,0,-200,0,.2,1,.8)
|
frame = window:newFrame(0,0,0,-200,0,.2,1,.8)
|
||||||
frame.visibility = 0
|
frame.visibility = 0
|
||||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
label = window:newTextLabel(q.title,0,0,0,0,0,0,1,.2)
|
||||||
label.align = ALIGN_CENTER
|
label.align = ALIGN_CENTER
|
||||||
label.textColor = color.question_font
|
label.textColor = color.question_font
|
||||||
label.color = color.question_bg
|
label.color = color.question_bg
|
||||||
@@ -46,8 +46,9 @@ local function index(window, q, callback)
|
|||||||
useDefaultHandler(callback)
|
useDefaultHandler(callback)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
{imageA=IMAGE, description="First image to display"},
|
{title=label},
|
||||||
{imageB=IMAGE, description="Second image to display"},
|
{imageA=imageHolder, description="First image to display"},
|
||||||
|
{imageB=imageHolder2, description="Second image to display"},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -87,15 +87,12 @@ local function index(window, q, callback)
|
|||||||
|
|
||||||
-- Return the expected types
|
-- Return the expected types
|
||||||
return {
|
return {
|
||||||
{choices=LIST, description="List of options"}
|
{title=label},
|
||||||
|
{choices=LIST, description="List of options"},
|
||||||
|
{answer=NUMBER, description="Answer to multiple choice as a number"}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function update(dt) -- time in seconds that has passed since
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
index = index,
|
index = index
|
||||||
update = update
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ local imageHolder
|
|||||||
local function index(window, q, callback)
|
local function index(window, q, callback)
|
||||||
frame = window:newFrame(0,0,0,0,0,.2,1,.8)
|
frame = window:newFrame(0,0,0,0,0,.2,1,.8)
|
||||||
frame.visibility = 0
|
frame.visibility = 0
|
||||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
label = window:newTextLabel(q.title,0,0,0,0,0,0,1,.2)
|
||||||
label.align = ALIGN_CENTER
|
label.align = ALIGN_CENTER
|
||||||
label.textColor = color.question_font
|
label.textColor = color.question_font
|
||||||
label.color = color.question_bg
|
label.color = color.question_bg
|
||||||
@@ -32,7 +32,8 @@ local function index(window, q, callback)
|
|||||||
|
|
||||||
-- Return the expected types
|
-- Return the expected types
|
||||||
return {
|
return {
|
||||||
{image=IMGAE, description="Image the question is about"}
|
{title=label},
|
||||||
|
{image=imageHolder, description="Image the question is about"}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,9 @@
|
|||||||
|
|
||||||
callback true/false correct/wrong
|
callback true/false correct/wrong
|
||||||
]]
|
]]
|
||||||
local label
|
|
||||||
|
|
||||||
local function index(window, q, callback)
|
local function index(window, q, callback)
|
||||||
label = window:newTextLabel(q.title)
|
local label = window:newTextLabel(q.title)
|
||||||
label.visibility = 0--q.cosmetics.visibility
|
label.visibility = 0--q.cosmetics.visibility
|
||||||
label.align = ALIGN_CENTER
|
label.align = ALIGN_CENTER
|
||||||
label:fullFrame()
|
label:fullFrame()
|
||||||
@@ -20,13 +19,10 @@ local function index(window, q, callback)
|
|||||||
label.drawBorder = false
|
label.drawBorder = false
|
||||||
|
|
||||||
useDefaultHandler(callback)
|
useDefaultHandler(callback)
|
||||||
end
|
|
||||||
|
|
||||||
local function update(dt) -- time in seconds that has passed since
|
return {title=label}
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
index = index,
|
index = index
|
||||||
update = update
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ local function index(window, q, callback)
|
|||||||
|
|
||||||
-- Return the expected types
|
-- Return the expected types
|
||||||
return {
|
return {
|
||||||
|
{title=label},
|
||||||
{sound=AUDIO, description="Sound that will be played"}
|
{sound=AUDIO, description="Sound that will be played"}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ local function index(window, q, callback)
|
|||||||
callback()
|
callback()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
frame = window:newFrame(0,0,0,-200,0,.2,1,.8)
|
local frame = window:newFrame(0,0,0,-200,0,.2,1,.8)
|
||||||
frame.visibility = 0
|
frame.visibility = 0
|
||||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
||||||
label.align = ALIGN_CENTER
|
label.align = ALIGN_CENTER
|
||||||
@@ -39,6 +39,7 @@ local function index(window, q, callback)
|
|||||||
|
|
||||||
-- Return the expected types
|
-- Return the expected types
|
||||||
return {
|
return {
|
||||||
|
{title=label},
|
||||||
{video=VIDEO, description="Video that will be played"}
|
{video=VIDEO, description="Video that will be played"}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
+6
-15
@@ -6,13 +6,12 @@
|
|||||||
|
|
||||||
callback true/false correct/wrong
|
callback true/false correct/wrong
|
||||||
]]
|
]]
|
||||||
local label
|
|
||||||
local imageHolder
|
local imageHolder
|
||||||
|
|
||||||
local function index(window, q, callback)
|
local function index(window, q, callback)
|
||||||
frame = window:newFrame(0,0,0,0,0,.2,1,.8)
|
local frame = window:newFrame(0,0,0,0,0,.2,1,.8)
|
||||||
frame.visibility = 0
|
frame.visibility = 0
|
||||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
local label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
||||||
label.align = ALIGN_CENTER
|
label.align = ALIGN_CENTER
|
||||||
label.textColor = color.question_font
|
label.textColor = color.question_font
|
||||||
label.color = color.question_bg
|
label.color = color.question_bg
|
||||||
@@ -76,18 +75,10 @@ local function index(window, q, callback)
|
|||||||
|
|
||||||
-- Return the expected types
|
-- Return the expected types
|
||||||
return {
|
return {
|
||||||
{
|
{title=label},
|
||||||
zoom=IMAGE,
|
{zoom=IMAGE,description = "Full zoom in on an image"},
|
||||||
description = "Full zoom in on an image"
|
{minzoom=IMAGE,description = "Minimum zoom before the full image is revealed"},
|
||||||
},
|
{fullimage=IMAGE,description = "Full image to show"}
|
||||||
{
|
|
||||||
minzoom=IMAGE,
|
|
||||||
description = "Minimum zoom before the full image is revealed"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fullimage=IMAGE,
|
|
||||||
description = "Full image to show"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user