Page 1 of 1

Running inherited function with self as parameter.

Posted: Sun Apr 01, 2018 11:27 am
by littlegaming
I'm trying to make a simple Gui library for a new project and I'm trying to make each object loop through its children and their update and draw functions.

This is Jammi.lua:

Code: Select all

local Jammi = {}
Jammi.children = {}

function Jammi:new(o)
	o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end

function Jammi:addchild(o)
	self.children[#self.children+1] = o
end

function Jammi.draw(thing)
	for i, child in ipairs(thing.children) do
		child:draw()
	end
end
function Jammi.update(thing, dt)
	for i, child in ipairs(thing.children) do
		child:update(dt)
	end
end

Jammi.Box = Jammi:new()

function Jammi.Box:draw()
	love.graphics.setColor(self.r or 255, self.g or 255, self.b or 255)
	love.graphics.rectangle(
		self.drawtype or "fill", 
		self.x or 0, 
		self.y or 0, 
		self.width or 20, 
		self.height or 20,
		self.rx or 0,
		self.ry or self.rx,
		self.segments or nil
	)
	Jammi.draw(self)
end

function Jammi.Box:update(dt)
	Jammi.update(self)
end

Jammi.Text = Jammi:new()

function Jammi.Text:draw()
	love.graphics.setColor(self.r or 255, self.g or 255, self.b or 255, self.a or 255)
	love.graphics.printf(
		self.text,
		self.x or 0,
		self.y or 0,
		self.wraplimit or love.graphics.getWidth(),
		self.alignmode or "left",
		self.angle or 0,
		self.sx or 1,
		self.sy or self.sx,
		ox or 0,
		oy or 0,
		kx or 0,
		ky or 0
	)
	Jammi.draw(self)
end

Jammi.Button = Jammi:new()
Jammi.Button.Held = false

function Jammi.Button:draw()
	love.graphics.setColor(self.Box.r or 255, self.Box.g or 255, self.Box.b or 255, self.Box.a or 255)
	love.graphics.rectangle(
		self.Box.drawtype or "fill", 
		self.Box.x or self.x, 
		self.Box.y or self.y, 
		self.Box.width or self.width, 
		self.Box.height or self.height,
		self.Box.rx or 0,
		self.Box.ry or self.rx,
		self.Box.segments or nil
	)
	love.graphics.setColor(self.Text.r or 255, self.Text.g or 255, self.Text.b or 255, self.Text.a or 255)
	love.graphics.printf(
		self.Text.text or "",
		self.Text.x or self.x,
		self.Text.y or self.y,
		self.Text.wraplimit or self.width,
		self.alignmode or "center"
	)
	Jammi.draw(self)
end

function Jammi.Button:update(dt)
	if (self.x < love.mouse.getX()+1 and love.mouse.getX() < self.x+self.width and self.y < love.mouse.getY()+1 and love.mouse.getY() < self.y+self.height) then
		if love.mouse.isDown(1) then
			if self.Held and not self.canHold then
				return
			end
			if self.onClick then self.onClick() end
			self.Held = true
			return
		end
	end
	self.Held = false
	Jammi.update(self, dt)
end

return Jammi
And main.lua:

Code: Select all

local Jammi = require("/Jammi")
local Gui = Jammi:new()
Gui:addchild(Jammi.Box:new({x=20, y=20, width=180, height=400}))


function love.update(dt)
	Gui.update(Gui, dt)
end

function love.draw()
	Gui.draw(Gui)
end
And this is the output:

Code: Select all

Error: /Jammi.lua:21: stack overflow
stack traceback:
	/Jammi.lua:21: in function 'update'
	/Jammi.lua:44: in function 'update'
	/Jammi.lua:22: in function 'update'
	/Jammi.lua:44: in function 'update'
	/Jammi.lua:22: in function 'update'
	/Jammi.lua:44: in function 'update'
	/Jammi.lua:22: in function 'update'
	/Jammi.lua:44: in function 'update'
	/Jammi.lua:22: in function 'update'
	...
	/Jammi.lua:44: in function 'update'
	/Jammi.lua:22: in function 'update'
	/Jammi.lua:44: in function 'update'
	/Jammi.lua:22: in function 'update'
	/Jammi.lua:44: in function 'update'
	/Jammi.lua:22: in function 'update'
	main.lua:7: in function 'update'
	[string "boot.lua"]:464: in function <[string "boot.lua"]:436>
	[C]: in function 'xpcall'
I know why it's spitting out stack overflow, but I can't think of how to correct it. From what I know this should be looping through every object's children and their children running their methods along the way. Any suggestions on how to optimise anything else is welcome too.

Re: Running inherited function with self as parameter.

Posted: Sun Apr 01, 2018 11:34 am
by Tjakka5
Simply changing

Code: Select all

function Jammi:new(o)
	o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end
to

Code: Select all

function Jammi:new(o)
	o = o or {}
	o.children = {}
    setmetatable(o, self)
    self.__index = self
    return o
end
should fix it.

However, there's quite a few other things that don't seem quite right about your implementation. Maybe you should have another look at how classes are implemented exactly, to avoid further confusion.

Re: Running inherited function with self as parameter.

Posted: Sun Apr 01, 2018 11:38 am
by zorg
And do check how the : colon syntax works exactly, you might not be doing what you want with that either.

Re: Running inherited function with self as parameter.

Posted: Sun Apr 01, 2018 11:50 am
by littlegaming
Ah, I see what I did now, thank you.