Skip to content
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

Exported variables do not call _set method #56614

Open
logicalstrokes opened this issue Jan 8, 2022 · 14 comments
Open

Exported variables do not call _set method #56614

logicalstrokes opened this issue Jan 8, 2022 · 14 comments

Comments

@logicalstrokes
Copy link

logicalstrokes commented Jan 8, 2022

Godot version

3.4.stable

System information

Windows 10

Issue description

When I export a script property with export keyword or the _get_property_list method, this does not call _set method. In the case of using _get_property_list, if the property name does not match a script property, it calls the _set method, but it cannot set this property.

Steps to reproduce

I let a minimal project where there is a resource file with Number property.

  1. Open test.tres file in the inspector.
  2. For example, if Local To Scene property is changed, it is printed changed.
  3. If Number property is changed, it does nothing.

Minimal reproduction project

Test.zip

@logicalstrokes logicalstrokes changed the title Exported variables does not call _set method Exported variables do not call _set method Jan 8, 2022
@AnidemDex
Copy link

As far I tested, _set is only called if the script doesn't have a definition for that property (this means that you don't have var foo somewhere in the script)

@bram-dingelstad
Copy link

I have the same issue on macOS (M1)

@Calinou Calinou added this to the 3.5 milestone Jan 20, 2022
@Zylann
Copy link
Contributor

Zylann commented Jan 20, 2022

test.gd

tool
class_name Test
extends Resource

export var number = 0

func _set(property, value):
	print("changed")
	match property:
		"Number":
			number = value
		_:
			return false
	return true

You match for Number with an uppercase N but your exported variable is number with a lowercase n. Is it intentional?

If you want a setter to be called for a property with export, you have to use setget.

No idea why _set would be called for some existing properties but not script vars though.

@logicalstrokes
Copy link
Author

logicalstrokes commented Jan 20, 2022

You match for Number with an uppercase N but your exported variable is number with a lowercase n. Is it intentional?

I read a tutorial, which did it like this, but I got the problem that it does not call the _set function. So I could not check if I should use snake_case there.

I do not know if this could get to work on some older version.

@QbieShay
Copy link
Contributor

Can confirm the issue. Currently trying to make the script generate a texture every time one of 4 different variables is assigned. Having to write setget for all fo them is a hassle :[

@YuriSizov
Copy link
Contributor

AFAIK _set and _get only get called when accessing properties that do not exist as class members. I think this is similar to such "magic" methods of other languages too. And yeah, you either need to make your properties "virtual", not relying on an exported member, or you need to create setget boilerplate hell, as per traditions and customs. 🙃

@JayCee-101
Copy link

Just ran into this and found a workaround, which is to add a / before your variable name:

"name": "/variable_name",

_set is then called every time the variable is updated.

@RechieKho
Copy link
Contributor

It doesn't work in godot 4.0.2 as well

@RechieKho
Copy link
Contributor

RechieKho commented May 16, 2023

This is just my speculation.

After quick scan through the godot source code, here
https://github.com/godotengine/godot/blob/master/core/object/object.cpp#L253
It calls built-in setter (assuming this is where _set is called) after unable to set the script property.
The script property is either calling its bounded setter or directly write into the value if it is defined (without any setter https://github.com/godotengine/godot/blob/master/modules/gdscript/gdscript.cpp#L1499; Again my speculation).
So in godot 4, if you didn't give a setter directly. It will just by pass the built-in setter _set and directly write it into the value.

@thornySoap
Copy link

@YuriSizov AFAIK _set and _get only get called when accessing properties that do not exist as class members.

But what is then the reason for _set() to return a boolean? According to the docs it should return "false if the property should be handled normally", which only makes sense if there is a member to be handled normally.

@YuriSizov
Copy link
Contributor

@thornySoap Normally also means that if you don't override the method it is going to fail because that property doesn't exist. Docs can probably be improved.

@thornySoap
Copy link

@YuriSizov But on the other hand inherited class members (at least from built-in classes) do trigger _set(). Isn't that unintuitive?

@YuriSizov
Copy link
Contributor

If that's the case, then there is probably an issue with the multi-level call implementation for Object.set. Since each class in a hierarchy is considered in order, I guess it's possible that extending classes don't know about some parent members. I agree, this is a conflicting behavior, but I'd need to test it to see what's going on.

@AnidemDex
Copy link

Is this still a valid issue?

@lawnjelly lawnjelly modified the milestones: 3.5, 3.x Mar 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests