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 atlases = {}
|
||||
local createdAtlas
|
||||
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()
|
||||
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
|
||||
|
||||
function atlas.onscreenchange(newW, newH)
|
||||
@ -17,10 +56,11 @@ function atlas.new(w, h)
|
||||
local tiles = {}
|
||||
|
||||
local ymax = math.floor(h/BLOCK_SIZE)
|
||||
local xmax = math.floor(w/BLOCK_SIZE)
|
||||
for y = 1, ymax do
|
||||
tiles[y] = {}
|
||||
tiles[y].empty = ymax
|
||||
for x = 1, math.floor(w/BLOCK_SIZE) do
|
||||
tiles[y].empty = xmax
|
||||
for x = 1, xmax do
|
||||
tiles[y][x] = {
|
||||
taken = false
|
||||
}
|
||||
@ -30,7 +70,10 @@ function atlas.new(w, h)
|
||||
local self = {
|
||||
w = w,
|
||||
h = h,
|
||||
tileW = xmax,
|
||||
tileH = ymax,
|
||||
ideal_area = w*h,
|
||||
taken_area = 0,
|
||||
canvas = love.graphics.newCanvas(w, h),
|
||||
users = {},
|
||||
tiles = tiles,
|
||||
@ -39,17 +82,98 @@ function atlas.new(w, h)
|
||||
return setmetatable(self, atlas)
|
||||
end
|
||||
|
||||
function atlas:assignElement(elW, elH, element)
|
||||
local tileSizeY, tileSizeW = math.ceil(elH/BLOCK_SIZE), math.ceil(elW/BLOCK_SIZE)
|
||||
function atlas:assignElement(element)
|
||||
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
|
||||
|
||||
--Work only with rounded values inside here
|
||||
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
|
||||
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
|
||||
local result, y, x = self:slice(y, x, sizeY, sizeX)
|
||||
|
||||
@ -62,21 +186,25 @@ function atlas:find(sizeY, sizeX)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function atlas:slice(startY, startX, sizeY, sizeX)
|
||||
for y = startY, startY+sizeY do
|
||||
for x = startX, sizeX do
|
||||
for x = startX, startX+sizeX do
|
||||
if self.tiles[y][x].taken then
|
||||
return false, y, x
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
return true, startY, startX
|
||||
end
|
||||
|
||||
function atlas:unassignElement(element)
|
||||
|
||||
local user = self.users[element]
|
||||
self:unMarkTiles(user.x, user.y, user.w, user.h)
|
||||
self.users[element] = nil
|
||||
end
|
||||
|
||||
return atlas
|
||||
@ -4,7 +4,7 @@ local path = string.sub(..., 1, string.len(...) - string.len(".core.element"))
|
||||
local helium = require(path .. ".dummy")
|
||||
local context = require(path.. ".core.stack")
|
||||
|
||||
---@class element
|
||||
---@class Element
|
||||
local element = {}
|
||||
element.__index = element
|
||||
|
||||
@ -103,8 +103,8 @@ end
|
||||
--Random coefficients, if these reach 1.5 then canvas is made
|
||||
local childrenNum = 5
|
||||
local selfRenderTime = false
|
||||
local screenSize = 1/50
|
||||
local coefficient = 1000000
|
||||
local screenSize = 1/4
|
||||
local coefficient = 1.50
|
||||
|
||||
function element.setBench(time)
|
||||
selfRenderTime = time
|
||||
@ -112,10 +112,10 @@ end
|
||||
|
||||
function element:calculateCanvasCoeficient(selfTime)
|
||||
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 areaCoef = 1 - (area/areaBelow)
|
||||
local areaCoef = (1-helium.atlas.getRatio()) - (area/areaBelow)
|
||||
local childCoef = self.context:getChildrenCount()/childrenNum
|
||||
local sizeCoef = selfTime/selfRenderTime
|
||||
|
||||
@ -124,11 +124,10 @@ 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.settings.canvasW = self.view.w
|
||||
self.settings.canvasH = self.view.h
|
||||
|
||||
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.canvas, self.quad = helium.atlas.assign(self)
|
||||
end
|
||||
|
||||
function element:setParam(p)
|
||||
@ -145,7 +144,7 @@ end
|
||||
|
||||
function element:updateInputCtx()
|
||||
self.context.inputContext:update()
|
||||
if self.settings.canvasW then
|
||||
--[[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
|
||||
@ -161,7 +160,7 @@ function element:updateInputCtx()
|
||||
end
|
||||
|
||||
self.quad = love.graphics.newQuad(0, 0, self.view.w, self.view.h, self.settings.canvasW, self.settings.canvasH)
|
||||
end
|
||||
end]]
|
||||
end
|
||||
|
||||
local dummy = function() end
|
||||
@ -202,19 +201,12 @@ function element:internalRender()
|
||||
calcT = love.timer.getTime()
|
||||
end
|
||||
|
||||
local status, err = pcall(self.renderer)
|
||||
self.renderer()
|
||||
if self.settings.testRenderPasses > 0 and selfRenderTime then
|
||||
self.settings.testRenderPasses = self.settings.testRenderPasses-1
|
||||
local selfTime = love.timer.getTime()-calcT
|
||||
table.insert(self.renderBench, self.context:endSelfRender(selfTime))
|
||||
end
|
||||
|
||||
if not status then
|
||||
if helium.conf.HARD_ERROR then
|
||||
error(status)
|
||||
end
|
||||
self:errorRender(status)
|
||||
end
|
||||
end
|
||||
|
||||
local draw = love.graphics.draw
|
||||
@ -242,9 +234,13 @@ function element:externalRender()
|
||||
if self.settings.needsRendering then
|
||||
if self.settings.hasCanvas then
|
||||
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.origin()
|
||||
local ox, oy = self.quad:getViewport()
|
||||
|
||||
love.graphics.translate(ox, oy)
|
||||
|
||||
self:renderWrapper()
|
||||
self.settings.needsRendering = false
|
||||
|
||||
@ -37,6 +37,13 @@ end
|
||||
local activeWindow
|
||||
local windowStack = {}
|
||||
|
||||
function input.unload()
|
||||
windowStack = {}
|
||||
activeWindow = nil
|
||||
windowMachine = {}
|
||||
input.subscriptions = {}
|
||||
end
|
||||
|
||||
local dummyfunc = function() end
|
||||
---@class 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.input = require(path..".core.input")
|
||||
helium.loader = require(path..".loader")
|
||||
helium.atlas = require(path..".core.atlas")
|
||||
helium.elementBuffer = {}
|
||||
helium.__index = helium
|
||||
|
||||
@ -26,7 +27,18 @@ end})
|
||||
|
||||
local first = 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
|
||||
--love.graphics.setScissor(500, 500, 1, 1)
|
||||
|
||||
@ -86,7 +98,7 @@ end
|
||||
]]
|
||||
if helium.conf.AUTO_RUN then
|
||||
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.
|
||||
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
|
||||
|
||||
st = love.timer.getTime()
|
||||
helium.render()
|
||||
helium.draw()
|
||||
heliumTime=heliumTime+love.timer.getTime()-st
|
||||
|
||||
love.graphics.present()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user