First commit
This commit is contained in:
parent
99865de03a
commit
ba5ecca443
23
LICENSE
Executable file
23
LICENSE
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
Copyright (c) 2019, Elmārs Āboliņš
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
281
core/element.lua
Executable file
281
core/element.lua
Executable file
@ -0,0 +1,281 @@
|
|||||||
|
--[[ Element superclass ]]
|
||||||
|
local path = string.sub(..., 1, string.len(...) - string.len(".core.element"))
|
||||||
|
local helium = require(path .. ".dummy")
|
||||||
|
|
||||||
|
local context = {}
|
||||||
|
context.__index = context
|
||||||
|
|
||||||
|
local activeContext
|
||||||
|
|
||||||
|
function context.new(elem)
|
||||||
|
local ctx = setmetatable({view = elem.view, element = elem}, context)
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
end
|
||||||
|
|
||||||
|
function context:bubbleUpdate()
|
||||||
|
self.element.settings.pendingUpdate = true
|
||||||
|
self.element.settings.needsRendering = true
|
||||||
|
|
||||||
|
if self.parentCtx then
|
||||||
|
self.parentCtx:bubbleUpdate()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function context:set()
|
||||||
|
if activeContext then
|
||||||
|
self.parentCtx = activeContext
|
||||||
|
|
||||||
|
self.absX = self.parentCtx.absX + self.view.x
|
||||||
|
self.absY = self.parentCtx.absY + self.view.y
|
||||||
|
|
||||||
|
activeContext = self
|
||||||
|
else
|
||||||
|
self.absX = self.view.x
|
||||||
|
self.absY = self.view.y
|
||||||
|
|
||||||
|
activeContext = self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function context:unset()
|
||||||
|
if self.parentCtx then
|
||||||
|
activeContext = self.parentCtx
|
||||||
|
else
|
||||||
|
activeContext = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local element = {}
|
||||||
|
element.__index = element
|
||||||
|
|
||||||
|
setmetatable(element,{
|
||||||
|
__call = function(cls, ...)
|
||||||
|
local self
|
||||||
|
if type(...)=='function' then
|
||||||
|
self = setmetatable({}, element)
|
||||||
|
self.renderer = ...
|
||||||
|
self.classless = true
|
||||||
|
elseif type(cls)=='table' then
|
||||||
|
self = setmetatable({}, cls)
|
||||||
|
self.classless = false
|
||||||
|
end
|
||||||
|
|
||||||
|
self:new(...)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
--Dummy functions
|
||||||
|
function element:renderer() print('no renderer') end
|
||||||
|
|
||||||
|
function element:updater() end
|
||||||
|
|
||||||
|
function element:constructor() end
|
||||||
|
|
||||||
|
--Control functions
|
||||||
|
--The new function that should be used for element creation
|
||||||
|
function element:new()
|
||||||
|
local dimensions
|
||||||
|
--save the parameters
|
||||||
|
self.parameters = {}
|
||||||
|
|
||||||
|
--The element canvas
|
||||||
|
self.canvas = nil
|
||||||
|
|
||||||
|
--Internal settings
|
||||||
|
self.settings = {
|
||||||
|
isSetup = false,
|
||||||
|
pendingUpdate = true,
|
||||||
|
needsRendering = true,
|
||||||
|
calculatedDimensions = true,
|
||||||
|
inserted = false
|
||||||
|
}
|
||||||
|
|
||||||
|
self.view = {
|
||||||
|
x = 0,
|
||||||
|
y = 0,
|
||||||
|
w = 10,
|
||||||
|
h = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.classless then
|
||||||
|
self.classlessState = {}
|
||||||
|
self.classlessData = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--Called once dimensions are validated
|
||||||
|
function element:setup()
|
||||||
|
self.state =
|
||||||
|
setmetatable(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
__index = function(t, index)
|
||||||
|
return self.baseState[index]
|
||||||
|
end,
|
||||||
|
__newindex = function(t, index, val)
|
||||||
|
if self.baseState[index] ~= val then
|
||||||
|
self.baseState[index] = val
|
||||||
|
self.context:bubbleUpdate()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.parameters =
|
||||||
|
setmetatable(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
__index = function(t, index)
|
||||||
|
return self.baseParams[index] or nil
|
||||||
|
end,
|
||||||
|
__newindex = function(t, index, val)
|
||||||
|
if self.baseParams[index] ~= val then
|
||||||
|
self.baseParams[index] = val
|
||||||
|
self.context:bubbleUpdate()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.canvas = love.graphics.newCanvas(self.view.w, self.view.h)
|
||||||
|
|
||||||
|
self.quad = love.graphics.newQuad(0, 0, self.view.w, self.view.h, self.view.w, self.view.h)
|
||||||
|
|
||||||
|
--Context makes sure element internals don't have to worry about absolute coordinates
|
||||||
|
self.inputContext = helium.input.newContext(self)
|
||||||
|
self.context = context.new(self)
|
||||||
|
|
||||||
|
self.settings.isSetup = true
|
||||||
|
|
||||||
|
--Classless rendering
|
||||||
|
if self.classless then
|
||||||
|
self.classlessData.loadEffect = function (func)
|
||||||
|
if self.classlessData.loadCaptured then
|
||||||
|
return unpack(self.classlessData.loadCaptured)
|
||||||
|
else
|
||||||
|
self.classlessData.loadCaptured = func()
|
||||||
|
if type(self.classlessData.loadCaptured) == 'table' then
|
||||||
|
return unpack(self.classlessData.loadCaptured)
|
||||||
|
elseif self.classlessData.loadCaptured then
|
||||||
|
return self.classlessData.loadCaptured
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.classlessData.useState = function (initial)
|
||||||
|
self.settings.indice = self.settings.indice + 1
|
||||||
|
local indice = self.settings.indice
|
||||||
|
|
||||||
|
if self.classlessState[indice] and self.classlessState[indice].state then
|
||||||
|
return self.classlessState[indice].state, self.classlessState[indice].setState
|
||||||
|
else
|
||||||
|
self.classlessState[indice] = {}
|
||||||
|
self.classlessState[indice].state = initial
|
||||||
|
|
||||||
|
self.classlessState[indice].setState = function(set)
|
||||||
|
self.classlessState[indice].state = set
|
||||||
|
self.context:bubbleUpdate()
|
||||||
|
end
|
||||||
|
return self.classlessState[indice].state, self.classlessState[indice].setState
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function element:classlessRender()
|
||||||
|
self.inputContext:set()
|
||||||
|
self.settings.indice = 0
|
||||||
|
|
||||||
|
local denv = getfenv(self.renderer)
|
||||||
|
denv['useState'] = self.classlessData.useState
|
||||||
|
denv['loadEffect'] = self.classlessData.loadEffect
|
||||||
|
|
||||||
|
self.renderer(self.parameters, self.view.w, self.view.h)
|
||||||
|
|
||||||
|
denv['useState'] = nil
|
||||||
|
denv['loadEffect'] = nil
|
||||||
|
self.inputContext:unset()
|
||||||
|
end
|
||||||
|
|
||||||
|
function element:renderWrapper()
|
||||||
|
local cnvs = love.graphics.getCanvas()
|
||||||
|
love.graphics.setCanvas({self.canvas, stencil = true})
|
||||||
|
|
||||||
|
love.graphics.clear()
|
||||||
|
|
||||||
|
if self.classless and self.parameters then
|
||||||
|
self:classlessRender()
|
||||||
|
self.settings.pendingUpdate = false
|
||||||
|
else
|
||||||
|
self:renderer()
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.setCanvas(cnvs)
|
||||||
|
end
|
||||||
|
|
||||||
|
function element:externalRender()
|
||||||
|
self.context:set()
|
||||||
|
|
||||||
|
if self.settings.needsRendering then
|
||||||
|
self:renderWrapper()
|
||||||
|
self.settings.needsRendering = false
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.setColor(1,1,1)
|
||||||
|
love.graphics.draw(self.canvas, self.quad, self.view.x, self.view.y)
|
||||||
|
|
||||||
|
self.context:unset()
|
||||||
|
end
|
||||||
|
|
||||||
|
function element:externalUpdate()
|
||||||
|
if self.settings.pendingUpdate then
|
||||||
|
if self.updater then
|
||||||
|
self:updater()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.settings.needsRendering = true
|
||||||
|
self.settings.pendingUpdate = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--External functions
|
||||||
|
--Acts as the entrypoint for beginning rendering
|
||||||
|
function element:draw(params, x, y, w, h)
|
||||||
|
self.view.x = x or self.view.x
|
||||||
|
self.view.y = y or self.view.y
|
||||||
|
self.view.w = w or self.view.w
|
||||||
|
self.view.h = h or self.view.h
|
||||||
|
|
||||||
|
if params then
|
||||||
|
if type(params)=='table' and self.baseParams then
|
||||||
|
helium.utils.tableMerge(params, self.parameters)
|
||||||
|
elseif self.baseParams==nil then
|
||||||
|
self.baseParams = params
|
||||||
|
else
|
||||||
|
self.parameters = params
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self.settings.isSetup then
|
||||||
|
self:setup()
|
||||||
|
end
|
||||||
|
|
||||||
|
if activeContext then
|
||||||
|
self:externalRender()
|
||||||
|
elseif not self.settings.inserted then
|
||||||
|
self.settings.inserted = true
|
||||||
|
table.insert(helium.elementBuffer, self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function element:undraw()
|
||||||
|
self.settings.remove = true
|
||||||
|
self.settings.isSetup = false
|
||||||
|
end
|
||||||
|
|
||||||
|
return element
|
||||||
281
core/input.lua
Executable file
281
core/input.lua
Executable file
@ -0,0 +1,281 @@
|
|||||||
|
local path = string.sub(..., 1, string.len(...) - string.len(".core.input"))
|
||||||
|
local helium = require(path .. ".dummy")
|
||||||
|
|
||||||
|
local input={
|
||||||
|
eventHandlers = {},
|
||||||
|
subscriptions = {},
|
||||||
|
activeEvents = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
local subscription = {}
|
||||||
|
subscription.__index = subscription
|
||||||
|
|
||||||
|
local context = {}
|
||||||
|
context.__index = context
|
||||||
|
|
||||||
|
local activeContext
|
||||||
|
|
||||||
|
--[[Event types
|
||||||
|
###SIMPLE EVENTS###
|
||||||
|
mousepressed,--press started
|
||||||
|
mousereleased,--press released after an event inside started
|
||||||
|
|
||||||
|
mousepressed_outside --mousepressed outside of the subscription
|
||||||
|
mousereleased_outside --mousereleased outside of the subscription
|
||||||
|
|
||||||
|
keypressed,--key pressed
|
||||||
|
keyreleased,--key released
|
||||||
|
|
||||||
|
###COMPLEX EVENTS###
|
||||||
|
dragged,
|
||||||
|
clicked,
|
||||||
|
hover,
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
function input.newContext(element)
|
||||||
|
local ctx = setmetatable({view = element.view, subs = {}}, context)
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
end
|
||||||
|
|
||||||
|
function context:set()
|
||||||
|
if activeContext then
|
||||||
|
self.parentCtx = activeContext
|
||||||
|
self.absX = self.parentCtx.absX + self.view.x
|
||||||
|
self.absY = self.parentCtx.absY + self.view.y
|
||||||
|
activeContext = self
|
||||||
|
else
|
||||||
|
self.absX = self.view.x
|
||||||
|
self.absY = self.view.y
|
||||||
|
activeContext = self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function context:unset()
|
||||||
|
if self.parentCtx then
|
||||||
|
activeContext = self.parentCtx
|
||||||
|
else
|
||||||
|
activeContext = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function context:destroy()
|
||||||
|
for i, e in ipairs(self.subs) do
|
||||||
|
self.subs:destroy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function subscription.create(x, y, w, h, eventType, callback, doff)
|
||||||
|
local sub
|
||||||
|
if activeContext then
|
||||||
|
sub = setmetatable({
|
||||||
|
x = activeContext.absX + x,
|
||||||
|
y = activeContext.absY + y,
|
||||||
|
w = w,
|
||||||
|
h = h,
|
||||||
|
eventType = eventType,
|
||||||
|
active = doff or true,
|
||||||
|
callback = callback
|
||||||
|
},subscription)
|
||||||
|
else
|
||||||
|
sub = setmetatable({
|
||||||
|
x = x,
|
||||||
|
y = y,
|
||||||
|
w = w,
|
||||||
|
h = h,
|
||||||
|
eventType = eventType,
|
||||||
|
active = doff or true,
|
||||||
|
callback = callback
|
||||||
|
},subscription)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not input.subscriptions[eventType] then
|
||||||
|
input.subscriptions[eventType] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(input.subscriptions[eventType],sub)
|
||||||
|
|
||||||
|
return sub
|
||||||
|
end
|
||||||
|
|
||||||
|
function subscription:off()
|
||||||
|
self.active = false
|
||||||
|
end
|
||||||
|
|
||||||
|
function subscription:on()
|
||||||
|
self.active = true
|
||||||
|
end
|
||||||
|
|
||||||
|
function subscription:destroy()
|
||||||
|
self.destroy = true
|
||||||
|
self.active = false
|
||||||
|
end
|
||||||
|
|
||||||
|
function subscription:update(x, y, w, h)
|
||||||
|
self.x = x or self.x
|
||||||
|
self.y = y or self.y
|
||||||
|
self.w = w or self.w
|
||||||
|
self.h = h or self.h
|
||||||
|
end
|
||||||
|
|
||||||
|
function subscription:emit(...)
|
||||||
|
return self.callback(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
function subscription:checkInside(x, y)
|
||||||
|
if x>self.x and x<self.x+self.w and y>self.y and y<self.y+self.h then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function subscription:checkOutside(x, y)
|
||||||
|
if x>self.x and x<self.x+self.w and y>self.y and y<self.y+self.h then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
input.subscribe = function(...)
|
||||||
|
return subscription.create(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function input.eventHandlers.mousereleased(x, y, btn)
|
||||||
|
local captured = false
|
||||||
|
if input.subscriptions.mousereleased then
|
||||||
|
for index, sub in ipairs(input.subscriptions.mousereleased) do
|
||||||
|
local succ = sub:checkInside(x, y)
|
||||||
|
|
||||||
|
if succ and sub.active then
|
||||||
|
sub:emit(x, y, btn)
|
||||||
|
captured = true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if input.subscriptions.mousereleased_outside then
|
||||||
|
for index, sub in ipairs(input.subscriptions.mousereleased_outside) do
|
||||||
|
local succ = sub:checkOutside(x, y)
|
||||||
|
|
||||||
|
if succ and sub.active then
|
||||||
|
sub:emit(x, y, btn)
|
||||||
|
captured = true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if input.subscriptions.clicked then
|
||||||
|
for index, sub in ipairs(input.subscriptions.clicked) do
|
||||||
|
if sub.currentEvent then
|
||||||
|
sub.currentEvent = false
|
||||||
|
captured = true
|
||||||
|
if sub.cleanUp then
|
||||||
|
sub.cleanUp(x, y, btn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return captured
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function input.eventHandlers.mousepressed(x, y, btn)
|
||||||
|
local captured = false
|
||||||
|
if input.subscriptions.mousepressed then
|
||||||
|
for index, sub in ipairs(input.subscriptions.mousepressed) do
|
||||||
|
local succ = sub:checkInside(x, y)
|
||||||
|
|
||||||
|
if succ and sub.active then
|
||||||
|
sub:emit(x, y, btn)
|
||||||
|
captured = true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if input.subscriptions.mousepressed_outside then
|
||||||
|
for index, sub in ipairs(input.subscriptions.mousepressed_outside) do
|
||||||
|
local succ = sub:checkOutside(x, y)
|
||||||
|
|
||||||
|
if succ and sub.active then
|
||||||
|
sub:emit(x, y, btn)
|
||||||
|
captured = true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if input.subscriptions.clicked then
|
||||||
|
for index, sub in ipairs(input.subscriptions.clicked) do
|
||||||
|
local succ = sub:checkInside(x, y)
|
||||||
|
|
||||||
|
if succ and sub.active then
|
||||||
|
sub.cleanUp = sub:emit(x, y, btn)
|
||||||
|
sub.currentEvent = true
|
||||||
|
captured = true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return captured
|
||||||
|
end
|
||||||
|
|
||||||
|
function input.eventHandlers.keypressed(btn)
|
||||||
|
local captured = false
|
||||||
|
if input.subscriptions.keypressed then
|
||||||
|
for index, sub in ipairs(input.subscriptions.keypressed) do
|
||||||
|
if sub.active ==true then
|
||||||
|
sub:emit( btn)
|
||||||
|
captured = true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return captured
|
||||||
|
end
|
||||||
|
|
||||||
|
function input.eventHandlers.keyreleased(btn)
|
||||||
|
local captured = false
|
||||||
|
if input.subscriptions.keyreleased then
|
||||||
|
for index, sub in ipairs(input.subscriptions.keyreleased) do
|
||||||
|
if sub.active then
|
||||||
|
sub:emit(btn)
|
||||||
|
captured = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return captured
|
||||||
|
end
|
||||||
|
|
||||||
|
function input.eventHandlers.mousemoved(x, y)
|
||||||
|
local captured = false
|
||||||
|
|
||||||
|
if input.subscriptions.hover then
|
||||||
|
for index, sub in ipairs(input.subscriptions.hover) do
|
||||||
|
local succ = sub:checkInside(x, y)
|
||||||
|
|
||||||
|
if succ and sub.active and not sub.currentEvent then
|
||||||
|
sub.cleanUp = sub:emit(x, y)
|
||||||
|
sub.currentEvent = true
|
||||||
|
captured = true
|
||||||
|
elseif sub.currentEvent and not sub:checkInside(x, y) then
|
||||||
|
sub.currentEvent = false
|
||||||
|
captured = true
|
||||||
|
if sub.cleanUp then
|
||||||
|
sub.cleanUp(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return captured
|
||||||
|
end
|
||||||
|
|
||||||
|
return input
|
||||||
BIN
helium-draft.pdf
Executable file
BIN
helium-draft.pdf
Executable file
Binary file not shown.
118
init.lua
Executable file
118
init.lua
Executable file
@ -0,0 +1,118 @@
|
|||||||
|
--[[--------------------------------------------------
|
||||||
|
Helium UI by qfx (qfluxstudios@gmail.com)
|
||||||
|
Copyright (c) 2019 Elmārs Āboliņš
|
||||||
|
gitlab.com/project link here
|
||||||
|
----------------------------------------------------]]
|
||||||
|
local path = ...
|
||||||
|
local helium = require(path..".dummy")
|
||||||
|
helium.utils = require(path..".utils")
|
||||||
|
helium.element = require(path..".core.element")
|
||||||
|
helium.input = require(path..".core.input")
|
||||||
|
helium.elementBuffer = {}
|
||||||
|
|
||||||
|
function helium.render()
|
||||||
|
for i, e in ipairs(helium.elementBuffer) do
|
||||||
|
e:externalRender()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function helium.update()
|
||||||
|
local remove = false
|
||||||
|
|
||||||
|
for i, e in ipairs(helium.elementBuffer) do
|
||||||
|
if e.settings.remove then
|
||||||
|
remove = true
|
||||||
|
else
|
||||||
|
e:externalUpdate()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if remove then
|
||||||
|
helium.utils.ArrayRemove(helium.elementBuffer, function(t, i)
|
||||||
|
--returns false or (true if nil)
|
||||||
|
return (not t[i].settings.remove)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
A user doesn't have to use this particular love.run
|
||||||
|
|
||||||
|
*.element.bufferUpdate()
|
||||||
|
*.draw()
|
||||||
|
|
||||||
|
Need to be called either through love.update and love.draw respectively
|
||||||
|
or put in to your custom love.run
|
||||||
|
|
||||||
|
And for inputs to work the love.event part needs to look something like this:
|
||||||
|
|
||||||
|
for name, a,b,c,d,e,f in love.event.poll() do
|
||||||
|
if name == "quit" then
|
||||||
|
if not love.quit or not love.quit() then
|
||||||
|
return a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not(gui.eventHandlers[name]) or not(helium.eventHandlers[name](a, b, c, d, e, f)) then
|
||||||
|
love.handlers[name](a, b, c, d, e, f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
]]
|
||||||
|
function love.run()
|
||||||
|
|
||||||
|
if love.math then
|
||||||
|
love.math.setRandomSeed(os.time())
|
||||||
|
end
|
||||||
|
|
||||||
|
if love.load then love.load(arg) end
|
||||||
|
|
||||||
|
-- We don't want the first frame's dt to include time taken by love.load.
|
||||||
|
if love.timer then love.timer.step() end
|
||||||
|
|
||||||
|
local dt = 0
|
||||||
|
|
||||||
|
-- Main loop time.
|
||||||
|
while true do
|
||||||
|
-- Process events.
|
||||||
|
if love.event then
|
||||||
|
love.event.pump()
|
||||||
|
for name, a,b,c,d,e,f in love.event.poll() do
|
||||||
|
if name == "quit" then
|
||||||
|
if not love.quit or not love.quit() then
|
||||||
|
return a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not(helium.input.eventHandlers[name]) or not(helium.input.eventHandlers[name](a, b, c, d, e, f)) then
|
||||||
|
love.handlers[name](a, b, c, d, e, f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Update dt, as we'll be passing it to update
|
||||||
|
if love.timer then
|
||||||
|
love.timer.step()
|
||||||
|
dt = love.timer.getDelta()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Call update and draw
|
||||||
|
if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled
|
||||||
|
helium.update()
|
||||||
|
|
||||||
|
if love.graphics and love.graphics.isActive() then
|
||||||
|
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||||
|
love.graphics.origin()
|
||||||
|
if love.draw then love.draw() end
|
||||||
|
helium.render()
|
||||||
|
love.graphics.present()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if love.timer then love.timer.sleep(0.00001) end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return helium
|
||||||
30
utils.lua
Executable file
30
utils.lua
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
local utils = {}
|
||||||
|
|
||||||
|
function utils.ArrayRemove(t, fnKeep)
|
||||||
|
local j, n = 1, #t;
|
||||||
|
|
||||||
|
for i=1,n do
|
||||||
|
if (fnKeep(t, i, j)) then
|
||||||
|
-- Move i's kept value to j's position, if it's not already there.
|
||||||
|
if (i ~= j) then
|
||||||
|
t[j] = t[i];
|
||||||
|
t[i] = nil;
|
||||||
|
end
|
||||||
|
j = j + 1; -- Increment position of where we'll place the next kept value.
|
||||||
|
else
|
||||||
|
t[i] = nil;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return t;
|
||||||
|
end
|
||||||
|
|
||||||
|
function utils.tableMerge(t, bt)
|
||||||
|
for i, e in pairs(t) do
|
||||||
|
if e ~= bt[i] then
|
||||||
|
bt[i] = e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return utils
|
||||||
Loading…
x
Reference in New Issue
Block a user