Hotswapping
This commit is contained in:
parent
2f4fbad405
commit
c30480520f
@ -55,7 +55,8 @@ element.__index = element
|
|||||||
setmetatable(element,{
|
setmetatable(element,{
|
||||||
__call = function(cls, ...)
|
__call = function(cls, ...)
|
||||||
local self
|
local self
|
||||||
if type(...)=='function' then
|
local func, loader = ...
|
||||||
|
if type(func)=='function' then
|
||||||
self = setmetatable({}, element)
|
self = setmetatable({}, element)
|
||||||
self.renderer = ...
|
self.renderer = ...
|
||||||
self.classless = true
|
self.classless = true
|
||||||
@ -64,7 +65,14 @@ setmetatable(element,{
|
|||||||
self.classless = false
|
self.classless = false
|
||||||
end
|
end
|
||||||
|
|
||||||
self:new(...)
|
if loader then
|
||||||
|
local function f(newFunc)
|
||||||
|
self:reLoader(newFunc)
|
||||||
|
end
|
||||||
|
loader(f)
|
||||||
|
end
|
||||||
|
|
||||||
|
self:new()
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -77,6 +85,7 @@ function element:updater() end
|
|||||||
|
|
||||||
function element:constructor() end
|
function element:constructor() end
|
||||||
|
|
||||||
|
|
||||||
--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()
|
function element:new()
|
||||||
@ -109,6 +118,12 @@ function element:new()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--Hotswapping code
|
||||||
|
function element:reLoader(newFunc)
|
||||||
|
self.renderer = newFunc
|
||||||
|
self.context:bubbleUpdate()
|
||||||
|
end
|
||||||
|
|
||||||
--Called once dimensions are validated
|
--Called once dimensions are validated
|
||||||
function element:setup()
|
function element:setup()
|
||||||
self.state =
|
self.state =
|
||||||
@ -156,13 +171,12 @@ function element:setup()
|
|||||||
--Classless rendering
|
--Classless rendering
|
||||||
if self.classless then
|
if self.classless then
|
||||||
self.classlessData.loadEffect = function (func)
|
self.classlessData.loadEffect = function (func)
|
||||||
if self.classlessData.loadCaptured then
|
if self.classlessData.loaded and self.classlessData.loadCaptured then
|
||||||
return unpack(self.classlessData.loadCaptured)
|
return self.classlessData.loadCaptured
|
||||||
else
|
elseif not self.classlessData.loaded then
|
||||||
self.classlessData.loadCaptured = func()
|
self.classlessData.loadCaptured = func()
|
||||||
if type(self.classlessData.loadCaptured) == 'table' then
|
self.classlessData.loaded = true
|
||||||
return unpack(self.classlessData.loadCaptured)
|
if self.classlessData.loadCaptured then
|
||||||
elseif self.classlessData.loadCaptured then
|
|
||||||
return self.classlessData.loadCaptured
|
return self.classlessData.loadCaptured
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -184,7 +198,11 @@ function element:setup()
|
|||||||
self.classlessState[indice].state = set
|
self.classlessState[indice].state = set
|
||||||
self.context:bubbleUpdate()
|
self.context:bubbleUpdate()
|
||||||
end
|
end
|
||||||
return self.classlessState[indice].state, self.classlessState[indice].setState
|
|
||||||
|
self.classlessState[indice].getState = function()
|
||||||
|
return self.classlessState[indice].state
|
||||||
|
end
|
||||||
|
return self.classlessState[indice].state, self.classlessState[indice].setState, self.classlessState[indice].getState
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -193,15 +211,28 @@ end
|
|||||||
function element:classlessRender()
|
function element:classlessRender()
|
||||||
self.inputContext:set()
|
self.inputContext:set()
|
||||||
self.settings.indice = 0
|
self.settings.indice = 0
|
||||||
|
if type(self.renderer)=='function' then
|
||||||
|
local denv = getfenv(self.renderer)
|
||||||
|
denv['useState'] = self.classlessData.useState
|
||||||
|
denv['loadEffect'] = self.classlessData.loadEffect
|
||||||
|
|
||||||
local denv = getfenv(self.renderer)
|
local status,err = pcall(self.renderer,self.parameters, self.view.w, self.view.h)
|
||||||
denv['useState'] = self.classlessData.useState
|
|
||||||
denv['loadEffect'] = self.classlessData.loadEffect
|
|
||||||
|
|
||||||
self.renderer(self.parameters, self.view.w, self.view.h)
|
if not status then
|
||||||
|
love.graphics.setColor(1,0,0)
|
||||||
|
love.graphics.rectangle('line',0,0,self.view.w,self.view.h)
|
||||||
|
love.graphics.setColor(1,1,1)
|
||||||
|
love.graphics.printf("Error: "..err,0,0,self.view.w)
|
||||||
|
end
|
||||||
|
|
||||||
denv['useState'] = nil
|
denv['useState'] = nil
|
||||||
denv['loadEffect'] = nil
|
denv['loadEffect'] = nil
|
||||||
|
elseif type(self.renderer)=='string' then
|
||||||
|
love.graphics.setColor(1,0,0)
|
||||||
|
love.graphics.rectangle('line',0,0,self.view.w,self.view.h)
|
||||||
|
love.graphics.setColor(1,1,1)
|
||||||
|
love.graphics.printf("Error: "..self.renderer,0,0,self.view.w)
|
||||||
|
end
|
||||||
self.inputContext:unset()
|
self.inputContext:unset()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
106
debugLoader.lua
Normal file
106
debugLoader.lua
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
local path = string.sub(..., 1, string.len(...) - string.len(".debugLoader"))
|
||||||
|
local helium = require(path..'.dummy')
|
||||||
|
local elements = {}
|
||||||
|
local debugLoader = {}
|
||||||
|
--Return level: 1--string; 2--chunk; 3--return value; default: element factory
|
||||||
|
local function loader(path)
|
||||||
|
local succ = true
|
||||||
|
|
||||||
|
--File string
|
||||||
|
local fileContents, err = love.filesystem.read(path)
|
||||||
|
|
||||||
|
if fileContents==nil then
|
||||||
|
print('Error loading ',path,':',tostring(err),', will continue watching!')
|
||||||
|
succ = false
|
||||||
|
end
|
||||||
|
|
||||||
|
local t, lastLoaded
|
||||||
|
if succ then
|
||||||
|
t = love.filesystem.getInfo(path)
|
||||||
|
lastLoaded = t['modtime']
|
||||||
|
end
|
||||||
|
|
||||||
|
--Chunk
|
||||||
|
local status, err
|
||||||
|
if succ then
|
||||||
|
status, err = pcall(loadstring,fileContents)
|
||||||
|
end
|
||||||
|
|
||||||
|
if status==false or status==nil then
|
||||||
|
print('Error compiling ',path,':',tostring(err),', will continue watching!')
|
||||||
|
succ = false
|
||||||
|
end
|
||||||
|
|
||||||
|
--Return values
|
||||||
|
local ret
|
||||||
|
if succ then
|
||||||
|
succ, ret = pcall(err,path)
|
||||||
|
if not succ then
|
||||||
|
print('Error calling ',path,':',tostring(ret))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return fileContents, err, ret, lastLoaded
|
||||||
|
end
|
||||||
|
|
||||||
|
debugLoader.loader = function(path,returnLevel)
|
||||||
|
local level = returnLevel or 6
|
||||||
|
if elements[path] then
|
||||||
|
return elements[path][level]
|
||||||
|
end
|
||||||
|
|
||||||
|
local setfuncs = {}
|
||||||
|
|
||||||
|
local fileContents, func, ret, lastLoaded = loader(path)
|
||||||
|
local reloader = function(setFunc)
|
||||||
|
setfuncs[#setfuncs+1] = setFunc
|
||||||
|
end
|
||||||
|
|
||||||
|
local factory = function()
|
||||||
|
return helium.element(ret, reloader)
|
||||||
|
end
|
||||||
|
|
||||||
|
elements[path] = { fileContents, func, ret, path, lastLoaded, factory, setfuncs = setfuncs }
|
||||||
|
return elements[path][level]
|
||||||
|
end
|
||||||
|
|
||||||
|
local counter = 0
|
||||||
|
function debugLoader.update(dt)
|
||||||
|
counter = counter+dt
|
||||||
|
if counter>2 then
|
||||||
|
for ind, elem in pairs(elements) do
|
||||||
|
--Get the current last save time
|
||||||
|
local t = love.filesystem.getInfo(elem[4])
|
||||||
|
local ll = t['modtime']
|
||||||
|
if ll ~= elem[5] then
|
||||||
|
--If last save time differs then start reload sequence
|
||||||
|
local _, _, ret, lastLoaded = loader(elem[4])
|
||||||
|
|
||||||
|
|
||||||
|
local setfuncs = {}
|
||||||
|
|
||||||
|
local reloader = function(setFunc)
|
||||||
|
setfuncs[#setfuncs+1] = setFunc
|
||||||
|
end
|
||||||
|
|
||||||
|
local factory = function()
|
||||||
|
return helium.element(ret, reloader)
|
||||||
|
end
|
||||||
|
|
||||||
|
elem[5] = lastLoaded
|
||||||
|
|
||||||
|
elem[6] = factory
|
||||||
|
|
||||||
|
for i, func in ipairs(elem.setfuncs) do
|
||||||
|
func(ret)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
counter = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
HeliumLoader = debugLoader.loader
|
||||||
|
|
||||||
|
return debugLoader
|
||||||
4
init.lua
4
init.lua
@ -8,6 +8,7 @@ local helium = require(path..".dummy")
|
|||||||
helium.utils = require(path..".utils")
|
helium.utils = require(path..".utils")
|
||||||
helium.element = require(path..".core.element")
|
helium.element = require(path..".core.element")
|
||||||
helium.input = require(path..".core.input")
|
helium.input = require(path..".core.input")
|
||||||
|
helium.debugLoader = require(path..".debugLoader")
|
||||||
helium.elementBuffer = {}
|
helium.elementBuffer = {}
|
||||||
|
|
||||||
function helium.render()
|
function helium.render()
|
||||||
@ -99,7 +100,8 @@ function love.run()
|
|||||||
|
|
||||||
-- Call update and draw
|
-- Call update and draw
|
||||||
if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled
|
if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled
|
||||||
helium.update()
|
helium.update(dt)
|
||||||
|
helium.debugLoader.update(dt)
|
||||||
|
|
||||||
if love.graphics and love.graphics.isActive() then
|
if love.graphics and love.graphics.isActive() then
|
||||||
love.graphics.clear(love.graphics.getBackgroundColor())
|
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user