atlas finished
This commit is contained in:
parent
8e7423fc86
commit
1a13369dae
150
core/atlas.lua
150
core/atlas.lua
@ -1,12 +1,51 @@
|
|||||||
local atlas = {}
|
local atlas = {}
|
||||||
local atlases = {}
|
local createdAtlas
|
||||||
atlas.__index = atlas
|
atlas.__index = atlas
|
||||||
local BLOCK_SIZE = 10
|
local BLOCK_SIZE = 5
|
||||||
|
|
||||||
|
function atlas.load()
|
||||||
|
if not createdAtlas then
|
||||||
|
atlas.init()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function atlas.getRatio()
|
||||||
|
return createdAtlas.taken_area/createdAtlas.ideal_area
|
||||||
|
end
|
||||||
|
|
||||||
|
function atlas.getFreeArea()
|
||||||
|
return createdAtlas.ideal_area - createdAtlas.taken_area
|
||||||
|
end
|
||||||
|
|
||||||
function atlas.init()
|
function atlas.init()
|
||||||
local w, h = love.graphics.getDimensions()
|
local w, h = love.graphics.getDimensions()
|
||||||
|
|
||||||
|
createdAtlas = atlas.new(w, h/2)
|
||||||
|
atlas.createdAtlas = createdAtlas
|
||||||
|
end
|
||||||
|
|
||||||
|
function atlas.assign(element)
|
||||||
|
local elW = element.view.w
|
||||||
|
local elH = element.view.h
|
||||||
|
local canvas, quad = createdAtlas:assignElement(element)
|
||||||
|
if not canvas and createdAtlas.ideal_area > createdAtlas.taken_area*1.25 then
|
||||||
|
print('refragmenting ;3')
|
||||||
|
createdAtlas:refragment()
|
||||||
|
local canvas, quad = createdAtlas:assignElement(element)
|
||||||
|
else
|
||||||
|
print('wont refragment')
|
||||||
|
end
|
||||||
|
return canvas, quad
|
||||||
|
end
|
||||||
|
|
||||||
|
function atlas.unassign(element)
|
||||||
|
createdAtlas:unassignElement(element)
|
||||||
|
end
|
||||||
|
|
||||||
|
function atlas.unassignAll()
|
||||||
|
createdAtlas.users = {}
|
||||||
|
createdAtlas:unMarkTiles(1, 1, createdAtlas.tileW, createdAtlas.tileH)
|
||||||
|
createdAtlas.taken_area = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function atlas.onscreenchange(newW, newH)
|
function atlas.onscreenchange(newW, newH)
|
||||||
@ -17,10 +56,11 @@ function atlas.new(w, h)
|
|||||||
local tiles = {}
|
local tiles = {}
|
||||||
|
|
||||||
local ymax = math.floor(h/BLOCK_SIZE)
|
local ymax = math.floor(h/BLOCK_SIZE)
|
||||||
|
local xmax = math.floor(w/BLOCK_SIZE)
|
||||||
for y = 1, ymax do
|
for y = 1, ymax do
|
||||||
tiles[y] = {}
|
tiles[y] = {}
|
||||||
tiles[y].empty = ymax
|
tiles[y].empty = xmax
|
||||||
for x = 1, math.floor(w/BLOCK_SIZE) do
|
for x = 1, xmax do
|
||||||
tiles[y][x] = {
|
tiles[y][x] = {
|
||||||
taken = false
|
taken = false
|
||||||
}
|
}
|
||||||
@ -30,7 +70,10 @@ function atlas.new(w, h)
|
|||||||
local self = {
|
local self = {
|
||||||
w = w,
|
w = w,
|
||||||
h = h,
|
h = h,
|
||||||
|
tileW = xmax,
|
||||||
|
tileH = ymax,
|
||||||
ideal_area = w*h,
|
ideal_area = w*h,
|
||||||
|
taken_area = 0,
|
||||||
canvas = love.graphics.newCanvas(w, h),
|
canvas = love.graphics.newCanvas(w, h),
|
||||||
users = {},
|
users = {},
|
||||||
tiles = tiles,
|
tiles = tiles,
|
||||||
@ -39,17 +82,98 @@ function atlas.new(w, h)
|
|||||||
return setmetatable(self, atlas)
|
return setmetatable(self, atlas)
|
||||||
end
|
end
|
||||||
|
|
||||||
function atlas:assignElement(elW, elH, element)
|
function atlas:assignElement(element)
|
||||||
local tileSizeY, tileSizeW = math.ceil(elH/BLOCK_SIZE), math.ceil(elW/BLOCK_SIZE)
|
local elH, elW = element.view.h, element.view.w
|
||||||
|
local tileSizeY, tileSizeX = math.ceil(elH/BLOCK_SIZE), math.ceil(elW/BLOCK_SIZE)
|
||||||
|
|
||||||
|
local t, y, x = self:find(tileSizeY, tileSizeX)
|
||||||
|
|
||||||
|
if t then
|
||||||
|
local quad
|
||||||
|
--Refragmenting path
|
||||||
|
if self.users[element] then
|
||||||
|
--update by reference owo
|
||||||
|
self.users[element].quad:setViewport((x-1)*BLOCK_SIZE, (y-1)*BLOCK_SIZE, elW, elH)
|
||||||
|
quad = self.users[element].quad
|
||||||
|
else
|
||||||
|
quad = love.graphics.newQuad((x-1)*BLOCK_SIZE, (y-1)*BLOCK_SIZE, elW, elH, self.w, self.h)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.users[element] = {
|
||||||
|
element = element,
|
||||||
|
x = x,
|
||||||
|
y = y,
|
||||||
|
w = tileSizeX,
|
||||||
|
h = tileSizeY,
|
||||||
|
quad = quad
|
||||||
|
}
|
||||||
|
|
||||||
|
self:markTiles(x, y, tileSizeX, tileSizeY)
|
||||||
|
|
||||||
|
self.taken_area = self.taken_area + tileSizeY*BLOCK_SIZE + tileSizeX*BLOCK_SIZE
|
||||||
|
|
||||||
|
return self.canvas, self.users[element].quad
|
||||||
|
else
|
||||||
|
print('failed to allocate :X')
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sortFunc(el1, el2)
|
||||||
|
return el1.view.h > el2.view.h
|
||||||
|
end
|
||||||
|
|
||||||
|
function atlas:refragment()
|
||||||
|
self:unMarkTiles(1, 1, self.tileW-1, self.tileH-1)
|
||||||
|
self.taken_area = 0
|
||||||
|
|
||||||
|
local elementArray = {}
|
||||||
|
|
||||||
|
for i, e in pairs(self.users) do
|
||||||
|
i.settings.needsRendering = true
|
||||||
|
table.insert(elementArray, i)
|
||||||
|
end
|
||||||
|
|
||||||
|
--self.users = {}
|
||||||
|
love.graphics.setCanvas(self.canvas)
|
||||||
|
love.graphics.clear(0,0,0,0)
|
||||||
|
love.graphics.setCanvas()
|
||||||
|
--Should be sorted large to small
|
||||||
|
table.sort(elementArray, sortFunc)
|
||||||
|
|
||||||
|
for index, element in ipairs(elementArray) do
|
||||||
|
self:assignElement(element)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function atlas:markTiles(x, y, w, h)
|
||||||
|
for y = y, y+h do
|
||||||
|
self.tiles[y].empty = self.tiles[y].empty - w
|
||||||
|
|
||||||
|
for x = x, x+w do
|
||||||
|
self.tiles[y][x].taken = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function atlas:unMarkTiles(x, y, w, h)
|
||||||
|
for y = y, y+h do
|
||||||
|
self.tiles[y].empty = self.tiles[y].empty + w
|
||||||
|
|
||||||
|
for x = x, x+w do
|
||||||
|
self.tiles[y][x].taken = false
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--Work only with rounded values inside here
|
--Work only with rounded values inside here
|
||||||
function atlas:find(sizeY, sizeX)
|
function atlas:find(sizeY, sizeX)
|
||||||
for y = 1, #self.tiles do
|
local maxX, maxY = #self.tiles[1], #self.tiles
|
||||||
|
|
||||||
|
for y = 1, #self.tiles-sizeY+1 do
|
||||||
local skipUntilX=0
|
local skipUntilX=0
|
||||||
if self.tiles[y].empty > sizeY then
|
if self.tiles[y].empty > sizeY then
|
||||||
for x = 1, #self.tiles[1] do
|
for x = 1, #self.tiles[1]-sizeX do
|
||||||
if not self.tiles[y][x].taken and x>skipUntilX then
|
if not self.tiles[y][x].taken and x>skipUntilX then
|
||||||
local result, y, x = self:slice(y, x, sizeY, sizeX)
|
local result, y, x = self:slice(y, x, sizeY, sizeX)
|
||||||
|
|
||||||
@ -62,21 +186,25 @@ function atlas:find(sizeY, sizeX)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function atlas:slice(startY, startX, sizeY, sizeX)
|
function atlas:slice(startY, startX, sizeY, sizeX)
|
||||||
for y = startY, startY+sizeY do
|
for y = startY, startY+sizeY do
|
||||||
for x = startX, sizeX do
|
for x = startX, startX+sizeX do
|
||||||
if self.tiles[y][x].taken then
|
if self.tiles[y][x].taken then
|
||||||
return false, y, x
|
return false, y, x
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true, startY, startX
|
||||||
end
|
end
|
||||||
|
|
||||||
function atlas:unassignElement(element)
|
function atlas:unassignElement(element)
|
||||||
|
local user = self.users[element]
|
||||||
|
self:unMarkTiles(user.x, user.y, user.w, user.h)
|
||||||
|
self.users[element] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
return atlas
|
return atlas
|
||||||
@ -4,7 +4,7 @@ local path = string.sub(..., 1, string.len(...) - string.len(".core.element"))
|
|||||||
local helium = require(path .. ".dummy")
|
local helium = require(path .. ".dummy")
|
||||||
local context = require(path.. ".core.stack")
|
local context = require(path.. ".core.stack")
|
||||||
|
|
||||||
---@class element
|
---@class Element
|
||||||
local element = {}
|
local element = {}
|
||||||
element.__index = element
|
element.__index = element
|
||||||
|
|
||||||
@ -103,8 +103,8 @@ end
|
|||||||
--Random coefficients, if these reach 1.5 then canvas is made
|
--Random coefficients, if these reach 1.5 then canvas is made
|
||||||
local childrenNum = 5
|
local childrenNum = 5
|
||||||
local selfRenderTime = false
|
local selfRenderTime = false
|
||||||
local screenSize = 1/50
|
local screenSize = 1/4
|
||||||
local coefficient = 1000000
|
local coefficient = 1.50
|
||||||
|
|
||||||
function element.setBench(time)
|
function element.setBench(time)
|
||||||
selfRenderTime = time
|
selfRenderTime = time
|
||||||
@ -112,10 +112,10 @@ end
|
|||||||
|
|
||||||
function element:calculateCanvasCoeficient(selfTime)
|
function element:calculateCanvasCoeficient(selfTime)
|
||||||
local sW, sH = love.graphics.getDimensions()
|
local sW, sH = love.graphics.getDimensions()
|
||||||
local areaBelow = (sW * sH) * screenSize
|
local areaBelow = helium.atlas.getFreeArea()
|
||||||
local area = self.view.h * self.view.w
|
local area = self.view.h * self.view.w
|
||||||
|
|
||||||
local areaCoef = 1 - (area/areaBelow)
|
local areaCoef = (1-helium.atlas.getRatio()) - (area/areaBelow)
|
||||||
local childCoef = self.context:getChildrenCount()/childrenNum
|
local childCoef = self.context:getChildrenCount()/childrenNum
|
||||||
local sizeCoef = selfTime/selfRenderTime
|
local sizeCoef = selfTime/selfRenderTime
|
||||||
|
|
||||||
@ -124,11 +124,10 @@ end
|
|||||||
|
|
||||||
local newCanvas, newQuad = love.graphics.newCanvas, love.graphics.newQuad
|
local newCanvas, newQuad = love.graphics.newCanvas, love.graphics.newQuad
|
||||||
function element:createCanvas()
|
function element:createCanvas()
|
||||||
self.settings.canvasW = self.view.w*1.25
|
self.settings.canvasW = self.view.w
|
||||||
self.settings.canvasH = self.view.h*1.25
|
self.settings.canvasH = self.view.h
|
||||||
|
|
||||||
self.canvas = newCanvas(self.view.w*1.25, self.view.h*1.25)
|
self.canvas, self.quad = helium.atlas.assign(self)
|
||||||
self.quad = newQuad(0, 0, self.view.w, self.view.h, self.view.w*1.25, self.view.h*1.25)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function element:setParam(p)
|
function element:setParam(p)
|
||||||
@ -145,7 +144,7 @@ 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
|
||||||
@ -161,7 +160,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
|
||||||
@ -202,19 +201,12 @@ function element:internalRender()
|
|||||||
calcT = love.timer.getTime()
|
calcT = love.timer.getTime()
|
||||||
end
|
end
|
||||||
|
|
||||||
local status, err = pcall(self.renderer)
|
self.renderer()
|
||||||
if self.settings.testRenderPasses > 0 and selfRenderTime then
|
if self.settings.testRenderPasses > 0 and selfRenderTime then
|
||||||
self.settings.testRenderPasses = self.settings.testRenderPasses-1
|
self.settings.testRenderPasses = self.settings.testRenderPasses-1
|
||||||
local selfTime = love.timer.getTime()-calcT
|
local selfTime = love.timer.getTime()-calcT
|
||||||
table.insert(self.renderBench, self.context:endSelfRender(selfTime))
|
table.insert(self.renderBench, self.context:endSelfRender(selfTime))
|
||||||
end
|
end
|
||||||
|
|
||||||
if not status then
|
|
||||||
if helium.conf.HARD_ERROR then
|
|
||||||
error(status)
|
|
||||||
end
|
|
||||||
self:errorRender(status)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local draw = love.graphics.draw
|
local draw = love.graphics.draw
|
||||||
@ -242,9 +234,13 @@ function element:externalRender()
|
|||||||
if self.settings.needsRendering then
|
if self.settings.needsRendering then
|
||||||
if self.settings.hasCanvas then
|
if self.settings.hasCanvas then
|
||||||
setCanvas(self.canvas)
|
setCanvas(self.canvas)
|
||||||
love.graphics.clear(0,0,0,0)
|
--need scissors
|
||||||
|
--love.graphics.clear(0,0,0,0)
|
||||||
love.graphics.push('all')
|
love.graphics.push('all')
|
||||||
love.graphics.origin()
|
love.graphics.origin()
|
||||||
|
local ox, oy = self.quad:getViewport()
|
||||||
|
|
||||||
|
love.graphics.translate(ox, oy)
|
||||||
|
|
||||||
self:renderWrapper()
|
self:renderWrapper()
|
||||||
self.settings.needsRendering = false
|
self.settings.needsRendering = false
|
||||||
|
|||||||
@ -37,6 +37,13 @@ end
|
|||||||
local activeWindow
|
local activeWindow
|
||||||
local windowStack = {}
|
local windowStack = {}
|
||||||
|
|
||||||
|
function input.unload()
|
||||||
|
windowStack = {}
|
||||||
|
activeWindow = nil
|
||||||
|
windowMachine = {}
|
||||||
|
input.subscriptions = {}
|
||||||
|
end
|
||||||
|
|
||||||
local dummyfunc = function() end
|
local dummyfunc = function() end
|
||||||
---@class subscription
|
---@class subscription
|
||||||
local subscription = {}
|
local subscription = {}
|
||||||
|
|||||||
18
init.lua
18
init.lua
@ -10,6 +10,7 @@ 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.loader = require(path..".loader")
|
helium.loader = require(path..".loader")
|
||||||
|
helium.atlas = require(path..".core.atlas")
|
||||||
helium.elementBuffer = {}
|
helium.elementBuffer = {}
|
||||||
helium.__index = helium
|
helium.__index = helium
|
||||||
|
|
||||||
@ -26,7 +27,18 @@ end})
|
|||||||
|
|
||||||
local first = true
|
local first = true
|
||||||
local skip = true
|
local skip = true
|
||||||
function helium.render()
|
|
||||||
|
function helium.load()
|
||||||
|
helium.atlas.load()
|
||||||
|
end
|
||||||
|
|
||||||
|
function helium.unload()
|
||||||
|
helium.atlas.unassignAll()
|
||||||
|
helium.elementBuffer = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function helium.draw()
|
||||||
if first and not skip then
|
if first and not skip then
|
||||||
--love.graphics.setScissor(500, 500, 1, 1)
|
--love.graphics.setScissor(500, 500, 1, 1)
|
||||||
|
|
||||||
@ -86,7 +98,7 @@ end
|
|||||||
]]
|
]]
|
||||||
if helium.conf.AUTO_RUN then
|
if helium.conf.AUTO_RUN then
|
||||||
function love.run()
|
function love.run()
|
||||||
if love.load then love.load(love.arg.parseGameArguments(arg), arg) end
|
if love.load then love.load() end--love.arg.parseGameArguments(arg), arg) end
|
||||||
|
|
||||||
-- We don't want the first frame's dt to include time taken by love.load.
|
-- We don't want the first frame's dt to include time taken by love.load.
|
||||||
if love.timer then love.timer.step() end
|
if love.timer then love.timer.step() end
|
||||||
@ -128,7 +140,7 @@ if helium.conf.AUTO_RUN then
|
|||||||
if love.draw then love.draw() end
|
if love.draw then love.draw() end
|
||||||
|
|
||||||
st = love.timer.getTime()
|
st = love.timer.getTime()
|
||||||
helium.render()
|
helium.draw()
|
||||||
heliumTime=heliumTime+love.timer.getTime()-st
|
heliumTime=heliumTime+love.timer.getTime()-st
|
||||||
|
|
||||||
love.graphics.present()
|
love.graphics.present()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user