diff --git a/elements/clipRegion.lua b/elements/clipRegion.lua new file mode 100644 index 0000000..fb075e9 --- /dev/null +++ b/elements/clipRegion.lua @@ -0,0 +1,91 @@ +local graphics +graphics = love.graphics +local element = require(tostring((...):sub(1, -11)) .. "/element") +local recursiveDraw +recursiveDraw = function(children, x, y) + for i = 1, #children do + local child = children[i] + local drawChildren + if child.draw then + child.data.x = child.data.x - x + child.data.y = child.data.y - y + drawChildren = child:draw() + child.data.x = child.data.x + x + child.data.y = child.data.y + y + end + if drawChildren ~= false then + recursiveDraw(child.child, x, y) + end + end +end +local canvasDraw +local major, minor = love.getVersion() +if major == 0 and minor == 10 then + canvasDraw = function(canvas, x, y) + return graphics.draw(canvas, x, y) + end +else + canvasDraw = function(canvas, x, y) + local mode, alpha = graphics.getBlendMode() + graphics.setBlendMode("alpha", "premultiplied") + graphics.draw(canvas, x, y) + return graphics.setBlendMode(mode, alpha) + end +end +local clipRegion +do + local _class_0 + local _parent_0 = element + local _base_0 = { + draw = function(self) + graphics.setCanvas(self.canvas) + graphics.clear() + recursiveDraw(self.child, self.data.x, self.data.y) + graphics.setCanvas() + graphics.setColor(255, 255, 255, 255) + canvasDraw(self.canvas, self.data.x, self.data.y) + return false + end + } + _base_0.__index = _base_0 + setmetatable(_base_0, _parent_0.__base) + _class_0 = setmetatable({ + __init = function(self, parent, data) + if data == nil then + data = { } + end + self.parent, self.data = parent, data + _class_0.__parent.__init(self, self.parent, self.data) + if self.data.type == "element" then + self.data.type = "clipRegion" + end + self.canvas = graphics.newCanvas(self.data.w, self.data.h) + end, + __base = _base_0, + __name = "clipRegion", + __parent = _parent_0 + }, { + __index = function(cls, name) + local val = rawget(_base_0, name) + if val == nil then + local parent = rawget(cls, "__parent") + if parent then + return parent[name] + end + else + return val + end + end, + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 + end + }) + _base_0.__class = _class_0 + if _parent_0.__inherited then + _parent_0.__inherited(_parent_0, _class_0) + end + clipRegion = _class_0 + return _class_0 +end diff --git a/elements/clipRegion.moon b/elements/clipRegion.moon new file mode 100644 index 0000000..7401f78 --- /dev/null +++ b/elements/clipRegion.moon @@ -0,0 +1,48 @@ +import graphics from love + +element = require "#{(...)\sub 1, -11}/element" + +recursiveDraw = (children, x, y) -> + for i = 1, #children + child = children[i] + local drawChildren + if child.draw + child.data.x -= x + child.data.y -= y + drawChildren = child\draw! + child.data.x += x + child.data.y += y + if drawChildren != false + recursiveDraw child.child, x, y + +local canvasDraw +major, minor = love.getVersion! + +if major == 0 and minor == 10 + canvasDraw = (canvas, x, y) -> + graphics.draw canvas, x, y +else + canvasDraw = (canvas, x, y) -> + mode, alpha = graphics.getBlendMode! + graphics.setBlendMode "alpha", "premultiplied" + graphics.draw canvas, x, y + graphics.setBlendMode mode, alpha + +-- canvasDraw = (canvas, x, y) -> +-- graphics.draw canvas, x, y + +class clipRegion extends element + new: (@parent, @data={}) => + super @parent, @data + + @data.type = "clipRegion" if @data.type == "element" + @canvas = graphics.newCanvas @data.w, @data.h + + draw: => + graphics.setCanvas @canvas + graphics.clear! + recursiveDraw @child, @data.x, @data.y + graphics.setCanvas! + graphics.setColor 255, 255, 255, 255 + canvasDraw @canvas, @data.x, @data.y + return false diff --git a/elements/element.lua b/elements/element.lua index ef2f21d..c420bcb 100644 --- a/elements/element.lua +++ b/elements/element.lua @@ -178,6 +178,14 @@ do getPadding = function(self) return self.data.padding end, + setMargin = function(self, margin) + self.data.margin = margin + self:align() + return self + end, + getMargin = function(self) + return self.data.margin + end, indexOf = function(self, element) for i = 1, #self.child do if self.child[i] == element then @@ -267,6 +275,15 @@ do if not (self.data.type) then self.data.type = "element" end + if self.data.update == nil then + self.data.update = true + end + if self.data.draw == nil then + self.data.draw = true + end + if self.data.hoverable == nil then + self.data.hoverable = true + end if not (self.data.x) then if self.parent then self.data.x = self.parent.data.x @@ -287,14 +304,14 @@ do if not (self.data.h) then self.data.h = 0 end - if self.data.update == nil then - self.data.update = true + if not (self.data.size) then + self.data.size = 0 end - if self.data.draw == nil then - self.data.draw = true + if not (self.data.verticalSize) then + self.data.verticalSize = 0 end - if self.data.hoverable == nil then - self.data.hoverable = true + if not (self.data.horizontalSize) then + self.data.horizontalSize = 0 end if (self.data.align == nil) and self.parent then self.data.align = true @@ -324,6 +341,13 @@ do self.data.verticalPadding = 0 end self.child = { } + if not (self.__class.align) then + if self.data.size ~= 0 or self.data.verticalSize ~= 0 or self.data.horizontalSize ~= 0 then + return self:setSize(self.parent.data.w * (self.data.size + self.data.verticalSize), self.parent.data.h * (self.data.size + self.data.horizontalSize)) + elseif self.data.align then + return self:align() + end + end end, __base = _base_0, __name = "element" diff --git a/elements/element.moon b/elements/element.moon index 3f578b6..3ca9b00 100644 --- a/elements/element.moon +++ b/elements/element.moon @@ -25,6 +25,11 @@ class element @data.child = {} unless @data.child @data.type = "element" unless @data.type + @data.update = true if @data.update == nil + @data.draw = true if @data.draw == nil + @data.hoverable = true if @data.hoverable == nil + -- @data.static = false if @data.static == nil + unless @data.x if @parent @data.x = @parent.data.x @@ -38,10 +43,9 @@ class element @data.w = 0 unless @data.w @data.h = 0 unless @data.h - @data.update = true if @data.update == nil - @data.draw = true if @data.draw == nil - @data.hoverable = true if @data.hoverable == nil - --@data.static = false if @data.static == nil + @data.size = 0 unless @data.size + @data.verticalSize = 0 unless @data.verticalSize + @data.horizontalSize = 0 unless @data.horizontalSize @data.align = true if (@data.align == nil) and @parent @data.verticalAlign = "top" unless @data.verticalAlign @@ -57,6 +61,12 @@ class element @child = {} + unless @__class.align -- this is so elements setting up their own alignment (such as window) won't break by alignment being called prematurely + if @data.size != 0 or @data.verticalSize != 0 or @data.horizontalSize != 0 + @setSize @parent.data.w * (@data.size + @data.verticalSize), @parent.data.h * (@data.size + @data.horizontalSize) + elseif @data.align + @align! + --- @todo doc me align: (horizontal, vertical, toPixel=true) => unless @data.align return @ @@ -227,6 +237,14 @@ class element getPadding: => return @data.padding + setMargin: (margin) => + @data.margin = margin + @align! + return @ + + getMargin: => + return @data.margin + indexOf: (element) => for i = 1, #@child if @child[i] == element diff --git a/elements/window.lua b/elements/window.lua index d4367b3..93c66b6 100644 --- a/elements/window.lua +++ b/elements/window.lua @@ -350,7 +350,11 @@ do end return false end - return self:align() + if self.data.size ~= 0 or self.data.verticalSize ~= 0 or self.data.horizontalSize ~= 0 then + return self:setSize(self.parent.data.w * (self.data.size + self.data.verticalSize), self.parent.data.h * (self.data.size + self.data.horizontalSize)) + elseif self.data.align then + return self:align() + end end, __base = _base_0, __name = "window", diff --git a/elements/window.moon b/elements/window.moon index ffb62f0..996409a 100644 --- a/elements/window.moon +++ b/elements/window.moon @@ -160,7 +160,10 @@ class window extends element return true return false - @align! + if @data.size != 0 or @data.verticalSize != 0 or @data.horizontalSize != 0 + @setSize @parent.data.w * (@data.size + @data.verticalSize), @parent.data.h * (@data.size + @data.horizontalSize) + elseif @data.align + @align! align: (...) => unless @data.align return @ diff --git a/init.lua b/init.lua index 83b3450..ee2c93e 100644 --- a/init.lua +++ b/init.lua @@ -242,11 +242,14 @@ pop.draw = function(element) element = pop.screen end if element.data.draw then + local drawChildren if element.draw then - element:draw() + drawChildren = element:draw() end - for i = 1, #element.child do - pop.draw(element.child[i]) + if drawChildren ~= false then + for i = 1, #element.child do + pop.draw(element.child[i]) + end end end end diff --git a/init.moon b/init.moon index b1e59a7..ac5435c 100644 --- a/init.moon +++ b/init.moon @@ -283,10 +283,12 @@ pop.update = (dt, element=pop.screen) -> pop.draw = (element=pop.screen) -> -- data.draw boolean controls an element and its children being drawn if element.data.draw + local drawChildren if element.draw - element\draw! - for i = 1, #element.child - pop.draw element.child[i] + drawChildren = element\draw! + if drawChildren != false + for i = 1, #element.child + pop.draw element.child[i] diff --git a/main.lua b/main.lua index c2d1a6b..8f1304d 100644 --- a/main.lua +++ b/main.lua @@ -153,6 +153,157 @@ love.load = function() w = 125 }, "Body can't leave") end + local test_original_color_clipRegion + test_original_color_clipRegion = function() + local testWindow = pop.window({ + windowBackground = { + 200, + 200, + 200 + }, + closeable = true, + maximizeable = true, + minimizeable = true + }, "Testing Window"):move(20, 20):setSize(200, 100):align("right", "top") + print(testWindow.window_area) + pop.window({ + maximizeable = true + }, "Test Window #2"):align("center", "bottom") + pop.window({ + moveable = false + }, "Immoveable!") + local centerBox = pop.box({ + w = 200, + h = 200 + }, { + 0, + 0, + 0, + 255 + }):align("center", "center") + pop.box(centerBox, { + w = 10, + h = 20 + }):align("left", "top") + pop.box(centerBox, { + w = 30, + h = 30 + }):align("center", "top") + pop.box(centerBox, { + w = 5, + h = 40 + }):align("left", "center") + pop.box(centerBox, { + w = 50, + h = 50 + }):align("right", "center") + pop.box(centerBox):align("left", "bottom"):setSize(5, 5) + pop.box(centerBox, { + w = 25, + h = 10 + }):align("center", "bottom") + pop.text(centerBox, "Align me!"):align("right", "top") + pop.window(centerBox, { + closeable = true, + w = 80, + h = 63 + }):align("right", "bottom") + pop.window(centerBox, { + titleColor = { + 0, + 0, + 0, + 150 + }, + titleBackground = { + 0, + 0, + 255, + 255 + }, + windowBackground = { + 200, + 200, + 255, + 100 + }, + w = 60, + h = 50 + }):align("center", "bottom") + centerBox:setPadding(5) + pop.box(centerBox, { + w = 10, + h = 20, + background = { + 0, + 0, + 255, + 255 + } + }):align("left", "top") + pop.box(centerBox, { + w = 30, + h = 30, + background = { + 0, + 255, + 0, + 255 + } + }):align("center", "top") + pop.box(centerBox, { + w = 5, + h = 40, + background = { + 255, + 0, + 0, + 255 + } + }):align("left", "center") + pop.box(centerBox, { + w = 50, + h = 50, + background = { + 0, + 255, + 255, + 255 + } + }):align("right", "center") + pop.text(centerBox, { + color = { + 255, + 0, + 255, + 255 + } + }, "Text!"):align("left", "bottom") + pop.box(centerBox, { + w = 25, + h = 10, + background = { + 100, + 100, + 255, + 255 + } + }):align("center", "bottom") + pop.text(centerBox, { + color = { + 255, + 255, + 0, + 255 + } + }, "Align me!"):align("right", "top") + return pop.window(centerBox, { + containMethod = "body", + w = 125, + h = 30, + margin = 30 + }, "Body can't leave") + end local test_obession test_obession = function() local partsGrid = pop.dynamicGrid() @@ -172,7 +323,7 @@ love.load = function() }) }) end - return test_original() + return test_original_color_clipRegion() end love.update = function(dt) return pop.update(dt) diff --git a/main.moon b/main.moon index ab4d39d..f10e999 100644 --- a/main.moon +++ b/main.moon @@ -16,8 +16,8 @@ love.load = -> pop.window({maximizeable: true}, "Test Window #2")\align "center", "bottom" pop.window({moveable: false}, "Immoveable!") - -- alignment testing centerBox = pop.box({w: 200, h: 200}, {255, 255, 0, 120})\align "center", "center" + pop.box(centerBox, {w: 10, h: 20})\align "left", "top" pop.box(centerBox, {w: 30, h: 30})\align "center", "top" pop.box(centerBox, {w: 5, h: 40})\align "left", "center" @@ -40,6 +40,43 @@ love.load = -> pop.window(centerBox, {containMethod: "title", w: 125}, "Title can't leave") pop.window(centerBox, {containMethod: "body", w: 125}, "Body can't leave") + test_original_color_clipRegion = -> + testWindow = pop.window({windowBackground: {200, 200, 200}, closeable: true, maximizeable: true, minimizeable: true}, "Testing Window")\move(20, 20)\setSize(200, 100)\align "right", "top" + print testWindow.window_area + + pop.window({maximizeable: true}, "Test Window #2")\align "center", "bottom" + pop.window({moveable: false}, "Immoveable!") + + -- alignment testing + -- centerBox = pop.clipRegion {w: 200, h: 200, verticalAlign: "center", horizontalAlign: "center"} + + -- centerBox = pop.box({w: 200, h: 200}, {255, 255, 0, 120})\align "center", "center" + centerBox = pop.box({w: 200, h: 200}, {0, 0, 0, 255})\align "center", "center" + + pop.box(centerBox, {w: 10, h: 20})\align "left", "top" + pop.box(centerBox, {w: 30, h: 30})\align "center", "top" + pop.box(centerBox, {w: 5, h: 40})\align "left", "center" + pop.box(centerBox, {w: 50, h: 50})\align "right", "center" + pop.box(centerBox)\align("left", "bottom")\setSize 5, 5 + pop.box(centerBox, {w: 25, h: 10})\align "center", "bottom" + pop.text(centerBox, "Align me!")\align "right", "top" + + pop.window(centerBox, {closeable: true, w: 80, h: 63})\align "right", "bottom" + pop.window(centerBox, {titleColor: {0, 0, 0, 150}, titleBackground: {0, 0, 255, 255}, windowBackground: {200, 200, 255, 100}, w: 60, h: 50})\align "center", "bottom" + + centerBox\setPadding 5 + + pop.box(centerBox, {w: 10, h: 20, background: {0, 0, 255, 255}})\align "left", "top" + pop.box(centerBox, {w: 30, h: 30, background: {0, 255, 0, 255}})\align "center", "top" + pop.box(centerBox, {w: 5, h: 40, background: {255, 0, 0, 255}})\align "left", "center" + pop.box(centerBox, {w: 50, h: 50, background: {0, 255, 255, 255}})\align "right", "center" + pop.text(centerBox, {color: {255, 0, 255, 255}}, "Text!")\align("left", "bottom")--\setSize 5, 5 + pop.box(centerBox, {w: 25, h: 10, background: {100, 100, 255, 255}})\align "center", "bottom" + pop.text(centerBox, {color: {255, 255, 0, 255}}, "Align me!")\align "right", "top" + + -- pop.window(centerBox, {containMethod: "title", w: 125}, "Title can't leave") + pop.window(centerBox, {containMethod: "body", w: 125, h: 30, margin: 30}, "Body can't leave") + test_obession = -> partsGrid = pop.dynamicGrid! pop.window({w: graphics.getWidth!/2, h: graphics.getHeight!, titleBar: false})\add({ @@ -54,7 +91,8 @@ love.load = -> }) }) - test_original! + -- test_original! + test_original_color_clipRegion! -- test_obession! love.update = (dt) ->