big chungus commit
This commit is contained in:
parent
b6e29a3ed7
commit
a200960ad1
@ -29,14 +29,14 @@ function atlas.assign(element)
|
||||
local elH = element.view.h
|
||||
local canvas, quad = createdAtlas:assignElement(element)
|
||||
if not canvas and createdAtlas.ideal_area < createdAtlas.taken_area*4 then
|
||||
print('refragmenting ;3')
|
||||
--print('refragmenting ;3')
|
||||
createdAtlas:refragment()
|
||||
canvas, quad = createdAtlas:assignElement(element)
|
||||
if not canvas then
|
||||
print('ran out of space')
|
||||
--print('ran out of space')
|
||||
end
|
||||
else
|
||||
print('wont refragment', createdAtlas.ideal_area, createdAtlas.taken_area)
|
||||
--print('wont refragment', createdAtlas.ideal_area, createdAtlas.taken_area)
|
||||
end
|
||||
return canvas, quad
|
||||
end
|
||||
@ -206,6 +206,7 @@ end
|
||||
function atlas:unassignElement(element)
|
||||
local user = self.users[element]
|
||||
self:unMarkTiles(user.x, user.y, user.w, user.h)
|
||||
self.taken_area = self.taken_area - ((user.w*BLOCK_SIZE)*(user.h*BLOCK_SIZE))
|
||||
self.users[element] = nil
|
||||
end
|
||||
|
||||
|
||||
133
core/element.lua
133
core/element.lua
@ -19,7 +19,7 @@ setmetatable(element, {
|
||||
self.parentFunc = func
|
||||
|
||||
self:new(param,nil, w, h)
|
||||
self:createProxies(param)
|
||||
self:createProxies()
|
||||
|
||||
return self
|
||||
end
|
||||
@ -29,7 +29,6 @@ setmetatable(element, {
|
||||
--The new function that should be used for element creation
|
||||
function element:new(param, immediate, w, h)
|
||||
self.parameters = {}
|
||||
|
||||
self.baseParams = param
|
||||
|
||||
--Internal settings
|
||||
@ -57,28 +56,48 @@ function element:new(param, immediate, w, h)
|
||||
self.renderBench = {
|
||||
|
||||
}
|
||||
|
||||
self.baseView = {
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = w or 10,
|
||||
h = h or 10,
|
||||
minW = w or 10,
|
||||
minH = h or 10,
|
||||
minW = w or 0,
|
||||
minH = h or 0,
|
||||
}
|
||||
|
||||
|
||||
self.size = setmetatable({}, {__index = function(t, index)
|
||||
return self.baseView[index]
|
||||
end,})
|
||||
|
||||
self.view = self.baseView
|
||||
|
||||
end
|
||||
|
||||
function element:sizeChange()
|
||||
function element:sizeChange(i, v)
|
||||
local increase = self.baseView[i] < v
|
||||
|
||||
if i == 'w' then
|
||||
self.baseView.w = math.max(self.baseView.minW, v)
|
||||
else
|
||||
self.baseView.h = math.max(self.baseView.minH, v)
|
||||
end
|
||||
|
||||
function element:posChange()
|
||||
--defer resize
|
||||
if self.deferResize then
|
||||
if not self.deferResize.increased then
|
||||
self.deferResize.increased = increase
|
||||
end
|
||||
else
|
||||
self.deferResize = { increased = increase }
|
||||
end
|
||||
end
|
||||
|
||||
function element:posChange(i, v)
|
||||
self.baseView[i] = v
|
||||
--defer resize
|
||||
|
||||
if not self.deferRepos then
|
||||
self.deferRepos = true
|
||||
end
|
||||
end
|
||||
|
||||
function element:onUpdate()
|
||||
@ -104,14 +123,12 @@ function element:createProxies()
|
||||
end,
|
||||
__newindex = function(t, index, val)
|
||||
if self.baseView[index] ~= val then
|
||||
self.baseView[index] = val
|
||||
if index=='w' or index=='h' then
|
||||
self:sizeChange()
|
||||
self:sizeChange(index, val)
|
||||
else
|
||||
self:posChange()
|
||||
self:posChange(index, val)
|
||||
end
|
||||
self.context:bubbleUpdate()
|
||||
self:updateInputCtx()
|
||||
end
|
||||
end
|
||||
})
|
||||
@ -142,14 +159,22 @@ function element.setBench(time)
|
||||
selfRenderTime = time
|
||||
end
|
||||
|
||||
function element:calculateCanvasCoeficient(selfTime)
|
||||
function element:calculateCanvasCoeficient()
|
||||
local avg, sum = 0, 0
|
||||
|
||||
for i, e in ipairs(self.renderBench) do
|
||||
sum = sum + e
|
||||
end
|
||||
|
||||
avg = sum/#self.renderBench
|
||||
|
||||
local sW, sH = love.graphics.getDimensions()
|
||||
local areaBelow = helium.atlas.getFreeArea()
|
||||
local area = self.view.h*self.view.w
|
||||
|
||||
local areaCoef = (2-(helium.atlas.getRatio()) )-(area/(areaBelow/(4+3*helium.atlas.getRatio())))
|
||||
local childCoef = self.context:getChildrenCount()/childrenNum
|
||||
local sizeCoef = selfTime/selfRenderTime
|
||||
local sizeCoef = avg/selfRenderTime
|
||||
|
||||
return (areaCoef+childCoef+sizeCoef)>coefficient
|
||||
end
|
||||
@ -163,6 +188,7 @@ function element:createCanvas()
|
||||
|
||||
if not self.canvas then
|
||||
self.settings.failedCanvas = true
|
||||
self.settings.hasCanvas = false
|
||||
return
|
||||
end
|
||||
self.settings.hasCanvas = true
|
||||
@ -180,27 +206,6 @@ function element:setCalculatedSize(w, h)
|
||||
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
|
||||
|
||||
self.canvas = love.graphics.newCanvas(self.view.w*1.25, self.view.h*1.25)
|
||||
end
|
||||
|
||||
self.quad = love.graphics.newQuad(0, 0, self.view.w, self.view.h, self.settings.canvasW, self.settings.canvasH)
|
||||
end]]
|
||||
end
|
||||
|
||||
local dummy = function() end
|
||||
--Immediate mode code(don't call directly)
|
||||
function element.immediate(param, func, x, y, w, h)
|
||||
@ -209,7 +214,7 @@ function element.immediate(param, func, x, y, w, h)
|
||||
local ctx = context.getContext()
|
||||
if ctx then
|
||||
local self = setmetatable({}, element)
|
||||
self = element:new(param, true)
|
||||
self = self:new(param, true)
|
||||
else
|
||||
error("Can't render immediate outside of persistent")
|
||||
end
|
||||
@ -218,7 +223,7 @@ end
|
||||
--Called once dimensions are validated
|
||||
function element:setup()
|
||||
self.context:set()
|
||||
self.renderer = self.parentFunc(self.parameters, self.view.w, self.view.h)
|
||||
self.renderer = self.parentFunc(self.parameters, self.size)
|
||||
self.context:unset()
|
||||
|
||||
self.settings.isSetup = true
|
||||
@ -302,20 +307,12 @@ function element:externalRender()
|
||||
end
|
||||
|
||||
function element:externalUpdate()
|
||||
self.context:zIndex()
|
||||
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
|
||||
love.graphics.push()
|
||||
love.graphics.origin()
|
||||
if self:calculateCanvasCoeficient() then
|
||||
self:createCanvas()
|
||||
love.graphics.pop()
|
||||
|
||||
self.settings.pendingUpdate = true
|
||||
else
|
||||
self.settings.failedCanvas = true
|
||||
@ -327,6 +324,27 @@ function element:externalUpdate()
|
||||
self.settings.pendingUpdate = false
|
||||
end
|
||||
|
||||
if self.deferResize then
|
||||
self.context:sizeChanged()
|
||||
if self.settings.hasCanvas then
|
||||
helium.atlas.unassign(self)
|
||||
|
||||
if self:calculateCanvasCoeficient() then
|
||||
self:createCanvas()
|
||||
else
|
||||
self.settings.hasCanvas = false
|
||||
self.canvas = nil
|
||||
self.quad = nil
|
||||
self.deferResize = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.deferRepos then
|
||||
self.context:posChanged()
|
||||
self.deferRepos = false
|
||||
end
|
||||
|
||||
return self.settings.remove
|
||||
end
|
||||
|
||||
@ -337,21 +355,20 @@ local insert = table.insert
|
||||
---@param x number
|
||||
---@param y number
|
||||
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 w then self.view.w = w end
|
||||
if h then self.view.h = h end
|
||||
|
||||
if context.getContext() then
|
||||
if context.getContext().childRender(self) then
|
||||
local cx = context.getContext()
|
||||
if cx then
|
||||
if cx:childRender(self) then
|
||||
self:externalUpdate()
|
||||
self:externalRender()
|
||||
end
|
||||
elseif not self.settings.inserted then
|
||||
self.settings.inserted = true
|
||||
insert(helium.elementBuffer, self)
|
||||
insert(helium.elementInsertionQueue, self)
|
||||
end
|
||||
|
||||
if self.settings.firstDraw then
|
||||
@ -360,6 +377,10 @@ function element:draw(x, y, w, h)
|
||||
end
|
||||
end
|
||||
|
||||
function element:getSize()
|
||||
return self.view.w, self.view.h
|
||||
end
|
||||
|
||||
function element:destroy()
|
||||
self.settings.remove = true
|
||||
self.settings.firstDraw = true
|
||||
|
||||
@ -9,45 +9,31 @@ function eventClass.new()
|
||||
return setmetatable(self, eventClass)
|
||||
end
|
||||
|
||||
function eventClass:sub(name, func)
|
||||
local sub = { func = func }
|
||||
|
||||
self:provideQueue(name)
|
||||
self.eventSubs[name][func] = func
|
||||
|
||||
return sub
|
||||
function eventClass:newQueue(name)
|
||||
self.eventSubs[name] = {}
|
||||
end
|
||||
|
||||
function eventClass:push(name, event)
|
||||
if self.eventSubs[name] then
|
||||
table.insert(self.eventSubs[name].queue, event)
|
||||
--Data is the individualized table to pass to each subscriber (or middleware)
|
||||
function eventClass:sub(name, func, data)
|
||||
self.eventSubs[name][func] = {func = func, data = data}
|
||||
|
||||
return func
|
||||
end
|
||||
|
||||
function eventClass:unsub(name, func)
|
||||
self.eventSubs[name][func] = nil
|
||||
end
|
||||
|
||||
function eventClass:push(name, evntData)
|
||||
local pushData = evntData
|
||||
for i, e in pairs(self.eventSubs[name]) do
|
||||
if self.eventSubs[name].beforeEach then
|
||||
pushData = self.eventSubs[name].beforeEach(e.data, evntData) or evntData
|
||||
end
|
||||
|
||||
e.func(pushData)
|
||||
end
|
||||
end
|
||||
|
||||
function eventClass:flush(name)
|
||||
|
||||
end
|
||||
|
||||
function eventClass:flushAll()
|
||||
for i, subs in pairs(self.eventSubs) do
|
||||
local assembledEvent = {}
|
||||
|
||||
for i, e in ipairs(subs.queue) do
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function eventClass:provideQueue(name)
|
||||
if not self.eventSubs[name] then
|
||||
self.eventSubs[name] = {
|
||||
queue = {}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function eventClass:unsub(name, event)
|
||||
self.eventSubs[name][event] = nil
|
||||
end
|
||||
|
||||
return eventClass
|
||||
386
core/input.lua
386
core/input.lua
@ -1,5 +1,5 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".core.input"))
|
||||
local helium = require(path .. ".dummy")
|
||||
local stack = require(path .. ".core.stack")
|
||||
|
||||
local input = {
|
||||
eventHandlers = {},
|
||||
@ -8,52 +8,33 @@ local input={
|
||||
}
|
||||
input.__index = input
|
||||
|
||||
local windowMachine = {}
|
||||
windowMachine.__index = windowMachine
|
||||
local windowCurrent = false
|
||||
|
||||
--Go forward
|
||||
windowMachine.push = function(window)
|
||||
windowMachine[#windowMachine+1] = window
|
||||
windowCurrent = #windowMachine
|
||||
local function sortFunc(t1, t2)
|
||||
if t1.stack.temporalZ.z == t2.stack.temporalZ.z then
|
||||
print('same Z ???',t1.stack.temporalZ.z, t2.stack.temporalZ.z)
|
||||
end
|
||||
if t1 == t2 then
|
||||
print(tostring(t1), tostring(t2))
|
||||
return false
|
||||
end
|
||||
return t1.stack.temporalZ.z > t2.stack.temporalZ.z
|
||||
end
|
||||
|
||||
--Go a level back
|
||||
windowMachine.pop = function()
|
||||
windowMachine[#windowMachine] = nil
|
||||
if windowCurrent>1 then
|
||||
windowCurrent = windowCurrent-1
|
||||
else
|
||||
windowCurrent = false
|
||||
function input.sortZ()
|
||||
for i, subs in pairs(input.subscriptions) do
|
||||
table.sort(subs, sortFunc)
|
||||
print(#subs)
|
||||
end
|
||||
end
|
||||
|
||||
windowMachine.get = function()
|
||||
if windowCurrent then
|
||||
return windowMachine[windowCurrent]
|
||||
end
|
||||
end
|
||||
|
||||
local activeWindow
|
||||
local windowStack = {}
|
||||
|
||||
function input.unload()
|
||||
windowStack = {}
|
||||
activeWindow = nil
|
||||
windowMachine = {}
|
||||
input.subscriptions = {}
|
||||
end
|
||||
|
||||
local dummyfunc = function() end
|
||||
---@class subscription
|
||||
local subscription = {}
|
||||
subscription.__index = subscription
|
||||
|
||||
---@class inputContext
|
||||
local context = {}
|
||||
context.__index = context
|
||||
|
||||
local activeContext
|
||||
function input.unload()
|
||||
input.subscriptions = {}
|
||||
input.activeEvents = {}
|
||||
end
|
||||
|
||||
--[[Event types
|
||||
###SIMPLE EVENTS###
|
||||
@ -73,80 +54,6 @@ local activeContext
|
||||
|
||||
|
||||
]]
|
||||
function input.newContext(element)
|
||||
local ctx = setmetatable({elem = element, subs = {}, childContexts={}}, context)
|
||||
|
||||
return ctx
|
||||
end
|
||||
|
||||
function context:set()
|
||||
self.activeWindow = windowMachine.get()
|
||||
|
||||
if activeContext and activeContext~=self then
|
||||
if not self.parentCtx then
|
||||
activeContext.childContexts[#activeContext.childContexts+1] = self
|
||||
self.parentCtx = activeContext
|
||||
end
|
||||
self.absX = self.parentCtx.absX + self.elem.view.x
|
||||
self.absY = self.parentCtx.absY + self.elem.view.y
|
||||
activeContext = self
|
||||
else
|
||||
self.absX = self.elem.view.x
|
||||
self.absY = self.elem.view.y
|
||||
activeContext = self
|
||||
end
|
||||
end
|
||||
|
||||
function context:update()
|
||||
if self.parentCtx then
|
||||
self.absX = self.parentCtx.absX + self.elem.view.x
|
||||
self.absY = self.parentCtx.absY + self.elem.view.y
|
||||
else
|
||||
self.absX = self.elem.view.x
|
||||
self.absY = self.elem.view.y
|
||||
end
|
||||
for i, e in ipairs(self.childContexts) do
|
||||
e:update()
|
||||
end
|
||||
for i, sub in ipairs(self.subs) do
|
||||
sub:contextUpdate(self.absX,self.absY,self)
|
||||
end
|
||||
end
|
||||
|
||||
function context:unset()
|
||||
if self.parentCtx then
|
||||
activeContext = self.parentCtx
|
||||
else
|
||||
activeContext = nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function context:afterLoad()
|
||||
--If i created window, pop it
|
||||
if self.window then
|
||||
windowMachine.pop()
|
||||
end
|
||||
end
|
||||
|
||||
function context:unsuspend()
|
||||
for i, e in ipairs(self.subs) do
|
||||
e:unsuspend()
|
||||
end
|
||||
for i, e in ipairs(self.childContexts) do
|
||||
e:unsuspend()
|
||||
end
|
||||
end
|
||||
|
||||
function context:suspend()
|
||||
for i, e in ipairs(self.subs) do
|
||||
e:suspend()
|
||||
end
|
||||
for i, e in ipairs(self.childContexts) do
|
||||
e:suspend()
|
||||
end
|
||||
end
|
||||
|
||||
---@param x number
|
||||
---@param y number
|
||||
---@param w number
|
||||
@ -156,70 +63,45 @@ end
|
||||
---@param doff boolean
|
||||
---@return subscription
|
||||
function subscription.create(x, y, w, h, eventType, callback, doff)
|
||||
local sub
|
||||
if activeContext then
|
||||
local wratio,hratio,xratio,yratio
|
||||
if x<=1 and x~=0 then
|
||||
xratio = x
|
||||
x = activeContext.elem.view.w * x
|
||||
end
|
||||
local stack = stack.getContext()
|
||||
local xn, yn = stack:normalizePos(x, y)
|
||||
local wn, hn = stack:normalizeSize(w, h)
|
||||
|
||||
if y<=1 and y~=0 then
|
||||
yratio = y
|
||||
y = activeContext.elem.view.h * y
|
||||
end
|
||||
|
||||
if w<=1 and w~=0 then
|
||||
wratio = w
|
||||
w = activeContext.elem.view.w * w
|
||||
end
|
||||
|
||||
if h<=1 and h~=0 then
|
||||
hratio = h
|
||||
h = activeContext.elem.view.h * h
|
||||
end
|
||||
|
||||
sub = setmetatable({
|
||||
x = activeContext.absX + x,
|
||||
y = activeContext.absY + y,
|
||||
w = w,
|
||||
h = h,
|
||||
wratio = wratio,
|
||||
hratio = hratio,
|
||||
xratio = xratio,
|
||||
yratio = yratio,
|
||||
ix = x,
|
||||
iy = y,
|
||||
local sub = setmetatable({
|
||||
x = xn,
|
||||
y = yn,
|
||||
w = wn,
|
||||
h = hn,
|
||||
origX = x,
|
||||
origY = y,
|
||||
origW = w,
|
||||
origH = h,
|
||||
eventType = eventType,
|
||||
active = true,
|
||||
stack = stack,
|
||||
callback = callback
|
||||
},subscription)
|
||||
|
||||
sub.onSizeChange = stack:onSizeChange(function()
|
||||
sub.w, sub.h = sub.stack:normalizeSize(sub.origW, sub.origH)
|
||||
end)
|
||||
|
||||
sub.onPosChange = stack:onPosChange(function()
|
||||
sub.x, sub.y = sub.stack:normalizePos(sub.origX, sub.origY)
|
||||
print(sub.y, sub.stack.absY)
|
||||
end)
|
||||
|
||||
if doff == false then
|
||||
sub:off()
|
||||
end
|
||||
|
||||
if activeContext.window or activeContext.activeWindow then
|
||||
sub.parentWindow = activeContext.window or activeContext.activeWindow
|
||||
end
|
||||
activeContext.subs[#activeContext.subs+1] = sub
|
||||
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
|
||||
|
||||
input.subscriptions[eventType][#input.subscriptions[eventType]+1] = sub
|
||||
table.insert(input.subscriptions[eventType],1,sub)
|
||||
|
||||
input.sortZ()
|
||||
|
||||
return sub
|
||||
end
|
||||
@ -232,40 +114,9 @@ function subscription:on()
|
||||
self.active = true
|
||||
end
|
||||
|
||||
function subscription:suspend()
|
||||
self.destroyStat = true
|
||||
self.preActive = self.active
|
||||
self.active = false
|
||||
end
|
||||
|
||||
function subscription:unsuspend()
|
||||
self.active = self.preActive
|
||||
end
|
||||
|
||||
function subscription:contextUpdate(absX, absY,activeContext)
|
||||
if self.xratio then
|
||||
self.x = absX + activeContext.elem.view.w * self.xratio
|
||||
else
|
||||
self.x = absX + self.ix
|
||||
end
|
||||
if self.yratio then
|
||||
self.y = absY + activeContext.elem.view.h * self.yratio
|
||||
else
|
||||
self.y = absY + self.iy
|
||||
end
|
||||
if self.hratio then
|
||||
self.h = activeContext.elem.view.h * self.hratio
|
||||
end
|
||||
if self.wratio then
|
||||
self.w = activeContext.elem.view.w * self.wratio
|
||||
end
|
||||
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
|
||||
function subscription:remove()
|
||||
--input.subscriptions[self.eventType][self] = nil
|
||||
input.sortZ()
|
||||
end
|
||||
|
||||
function subscription:emit(...)
|
||||
@ -297,73 +148,11 @@ input.__call = function(self, eventType, callback, cbOff, x, y, w, h)
|
||||
return subscription.create(x,y,w,h,eventType,callback,cbOff)
|
||||
end
|
||||
|
||||
--Will block ui clicks from going through it
|
||||
input.window = function(x,y,w,h)
|
||||
x = x or 0
|
||||
y = y or 0
|
||||
w = w or 1
|
||||
h = h or 1
|
||||
|
||||
activeContext.window = subscription.create(x,y,w,h,'window',nil,false)
|
||||
windowMachine.push(activeContext.window)
|
||||
windowStack[#windowStack+1] = activeContext.window
|
||||
return activeContext.window
|
||||
end
|
||||
|
||||
--Run once per applicable event
|
||||
--The windows should be basically pre sorted, so if something is a hit on a lower window
|
||||
--And is on a higher one too, the lower one is discarded
|
||||
local hits = {}
|
||||
input.checkWindows = function(x,y)
|
||||
local hit = false
|
||||
for i = 1, #windowStack do
|
||||
if windowStack[i]:checkInside(x,y) and windowStack[i].active then
|
||||
hit = windowStack[i]
|
||||
end
|
||||
end
|
||||
--Returns latest hit
|
||||
return hit
|
||||
end
|
||||
|
||||
--Run per sub
|
||||
function input.checkSub(sub,hit)
|
||||
if sub.parentWindow and sub.parentWindow == hit then
|
||||
return true
|
||||
elseif not hit then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--Since the introduction of the relative subscriptions, there is more utility in ommiting coordinates by default
|
||||
setmetatable(input, input)
|
||||
|
||||
function input.eventHandlers.mousereleased(x, y, btn)
|
||||
local captured = false
|
||||
local hit = input.checkWindows(x, y)
|
||||
if input.subscriptions.mousereleased then
|
||||
for index, sub in ipairs(input.subscriptions.mousereleased) do
|
||||
--local succ = sub:checkInside(x, y)
|
||||
|
||||
if sub.active and sub:checkInside(x, y) and input.checkSub(sub,hit) then -- succ and sub:check
|
||||
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 sub.active and sub:checkOutside(x, y) and input.checkSub(sub,hit) then -- 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
|
||||
@ -388,44 +177,40 @@ function input.eventHandlers.mousereleased(x, y, btn)
|
||||
end
|
||||
end
|
||||
|
||||
if input.subscriptions.mousereleased then
|
||||
for index, sub in ipairs(input.subscriptions.mousereleased) do
|
||||
if sub.active and sub:checkInside(x, y) 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
|
||||
if sub.active and sub:checkOutside(x, y) then
|
||||
sub:emit(x, y, btn)
|
||||
captured = true
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
return captured
|
||||
end
|
||||
|
||||
|
||||
|
||||
function input.eventHandlers.mousepressed(x, y, btn)
|
||||
local captured = false
|
||||
local hit = input.checkWindows(x, y)
|
||||
if input.subscriptions.mousepressed then
|
||||
for index, sub in ipairs(input.subscriptions.mousepressed) do
|
||||
--local succ = sub:checkInside(x, y)
|
||||
|
||||
if sub.active and sub:checkInside(x, y) and input.checkSub(sub,hit) then -- succ and sub:check
|
||||
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 sub.active and sub:checkOutside(x, y) and input.checkSub(sub,hit) then -- 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 and input.checkSub(sub,hit) then
|
||||
if succ and sub.active then
|
||||
sub.cleanUp = sub:emit(x, y, btn) or dummyfunc
|
||||
sub.currentEvent = true
|
||||
captured = true
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
@ -433,16 +218,33 @@ function input.eventHandlers.mousepressed(x, y, btn)
|
||||
|
||||
if input.subscriptions.dragged then
|
||||
for index, sub in ipairs(input.subscriptions.dragged) do
|
||||
--local succ = sub:checkInside(x, y)
|
||||
|
||||
if sub.active and sub:checkInside(x, y) and input.checkSub(sub,hit) then -- succ and sub:check
|
||||
if sub.active and sub:checkInside(x, y) then
|
||||
sub.currentEvent = true
|
||||
captured = true
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
if input.subscriptions.mousepressed then
|
||||
for index, sub in ipairs(input.subscriptions.mousepressed) do
|
||||
if sub.active and sub:checkInside(x, y) then
|
||||
sub:emit(x, y, btn)
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
if input.subscriptions.mousepressed_outside then
|
||||
for index, sub in ipairs(input.subscriptions.mousepressed_outside) do
|
||||
if sub.active and sub:checkOutside(x, y) then
|
||||
sub:emit(x, y, btn)
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
return captured
|
||||
end
|
||||
|
||||
@ -450,7 +252,7 @@ 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 then -- ==true then
|
||||
if sub.active then
|
||||
sub:emit( btn)
|
||||
captured = true
|
||||
end
|
||||
@ -485,13 +287,13 @@ function input.eventHandlers.mousemoved(x, y, dx, dy)
|
||||
if sub.active and not sub.currentEvent and succ then
|
||||
sub.cleanUp = sub:emit(x, y, dx, dy) or dummyfunc
|
||||
sub.currentEvent = true
|
||||
captured = true
|
||||
return true
|
||||
elseif sub.currentEvent and not succ then
|
||||
sub.currentEvent = false
|
||||
captured = true
|
||||
if sub.cleanUp then
|
||||
sub.cleanUp(x, y)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -505,8 +307,8 @@ function input.eventHandlers.mousemoved(x, y, dx, dy)
|
||||
else
|
||||
sub:emit(x, y, dx, dy)
|
||||
end
|
||||
--sub.currentEvent = true -- checked in the condition so must be true
|
||||
captured = true
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
115
core/stack.lua
115
core/stack.lua
@ -2,12 +2,14 @@
|
||||
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".core.stack"))
|
||||
local helium = require(path .. ".dummy")
|
||||
local event = require(path..'.core.events')
|
||||
|
||||
---@class context
|
||||
local context = {}
|
||||
context.__index = context
|
||||
|
||||
local activeContext
|
||||
local currentTemporalZ = 0
|
||||
|
||||
---@param elem element
|
||||
function context.new(elem)
|
||||
@ -15,12 +17,16 @@ function context.new(elem)
|
||||
view = elem.view,
|
||||
element = elem,
|
||||
childrenContexts = {},
|
||||
inputContext = helium.input.newContext(elem),
|
||||
childRenderTime = 0,
|
||||
deferChildren = false,
|
||||
events = event.new(),
|
||||
capturedChilds = {},
|
||||
temporalZ = {z = nil},
|
||||
}, context)
|
||||
|
||||
ctx.events:newQueue('resize')
|
||||
ctx.events:newQueue('poschange')
|
||||
|
||||
return ctx
|
||||
end
|
||||
|
||||
@ -56,14 +62,9 @@ function context:set()
|
||||
|
||||
activeContext = self
|
||||
end
|
||||
|
||||
self.inputContext:set()
|
||||
end
|
||||
|
||||
function context:unset()
|
||||
self.inputContext:unset()
|
||||
self.inputContext:afterLoad()
|
||||
|
||||
if self.parentCtx then
|
||||
activeContext = self.parentCtx
|
||||
else
|
||||
@ -71,8 +72,9 @@ function context:unset()
|
||||
end
|
||||
end
|
||||
|
||||
function context:unsuspend()
|
||||
self.inputContext:unsuspend()
|
||||
function context:zIndex()
|
||||
currentTemporalZ = currentTemporalZ+1
|
||||
self.temporalZ.z = currentTemporalZ
|
||||
end
|
||||
|
||||
function context:startSelfRender()
|
||||
@ -97,12 +99,6 @@ function context:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function context:suspend()
|
||||
self.inputContext:set()
|
||||
self.inputContext:suspend()
|
||||
self.inputContext:unset()
|
||||
end
|
||||
|
||||
function context:getChildrenCount()
|
||||
return #self.childrenContexts
|
||||
end
|
||||
@ -124,12 +120,103 @@ end
|
||||
|
||||
function context:stopDeferingChildren()
|
||||
self.deferChildren = false
|
||||
|
||||
return self.capturedChilds
|
||||
end
|
||||
|
||||
function context:normalizePos(x, y)
|
||||
local xPX, yPX
|
||||
|
||||
if x<=1 and x~=0 then
|
||||
xPX = self.element.view.w * x
|
||||
end
|
||||
|
||||
if y<=1 and y~=0 then
|
||||
yPX = self.element.view.h * y
|
||||
end
|
||||
|
||||
return (xPX or x) + self.absX, (yPX or y) + self.absY
|
||||
end
|
||||
|
||||
function context:normY(y)
|
||||
local yPX
|
||||
|
||||
if y<=1 and y~=0 then
|
||||
yPX = self.element.view.h * y
|
||||
end
|
||||
|
||||
return (yPX or y)
|
||||
end
|
||||
|
||||
function context:normX(x)
|
||||
local xPX
|
||||
|
||||
if x<=1 and x~=0 then
|
||||
xPX = self.element.view.w * x
|
||||
end
|
||||
|
||||
return (xPX or x)
|
||||
end
|
||||
|
||||
function context:normalizeSize(w, h)
|
||||
local wPX, hPX
|
||||
|
||||
if w<=1 and w~=0 then
|
||||
wPX = self.element.view.w * w
|
||||
end
|
||||
|
||||
if h<=1 and h~=0 then
|
||||
hPX = self.element.view.h * h
|
||||
end
|
||||
|
||||
return wPX or w, hPX or h
|
||||
end
|
||||
|
||||
--To be used by the element
|
||||
function context:sizeChanged()
|
||||
self.events:push('resize')
|
||||
end
|
||||
|
||||
function context:posChanged()
|
||||
if self.parentCtx then
|
||||
self.absX = self.parentCtx.absX + self.view.x
|
||||
self.absY = self.parentCtx.absY + self.view.y
|
||||
else
|
||||
self.absX = self.view.x
|
||||
self.absY = self.view.y
|
||||
end
|
||||
|
||||
self.events:push('poschange')
|
||||
end
|
||||
|
||||
--Event subscriptions
|
||||
function context:onSizeChange(callback)
|
||||
return self.events:sub('resize', callback)
|
||||
end
|
||||
|
||||
function context:onPosChange(callback)
|
||||
return self.events:sub('poschange', callback)
|
||||
end
|
||||
|
||||
function context:offSizeChange(callback)
|
||||
self.events:unsub('resize', callback)
|
||||
end
|
||||
|
||||
function context:offPosChange(callback)
|
||||
self.events:unsub('poschange', callback)
|
||||
end
|
||||
|
||||
--Function meant for external context capture
|
||||
function context.getContext()
|
||||
return activeContext
|
||||
end
|
||||
|
||||
function context.newFrame()
|
||||
currentTemporalZ = 0
|
||||
end
|
||||
|
||||
function context.unload()
|
||||
activeContext = nil
|
||||
end
|
||||
|
||||
return context
|
||||
20
init.lua
20
init.lua
@ -10,8 +10,10 @@ helium.utils = require(path..".utils")
|
||||
helium.element = require(path..".core.element")
|
||||
helium.input = require(path..".core.input")
|
||||
helium.loader = require(path..".loader")
|
||||
helium.stack = require(path..".core.stack")
|
||||
helium.atlas = require(path..".core.atlas")
|
||||
helium.elementBuffer = {}
|
||||
helium.elementInsertionQueue = {}
|
||||
helium.__index = helium
|
||||
|
||||
setmetatable(helium, {__call = function(s, chunk)
|
||||
@ -61,15 +63,17 @@ function helium.draw()
|
||||
for i, e in ipairs(helium.elementBuffer) do
|
||||
e:externalRender()
|
||||
end
|
||||
|
||||
for i, e in ipairs(helium.elementInsertionQueue) do
|
||||
table.insert(helium.elementBuffer, e)
|
||||
end
|
||||
helium.elementInsertionQueue = {}
|
||||
end
|
||||
|
||||
function helium.update(dt)
|
||||
if helium.conf.HOTSWAP then
|
||||
helium.loader.update(dt)
|
||||
end
|
||||
|
||||
for i = #helium.elementBuffer, 1, -1 do
|
||||
if helium.elementBuffer[i]:externalUpdate() then
|
||||
for i = 1, #helium.elementBuffer do
|
||||
if helium.elementBuffer[i]:externalUpdate(i) then
|
||||
table.remove(helium.elementBuffer,i)
|
||||
end
|
||||
end
|
||||
@ -110,6 +114,7 @@ if helium.conf.AUTO_RUN then
|
||||
-- Main loop time.
|
||||
return function()
|
||||
-- Process events.
|
||||
helium.stack.newFrame()
|
||||
if love.event then
|
||||
love.event.pump()
|
||||
for name, a,b,c,d,e,f in love.event.poll() do
|
||||
@ -139,12 +144,13 @@ if helium.conf.AUTO_RUN then
|
||||
love.graphics.origin()
|
||||
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||
|
||||
if love.draw then love.draw() end
|
||||
|
||||
st = love.timer.getTime()
|
||||
helium.draw()
|
||||
heliumTime=heliumTime+love.timer.getTime()-st
|
||||
|
||||
if love.draw then love.draw() end
|
||||
|
||||
|
||||
love.graphics.present()
|
||||
end
|
||||
|
||||
|
||||
11
layout/column.lua
Normal file
11
layout/column.lua
Normal file
@ -0,0 +1,11 @@
|
||||
return function(x, y, width, height, children, hpad, vpad, alignX)
|
||||
local carriagePos = 0
|
||||
if children then
|
||||
for i, e in ipairs(children) do
|
||||
local _, h = e:getSize()
|
||||
e:draw(x, y+carriagePos+vpad)
|
||||
carriagePos = carriagePos + h + vpad
|
||||
end
|
||||
end
|
||||
print('finished layout')
|
||||
end
|
||||
0
layout/flow.lua
Normal file
0
layout/flow.lua
Normal file
128
layout/init.lua
128
layout/init.lua
@ -1,88 +1,144 @@
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".core.layout"))
|
||||
local path = string.sub(..., 1, string.len(...) - string.len(".layout"))
|
||||
|
||||
local layout = {}
|
||||
local layouts = {}
|
||||
layouts.column = require(path..'.layout.column')
|
||||
layout.__index = layout
|
||||
local element = require(path..'core.element')
|
||||
local stack = require(path..'core.stack')
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
layout(0,0,1,1)
|
||||
local element = require(path..'.core.element')
|
||||
local stack = require(path..'.core.stack')
|
||||
|
||||
--Start prep phase
|
||||
function layout.type(type)
|
||||
local curStack = stack.getContext()
|
||||
curStack:startDeferingChildren()
|
||||
|
||||
local self = {
|
||||
vars = {
|
||||
type = type or 'flow',
|
||||
type = type or 'column',
|
||||
offLeft = 0,
|
||||
offTop = 0,
|
||||
width = 1,
|
||||
hpad = 3,
|
||||
vpad = 3,
|
||||
height = 1,
|
||||
alignX = 'left', --options: left, center, right
|
||||
alignY = 'top', --options: top, center, bottom
|
||||
flowDir = 'rtl' --options: rtl/ttb
|
||||
--flowDir = 'rtl', --options: rtl/ttb
|
||||
},
|
||||
stack = curStack
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return setmetatable(self, layout)
|
||||
end
|
||||
|
||||
function layout:alignVert(pos)
|
||||
self.vars.alignY = pos
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function layout:alignHoriz(pos)
|
||||
self.vars.alignX = pos
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--Sets up the box of the layout
|
||||
function layout:width(w)
|
||||
self.vars.width = w
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function layout:height(h)
|
||||
self.vars.height = h
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function layout:left(x)
|
||||
self.vars.offTop = x
|
||||
self.vars.offLeft = x
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function layout:right(x)
|
||||
self.vars.offRight = x
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function layout:top(y)
|
||||
self.vars.offTop = y
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function layout:bottom(y)
|
||||
self.vars.offBot = y
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function layout:vPadding(px)
|
||||
self.vars.vpad = px
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function layout:hPadding(px)
|
||||
self.vars.hpad = px
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--Schemes: left + right = width ignored
|
||||
--top + bottom = height ignored
|
||||
--top px + bottom relative works
|
||||
--left relative + bottom px works
|
||||
function layout:draw()
|
||||
local stack = self.stack
|
||||
local children = stack:stopDeferingChildren()
|
||||
local height, width, x, y, _, marginV, marginH
|
||||
local maxW, maxH = stack:normalizeSize(1,1)
|
||||
|
||||
if self.vars.offTop and self.vars.offBot then
|
||||
marginV = stack:normY(self.vars.offTop) + stack:normY(self.vars.offBot)
|
||||
height = stack:normY(1) - marginV
|
||||
elseif self.vars.offTop then
|
||||
y = stack:normY(self.vars.offTop)
|
||||
height = math.min(stack:normY(self.vars.height), maxH-y)
|
||||
elseif self.vars.offBot then
|
||||
y = stack:normY(self.vars.offBot)
|
||||
height = math.min(stack:normY(self.vars.height), maxH-y)
|
||||
y = 0
|
||||
end
|
||||
|
||||
if self.vars.offLeft and self.vars.offRight then
|
||||
marginH = stack:normX(self.vars.offLeft) + stack:normX(self.vars.offRight)
|
||||
width = stack:normX(1) - marginH
|
||||
elseif self.vars.offLeft then
|
||||
x = stack:normX(self.vars.offLeft)
|
||||
width = math.min(stack:normX(self.vars.width), maxW-x)
|
||||
elseif self.vars.offRight then
|
||||
x = stack:normX(self.vars.offRight)
|
||||
height = math.min(stack:normX(self.vars.width), maxW-x)
|
||||
x = 0
|
||||
end
|
||||
|
||||
layouts[self.vars.type](
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
children,
|
||||
self.vars.hpad,
|
||||
self.vars.vpad,
|
||||
self.vars.alignX,
|
||||
self.vars.alignY
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
|
||||
setmetatable(layout, {__call = function(s, type) return layout.type(type) end }
|
||||
setmetatable(layout, {__call = function(s, type) return layout.type(type) end })
|
||||
return layout
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user