-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug Report: Vector3 metatable not working when nested in an object #200
Comments
Seems to not work on other nested types such as godot arrays too. |
Works with nested basic types like bool, float, and string |
This is a side effect to how we handle metatables. Properties are not passed by reference unless they are a Object type. So types like Vector3 what ends up happening is obj.vec pushes a copy of the vector onto the stack. obj.vec.x = 10 modifies the copy of the vector and not the objects vector. And since the first obj.vec is only a index call and not a newindex call the copy is not reapplied to the object ever. Realevent areas of the code base are the following. godot_luaAPI/src/metatables.cpp Lines 176 to 192 in edf4afe
godot_luaAPI/src/classes/luaObjectMetatable.cpp Lines 197 to 213 in edf4afe
godot_luaAPI/src/classes/luaObjectMetatable.cpp Lines 214 to 237 in edf4afe
I will need to spend some time thinking on this to find a good solution. This is not the intended behavior. |
Sounds good. Would it be possible to somehow recursively instantiate object properties the same way globals are created? I'm pretty new to Lua so not sure if it works like this but basically instead of just copying all the object's properties we could iterate over them and if they're a non basic type they get their own metatable like the globals do. If it encounters another object, it recurses and thus it could work for several layers of nesting & complex data types. |
So this is not actually the issue here. The data type has a metatable. The issue is the vector being modified is not the objects vector but a copy. If a property on the object is modified IE the call goes through __newindex we update it via reference like with obj.prop=val. But if its not modified directly on the object IE the call goes through __index like with obj.prob.x=val the property is pushed as a copy. Then that copy is what gets modified. So in your example if you changed the lua code to vec.x = 10
print(vec) -- (10, 0, 0)
luaClass.vec = Vector3(10, 0, 0)
print(luaClass.vec) -- (10, 0, 0) It would then work as expected. |
A fix would be to always push properties by ref. But I think that would create other issues. some_vec = obj.vec you wouldnt expect some_vec to be a ref to obj.vec in that case but it would end up being so. |
Makes sense. So for globals it just modifies the vector directly on the global table instead of being a copy, but it's a copy for nested types? Another idea could be to somehow pass __newindex calls up the owner chain. So if a child vector gets a new property assigned and it's being referenced from an object the object would get the new vector which got the new property. Or could push by ref but create copies on assignment, so some_vec = obj.vec would copy |
The last option seems to be the most reasonable one. |
Describe the bug
When pushing an object variant that contains a Vector3 property, it's not updated correctly. Only global level Vector3s are being updated.
To Reproduce
The text was updated successfully, but these errors were encountered: