working on game
This commit is contained in:
parent
2d74ca0745
commit
3f1d83f790
|
Before Width: | Height: | Size: 961 KiB After Width: | Height: | Size: 961 KiB |
BIN
anime/assets/zanarkand.mp3
Normal file
BIN
anime/assets/zanarkand.mp3
Normal file
Binary file not shown.
@ -9,7 +9,7 @@ settings:
|
||||
categories: # the name of each category should correspond to a yaml file with the same name
|
||||
- name: shounen # name must be alphanumeric, cannot start with a number or contain special characters "-" and "." are ok if they are not at the beginning
|
||||
displayName: "Shounen" # if blank will use name
|
||||
image: "assets/14018-3193093789.gif" # if set will display image instead of name, categories are referenced by name which is required
|
||||
image: "anime/assets/14018-3193093789.gif" # if set will display image instead of name, categories are referenced by name which is required
|
||||
- name: openings
|
||||
displayName: "Openings" # if blank will use name
|
||||
- name: sadness
|
||||
|
||||
@ -25,4 +25,11 @@ questions: # expects a list equal to the tier
|
||||
time-limit: 10 # If omitted there is no time limit
|
||||
answer: "Katsuhiro Otomo"
|
||||
template: "whatis" # template to use
|
||||
display-answer: true # displays the correct answer before returning to the main screen
|
||||
- title: "What is this?"
|
||||
answer: "Bunny shit"
|
||||
video: "anime/assets/bunny.ogv"
|
||||
start: 4
|
||||
playFor: 3
|
||||
template: "whatvideo" # template to use
|
||||
display-answer: true # displays the correct answer before returning to the main screen
|
||||
BIN
assets/speaker.png
Normal file
BIN
assets/speaker.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 123 KiB |
@ -269,7 +269,9 @@ function LoadTemplate(name, path)
|
||||
error = multi.error,
|
||||
theme = theme,
|
||||
gui = gui,
|
||||
timer = timer
|
||||
timer = timer,
|
||||
-- love stuff
|
||||
newSource = love.audio.newSource
|
||||
}
|
||||
|
||||
env._G = env
|
||||
|
||||
@ -3,24 +3,34 @@ local theme = require("gui.core.theme")
|
||||
local color = require("gui.core.color")
|
||||
local multi, thread = require("multi"):init()
|
||||
local mediaProc = gui:newProcessor()
|
||||
local miscProc = gui:newProcessor()
|
||||
|
||||
local function noOf(sx,sy,sw,sh)
|
||||
return nil,nil,nil,nil,sx,sy,sw,sh
|
||||
end
|
||||
|
||||
function gui:newVideoPlayer(source, x, y, w, h, sx, sy, sw, sh)
|
||||
local window = gui:newWindow(x, y, w, h, source, true, theme:new({
|
||||
function gui:newVideoPlayer(source, x, y, w, h, sx, sy, sw, sh, draggable, th)
|
||||
local window = self:newWindow(x, y, w, h, sx, sy, sw, sh, "", draggable, th or theme:new({
|
||||
primary = "#000000",
|
||||
primaryDark = "#10465c",
|
||||
primaryText = "#ffffff"
|
||||
}))
|
||||
local video = window:newVideo(source, 0, 0, 0, 0, 0, .05, 1, .75)
|
||||
local play_pause = window:newImageButton("gui/assets/play.png",0,0,0,0,.45,.82,0,.175)
|
||||
local seek = window:newFrame(0,0,0,0,0,.8,1,.015)
|
||||
seek.color = color.new("#3c434c")
|
||||
local seeker = seek:newFrame(0,0,0,0,0,.1,0,.8)
|
||||
seeker.drawBorder = false
|
||||
seeker.color = color.new("#0c278a")
|
||||
local length = video:getDuration()
|
||||
local play_pause = window:newImageButton("gui/assets/play.png",0,0,0,0,.45,.86,0,.14)
|
||||
local seek = window:newProgressBar(0,0,0,0,0,.8,1,.05,length*100,0)
|
||||
seek.OnProgressUpdated(function(self,_,value, drag)
|
||||
if drag then
|
||||
local status = video:isPlaying()
|
||||
video:seek(value/100)
|
||||
if status then
|
||||
video:play()
|
||||
else
|
||||
video:stop()
|
||||
end
|
||||
end
|
||||
end)
|
||||
seek:isClickable(true)
|
||||
play_pause.square = "h"
|
||||
play_pause.isPaused = true
|
||||
play_pause:OnReleased(function(self)
|
||||
@ -34,16 +44,31 @@ function gui:newVideoPlayer(source, x, y, w, h, sx, sy, sw, sh)
|
||||
self.isPaused = not self.isPaused
|
||||
end)
|
||||
|
||||
local length = video:getDuration()
|
||||
mediaProc:newThread(function()
|
||||
while true do
|
||||
thread.yield()
|
||||
seeker:setDualDim(nil,nil,nil,nil,nil,nil,video:tell()/length)
|
||||
thread.hold(function() return video:isPlaying() end)
|
||||
local p = video:tell()
|
||||
seek:update(p*100)
|
||||
end
|
||||
end)
|
||||
|
||||
-- print()
|
||||
function window:seek(...)
|
||||
video.video:seek(...)
|
||||
end
|
||||
|
||||
function window:play()
|
||||
video:play()
|
||||
end
|
||||
|
||||
function window:stop()
|
||||
video:stop()
|
||||
end
|
||||
|
||||
window.OnClose(function()
|
||||
video:pause()
|
||||
end)
|
||||
|
||||
return window
|
||||
end
|
||||
|
||||
function gui:newCheckbox(label, x, y, size, sx, sy, checked)
|
||||
@ -117,21 +142,68 @@ end
|
||||
|
||||
function gui:newProgressBar(x, y, w, h, sx, sy, sw, sh, count, value)
|
||||
local value = value or 0
|
||||
local count = count or 100
|
||||
local progressbar = self:newFrame(x,y,w,h,sx,sy,sw,sh)
|
||||
local fillframe = progressbar:newFrame(noOf(.025, .1, .95, .8))
|
||||
local fillframe = progressbar:newFrame(2,2,-4,-4,0,0,1,1)
|
||||
local fill = fillframe:newFrame(noOf(0, 0, 1, 1))
|
||||
|
||||
local percentDisplay = fillframe:newTextLabel("",noOf(0,0,1,1))
|
||||
percentDisplay.align = gui.ALIGN_CENTER
|
||||
percentDisplay.textColor = color.new("#CC5500")
|
||||
fillframe.visibility = 0
|
||||
progressbar.color = color.new("#000000")
|
||||
fill.color = color.new("#ffffff")
|
||||
progressbar.fillframe = fillframe
|
||||
progressbar.fill = fill
|
||||
progressbar.display = percentDisplay
|
||||
progressbar.OnProgressUpdated = multi:newConnection()
|
||||
percentDisplay.visibility = 0
|
||||
local displayPercent = false
|
||||
|
||||
function progressbar:update(value)
|
||||
if value > count then value = count end
|
||||
if value < 0 then value = 0 end
|
||||
function progressbar:showPercent(bool)
|
||||
displayPercent = bool
|
||||
if bool then
|
||||
miscProc:newThread(function()
|
||||
thread.skip(2)
|
||||
_,_,_h = percentDisplay:getAbsolutes()
|
||||
percentDisplay:setFont(math.floor(h/1.3))
|
||||
self:update()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function progressbar:isClickable(bool)
|
||||
fillframe:respectHierarchy(not bool)
|
||||
-- Makes the bar updatable by clicking on it
|
||||
fillframe:enableDragging(bool and gui.MOUSE_PRIMARY)
|
||||
end
|
||||
|
||||
local calcFunc = function(self, dx, dy, x, y, istouch)
|
||||
local sx, sy, sw, sh = self:getAbsolutes()
|
||||
if x >= sx and x <= sx + sw then
|
||||
progressbar:update((((x - sx)/sw) * count), true)
|
||||
end
|
||||
end
|
||||
|
||||
fillframe:OnDragStart(calcFunc)
|
||||
|
||||
fillframe.OnDragging(calcFunc)
|
||||
|
||||
fillframe.OnPressed(function(self, x, y, dx, dy, istouch)
|
||||
calcFunc(self, dx, dy, x, y, istouch)
|
||||
end)
|
||||
|
||||
function progressbar:update(v, drag)
|
||||
v = v or value
|
||||
if v > count then v = count end
|
||||
if v < 0 then v = 0 end
|
||||
local percent = value/count
|
||||
fill:setDualDim(noOf(nil,nil,percent))
|
||||
if displayPercent then
|
||||
percentDisplay.text = math.floor((percent*100)+.5).. "%"
|
||||
percentDisplay:centerFont()
|
||||
end
|
||||
value = v
|
||||
self.OnProgressUpdated:Fire(self, percent, value, drag)
|
||||
end
|
||||
|
||||
function progressbar:add(n)
|
||||
@ -151,17 +223,27 @@ function gui:newProgressBar(x, y, w, h, sx, sy, sw, sh, count, value)
|
||||
end
|
||||
|
||||
function progressbar:max()
|
||||
value = count
|
||||
self:update(value)
|
||||
self:update(count)
|
||||
end
|
||||
|
||||
function progressbar:min()
|
||||
value = 0
|
||||
self:update(value)
|
||||
self:update(0)
|
||||
end
|
||||
|
||||
function progressbar:half()
|
||||
self:update(math.floor(count/2))
|
||||
end
|
||||
|
||||
function progressbar:getPercent()
|
||||
return math.floor(((value/count)*100)+.5)
|
||||
end
|
||||
|
||||
function progressbar:getValue()
|
||||
return value
|
||||
end
|
||||
|
||||
progressbar:update(value)
|
||||
|
||||
-- to change colors and modify main components
|
||||
return progressbar, fill, fillframe
|
||||
return progressbar, fill, percentDisplay, fillframe
|
||||
end
|
||||
@ -312,7 +312,7 @@ end
|
||||
|
||||
-- ── window constructor (unchanged from original) ──────────────────────────────
|
||||
local windowCount = 0
|
||||
function gui:newWindow(x, y, w, h, text, draggable, theme)
|
||||
function gui:newWindow(x, y, w, h, sx, sy, sw, sh, text, draggable, theme)
|
||||
local process = gui:newProcessor(text or "window_"..windowCount)
|
||||
windowCount = windowCount + 1
|
||||
local parent = self
|
||||
@ -323,9 +323,9 @@ function gui:newWindow(x, y, w, h, text, draggable, theme)
|
||||
local sizenwse = love.mouse.getSystemCursor("sizenwse")
|
||||
local theme = theme or default_theme
|
||||
|
||||
local header = self:newFrame(x, y, w, 35)
|
||||
local header = self:newFrame(x, y, w, 35, sx, sy, sw)
|
||||
header:setRoundness(10, 10, nil, "top")
|
||||
local window = header:newFrame(0, 35, 0, h - 35, 0, 0, 1)
|
||||
local window = header:newFrame(0, 35, 0, h, sx, sy, 1, sh)
|
||||
window.clipDescendants = true
|
||||
local left = window:newFrame(0, -4, 4, 0, 0, 0, 0, 1):tag("left")
|
||||
local right = window:newFrame(-4, -4, 4, 0, 1, 0, 0, 1):tag("right")
|
||||
@ -384,8 +384,11 @@ function gui:newWindow(x, y, w, h, text, draggable, theme)
|
||||
|
||||
local X = header:newTextButton("", -25, -25, 20, 20, 1, 1)
|
||||
X:setRoundness(10, 10)
|
||||
X:respectHierarchy(false)
|
||||
X.align = gui.ALIGN_CENTER
|
||||
X.color = color.red
|
||||
window.XButton = X
|
||||
|
||||
local darkenX = color.darken(color.red, .2)
|
||||
X.OnEnter(function(self) self.color = darkenX end)
|
||||
X.OnExit(function(self) self.color = color.red end)
|
||||
@ -403,7 +406,10 @@ function gui:newWindow(x, y, w, h, text, draggable, theme)
|
||||
end)
|
||||
end
|
||||
|
||||
window.OnClose = function() return window end % X.OnPressed
|
||||
window.OnClose = multi:newConnection()
|
||||
X.OnPressed(function(self, ...)
|
||||
window.OnClose:Fire(window, ...)
|
||||
end)
|
||||
window.OnClose(function()
|
||||
header:setParent(gui.virtual)
|
||||
love.mouse.setCursor(pointer)
|
||||
@ -758,7 +764,7 @@ function gui:showTaskManager()
|
||||
local WIN_W = TOTAL_W + 20
|
||||
local WIN_H = 620
|
||||
|
||||
taskManager = gui:newWindow(0, 0, WIN_W, WIN_H, "Task Manager", true, TM_THEME)
|
||||
taskManager = gui:newWindow(0, 0, WIN_W, WIN_H, nil, nil, nil, nil, "Task Manager", true, TM_THEME)
|
||||
taskManager.clipDescendants = true
|
||||
|
||||
-- ── tab bar ──────────────────────────────────────────────────────────────
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
local gui = require("gui")
|
||||
local multi, thread = require("multi"):init()
|
||||
local processor = gui:newProcessor("Transistion Processor")
|
||||
local processor = gui:newProcessor("Transition Processor")
|
||||
local transition = {}
|
||||
|
||||
local width, height, flags = love.window.getMode()
|
||||
@ -13,23 +13,26 @@ end
|
||||
transition.__index = transition
|
||||
transition.__call = function(t, start, stop, time, ...)
|
||||
local args = {...}
|
||||
return function(st, sp, ti) -- allow these values to be overridden
|
||||
if not (st or start) or not (sp or stop) then return multi.error("start and stop must be supplied") end
|
||||
if start == stop then
|
||||
return function(st, sp, ti)
|
||||
local s = st or start
|
||||
local e = sp or stop
|
||||
local dur = ti or time or 1
|
||||
if not s or not e then return multi.error("start and stop must be supplied") end
|
||||
if s == e then
|
||||
local temp = {
|
||||
OnStep = function() end,
|
||||
OnStep = function() end,
|
||||
OnStop = multi:newConnection()
|
||||
}
|
||||
proc:newTask(function()
|
||||
processor:newTask(function()
|
||||
temp.OnStop:Fire()
|
||||
end)
|
||||
return temp
|
||||
end
|
||||
local handle = t.func(t, start, stop, (ti or time) or 1, unpack(args))
|
||||
local handle = t.func(t, s, e, dur, unpack(args))
|
||||
return {
|
||||
OnStep = handle.OnStatus,
|
||||
OnStop = handle.OnReturn + handle.OnError,
|
||||
Kill = t.Kill
|
||||
Kill = function() t:Kill() end
|
||||
}
|
||||
end
|
||||
end
|
||||
@ -43,11 +46,11 @@ function transition:newTransition(func)
|
||||
c.OnStop = multi:newConnection()
|
||||
c.kill = false
|
||||
|
||||
function c:SetFPS(fps)
|
||||
self.fps = fps
|
||||
function c:SetFPS(f)
|
||||
self.fps = f
|
||||
end
|
||||
|
||||
function c:GetFPS(fps)
|
||||
function c:GetFPS()
|
||||
return self.fps
|
||||
end
|
||||
|
||||
@ -60,17 +63,29 @@ function transition:newTransition(func)
|
||||
return c
|
||||
end
|
||||
|
||||
transition.glide = transition:newTransition(function(t, start, stop, time, ...)
|
||||
local steps = t.fps*time
|
||||
local piece = time/steps
|
||||
local split = stop-start
|
||||
transition.glide = transition:newTransition(function(t, start, stop, time)
|
||||
local split = stop - start
|
||||
local startTime = love.timer.getTime()
|
||||
local endTime = startTime + time
|
||||
local stepTime = 1 / t.fps
|
||||
|
||||
t.running = true
|
||||
for i = 0, steps do
|
||||
if not(t.kill) then
|
||||
thread.sleep(piece)
|
||||
thread.pushStatus(start + i*(split/steps),piece*i)
|
||||
|
||||
while not t.kill do
|
||||
thread.sleep(stepTime)
|
||||
|
||||
local now = love.timer.getTime()
|
||||
local elapsed = now - startTime
|
||||
local clamped = math.min(elapsed, time)
|
||||
local value = start + (clamped / time) * split
|
||||
|
||||
thread.pushStatus(value, clamped)
|
||||
|
||||
if now >= endTime then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
t.running = false
|
||||
t.kill = false
|
||||
end)
|
||||
|
||||
212
gui/init.lua
212
gui/init.lua
@ -136,6 +136,7 @@ updater:newTask(function()
|
||||
Hook("joystickadded", gui.Events.OnJoystickAdded.Fire)
|
||||
end)
|
||||
|
||||
|
||||
-- Hotkeys
|
||||
|
||||
local function noOf(sx,sy,sw,sh)
|
||||
@ -485,13 +486,13 @@ function gui:canPress(mx, my) -- Get the intersection of the clip area and the s
|
||||
return not (mx > x + w or mx < x or my > y + h or my < y)
|
||||
end
|
||||
|
||||
function gui:isBeingCovered(mx, my)
|
||||
function gui:isBeingCovered(mx, my, respect)
|
||||
-- if not respect then return false end
|
||||
local children = gui:getAllChildren()
|
||||
for i = #children, 1, -1 do
|
||||
if children[i] == self then
|
||||
if children[i] == self or not respect then
|
||||
return false
|
||||
elseif children[i]:canPress(mx, my) and not (children[i] == self) and
|
||||
not (children[i].ignore) then
|
||||
elseif children[i]:canPress(mx, my) and not (children[i] == self) and not (children[i].ignore) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
@ -590,7 +591,8 @@ function gui:getUniques(tab)
|
||||
color = self.color,
|
||||
borderColor = self.borderColor,
|
||||
drawBorder = self.drawborder,
|
||||
rotation = self.rotation
|
||||
rotation = self.rotation,
|
||||
shader = self.shader
|
||||
}
|
||||
|
||||
if tab then for i, v in pairs(tab) do base[i] = tab[i] end end
|
||||
@ -619,6 +621,20 @@ local function testVisual(c, x, y, button, istouch, presses)
|
||||
return not(c:hasTag("visual") or c:parentHasTag("visual"))
|
||||
end
|
||||
|
||||
local extensions = {}
|
||||
|
||||
function gui.registerExtension(template)
|
||||
table.insert(extensions, template)
|
||||
end
|
||||
|
||||
function gui:extend(c)
|
||||
for i,v in pairs(extensions) do
|
||||
for key, value in pairs(v) do
|
||||
c[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Base Library
|
||||
function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
||||
local c = {}
|
||||
@ -633,7 +649,7 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
||||
|
||||
local function testHierarchy(c, x, y, button, istouch, presses)
|
||||
if hierarchy then
|
||||
return not (global_drag or c:isBeingCovered(x, y))
|
||||
return not (global_drag or c:isBeingCovered(x, y, true))
|
||||
end
|
||||
return true
|
||||
end
|
||||
@ -723,6 +739,12 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
||||
end)
|
||||
|
||||
local _mouseRelRef = gui.Events.OnMouseReleased(function(x, y, button, istouch, presses)
|
||||
pressed = false -- we need to handle dragging stopped even if an element is not active
|
||||
if dragging and button == dragbutton then
|
||||
dragging = false
|
||||
global_drag = false
|
||||
c.OnDragEnd:Fire(c, dx, dy, x, y, istouch, presses)
|
||||
end
|
||||
if not c:isActive() then return end
|
||||
if c:canPress(x, y) then
|
||||
c.OnReleased:Fire(c, x, y, button, istouch, presses)
|
||||
@ -731,12 +753,6 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
||||
else
|
||||
c.OnReleasedOther:Fire(c, x, y, button, istouch, presses)
|
||||
end
|
||||
pressed = false
|
||||
if dragging and button == dragbutton then
|
||||
dragging = false
|
||||
global_drag = false
|
||||
c.OnDragEnd:Fire(c, dx, dy, x, y, istouch, presses)
|
||||
end
|
||||
end)
|
||||
|
||||
local _mousePressRef = gui.Events.OnMousePressed(function(x, y, button, istouch, presses)
|
||||
@ -751,7 +767,7 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
||||
object_focus = c
|
||||
end
|
||||
|
||||
if draggable and button == dragbutton and not c:isBeingCovered(x, y) and
|
||||
if draggable and button == dragbutton and not c:isBeingCovered(x, y, hierarchy) and
|
||||
not global_drag then
|
||||
dragging = true
|
||||
global_drag = true
|
||||
@ -803,7 +819,9 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
||||
return self
|
||||
end
|
||||
|
||||
function c:respectHierarchy(bool) hierarchy = bool end
|
||||
function c:respectHierarchy(bool)
|
||||
hierarchy = bool
|
||||
end
|
||||
|
||||
local function centerthread()
|
||||
if centerX or centerY then
|
||||
@ -914,6 +932,41 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual)
|
||||
if typ == frame then
|
||||
gui.Events.OnCreated:Fire(c) -- Trigger frame types instantly
|
||||
end
|
||||
-- shader stuff
|
||||
|
||||
function c:setShader(shader)
|
||||
if type(shader) == "string" then
|
||||
self.shader = love.graphics.newShader(shader)
|
||||
else
|
||||
self.shader = shader -- already a compiled love Shader object
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function c:clearShader()
|
||||
self.shader = nil
|
||||
end
|
||||
|
||||
function c:setShaderUniform(name, ...)
|
||||
if not self.shader then return end
|
||||
if self.shader:hasUniform(name) then
|
||||
self.shader:send(name, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function c:enableShaderTime()
|
||||
self.__shaderTime = 0
|
||||
mainupdater.OnLoop(function(_, _, dt)
|
||||
if not self.shader then return end
|
||||
self.__shaderTime = self.__shaderTime + dt
|
||||
if self.shader:hasUniform("time") then
|
||||
self.shader:send("time", self.__shaderTime)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
gui:extend(c, typ)
|
||||
|
||||
return c
|
||||
end
|
||||
|
||||
@ -1122,6 +1175,7 @@ function gui:newTextBase(typ, txt, x, y, w, h, sx, sy, sw, sh)
|
||||
textColor = c.textColor
|
||||
})
|
||||
end
|
||||
|
||||
return c
|
||||
end
|
||||
|
||||
@ -1879,6 +1933,8 @@ function gui:newVideo(source, x, y, w, h, sx, sy, sw, sh)
|
||||
|
||||
function c:tell() return c.video:tell() end
|
||||
|
||||
function c:isPlaying() return c.video:isPlaying() end
|
||||
|
||||
updater:newThread("Video Handler",function()
|
||||
|
||||
local testCompletion = function() -- More intensive test
|
||||
@ -2048,7 +2104,13 @@ local draw_handler = function(child, no_draw, dt)
|
||||
end
|
||||
end
|
||||
|
||||
if child.shader and band(ctype, image) == 2 then
|
||||
if child.shader then
|
||||
if child.shader:hasUniform("size") then
|
||||
child.shader:send("size", {w, h})
|
||||
end
|
||||
if child.shader:hasUniform("position") then
|
||||
child.shader:send("position", {x, y})
|
||||
end
|
||||
love.graphics.setShader(child.shader)
|
||||
end
|
||||
|
||||
@ -2066,16 +2128,15 @@ local draw_handler = function(child, no_draw, dt)
|
||||
|
||||
love.graphics.setLineStyle("smooth")
|
||||
love.graphics.setLineWidth(1)
|
||||
|
||||
if drawB then
|
||||
love.graphics.setColor(bbg[1], bbg[2], bbg[3], vis)
|
||||
draw_factor(child,"line", x, y, w, h, rx, ry, nil, nil, segments)
|
||||
end
|
||||
|
||||
if drawB then
|
||||
if roundness == "top" then
|
||||
love.graphics.setColor(bg[1], bg[2], bg[3], vis)
|
||||
draw_factor(child,"fill", x, y + ry / 2, w, h - ry / 2 + 1)
|
||||
--love.graphics.rectangle("fill", x, y + ry / 2, w, h - ry / 2 + 1)
|
||||
love.graphics.setLineStyle("rough")
|
||||
love.graphics.setLineStyle("smooth")
|
||||
love.graphics.setColor(bbg[1], bbg[2], bbg[3], 1)
|
||||
love.graphics.setLineWidth(1)
|
||||
love.graphics.line(x, y + ry, x, y + h + 1, x + 1 + w, y + h + 1,
|
||||
@ -2087,9 +2148,10 @@ local draw_handler = function(child, no_draw, dt)
|
||||
love.graphics.line(x - 1, y + ry / 2 + 2, x - 1, y + h + 2)
|
||||
love.graphics.line(x + w + 2, y + ry / 2 + 2, x + w + 2, y + h + 2)
|
||||
elseif roundness == "bottom" then
|
||||
love.graphics.setColor(bg[1], bg[2], bg[3], vis)
|
||||
draw_factor(child,"fill", x, y, w, h - ry + 2)
|
||||
--love.graphics.rectangle("fill", x, y, w, h - ry + 2)
|
||||
love.graphics.setLineStyle("rough")
|
||||
love.graphics.setLineStyle("smooth")
|
||||
love.graphics.setColor(bbg[1], bbg[2], bbg[3], 1)
|
||||
love.graphics.setLineWidth(2)
|
||||
love.graphics.line(x - 1, y + ry + 1, x - 1, y - 1, x + w + 1, y - 1,
|
||||
@ -2123,14 +2185,114 @@ end
|
||||
|
||||
gui.draw_handler = draw_handler
|
||||
|
||||
local function has_blur_ancestor(child)
|
||||
local parent = child.parent
|
||||
while parent and parent ~= gui and parent ~= gui.virtual do
|
||||
if parent.__blur then return parent end
|
||||
parent = parent.parent
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function blur_draw(child, dt)
|
||||
local x, y, w, h = child:getAbsolutes()
|
||||
child.x = x
|
||||
child.y = y
|
||||
child.w = w
|
||||
child.h = h
|
||||
|
||||
local b = child.__blur
|
||||
local pw, ph = math.max(1, math.ceil(w)), math.max(1, math.ceil(h))
|
||||
|
||||
if not b.canvas1
|
||||
or b.canvas1:getWidth() ~= pw
|
||||
or b.canvas1:getHeight() ~= ph then
|
||||
b.canvas1 = love.graphics.newCanvas(pw, ph)
|
||||
b.canvas2 = love.graphics.newCanvas(pw, ph)
|
||||
end
|
||||
|
||||
local prevCanvas = love.graphics.getCanvas()
|
||||
local prevShader = love.graphics.getShader()
|
||||
local pr, pg, pb, pa = love.graphics.getColor()
|
||||
|
||||
-- -------------------------------------------------------
|
||||
-- Pass 1: draw the object AND all its descendants onto canvas1
|
||||
-- -------------------------------------------------------
|
||||
love.graphics.setCanvas(b.canvas1)
|
||||
love.graphics.setShader()
|
||||
love.graphics.clear(0, 0, 0, 0)
|
||||
love.graphics.setScissor()
|
||||
|
||||
-- Shift everything into canvas space by offsetting by -x, -y
|
||||
love.graphics.push()
|
||||
love.graphics.translate(-x, -y)
|
||||
|
||||
-- Draw the parent object itself
|
||||
draw_handler(child, nil, dt)
|
||||
|
||||
-- Draw all descendants in order
|
||||
local descendants = child:getAllChildren()
|
||||
for i = 1, #descendants do
|
||||
local desc = descendants[i]
|
||||
-- Recalculate absolutes so positions are correct
|
||||
local dx, dy, dw, dh = desc:getAbsolutes()
|
||||
desc.x = dx
|
||||
desc.y = dy
|
||||
desc.w = dw
|
||||
desc.h = dh
|
||||
draw_handler(desc, nil, dt)
|
||||
end
|
||||
|
||||
love.graphics.pop()
|
||||
|
||||
-- -------------------------------------------------------
|
||||
-- Pass 2: horizontal blur canvas1 → canvas2
|
||||
-- -------------------------------------------------------
|
||||
b.shader_h:send("size", {pw, ph})
|
||||
b.shader_h:send("radius", b.radius)
|
||||
|
||||
love.graphics.setCanvas(b.canvas2)
|
||||
love.graphics.clear(0, 0, 0, 0)
|
||||
love.graphics.setShader(b.shader_h)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.draw(b.canvas1, 0, 0)
|
||||
|
||||
-- -------------------------------------------------------
|
||||
-- Pass 3: vertical blur canvas2 → screen
|
||||
-- -------------------------------------------------------
|
||||
b.shader_v:send("size", {pw, ph})
|
||||
b.shader_v:send("radius", b.radius)
|
||||
|
||||
love.graphics.setCanvas(prevCanvas)
|
||||
love.graphics.setShader(b.shader_v)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.draw(b.canvas2, x, y)
|
||||
|
||||
-- Restore state
|
||||
love.graphics.setShader(prevShader)
|
||||
love.graphics.setColor(pr, pg, pb, pa)
|
||||
love.graphics.setScissor()
|
||||
end
|
||||
|
||||
local draw_loop = drawer:newLoop(function(self, dt)
|
||||
local children = gui:getAllChildren()
|
||||
for i = 1, #children do
|
||||
local child = children[i]
|
||||
if child.effect then
|
||||
-- Skip if this child belongs to a blur parent
|
||||
-- (blur_draw handles drawing it during the canvas capture pass)
|
||||
if has_blur_ancestor(child) then
|
||||
-- update x/y/w/h so layout still works, but don't draw
|
||||
local x, y, w, h = child:getAbsolutes()
|
||||
child.x = x
|
||||
child.y = y
|
||||
child.w = w
|
||||
child.h = h
|
||||
elseif child.__blur then
|
||||
blur_draw(child, dt)
|
||||
elseif child.effect then
|
||||
child.effect(function() draw_handler(child, nil, dt) end)
|
||||
else
|
||||
draw_handler(child,nil,dt)
|
||||
draw_handler(child, nil, dt)
|
||||
end
|
||||
end
|
||||
first_loop = true
|
||||
@ -2256,4 +2418,10 @@ gui.Events.OnResized(function(w, h)
|
||||
end
|
||||
end)
|
||||
|
||||
-- load shaders
|
||||
files = love.filesystem.getDirectoryItems("gui/shaders")
|
||||
for i,v in pairs(files) do
|
||||
require("gui.shaders."..v:sub(1,-5)).init(gui)
|
||||
end
|
||||
|
||||
return gui
|
||||
|
||||
70
gui/shaders/blur.lua
Normal file
70
gui/shaders/blur.lua
Normal file
@ -0,0 +1,70 @@
|
||||
local blur_h = love.graphics.newShader([[
|
||||
extern vec2 size;
|
||||
extern float radius;
|
||||
|
||||
vec4 effect(vec4 color, Image tex, vec2 tc, vec2 sc) {
|
||||
vec2 step = vec2(1.0 / size.x, 0.0);
|
||||
vec4 result = vec4(0.0);
|
||||
float total = 0.0;
|
||||
float sigma = radius * 0.5;
|
||||
float r = floor(radius);
|
||||
float i = -r;
|
||||
|
||||
while (i <= r) {
|
||||
float weight = exp(-0.5 * (i * i) / (sigma * sigma));
|
||||
result += Texel(tex, tc + step * i) * weight;
|
||||
total += weight;
|
||||
i = i + 1.0;
|
||||
}
|
||||
|
||||
return (result / total) * color;
|
||||
}
|
||||
]])
|
||||
|
||||
local blur_v = love.graphics.newShader([[
|
||||
extern vec2 size;
|
||||
extern float radius;
|
||||
|
||||
vec4 effect(vec4 color, Image tex, vec2 tc, vec2 sc) {
|
||||
vec2 step = vec2(0.0, 1.0 / size.y);
|
||||
vec4 result = vec4(0.0);
|
||||
float total = 0.0;
|
||||
float sigma = radius * 0.5;
|
||||
float r = floor(radius);
|
||||
float i = -r;
|
||||
|
||||
while (i <= r) {
|
||||
float weight = exp(-0.5 * (i * i) / (sigma * sigma));
|
||||
result += Texel(tex, tc + step * i) * weight;
|
||||
total += weight;
|
||||
i = i + 1.0;
|
||||
}
|
||||
|
||||
return (result / total) * color;
|
||||
}
|
||||
]])
|
||||
|
||||
local c = {}
|
||||
|
||||
function c:setBlur(radius)
|
||||
radius = radius or 8
|
||||
c.__blur = {
|
||||
radius = radius,
|
||||
canvas1 = nil, -- populated on first draw
|
||||
canvas2 = nil,
|
||||
shader_h = blur_h,
|
||||
shader_v = blur_v,
|
||||
}
|
||||
end
|
||||
|
||||
function c:clearBlur()
|
||||
c.__blur = nil
|
||||
end
|
||||
|
||||
function c:setBlurRadius(radius)
|
||||
if c.__blur then
|
||||
c.__blur.radius = radius
|
||||
end
|
||||
end
|
||||
|
||||
return {init = function(gui) gui.registerExtension(c) end}
|
||||
110
main.lua
110
main.lua
@ -4,6 +4,52 @@ local playerList = {}
|
||||
local playerStaticList = {}
|
||||
local scoreboard = {}
|
||||
|
||||
multi, thread = require("multi"):init({priority=true})
|
||||
multi.setClock(require("socket").gettime) -- When on linux os.clock doesn't reture actual seconds the program has elapsed for
|
||||
GLOBAL, THREAD = require("multi.integration.loveManager"):init()
|
||||
|
||||
gui = require("gui")
|
||||
color = require("gui.core.color")
|
||||
theme = require("gui.core.theme")
|
||||
utils = require("utils")
|
||||
board = require("board")
|
||||
yaml = require("yaml")
|
||||
loader = require("loader")
|
||||
require("gui.addons")
|
||||
|
||||
scoreUpdater = gui:getProcessor():newProcessor("score-updater")
|
||||
scoreUpdater.Start()
|
||||
|
||||
gui.registerExtension({
|
||||
sayHello = function(self)
|
||||
print("Extended Hello World")
|
||||
end,
|
||||
sayBye = function(self)
|
||||
print("Extended Bye World")
|
||||
end,
|
||||
})
|
||||
|
||||
function love.load()
|
||||
gui:cacheImage({"assets/checked.png","assets/unchecked.png","assets/speaker.png"})
|
||||
gui:setAspectSize(1920, 1080)
|
||||
gui.aspect_ratio = true
|
||||
|
||||
local bg = gui:newFrame()
|
||||
bg:fullFrame()
|
||||
bg.color = color.new("#242f9b")
|
||||
|
||||
-- bg:setBlur(10)
|
||||
bg:OnUpdate(function(self, dt)
|
||||
if self.__blur then
|
||||
-- pulse the blur between 2 and 12
|
||||
local t = love.timer.getTime()
|
||||
self:setBlurRadius(7 + 5 * math.sin(t * 2))
|
||||
end
|
||||
end)
|
||||
|
||||
StartGame(bg)
|
||||
end
|
||||
|
||||
function GetActivePlayer()
|
||||
if not activePlayer then return end
|
||||
return activePlayer.link
|
||||
@ -35,25 +81,6 @@ function love.filedropped(file)
|
||||
print("Load file? " .. file:getFilename())
|
||||
end
|
||||
|
||||
|
||||
function init()
|
||||
multi, thread = require("multi"):init({priority=true})
|
||||
multi.setClock(require("socket").gettime) -- When on linux os.clock doesn't reture actual seconds the program has elapsed for
|
||||
GLOBAL, THREAD = require("multi.integration.loveManager"):init()
|
||||
|
||||
gui = require("gui")
|
||||
color = require("gui.core.color")
|
||||
theme = require("gui.core.theme")
|
||||
utils = require("utils")
|
||||
board = require("board")
|
||||
yaml = require("yaml")
|
||||
loader = require("loader")
|
||||
require("gui.addons")
|
||||
|
||||
scoreUpdater = gui:getProcessor():newProcessor("score-updater")
|
||||
scoreUpdater.Start()
|
||||
end
|
||||
|
||||
function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh)
|
||||
-- Colors
|
||||
local C_BG_PANEL = color.new("#1a1a2e")
|
||||
@ -313,56 +340,15 @@ function ScoreBoard(frame, x, y, w, h, sx, sy, sw, sh)
|
||||
return scoreboard
|
||||
end
|
||||
|
||||
function LandingPage(bg)
|
||||
|
||||
|
||||
-- local webp = require("webp")
|
||||
init()
|
||||
|
||||
local function noOf(sx,sy,sw,sh)
|
||||
return nil,nil,nil,nil,sx,sy,sw,sh
|
||||
end
|
||||
|
||||
function love.load()
|
||||
gui:cacheImage({"assets/checked.png","assets/unchecked.png"})
|
||||
gui:setAspectSize(1920, 1080)
|
||||
gui.aspect_ratio = true
|
||||
-- local ext = require("gui.addons.extensions")
|
||||
local bg = gui:newFrame()
|
||||
bg:fullFrame()
|
||||
bg.color = color.new("#242f9b")
|
||||
|
||||
-- pb = bg:newProgressBar(0, 0, 200, 40, 0, 0, 0, 0, 200, 0)
|
||||
|
||||
-- thread:newThread(function()
|
||||
-- for i=1,200 do
|
||||
-- thread.sleep(.01)
|
||||
-- pb:add(1)
|
||||
-- end
|
||||
-- end)
|
||||
|
||||
-- local group = bg:newRadioGroup({
|
||||
-- padding = 5,
|
||||
-- "Option A",
|
||||
-- "Option B",
|
||||
-- "Option C"
|
||||
-- },0,0,0,0, 80)
|
||||
|
||||
-- group.OnSelectionChanged(function(group, selection)
|
||||
-- print(selection:getLabel())
|
||||
-- end)
|
||||
|
||||
|
||||
|
||||
|
||||
function StartGame(bg)
|
||||
local qframe = bg:newFrame(0, 0, 0, 0, .2, .05, .75, .9)
|
||||
qframe.color = color.new("#060ee9")
|
||||
local scoreboard = ScoreBoard(bg, 0, 0, 0, 0, .015, .05, .170, .9)
|
||||
|
||||
board.buildBoard(qframe, "anime")
|
||||
|
||||
-- gui:newVideoPlayer("test.ogv",0,0,428,240)
|
||||
-- local img = webp.load("test.webp")
|
||||
-- gui:newImageLabel(img,0,0,735,1041)
|
||||
end
|
||||
|
||||
function love.update(dt)
|
||||
|
||||
2
multi
2
multi
@ -1 +1 @@
|
||||
Subproject commit 4a52cd5e14abfc409bc82f6427d0cf79f8d2a894
|
||||
Subproject commit c86413351c8e2fdd3b595d3df1ba0b9ac7d1f9b1
|
||||
69
templates/whatsound.lua
Normal file
69
templates/whatsound.lua
Normal file
@ -0,0 +1,69 @@
|
||||
--[[ Constants
|
||||
* (all lua builtins that don't allow io/executing code)
|
||||
color (interface)
|
||||
gui (interface)
|
||||
multi (interface bound to a processor) no thread module
|
||||
|
||||
callback true/false correct/wrong
|
||||
]]
|
||||
local label
|
||||
local imageHolder
|
||||
|
||||
local function index(window, q, callback)
|
||||
if not q.sound or q.sound == "" then
|
||||
error("Missing 'sound' field for question!")
|
||||
callback()
|
||||
return
|
||||
end
|
||||
frame = window:newFrame(0,0,0,-200,0,.2,1,.8)
|
||||
frame.visibility = 0
|
||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
||||
label.align = ALIGN_CENTER
|
||||
label.textColor = color.white
|
||||
label.color = color.new("#060ce9")
|
||||
imageHolder = frame:newImageButton("assets/speaker.png",0,0,0,0,0,0,.3,.4)
|
||||
imageHolder:setAspectSize(imageHolder.imageWidth,imageHolder.imageHeight)
|
||||
imageHolder:centerX(true)
|
||||
imageHolder:centerY(true)
|
||||
local sound = newSource(q.sound,"stream")
|
||||
imageHolder:OnReleased(function()
|
||||
if tonumber(q.start) then
|
||||
sound:seek(q.start)
|
||||
end
|
||||
|
||||
sound:play()
|
||||
|
||||
timer(tonumber(q.playFor) or 10, function()
|
||||
sound:stop()
|
||||
sound:seek(0)
|
||||
end)
|
||||
end)
|
||||
local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5)
|
||||
correct.color = color.new("#52b11b")
|
||||
local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5)
|
||||
wrong.color = color.new("#bd2626")
|
||||
local skip = window:newTextButton("Skip",0,-100,0,100,.25,1,.5)
|
||||
skip.color = color.new("#5d5d5d")
|
||||
window.apply({
|
||||
fitFont={},
|
||||
align=window.ALIGN_CENTER,
|
||||
OnReleased=function(self)
|
||||
sound:stop()
|
||||
if self.text == "Skip" then
|
||||
callback()
|
||||
return
|
||||
end
|
||||
callback(self.text == "Correct")
|
||||
end,
|
||||
},correct,wrong,skip)
|
||||
end
|
||||
|
||||
local function update(dt) -- time in seconds that has passed since
|
||||
label:fitFont()
|
||||
label:centerFont()
|
||||
end
|
||||
|
||||
return {
|
||||
index = index,
|
||||
update = update
|
||||
}
|
||||
62
templates/whatvideo.lua
Normal file
62
templates/whatvideo.lua
Normal file
@ -0,0 +1,62 @@
|
||||
--[[ Constants
|
||||
* (all lua builtins that don't allow io/executing code)
|
||||
color (interface)
|
||||
gui (interface)
|
||||
multi (interface bound to a processor) no thread module
|
||||
|
||||
callback true/false correct/wrong
|
||||
]]
|
||||
local label
|
||||
local video
|
||||
|
||||
local function index(window, q, callback)
|
||||
if not q.video or q.video == "" then
|
||||
error("Missing 'video' field for question!")
|
||||
callback()
|
||||
return
|
||||
end
|
||||
frame = window:newFrame(0,0,0,-200,0,.2,1,.8)
|
||||
frame.visibility = 0
|
||||
label = window:newTextLabel(" " ..q.title.. " ",0,0,0,0,0,0,1,.2)
|
||||
label.align = ALIGN_CENTER
|
||||
label.textColor = color.white
|
||||
label.color = color.new("#060ce9")
|
||||
local holder = frame:newFrame(-300, -200, 600, 400, .5, .5)
|
||||
holder:centerX(true)
|
||||
holder:centerY(true)
|
||||
holder.visibility = 0
|
||||
video = holder:newVideoPlayer(q.video, 0, 0, 600, 400, false)
|
||||
video:setAspectSize(video.imageWidth,video.imageHeight)
|
||||
video:OnReleased(function()
|
||||
video:play()
|
||||
end)
|
||||
video.XButton.visible = false
|
||||
local correct = window:newTextButton("Correct",0,-200,0,100,0,1,.5)
|
||||
correct.color = color.new("#52b11b")
|
||||
local wrong = window:newTextButton("Wrong",0,-200,0,100,.5,1,.5)
|
||||
wrong.color = color.new("#bd2626")
|
||||
local skip = window:newTextButton("Skip",0,-100,0,100,.25,1,.5)
|
||||
skip.color = color.new("#5d5d5d")
|
||||
window.apply({
|
||||
fitFont={},
|
||||
align=window.ALIGN_CENTER,
|
||||
OnReleased=function(self)
|
||||
video:stop()
|
||||
if self.text == "Skip" then
|
||||
callback()
|
||||
return
|
||||
end
|
||||
callback(self.text == "Correct")
|
||||
end,
|
||||
},correct,wrong,skip)
|
||||
end
|
||||
|
||||
local function update(dt) -- time in seconds that has passed since
|
||||
label:fitFont()
|
||||
label:centerFont()
|
||||
end
|
||||
|
||||
return {
|
||||
index = index,
|
||||
update = update
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user