immediate mode implementation

This commit is contained in:
Elmārs Āboliņš 2020-08-12 02:07:06 +03:00
parent 02cd8eba19
commit c764f3ca9a
3 changed files with 47 additions and 57 deletions

View File

@ -25,6 +25,7 @@ setmetatable(element, {
end end
self:new(param) self:new(param)
self:createProxies(param)
return self return self
end end
@ -32,12 +33,9 @@ setmetatable(element, {
--Control functions --Control functions
--The new function that should be used for element creation --The new function that should be used for element creation
function element:new(param) function element:new(param, immediate)
local dimensions
--save the parameters
self.parameters = {} self.parameters = {}
--The element canvas
self.baseParams = param self.baseParams = param
--Internal settings --Internal settings
@ -54,13 +52,11 @@ function element:new(param)
--Has it been inserted in to the buffer --Has it been inserted in to the buffer
inserted = false, inserted = false,
--Whether this element is created and drawn instantly (and doesn't need a canvas) --Whether this element is created and drawn instantly (and doesn't need a canvas)
immediate = false, immediate = immediate or false,
--Render this element in the external buffer with absolute coordinates --Render this element in the external buffer with absolute coordinates
absolutePosition = false, absolutePosition = false,
} }
self.baseState = {}
self.baseView = { self.baseView = {
x = 0, x = 0,
y = 0, y = 0,
@ -69,7 +65,12 @@ function element:new(param)
minW = 10, minW = 10,
minH = 10, minH = 10,
} }
self.view = self.baseView
end
function element:createProxies()
self.view = setmetatable({}, { self.view = setmetatable({}, {
__index = function(t, index) __index = function(t, index)
return self.baseView[index] return self.baseView[index]
@ -83,10 +84,27 @@ function element:new(param)
end end
}) })
self.parameters = setmetatable({}, {
__index = function(t, index)
return self.baseParams[index]
end,
__newindex = function(t, index, val)
if self.baseParams[index] ~= val then
self.baseParams[index] = val
self.context:bubbleUpdate()
end
end
})
--Context makes sure element internals don't have to worry about absolute coordinates --Context makes sure element internals don't have to worry about absolute coordinates
self.context = context.new(self) self.context = context.new(self)
end end
function element:setParam(p)
self.baseParams = p
self.context:bubbleUpdate()
end
function element:setCalculatedSize(w, h) function element:setCalculatedSize(w, h)
self.view.minW = w or self.view.minW self.view.minW = w or self.view.minW
self.view.minH = h or self.view.minH self.view.minH = h or self.view.minH
@ -115,45 +133,23 @@ function element:updateInputCtx()
end end
end end
local dummy = function() end
--Immediate mode code(don't call directly) --Immediate mode code(don't call directly)
function element.immediate(param, func, x, y, w, h) function element.immediate(param, func, x, y, w, h)
--Need to capture this by the current parent context
end --Todo:
local ctx = context.getContext()
if ctx then
--Hotswapping code local self = setmetatable({}, element)
self = element:new(param, true)
function element:reLoader(newFunc)
self.context:set()
self.parentFunc = newFunc
if type(self.parentFunc) == 'function' then
self.renderer = self.parentFunc(self.parameters, self.state, self.view)
else else
self.renderer = self.parentFunc error("Can't render immediate outside of element")
end end
self.context:unset()
self.context:bubbleUpdate()
end end
local newCanvas,newQuad = love.graphics.newCanvas,love.graphics.newQuad local newCanvas, newQuad = love.graphics.newCanvas, love.graphics.newQuad
--Called once dimensions are validated --Called once dimensions are validated
function element:setup() function element:setup()
self.parameters = setmetatable({}, {
__index = function(t, index)
return self.baseParams[index]
end,
__newindex = function(t, index, val)
if self.baseParams[index] ~= val then
self.baseParams[index] = val
self.context:bubbleUpdate()
end
end
})
self.context:set() self.context:set()
self.renderer = self.parentFunc(self.parameters, self.view.w, self.view.h) self.renderer = self.parentFunc(self.parameters, self.view.w, self.view.h)
self.context:unset() self.context:unset()
@ -167,7 +163,7 @@ function element:setup()
self.settings.isSetup = true self.settings.isSetup = true
end end
local setColor,rectangle,setFont,printf = love.graphics.setColor,love.graphics.rectangle,love.graphics.setFont,love.graphics.printf local setColor, rectangle, setFont, printf = love.graphics.setColor, love.graphics.rectangle, love.graphics.setFont, love.graphics.printf
function element:errorRender(msg) function element:errorRender(msg)
setColor(1, 0, 0) setColor(1, 0, 0)
rectangle('line', 0, 0, self.view.w, self.view.h) rectangle('line', 0, 0, self.view.w, self.view.h)
@ -176,7 +172,6 @@ function element:errorRender(msg)
end end
function element:internalRender() function element:internalRender()
if type(self.renderer) == 'function' then if type(self.renderer) == 'function' then
love.graphics.push() love.graphics.push()
love.graphics.origin() love.graphics.origin()
@ -198,13 +193,8 @@ function element:internalRender()
end end
end end
local getCanvas,setCanvas,clear = love.graphics.getCanvas,love.graphics.setCanvas,love.graphics.clear local getCanvas, setCanvas, clear = love.graphics.getCanvas, love.graphics.setCanvas, love.graphics.clear
function element:renderWrapper() function element:renderWrapper()
if not self.settings.isSetup then
self:setup()
self.settings.isSetup = true
end
self.context:set() self.context:set()
local cnvs = getCanvas() local cnvs = getCanvas()
setCanvas({self.canvas, stencil = true}) setCanvas({self.canvas, stencil = true})
@ -227,6 +217,11 @@ function element:externalRender()
self.settings.needsRendering = true self.settings.needsRendering = true
end end
if not self.settings.isSetup then
self:setup()
self.settings.isSetup = true
end
if self.settings.needsRendering then if self.settings.needsRendering then
self:renderWrapper() self:renderWrapper()
self.settings.needsRendering = false self.settings.needsRendering = false
@ -265,9 +260,6 @@ function element:draw(x, y, w, h)
if self.settings.firstDraw then if self.settings.firstDraw then
self.settings.remove = false self.settings.remove = false
if self.baseState.onFirstDraw then
self.baseState.onFirstDraw()
end
self.settings.firstDraw = false self.settings.firstDraw = false
end end
@ -280,9 +272,6 @@ function element:draw(x, y, w, h)
end end
function element:destroy() function element:destroy()
if self.baseState.onDestroy then
self.baseState.onDestroy()
end
self.settings.remove = true self.settings.remove = true
self.settings.firstDraw = true self.settings.firstDraw = true
self.settings.isSetup = false self.settings.isSetup = false

View File

@ -68,7 +68,7 @@ end
function context:destroy() function context:destroy()
self.elem:undraw() self.elem:undraw()
for i=1,#self.childrenContexts do for i = 1, #self.childrenContexts do
self.childrenContexts[i]:destroy() self.childrenContexts[i]:destroy()
end end
end end

View File

@ -15,11 +15,12 @@ helium.__index = helium
setmetatable(helium, {__call = function(s, chunk) setmetatable(helium, {__call = function(s, chunk)
return setmetatable({ return setmetatable({
draw = function (param, x, y, w, h) draw = function (param, inputs, x, y, w, h)
return helium.element.immediate(param, chunk, x, y, w, h) return helium.element.immediate(param, inputs, chunk, x, y, w, h)
end end
},{__call = function(s, param) },
return helium.element(chunk, nil, param) {__call = function(s, param)
return helium.element(chunk, param)
end,}) end,})
end}) end})