Unexpected behaviour in events and objects

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
cristoferfb
Prole
Posts: 16
Joined: Wed May 15, 2019 12:41 am
Location: Valparaiso, Chile.

Unexpected behaviour in events and objects

Post by cristoferfb »

Hi, I implemented my object with the classic module: https://github.com/rxi/classic/blob/master/classic.lua

Code: Select all

Node = Object.extend(Object)

function Node:new (imgDir)
	self.img = love.graphics.newImage(imgDir)
end

function Node:draw (y, scale)
	-- This if works for know if a node is in the middle of the screen.
	if (y + self.img:getHeight()/2)*scale < (love.graphics.getHeight()/2 + self.img:getHeight()*scale/2) and (yPosition + self.img:getHeight()/2)*scale > (love.graphics.getHeight() / 2 - self.img:getHeight()*scale / 2) then
		love.graphics.setColor(102/255, 138/255, 1)
		love.event.push('fixPosition', love.graphics.getHeight()/2 - (y + self.img:getHeight()/2)*scale)
		love.event.push('setFocusNode', self)
	end

	centerX = love.graphics.getWidth() / 2 - self.img:getWidth() * scale / 2
        love.graphics.draw(self.img, centerX, y * scale, 0, scale, scale)
        love.graphics.setColor(1, 1, 1)
end

function Node:trigger () 
	test = 0
end
The only relevant part of the code above is the next:

Code: Select all

love.event.push('setFocusNode', self)
then in the event handler:

Code: Select all

function love.handlers.setFocusNode (node)
	node:trigger()
end
result in the next error:

Code: Select all

Error

main.lua:52: attempt to call method 'trigger' (a nil value)


Traceback

main.lua:52: in function <main.lua:51>
[C]: in function 'xpcall'
What do u think about that? I tried a lot of differents way for get it work.

pd: node:draw() is call in the function love.draw ().
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Unexpected behaviour in events and objects

Post by grump »

What you receive in the event handler is a copy of the table that has the original metatable stripped from it.

Code: Select all

function love.handlers.foo(t)
	print("received", t, getmetatable(t))
end

local t = setmetatable({}, {})
print("sending", t, getmetatable(t))
love.event.push("foo", t)
Output:

Code: Select all

sending	table: 0x418b3a00	table: 0x418b3a28
received	table: 0x403c6450	nil
cristoferfb
Prole
Posts: 16
Joined: Wed May 15, 2019 12:41 am
Location: Valparaiso, Chile.

Re: Unexpected behaviour in events and objects

Post by cristoferfb »

grump wrote: Sun May 03, 2020 5:59 am What you receive in the event handler is a copy of the table that has the original metatable stripped from it.

Code: Select all

function love.handlers.foo(t)
	print("received", t, getmetatable(t))
end

local t = setmetatable({}, {})
print("sending", t, getmetatable(t))
love.event.push("foo", t)
Output:

Code: Select all

sending	table: 0x418b3a00	table: 0x418b3a28
received	table: 0x403c6450	nil
Yeah, apparently I am trying to do the things in the C (pointers) style. I did a little more research on how lua works internally and i think I need to rethink my implementation.
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: Unexpected behaviour in events and objects

Post by pgimeno »

I believe this quirk happens because the events can be sent by a thread, therefore its contents need to be independent of the Lua context (because different threads use different Lua contexts in Löve), therefore the values need to be copied, not referenced. The metatable is not copied, but even if it was, since the target object is a copy and not the original object, the method could possibly be modifying the wrong object.
cristoferfb
Prole
Posts: 16
Joined: Wed May 15, 2019 12:41 am
Location: Valparaiso, Chile.

Re: Unexpected behaviour in events and objects

Post by cristoferfb »

pgimeno wrote: Sun May 03, 2020 1:33 pm I believe this quirk happens because the events can be sent by a thread, therefore its contents need to be independent of the Lua context (because different threads use different Lua contexts in Löve), therefore the values need to be copied, not referenced. The metatable is not copied, but even if it was, since the target object is a copy and not the original object, the method could possibly be modifying the wrong object.
Yes, every node check if himself is in the center of the screen, finally I externalized the logic for get it work.
Post Reply

Who is online

Users browsing this forum: No registered users and 83 guests