diff --git a/core/atlas.lua b/core/atlas.lua index 782ee15..06a59c1 100644 --- a/core/atlas.lua +++ b/core/atlas.lua @@ -1,5 +1,6 @@ local atlas = {} atlas.__index = atlas +---@class atlases local atlases ={} atlases.__index = atlases local BLOCK_SIZE = 5 @@ -11,8 +12,8 @@ function atlases.create() local self = { atlases = {} } - self.atlases[1] = atlas.new(sw, sh) - self.atlases[2] = atlas.new(sw, sh) + self.atlases[1] = atlas.new(sw*1.10, sh*1.10) + self.atlases[2] = atlas.new(sw*1.10, sh*1.10) return setmetatable(self, atlases) end @@ -80,7 +81,7 @@ function atlases:unassignAll() self.atlases[2].taken_area = 0 end -function atlases:onscreenchange(newW, newH) +function atlases:onresize(newW, newH) for i, e in ipairs(self.atlases[1].users) do e:reassignCanvas() end @@ -89,8 +90,8 @@ function atlases:onscreenchange(newW, newH) e:reassignCanvas() end - self.atlases[1] = atlas.new(newW, newH) - self.atlases[2] = atlas.new(newW, newH) + self.atlases[1] = atlas.new(newW*1.10, newH*1.10) + self.atlases[2] = atlas.new(newW*1.10, newH*1.10) end function atlas.new(w, h) @@ -246,9 +247,11 @@ 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 + if user then + 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 end return atlases \ No newline at end of file diff --git a/core/element.lua b/core/element.lua index 6d29934..2c8c42c 100644 --- a/core/element.lua +++ b/core/element.lua @@ -28,9 +28,10 @@ setmetatable(element, { --Control functions --The new function that should be used for element creation -function element:new(param, immediate, w, h) +function element:new(param, immediate, w, h, flags) self.parameters = {} self.baseParams = param + self.flags = flags or {} --Internal state callbacks self.callbacks = {} diff --git a/core/scene.lua b/core/scene.lua index ef1f08d..6f79fd7 100644 --- a/core/scene.lua +++ b/core/scene.lua @@ -80,6 +80,20 @@ function scene:draw() end +function scene:resize(nw, nh) + if self.atlas then + self.atlas:onresize(nw, nh) + end +end + +function scene:drawAtlases(x, y) + if self.atlas then + local aw = self.atlas.atlases[1].canvas:getWidth() + love.graphics.draw(self.atlas.atlases[1].canvas, x, y, 0, 0.5, 0.5) + love.graphics.draw(self.atlas.atlases[2].canvas, x+aw/2, y, 0, 0.5, 0.5) + end +end + ---Updates this scene and it's elements ---@param dt number function scene:update(dt) diff --git a/init.lua b/init.lua index f59a06e..48814f0 100644 --- a/init.lua +++ b/init.lua @@ -36,8 +36,8 @@ setmetatable(helium, {__call = function(s, chunk) draw = function (param, inputs, x, y, w, h) end }, - {__call = function(s, param, w, h) - return helium.element(chunk, param, w, h) + {__call = function(s, param, w, h, flags) + return helium.element(chunk, param, w, h, flags) end,}) end}) diff --git a/layout/column.lua b/layout/column.lua index 8e4def3..2d974a5 100644 --- a/layout/column.lua +++ b/layout/column.lua @@ -8,7 +8,7 @@ column.__index = column function column.new() local self = setmetatable({}, column) - return layout(self.draw) + return layout(self, self.draw) end function column:draw(x, y, width, height, children, hpad, vpad, alignX) diff --git a/layout/container.lua b/layout/container.lua new file mode 100644 index 0000000..5cad409 --- /dev/null +++ b/layout/container.lua @@ -0,0 +1,75 @@ +local path = string.sub(..., 1, string.len(...) - string.len(".container")) +local layout = require(path..'.init') + +---@class Container +local container = {} +container.__index = container + +---Positions an element within a container +---@param halign "'left'"|"'center'"|"'right'"|"'stretch'" +---@param valign "'top'"|"'center'"|"'bottom'"|"'stretch'" +---@return layout +function container.new(halign, valign) + local self = setmetatable({ + halign = halign or 'left', + valign = valign or 'top', + }, container) + + return layout(self, self.draw) +end + +local function alignLeft(x, wroot, wchild) + return x +end + +local function alignCenter(x, wroot, wchild) + return x+(wroot/2-wchild/2) +end + +local function alignRight(x, wroot, wchild) + return x+(wroot-wchild) +end + + +local function alignHandlerX(mode, x, wr, wc) + if mode == 'center' then + return alignCenter(x, wr, wc) + elseif mode == 'right' then + return alignRight(x, wr, wc) + else + return alignLeft(x) + end +end + +local function alignHandlerY(mode, y, hr, hc) + if mode == 'center' then + return alignCenter(y, hr, hc) + elseif mode == 'bottom' then + return alignRight(y, hr, hc) + else + return alignLeft(y) + end +end + +function container:draw(x, y, width, height, children, hpad, vpad, alignX) + local w, h = children[1]:getSize() + local x, y + + if self.halign =='stretch' then + w = width + x = x + else + x = alignHandlerX(self.halign, containerX, containerWidth, w) + end + + if self.valign =='stretch' then + h = h + y = y + else + y = alignHandlerY(self.valign, containerY, containerHeight, h) + end + + children[1]:draw(x, y, w, h) +end + +return container \ No newline at end of file diff --git a/layout/grid.lua b/layout/grid.lua index a1661f3..78e246b 100644 --- a/layout/grid.lua +++ b/layout/grid.lua @@ -35,19 +35,18 @@ local layout = require(path..'.init') ---@type GridConfig local preconfiguredGrid = { - colSpacing = 3, - rowSpacing = 3, - verticalStretchMode = 'normal', - horizontalStretchMode = 'normal', + colSpacing = 20, + rowSpacing = 20, + verticalStretchMode = 'stretch', + horizontalStretchMode = 'stretch', verticalAlignMode = 'center', horizontalAlignMode = 'center', - --rows = {1, 1, 1, 1}, - columns = {1, 1, 1, 1}, - --[[layout = { - {'header', 'header', 'header'}, - {'sidebar','content','content'}, - {'sidebar','content','content'}, - }]] + rows = {5,5}, + columns = {1,3,1}, + layout = { + {'sidebar','content','sidebar2'}, + {'sidebar','content','sidebar2'}, + } } ---@class grid @@ -99,7 +98,7 @@ local function alignHandlerY(mode, y, hr, hc) end end -function grid:draw(xRoot, yRoot, width, height, children, hpad, vpad) +function grid:draw(xRoot, yRoot, width, height, children) -- Either of these means no named layout local fullyAutoLayout = false local autoCols = false @@ -110,7 +109,8 @@ function grid:draw(xRoot, yRoot, width, height, children, hpad, vpad) local vertValueToPixels = 0 local horValueToPixels = 0 - local finalLayout = {} + local XIndexes = {} + local YIndexes = {} if self.gridLayout.columns then if not self.gridLayout.rows then @@ -120,12 +120,23 @@ function grid:draw(xRoot, yRoot, width, height, children, hpad, vpad) local total = 0 for i, col in ipairs(self.gridLayout.rows) do + YIndexes[i] = {} + + YIndexes[i].start = total total = total + col + YIndexes[i].finish = total end - vertValueToPixels = (height-(self.gridLayout.rowSpacing*total))/total + vertValueToPixels = height/total else - vertValueToPixels = (height-(self.gridLayout.rowSpacing*self.gridLayout.rows))/self.gridLayout.rows + vertValueToPixels = height/self.gridLayout.rows + + for y = 1, self.gridLayout.rows do + YIndexes[y] = {} + YIndexes[y].start = y-1 + YIndexes[y].finish = y + end + equalRows = true end end @@ -133,12 +144,23 @@ function grid:draw(xRoot, yRoot, width, height, children, hpad, vpad) local total = 0 for i, col in ipairs(self.gridLayout.columns) do + XIndexes[i] = {} + + XIndexes[i].start = total total = total + col + XIndexes[i].finish = total end horValueToPixels = width/total else horValueToPixels = width/self.gridLayout.columns + + for x = 1, self.gridLayout.columns do + XIndexes[x] = {} + XIndexes[x].start = x-1 + XIndexes[x].finish = x + end + equalCols = true end else @@ -154,18 +176,131 @@ function grid:draw(xRoot, yRoot, width, height, children, hpad, vpad) total = total + col end - vertValueToPixels = (height-(self.gridLayout.rowSpacing*total))/total + vertValueToPixels = (height)/total else - vertValueToPixels = (height-(self.gridLayout.rowSpacing*self.gridLayout.rows))/self.gridLayout.rows + vertValueToPixels = (height)/self.gridLayout.rows equalRows = true end end end - print(horValueToPixels, width) - if (not autoRows) and (not autoCols) then + if self.gridLayout.layout then + + local layout = {} + --flip layout table + for x = 1, #self.gridLayout.layout[1] do + layout[x] = {} + end + + for x = 1, #self.gridLayout.layout do + for y = 1, #self.gridLayout.layout[x] do + layout[y][x] = self.gridLayout.layout[x][y] + end + end + + local layoutDepth, layoutWidth = #self.gridLayout.layout, #layout + if type(self.gridLayout.rows) == "table" then + if not #self.gridLayout.rows == layoutDepth then + error('Layout table doesnt match row number') + end + else + if not self.gridLayout.rows == layoutDepth then + error('Layout table doesnt match row number') + end + end + if type(self.gridLayout.columns) == "table" then + if not #self.gridLayout.columns == layoutWidth then + error('Layout table doesnt match column number') + end + else + if not self.gridLayout.columns == layoutWidth then + error('Layout table doesnt match column number') + end + end + -- {x, y, width, height} + local fields = { + + } + + for x = 1, #layout do + for y = 1, #layout[x] do + if not fields[layout[x][y]] then + local finishedRow = false + local finishedCol = false + local curField = layout[x][y] + fields[curField] = {} + + fields[curField].x = XIndexes[x].start + fields[curField].y = YIndexes[y].start + fields[curField].finX = XIndexes[x].finish + fields[curField].finY = YIndexes[y].finish + + local parseX, parseY = x+1, y+1 + while not finishedRow do + if layout[x][parseY] and layout[x][parseY] == curField then + fields[curField].finY = YIndexes[parseY].finish + else + finishedRow = true + end + parseY = parseY + 1 + end + + while not finishedCol do + if layout[parseX] and layout[parseX][y] == curField then + fields[curField].finX = XIndexes[parseX].finish + else + finishedCol = true + end + parseX = parseX + 1 + end + + fields[curField].h = fields[curField].finY - fields[curField].y + fields[curField].w = fields[curField].finX - fields[curField].x + end + end + end + + for i, field in pairs(fields) do + for y, elem in ipairs(children) do + if elem.flags[i] then + field.element = elem + end + end + end + + for i, field in pairs(fields) do + if field.element then + local containerWidth = (field.w*horValueToPixels)-(self.gridLayout.colSpacing) + local containerHeight = (field.h*vertValueToPixels)-(self.gridLayout.rowSpacing) + + local containerX = ((field.x)*horValueToPixels)+(self.gridLayout.colSpacing/2) + local containerY = ((field.y)*vertValueToPixels)+(self.gridLayout.rowSpacing/2) + + local w, h = field.element:getSize() + local x, y + + if self.gridLayout.horizontalStretchMode =='stretch' then + w = containerWidth + x = containerX + else + x = alignHandlerX(self.gridLayout.horizontalAlignMode, containerX, containerWidth, w) + end + + if self.gridLayout.verticalStretchMode =='stretch' then + h = containerHeight + y = containerY + else + y = alignHandlerY(self.gridLayout.verticalAlignMode, containerY, containerHeight, h) + end + + field.element:draw(x+xRoot, y+yRoot, w, h) + end + end + else + error('please provide a layout table') + end elseif fullyAutoLayout then--one element per width, vertically down local carriagePos = 0 if children then @@ -204,12 +339,14 @@ function grid:draw(xRoot, yRoot, width, height, children, hpad, vpad) if self.gridLayout.horizontalStretchMode =='stretch' then w = width + x = xRoot else x = alignHandlerX(self.gridLayout.horizontalAlignMode, xRoot, width, w) end if self.gridLayout.verticalStretchMode =='stretch' then h = rowSize + y = carriagePos else y = alignHandlerY(self.gridLayout.verticalAlignMode, carriagePos, rowSize, h) end @@ -254,6 +391,7 @@ function grid:draw(xRoot, yRoot, width, height, children, hpad, vpad) if self.gridLayout.horizontalStretchMode =='stretch' then w = colSize + x = colDrawStart else x = alignHandlerX(self.gridLayout.horizontalAlignMode, colDrawStart, colSize, w) end diff --git a/layout/init.lua b/layout/init.lua index dd09e61..cb5da36 100644 --- a/layout/init.lua +++ b/layout/init.lua @@ -125,6 +125,7 @@ function layout:draw() 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 + y = self.vars.offTop elseif self.vars.offTop then y = stack:normY(self.vars.offTop) height = math.min(stack:normY(self.vars.height), maxH-y) @@ -137,6 +138,7 @@ function layout:draw() 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 + x = self.vars.offLeft elseif self.vars.offLeft then x = stack:normX(self.vars.offLeft) width = math.min(stack:normX(self.vars.width), maxW-x) @@ -150,5 +152,5 @@ function layout:draw() end -setmetatable(layout, {__call = function(s, callback, binder) return layout.type(callback, binder) end }) +setmetatable(layout, {__call = function(s, binder, callback) return layout.type(binder, callback) end }) return layout \ No newline at end of file diff --git a/layout/row.lua b/layout/row.lua index e886854..e681945 100644 --- a/layout/row.lua +++ b/layout/row.lua @@ -9,7 +9,7 @@ row.__index = row function row.new() local self = setmetatable({}, row) - return layout(self.draw) + return layout(self, self.draw) end function row:draw(x, y, width, height, children, hpad, vpad, alignX)