Changing one of the methods in a LÖVE object

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
User avatar
wolfboyft
Prole
Posts: 20
Joined: Sat Oct 21, 2017 5:28 pm
Location: London
Contact:

Changing one of the methods in a LÖVE object

Post by wolfboyft »

I made a deterministic maths library, and I want to make LÖVE's Transform objects use my sine and cosine algorithms for its rotate method. How can I do this?

I tried:

Code: Select all

local rotate = function(self, angle)
	-- TODO
	print("It worked.")
end

local originalNewTransform = love.math.newTransform
function love.math.newTransform(...)
	local new = originalNewTransform(...)
	new.rotate = rotate
	return new
end

local transform = love.math.newTransform()
transform:rotate(math.pi / 2)
OK, so I can't index Transforms because Transforms are userdata values. Metatables?

Code: Select all

local rotate = function(self, angle)
	-- TODO
	print("It worked.")
end

local transformMetatable = {
	__index = function(table, key)
		return key == "rotate" and rotate or rawget(table, "key")
	end
}

local originalNewTransform = love.math.newTransform
function love.math.newTransform(...)
	return setmetatable(originalNewTransform(...), transformMetatable)
end

local transform = love.math.newTransform()
transform:rotate(math.pi / 2)
I can't put metatables on userdata.

Help! What do I do? I thought maybe I could use FFI to replace the Transform class from LÖVE with a subclass that has its rotate method replaced (I could make my sine and cosine in C) but A: ffi.c.love doesn't exist and B: LÖVE is C++ and already compiled, so... yeah! Completely stumped.

Any help is appreciated! Thank you.
Tachytaenius
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Changing one of the methods in a LÖVE object

Post by pgimeno »

You can't set a new metatable from Lua, but you can alter its existing metatable. The details get tricky, though, as the __index metamethod is already being used.

Code: Select all

local rotate = function(self, angle)
	-- TODO
	print("It worked.")
end

local originalNewTransform = love.math.newTransform
function love.math.newTransform(...)
	local obj = originalNewTransform(...)
	local mt = getmetatable(obj)
	local originalIndex = mt.__index
	getmetatable(obj).__index = function(table, key)
		local idx = mt.__index
		mt.__index = originalIndex
		local result = key == "rotate" and rotate or table[key]
		mt.__index = idx
		return result
	end
	return obj
end

local transform = love.math.newTransform()
transform:rotate(math.pi / 2)
print(transform.type())
I personally think that's an aberration. The C++ code is certainly not going to call your overriden methods. Making your own transform class in Lua is a saner approach.
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Changing one of the methods in a LÖVE object

Post by grump »

Another way to do this is by altering the Transform table in the registry that holds all LÖVE classes.

Replacing the rotate function globally, for all calling Lua code:

Code: Select all

debug.getregistry().Transform.rotate = function(self, angle)
	print("It worked.")
end

love.math.newTransform():rotate(math.pi)
This only solves the "I want to replace this function" problem though, which is not enough to reach your goal. The actual math is not happening in the rotate function.

I agree with pgimeno, better roll your own Transform implementation. setMatrix and getMatrix can be used to convert between LÖVE's and your own transforms.
Post Reply

Who is online

Users browsing this forum: No registered users and 37 guests