help
This commit is contained in:
parent
32befc1a89
commit
3bd423243e
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
local_conf.lua
|
||||
local_conf.lua
|
||||
|
||||
64
README.md
64
README.md
@ -1,33 +1,33 @@
|
||||

|
||||
# Helium
|
||||
## Major features:
|
||||
### Custom elements
|
||||
Write your own elements, and interface with them however you want to,
|
||||
Whether you need a generalized button that can have many themes and options or something super specific, it can be done
|
||||
### Efficient rendering & updating
|
||||
The elements only update&re-render when state changes
|
||||
### Code hotswap
|
||||
Change and save a file loaded through the helium.loader, and see changes immediately
|
||||
|
||||
## Basic overview:
|
||||
Helium is practically more like a UI framework than a fully fledged UI library.
|
||||
The idea is to build custom, build simple and build fast, encapsulate.
|
||||
|
||||
## Demo's / Practical examples
|
||||
[There's a repository of examples here](https://github.com/qfluxstudio/helium_demos)
|
||||
|
||||
## Getting started:
|
||||
Load helium with `local helium = require 'helium'`
|
||||
|
||||
The basic structure for an element is:
|
||||
|
||||
```lua
|
||||
return function(param,state,view)
|
||||
--Setup zone
|
||||
return function()
|
||||
--Rendering zone
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||

|
||||
# Helium
|
||||
## Major features:
|
||||
### Custom elements
|
||||
Write your own elements, and interface with them however you want to,
|
||||
Whether you need a generalized button that can have many themes and options or something super specific, it can be done
|
||||
### Efficient rendering & updating
|
||||
The elements only update&re-render when state changes
|
||||
### Code hotswap
|
||||
Change and save a file loaded through the helium.loader, and see changes immediately
|
||||
|
||||
## Basic overview:
|
||||
Helium is practically more like a UI framework than a fully fledged UI library.
|
||||
The idea is to build custom, build simple and build fast, encapsulate.
|
||||
|
||||
## Demo's / Practical examples
|
||||
[There's a repository of examples here](https://github.com/qfluxstudio/helium_demos)
|
||||
|
||||
## Getting started:
|
||||
Load helium with `local helium = require 'helium'`
|
||||
|
||||
The basic structure for an element is:
|
||||
|
||||
```lua
|
||||
return function(param,state,view)
|
||||
--Setup zone
|
||||
return function()
|
||||
--Rendering zone
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
[The documentation outgrew this readme, see the github wiki](https://github.com/qfluxstudio/helium/wiki/)
|
||||
12
conf.lua
12
conf.lua
@ -1,7 +1,7 @@
|
||||
return {
|
||||
HOTSWAP = true, --Turns on hotswap, disable this once you're deploying a project
|
||||
AUTO_RUN = true, --Replaces the default love.run
|
||||
DEBUG = true, --Reserved for later
|
||||
PURE_G = true, --whether to keep _G pure
|
||||
HARD_ERROR = true, --Whether to display element errors inside or hard cras
|
||||
return {
|
||||
HOTSWAP = true, --Turns on hotswap, disable this once you're deploying a project
|
||||
AUTO_RUN = true, --Replaces the default love.run
|
||||
DEBUG = true, --Reserved for later
|
||||
PURE_G = true, --whether to keep _G pure
|
||||
HARD_ERROR = true, --Whether to display element errors inside or hard cras
|
||||
}
|
||||
@ -1,61 +1,61 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".core.layout"))
|
||||
|
||||
local layout = {}
|
||||
layout.__index = layout
|
||||
local element = require(path..'core.element')
|
||||
|
||||
local function layout_new(type, x, y, w, h)
|
||||
local ctx = element.getContext()
|
||||
|
||||
--The output will be in pixel numbers regardless of inputs
|
||||
if x <= 1 or not x then
|
||||
x = ctx.view.x * (x or 0)
|
||||
end
|
||||
|
||||
if y <= 1 then
|
||||
y = ctx.view.y * (y or 0)
|
||||
end
|
||||
|
||||
if w <= 1 then
|
||||
w = ctx.view.w * (w or 1)
|
||||
end
|
||||
|
||||
if h <= 1 then
|
||||
h = ctx.view.h * (h or 1)
|
||||
end
|
||||
|
||||
return setmetatable({
|
||||
x = x,
|
||||
y = y,
|
||||
w = w,
|
||||
h = h
|
||||
}, layout)
|
||||
end
|
||||
|
||||
|
||||
--Sets mode for the proceding operations
|
||||
function layout.mode()
|
||||
|
||||
end
|
||||
|
||||
--Sets padding for the next operations
|
||||
function layout.pad()
|
||||
|
||||
end
|
||||
|
||||
--Sets margins for the proceding operations
|
||||
function layout.margin()
|
||||
|
||||
end
|
||||
|
||||
function layout.offset()
|
||||
|
||||
end
|
||||
|
||||
function layout:draw()
|
||||
|
||||
end
|
||||
|
||||
layout(0,0,1,1)
|
||||
|
||||
return layout
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".core.layout"))
|
||||
|
||||
local layout = {}
|
||||
layout.__index = layout
|
||||
local element = require(path..'core.element')
|
||||
|
||||
local function layout_new(type, x, y, w, h)
|
||||
local ctx = element.getContext()
|
||||
|
||||
--The output will be in pixel numbers regardless of inputs
|
||||
if x <= 1 or not x then
|
||||
x = ctx.view.x * (x or 0)
|
||||
end
|
||||
|
||||
if y <= 1 then
|
||||
y = ctx.view.y * (y or 0)
|
||||
end
|
||||
|
||||
if w <= 1 then
|
||||
w = ctx.view.w * (w or 1)
|
||||
end
|
||||
|
||||
if h <= 1 then
|
||||
h = ctx.view.h * (h or 1)
|
||||
end
|
||||
|
||||
return setmetatable({
|
||||
x = x,
|
||||
y = y,
|
||||
w = w,
|
||||
h = h
|
||||
}, layout)
|
||||
end
|
||||
|
||||
|
||||
--Sets mode for the proceding operations
|
||||
function layout.mode()
|
||||
|
||||
end
|
||||
|
||||
--Sets padding for the next operations
|
||||
function layout.pad()
|
||||
|
||||
end
|
||||
|
||||
--Sets margins for the proceding operations
|
||||
function layout.margin()
|
||||
|
||||
end
|
||||
|
||||
function layout.offset()
|
||||
|
||||
end
|
||||
|
||||
function layout:draw()
|
||||
|
||||
end
|
||||
|
||||
layout(0,0,1,1)
|
||||
|
||||
return layout
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".control.size"))
|
||||
local stack = require(path..'.core.stack')
|
||||
|
||||
--Sets the computed/minimum size of an element to be used with layout calculations and rendering
|
||||
return function(w, h)
|
||||
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".control.size"))
|
||||
local stack = require(path..'.core.stack')
|
||||
|
||||
--Sets the computed/minimum size of an element to be used with layout calculations and rendering
|
||||
return function(w, h)
|
||||
local currentStack = stack.getContext()
|
||||
currentStack.element:setCalculatedSize(w, h)
|
||||
end
|
||||
@ -1,19 +1,19 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".control.state"))
|
||||
local context = require(path.. ".core.context")
|
||||
|
||||
return function (base)
|
||||
local base = base or {}
|
||||
local fakeBase = {}
|
||||
local activeContext = context.getContext()
|
||||
return setmetatable({},{
|
||||
__index = function(t, index)
|
||||
return fakeBase[index] or base[index]
|
||||
end,
|
||||
__newindex = function(t, index, val)
|
||||
if fakeBase[index] ~= val then
|
||||
fakeBase[index] = val
|
||||
activeContext:bubbleUpdate()
|
||||
end
|
||||
end
|
||||
})
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".control.state"))
|
||||
local context = require(path.. ".core.stack")
|
||||
|
||||
return function (base)
|
||||
base = base or {}
|
||||
local fakeBase = {}
|
||||
local activeContext = context.getContext()
|
||||
return setmetatable({},{
|
||||
__index = function(t, index)
|
||||
return fakeBase[index] or base[index]
|
||||
end,
|
||||
__newindex = function(t, index, val)
|
||||
if fakeBase[index] ~= val then
|
||||
fakeBase[index] = val
|
||||
activeContext:bubbleUpdate()
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
@ -87,14 +87,23 @@ function element:new(param)
|
||||
self.context = context.new(self)
|
||||
end
|
||||
|
||||
function element:setCalculatedSize(w, h)
|
||||
self.view.minW = w or self.view.minW
|
||||
self.view.minH = h or self.view.minH
|
||||
self.view.w = math.max(self.view.minW, self.view.w)
|
||||
self.view.h = math.max(self.view.minH, self.view.h)
|
||||
end
|
||||
|
||||
function element:updateInputCtx()
|
||||
self.context.inputContext:update()
|
||||
if self.settings.canvasW then
|
||||
--If canvas too small make a bigger one
|
||||
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.canvasH = self.view.h*1.25
|
||||
|
||||
self.canvas = love.graphics.newCanvas(self.view.w*1.25, self.view.h*1.25)
|
||||
--If canvas too big make a smaller one
|
||||
elseif self.settings.canvasW > self.view.w*1.50 or self.settings.canvasH > self.view.h*1.50 then
|
||||
self.settings.canvasW = self.view.w*1.25
|
||||
self.settings.canvasH = self.view.h*1.25
|
||||
@ -246,10 +255,12 @@ local insert = table.insert
|
||||
--Acts as the entrypoint for beginning rendering
|
||||
---@param x number
|
||||
---@param y number
|
||||
function element:draw(x, y)
|
||||
function element:draw(x, y, w, h)
|
||||
if not self.view.lock then
|
||||
if x then self.view.x = x end
|
||||
if y then self.view.y = y end
|
||||
if w then self.view.w = self.view.minW<=w and w or self.view.minW end
|
||||
if h then self.view.h = self.view.minH<=h and h or self.view.minH end
|
||||
end
|
||||
|
||||
if self.settings.firstDraw then
|
||||
|
||||
10
core/input.d.ts
vendored
10
core/input.d.ts
vendored
@ -1,6 +1,6 @@
|
||||
interface Subscription{
|
||||
on():void;
|
||||
off():void;
|
||||
}
|
||||
|
||||
interface Subscription{
|
||||
on():void;
|
||||
off():void;
|
||||
}
|
||||
|
||||
export default function input(it:string,cb:(x?:number,y?:number)=>void,doff?:boolean,x?:number,y?:number,w?:number,h?:number): Subscription;
|
||||
142
core/signals.lua
142
core/signals.lua
@ -1,72 +1,72 @@
|
||||
--Internal event/zone/perf-log system
|
||||
local signals = {}
|
||||
signals.__index = signals
|
||||
|
||||
function signals.newController()
|
||||
return setmetatable({
|
||||
stack = {},
|
||||
|
||||
eventSubs = {},
|
||||
zoneSubs = {},
|
||||
|
||||
startTime = 0,
|
||||
totalTime = 0
|
||||
}, signals)
|
||||
end
|
||||
|
||||
function signals:push(name)
|
||||
self.stack[#self.stack+1] = {name = name}
|
||||
|
||||
self.startTime = love.timer.getTime()
|
||||
|
||||
if self.zoneSubs[name] then
|
||||
for i, e in ipairs(self.zoneSubs[name]) do
|
||||
if e.on and e.func() then
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function signals:pop()
|
||||
local name = self.stack[#self.stack].name
|
||||
|
||||
if self.zoneSubs[name] then
|
||||
for i, e in ipairs(self.zoneSubs[name]) do
|
||||
if not e.on and e.func() then
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.totalTime = love.timer.getTime() - self.startTime
|
||||
self.stack[#self.stack] = nil
|
||||
end
|
||||
|
||||
function signals:emitEvent(name, content)
|
||||
if self.eventSubs[name] then
|
||||
for i,e in ipairs(self.eventSubs[name]) do
|
||||
e.func(content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function signals:onEvent(func, event)
|
||||
if not self.eventSubs[event] then
|
||||
self.eventSubs[event] = {}
|
||||
end
|
||||
self.eventSubs[event][#self.eventSubs[event]+1] = {func = func}
|
||||
|
||||
end
|
||||
|
||||
--on - true when new zone is pushed
|
||||
-- false when zone is popped
|
||||
function signals:onSignal(func, name, on)
|
||||
if not self.zoneSubs[name] then
|
||||
self.zoneSubs[name] = {}
|
||||
end
|
||||
self.zoneSubs[name][#self.zoneSubs[name]+1] = {func = func, on = on}
|
||||
|
||||
end
|
||||
|
||||
--Internal event/zone/perf-log system
|
||||
local signals = {}
|
||||
signals.__index = signals
|
||||
|
||||
function signals.newController()
|
||||
return setmetatable({
|
||||
stack = {},
|
||||
|
||||
eventSubs = {},
|
||||
zoneSubs = {},
|
||||
|
||||
startTime = 0,
|
||||
totalTime = 0
|
||||
}, signals)
|
||||
end
|
||||
|
||||
function signals:push(name)
|
||||
self.stack[#self.stack+1] = {name = name}
|
||||
|
||||
self.startTime = love.timer.getTime()
|
||||
|
||||
if self.zoneSubs[name] then
|
||||
for i, e in ipairs(self.zoneSubs[name]) do
|
||||
if e.on and e.func() then
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function signals:pop()
|
||||
local name = self.stack[#self.stack].name
|
||||
|
||||
if self.zoneSubs[name] then
|
||||
for i, e in ipairs(self.zoneSubs[name]) do
|
||||
if not e.on and e.func() then
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.totalTime = love.timer.getTime() - self.startTime
|
||||
self.stack[#self.stack] = nil
|
||||
end
|
||||
|
||||
function signals:emitEvent(name, content)
|
||||
if self.eventSubs[name] then
|
||||
for i,e in ipairs(self.eventSubs[name]) do
|
||||
e.func(content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function signals:onEvent(func, event)
|
||||
if not self.eventSubs[event] then
|
||||
self.eventSubs[event] = {}
|
||||
end
|
||||
self.eventSubs[event][#self.eventSubs[event]+1] = {func = func}
|
||||
|
||||
end
|
||||
|
||||
--on - true when new zone is pushed
|
||||
-- false when zone is popped
|
||||
function signals:onSignal(func, name, on)
|
||||
if not self.zoneSubs[name] then
|
||||
self.zoneSubs[name] = {}
|
||||
end
|
||||
self.zoneSubs[name][#self.zoneSubs[name]+1] = {func = func, on = on}
|
||||
|
||||
end
|
||||
|
||||
return signals
|
||||
174
core/stack.lua
174
core/stack.lua
@ -1,88 +1,88 @@
|
||||
--Builds the element stack basically
|
||||
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".core.stack"))
|
||||
local helium = require(path .. ".dummy")
|
||||
|
||||
---@class context
|
||||
local context = {}
|
||||
context.__index = context
|
||||
|
||||
local activeContext
|
||||
|
||||
---@param elem element
|
||||
function context.new(elem)
|
||||
local ctx = setmetatable({
|
||||
view = elem.view,
|
||||
element = elem,
|
||||
childrenContexts = {},
|
||||
inputContext = helium.input.newContext(elem)
|
||||
}, context)
|
||||
|
||||
return ctx
|
||||
end
|
||||
|
||||
function context:bubbleUpdate()
|
||||
self.element.settings.pendingUpdate = true
|
||||
self.element.settings.needsRendering = true
|
||||
|
||||
if self.parentCtx and self.parentCtx~=self then
|
||||
self.parentCtx:bubbleUpdate()
|
||||
end
|
||||
end
|
||||
|
||||
function context:set()
|
||||
if activeContext then
|
||||
if not self.parentCtx and activeContext~=self then
|
||||
self.parentCtx = activeContext
|
||||
activeContext.childrenContexts[#activeContext.childrenContexts] = self
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
self.inputContext:set()
|
||||
end
|
||||
|
||||
function context:unset()
|
||||
self.inputContext:unset()
|
||||
self.inputContext:afterLoad()
|
||||
|
||||
if self.parentCtx then
|
||||
activeContext = self.parentCtx
|
||||
else
|
||||
activeContext = nil
|
||||
end
|
||||
end
|
||||
|
||||
function context:unsuspend()
|
||||
self.inputContext:unsuspend()
|
||||
end
|
||||
|
||||
function context:destroy()
|
||||
self.elem:undraw()
|
||||
for i=1,#self.childrenContexts do
|
||||
self.childrenContexts[i]:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function context:suspend()
|
||||
self.inputContext:set()
|
||||
self.inputContext:suspend()
|
||||
self.inputContext:unset()
|
||||
end
|
||||
|
||||
--Function meant for external context capture
|
||||
function context.getContext()
|
||||
return activeContext
|
||||
end
|
||||
|
||||
|
||||
--Builds the element stack basically
|
||||
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".core.stack"))
|
||||
local helium = require(path .. ".dummy")
|
||||
|
||||
---@class context
|
||||
local context = {}
|
||||
context.__index = context
|
||||
|
||||
local activeContext
|
||||
|
||||
---@param elem element
|
||||
function context.new(elem)
|
||||
local ctx = setmetatable({
|
||||
view = elem.view,
|
||||
element = elem,
|
||||
childrenContexts = {},
|
||||
inputContext = helium.input.newContext(elem)
|
||||
}, context)
|
||||
|
||||
return ctx
|
||||
end
|
||||
|
||||
function context:bubbleUpdate()
|
||||
self.element.settings.pendingUpdate = true
|
||||
self.element.settings.needsRendering = true
|
||||
|
||||
if self.parentCtx and self.parentCtx~=self then
|
||||
self.parentCtx:bubbleUpdate()
|
||||
end
|
||||
end
|
||||
|
||||
function context:set()
|
||||
if activeContext then
|
||||
if not self.parentCtx and activeContext~=self then
|
||||
self.parentCtx = activeContext
|
||||
activeContext.childrenContexts[#activeContext.childrenContexts] = self
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
self.inputContext:set()
|
||||
end
|
||||
|
||||
function context:unset()
|
||||
self.inputContext:unset()
|
||||
self.inputContext:afterLoad()
|
||||
|
||||
if self.parentCtx then
|
||||
activeContext = self.parentCtx
|
||||
else
|
||||
activeContext = nil
|
||||
end
|
||||
end
|
||||
|
||||
function context:unsuspend()
|
||||
self.inputContext:unsuspend()
|
||||
end
|
||||
|
||||
function context:destroy()
|
||||
self.elem:undraw()
|
||||
for i=1,#self.childrenContexts do
|
||||
self.childrenContexts[i]:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function context:suspend()
|
||||
self.inputContext:set()
|
||||
self.inputContext:suspend()
|
||||
self.inputContext:unset()
|
||||
end
|
||||
|
||||
--Function meant for external context capture
|
||||
function context.getContext()
|
||||
return activeContext
|
||||
end
|
||||
|
||||
|
||||
return context
|
||||
@ -1,18 +1,18 @@
|
||||
Hooks are additional functions to utilize the element lifecycle more granularly
|
||||
e.g.
|
||||
|
||||
```lua
|
||||
local onDestroyHook = require("helium/hooks/onDestroy")
|
||||
|
||||
return function (param)
|
||||
|
||||
onDestroyHook(function()
|
||||
doSomething()
|
||||
end)
|
||||
|
||||
return function()
|
||||
love.graphics.print("Help")
|
||||
end
|
||||
end
|
||||
|
||||
Hooks are additional functions to utilize the element lifecycle more granularly
|
||||
e.g.
|
||||
|
||||
```lua
|
||||
local onDestroyHook = require("helium/hooks/onDestroy")
|
||||
|
||||
return function (param)
|
||||
|
||||
onDestroyHook(function()
|
||||
doSomething()
|
||||
end)
|
||||
|
||||
return function()
|
||||
love.graphics.print("Help")
|
||||
end
|
||||
end
|
||||
|
||||
```
|
||||
66
init.d.ts
vendored
66
init.d.ts
vendored
@ -1,33 +1,33 @@
|
||||
export interface parameters{
|
||||
[index: string]: any;
|
||||
[index: number]: any;
|
||||
}
|
||||
|
||||
export interface view{
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
lock?: boolean;
|
||||
onChange?(): null;
|
||||
}
|
||||
|
||||
export interface state{
|
||||
[index: string]: any;
|
||||
[index: number]: any;
|
||||
}
|
||||
|
||||
interface HeliumElement{
|
||||
view: view;
|
||||
state: state;
|
||||
parameters: parameters;
|
||||
draw(this,x:number,y:number): null;
|
||||
undraw(this): null;
|
||||
}
|
||||
|
||||
declare function HeliumLoader(filepath:string):(params:parameters, w:number, h:number)=>HeliumElement;
|
||||
|
||||
export module helium{
|
||||
export let input: typeof import("./core/input") ;
|
||||
}
|
||||
export function helium<T>(chunk:(params:T,state:state,view:view)=>()=>void):(params:T, w:number, h:number)=>HeliumElement;
|
||||
export interface parameters{
|
||||
[index: string]: any;
|
||||
[index: number]: any;
|
||||
}
|
||||
|
||||
export interface view{
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
lock?: boolean;
|
||||
onChange?(): null;
|
||||
}
|
||||
|
||||
export interface state{
|
||||
[index: string]: any;
|
||||
[index: number]: any;
|
||||
}
|
||||
|
||||
interface HeliumElement{
|
||||
view: view;
|
||||
state: state;
|
||||
parameters: parameters;
|
||||
draw(this,x:number,y:number): null;
|
||||
undraw(this): null;
|
||||
}
|
||||
|
||||
declare function HeliumLoader(filepath:string):(params:parameters, w:number, h:number)=>HeliumElement;
|
||||
|
||||
export module helium{
|
||||
export let input: typeof import("./core/input") ;
|
||||
}
|
||||
export function helium<T>(chunk:(params:T,state:state,view:view)=>()=>void):(params:T, w:number, h:number)=>HeliumElement;
|
||||
|
||||
14
init.lua
14
init.lua
@ -12,10 +12,16 @@ helium.input = require(path..".core.input")
|
||||
helium.loader = require(path..".loader")
|
||||
helium.elementBuffer = {}
|
||||
helium.__index = helium
|
||||
setmetatable(helium, {__call = function(s,chunk)
|
||||
return function(param,w,h)
|
||||
return helium.element(chunk,nil,w,h,param)
|
||||
end
|
||||
|
||||
setmetatable(helium, {__call = function(s, chunk)
|
||||
return {
|
||||
__call = function(s, param, w, h)
|
||||
return helium.element(chunk, nil, w, h, param)
|
||||
end,
|
||||
draw = function (param, x, y, w, h)
|
||||
return helium.element.immediate(param, chunk, x, y, w, h)
|
||||
end
|
||||
}
|
||||
end})
|
||||
|
||||
function helium.render()
|
||||
|
||||
214
loader.lua
214
loader.lua
@ -1,108 +1,108 @@
|
||||
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".loader"))
|
||||
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(param,w,h)
|
||||
return helium.element(ret, reloader, w, h, param)
|
||||
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
|
||||
|
||||
if helium.conf.PURE_G then
|
||||
HeliumLoader = debugLoader.loader
|
||||
end
|
||||
|
||||
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".loader"))
|
||||
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(param,w,h)
|
||||
return helium.element(ret, reloader, w, h, param)
|
||||
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
|
||||
|
||||
if helium.conf.PURE_G then
|
||||
HeliumLoader = debugLoader.loader
|
||||
end
|
||||
|
||||
return debugLoader
|
||||
Loading…
x
Reference in New Issue
Block a user