commit
This commit is contained in:
parent
c764f3ca9a
commit
f023959137
139
core/element.lua
139
core/element.lua
@ -12,19 +12,12 @@ local type,pcall = type,pcall
|
|||||||
setmetatable(element, {
|
setmetatable(element, {
|
||||||
__call = function(cls, ...)
|
__call = function(cls, ...)
|
||||||
local self
|
local self
|
||||||
local func, loader, param = ...
|
local func, param, w, h = ...
|
||||||
|
|
||||||
self = setmetatable({}, element)
|
self = setmetatable({}, element)
|
||||||
self.parentFunc = func
|
self.parentFunc = func
|
||||||
|
|
||||||
if loader then
|
self:new(param,nil, w, h)
|
||||||
local function f(newFunc)
|
|
||||||
self:reLoader(newFunc)
|
|
||||||
end
|
|
||||||
loader(f)
|
|
||||||
end
|
|
||||||
|
|
||||||
self:new(param)
|
|
||||||
self:createProxies(param)
|
self:createProxies(param)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -33,7 +26,7 @@ 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, immediate)
|
function element:new(param, immediate, w, h)
|
||||||
self.parameters = {}
|
self.parameters = {}
|
||||||
|
|
||||||
self.baseParams = param
|
self.baseParams = param
|
||||||
@ -43,27 +36,34 @@ function element:new(param, immediate)
|
|||||||
isSetup = false,
|
isSetup = false,
|
||||||
pendingUpdate = true,
|
pendingUpdate = true,
|
||||||
needsRendering = true,
|
needsRendering = true,
|
||||||
|
remove = false,
|
||||||
--Unused for now?
|
--Unused for now?
|
||||||
calculatedDimensions = true,
|
calculatedDimensions = true,
|
||||||
--Is this the first render
|
--Is this the first render
|
||||||
firstDraw = true,
|
firstDraw = true,
|
||||||
--Stabilize the internal canvas, draw it twice on first load
|
|
||||||
stabilize = true,
|
|
||||||
--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 = immediate or false,
|
immediate = immediate or false,
|
||||||
--Render this element in the external buffer with absolute coordinates
|
--Whether this element has a canvas assigned
|
||||||
absolutePosition = false,
|
hasCanvas = false,
|
||||||
|
--Current test render passes to be benchmarked
|
||||||
|
testRenderPasses = love.math.random(3, 6),
|
||||||
|
--
|
||||||
|
failedCanvas = false
|
||||||
|
}
|
||||||
|
|
||||||
|
self.renderBench = {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.baseView = {
|
self.baseView = {
|
||||||
x = 0,
|
x = 0,
|
||||||
y = 0,
|
y = 0,
|
||||||
w = 10,
|
w = w or 10,
|
||||||
h = 10,
|
h = h or 10,
|
||||||
minW = 10,
|
minW = w or 10,
|
||||||
minH = 10,
|
minH = h or 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.view = self.baseView
|
self.view = self.baseView
|
||||||
@ -100,6 +100,34 @@ function element:createProxies()
|
|||||||
self.context = context.new(self)
|
self.context = context.new(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--Random coefficients, if these reach 1.5 then canvas is made
|
||||||
|
local childrenNum = 5
|
||||||
|
local selfRenderTime = 0.0005
|
||||||
|
local screenSize = 1/8
|
||||||
|
local coefficient = 1.5
|
||||||
|
|
||||||
|
function element:calculateCanvasCoeficient(selfTime)
|
||||||
|
local sW, sH = love.graphics.getDimensions()
|
||||||
|
local areaBelow = (sW * sH) * screenSize
|
||||||
|
local area = self.view.h * self.view.w
|
||||||
|
|
||||||
|
local areaCoef = 1 - (area/areaBelow)
|
||||||
|
local childCoef = self.context:getChildrenCount()/childrenNum
|
||||||
|
local sizeCoef = selfTime/selfRenderTime
|
||||||
|
|
||||||
|
|
||||||
|
return (areaCoef+childCoef+sizeCoef)>coefficient
|
||||||
|
end
|
||||||
|
|
||||||
|
local newCanvas, newQuad = love.graphics.newCanvas, love.graphics.newQuad
|
||||||
|
function element:createCanvas()
|
||||||
|
self.settings.canvasW = self.view.w*1.25
|
||||||
|
self.settings.canvasH = self.view.h*1.25
|
||||||
|
|
||||||
|
self.canvas = newCanvas(self.view.w*1.25, self.view.h*1.25)
|
||||||
|
self.quad = newQuad(0, 0, self.view.w, self.view.h, self.view.w*1.25, self.view.h*1.25)
|
||||||
|
end
|
||||||
|
|
||||||
function element:setParam(p)
|
function element:setParam(p)
|
||||||
self.baseParams = p
|
self.baseParams = p
|
||||||
self.context:bubbleUpdate()
|
self.context:bubbleUpdate()
|
||||||
@ -113,8 +141,8 @@ function element:setCalculatedSize(w, h)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function element:updateInputCtx()
|
function element:updateInputCtx()
|
||||||
self.context.inputContext:update()
|
--self.context.inputContext:update()
|
||||||
if self.settings.canvasW then
|
--[[if self.settings.canvasW then
|
||||||
--If canvas too small make a bigger one
|
--If canvas too small make a bigger one
|
||||||
if self.settings.canvasW < self.view.w or self.settings.canvasH < self.view.h then
|
if self.settings.canvasW < self.view.w or self.settings.canvasH < self.view.h then
|
||||||
self.settings.canvasW = self.view.w*1.25
|
self.settings.canvasW = self.view.w*1.25
|
||||||
@ -130,7 +158,7 @@ function element:updateInputCtx()
|
|||||||
end
|
end
|
||||||
|
|
||||||
self.quad = love.graphics.newQuad(0, 0, self.view.w, self.view.h, self.settings.canvasW, self.settings.canvasH)
|
self.quad = love.graphics.newQuad(0, 0, self.view.w, self.view.h, self.settings.canvasW, self.settings.canvasH)
|
||||||
end
|
end]]
|
||||||
end
|
end
|
||||||
|
|
||||||
local dummy = function() end
|
local dummy = function() end
|
||||||
@ -143,23 +171,16 @@ function element.immediate(param, func, x, y, w, h)
|
|||||||
local self = setmetatable({}, element)
|
local self = setmetatable({}, element)
|
||||||
self = element:new(param, true)
|
self = element:new(param, true)
|
||||||
else
|
else
|
||||||
error("Can't render immediate outside of element")
|
error("Can't render immediate outside of persistent")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
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.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()
|
||||||
|
|
||||||
self.settings.canvasW = self.view.w*1.25
|
|
||||||
self.settings.canvasH = self.view.h*1.25
|
|
||||||
|
|
||||||
self.canvas = newCanvas(self.view.w*1.25, self.view.h*1.25)
|
|
||||||
self.quad = newQuad(0, 0, self.view.w, self.view.h, self.view.w*1.25, self.view.h*1.25)
|
|
||||||
|
|
||||||
self.settings.isSetup = true
|
self.settings.isSetup = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -171,11 +192,26 @@ function element:errorRender(msg)
|
|||||||
printf("Error: "..msg, 0, 0, self.view.w)
|
printf("Error: "..msg, 0, 0, self.view.w)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local calcT
|
||||||
|
|
||||||
function element:internalRender()
|
function element:internalRender()
|
||||||
if type(self.renderer) == 'function' then
|
|
||||||
love.graphics.push()
|
love.graphics.push()
|
||||||
|
if self.settings.hasCanvas then
|
||||||
love.graphics.origin()
|
love.graphics.origin()
|
||||||
|
else
|
||||||
|
love.graphics.translate(self.view.x, self.view.y)
|
||||||
|
local gx, gy = love.graphics.transformPoint(self.view.x, self.view.y)
|
||||||
|
end
|
||||||
|
if self.settings.testRenderPasses > 0 then
|
||||||
|
calcT = love.timer.getTime()
|
||||||
|
end
|
||||||
local status, err = pcall(self.renderer)
|
local status, err = pcall(self.renderer)
|
||||||
|
if self.settings.testRenderPasses > 0 then
|
||||||
|
self.settings.testRenderPasses = self.settings.testRenderPasses-1
|
||||||
|
local selfTime = love.timer.getTime()-calcT
|
||||||
|
table.insert(self.renderBench, self.context:endSelfRender(selfTime))
|
||||||
|
end
|
||||||
|
|
||||||
love.graphics.pop()
|
love.graphics.pop()
|
||||||
|
|
||||||
if not status then
|
if not status then
|
||||||
@ -184,20 +220,12 @@ function element:internalRender()
|
|||||||
end
|
end
|
||||||
self:errorRender(status)
|
self:errorRender(status)
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif type(self.renderer) == 'string' then
|
|
||||||
if helium.conf.HARD_ERROR then
|
|
||||||
error(self.renderer)
|
|
||||||
end
|
|
||||||
self:errorRender(self.renderer)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local draw = love.graphics.draw
|
||||||
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()
|
||||||
self.context:set()
|
self.context:set()
|
||||||
local cnvs = getCanvas()
|
|
||||||
setCanvas({self.canvas, stencil = true})
|
|
||||||
|
|
||||||
clear()
|
clear()
|
||||||
|
|
||||||
@ -206,32 +234,51 @@ function element:renderWrapper()
|
|||||||
self.settings.pendingUpdate = false
|
self.settings.pendingUpdate = false
|
||||||
end
|
end
|
||||||
|
|
||||||
setCanvas(cnvs)
|
|
||||||
self.context:unset()
|
self.context:unset()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local draw = love.graphics.draw
|
|
||||||
function element:externalRender()
|
function element:externalRender()
|
||||||
if self.settings.stabilize and not self.settings.needsRendering then
|
local cnvs = getCanvas()
|
||||||
self.settings.stabilize = false
|
|
||||||
self.settings.needsRendering = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if not self.settings.isSetup then
|
if not self.settings.isSetup then
|
||||||
self:setup()
|
self:setup()
|
||||||
self.settings.isSetup = true
|
self.settings.isSetup = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
setCanvas(self.canvas)
|
||||||
if self.settings.needsRendering then
|
if self.settings.needsRendering then
|
||||||
self:renderWrapper()
|
self:renderWrapper()
|
||||||
self.settings.needsRendering = false
|
self.settings.needsRendering = not self.settings.hasCanvas
|
||||||
end
|
end
|
||||||
|
|
||||||
|
setCanvas(cnvs)
|
||||||
|
if self.settings.hasCanvas then
|
||||||
|
|
||||||
setColor(1,1,1)
|
setColor(1,1,1)
|
||||||
draw(self.canvas, self.quad, self.view.x, self.view.y)
|
draw(self.canvas, self.quad, self.view.x, self.view.y)
|
||||||
|
love.graphics.rectangle('line', self.view.x, self.view.y, self.view.w, self.view.h)
|
||||||
|
end
|
||||||
|
print(self.view.x, self.view.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
function element:externalUpdate()
|
function element:externalUpdate()
|
||||||
|
if not self.settings.failedCanvas and self.settings.testRenderPasses == 0 and not self.settings.hasCanvas then
|
||||||
|
local avg, sum = 0, 0
|
||||||
|
|
||||||
|
for i, e in ipairs(self.renderBench) do
|
||||||
|
sum = sum + e
|
||||||
|
end
|
||||||
|
|
||||||
|
avg = sum/#self.renderBench
|
||||||
|
|
||||||
|
if self:calculateCanvasCoeficient(avg) then
|
||||||
|
self:createCanvas()
|
||||||
|
self.settings.hasCanvas = true
|
||||||
|
else
|
||||||
|
self.settings.failedCanvas = true
|
||||||
|
end
|
||||||
|
end
|
||||||
if self.settings.pendingUpdate then
|
if self.settings.pendingUpdate then
|
||||||
if self.updater then
|
if self.updater then
|
||||||
self:updater()
|
self:updater()
|
||||||
|
|||||||
@ -15,7 +15,8 @@ function context.new(elem)
|
|||||||
view = elem.view,
|
view = elem.view,
|
||||||
element = elem,
|
element = elem,
|
||||||
childrenContexts = {},
|
childrenContexts = {},
|
||||||
inputContext = helium.input.newContext(elem)
|
inputContext = helium.input.newContext(elem),
|
||||||
|
childRenderTime = 0
|
||||||
}, context)
|
}, context)
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
@ -66,6 +67,21 @@ function context:unsuspend()
|
|||||||
self.inputContext:unsuspend()
|
self.inputContext:unsuspend()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function context:startSelfRender()
|
||||||
|
self.childRenderTime = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function context:passTimeTo(time)
|
||||||
|
self.childRenderTime = self.childRenderTime + time
|
||||||
|
end
|
||||||
|
|
||||||
|
function context:endSelfRender(time)
|
||||||
|
if self.parentCtx then
|
||||||
|
self.parentCtx:passTimeTo(time)
|
||||||
|
end
|
||||||
|
return time-self.childRenderTime
|
||||||
|
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
|
||||||
@ -79,10 +95,15 @@ function context:suspend()
|
|||||||
self.inputContext:unset()
|
self.inputContext:unset()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function context:getChildrenCount()
|
||||||
|
return #self.childrenContexts
|
||||||
|
end
|
||||||
|
|
||||||
--Function meant for external context capture
|
--Function meant for external context capture
|
||||||
function context.getContext()
|
function context.getContext()
|
||||||
return activeContext
|
return activeContext
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return context
|
return context
|
||||||
5
init.lua
5
init.lua
@ -19,15 +19,14 @@ setmetatable(helium, {__call = function(s, chunk)
|
|||||||
return helium.element.immediate(param, inputs, chunk, x, y, w, h)
|
return helium.element.immediate(param, inputs, chunk, x, y, w, h)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{__call = function(s, param)
|
{__call = function(s, param, w, h)
|
||||||
return helium.element(chunk, param)
|
return helium.element(chunk, param, w, h)
|
||||||
end,})
|
end,})
|
||||||
end})
|
end})
|
||||||
|
|
||||||
function helium.render()
|
function helium.render()
|
||||||
--We don't want any side effects affecting internal rendering
|
--We don't want any side effects affecting internal rendering
|
||||||
love.graphics.reset()
|
love.graphics.reset()
|
||||||
|
|
||||||
for i, e in ipairs(helium.elementBuffer) do
|
for i, e in ipairs(helium.elementBuffer) do
|
||||||
e:externalRender()
|
e:externalRender()
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user