godotengine / godotengine/godot
Setter not called during duplicate for an exported property referencing an instance of a custom class
- Dominant language
- C++
- Stars
- 117k
- Forks
- 26.8k
- PR merge metrics
- PR metrics pending
Description
### Tested versions
v4.3.stable.official [77dcf97d8]
### System information
Godot v4.3.stable - Windows 11 10.0.22631 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1660 Ti (NVIDIA; 32.0.15.6094) - Intel(R) Core(TM) i7-9700F CPU @ 3.00GHz (8 Threads)
### Issue description
If a node includes an exported property that references a child defined as a custom class, the setter is called as expected when the node is created (first time, or when reading a scene). However, when duplicating a node, either through the editor gui, or in gdscript, the setter is not called (for such a child defined as a custom class).
### Steps to reproduce
### Create a custom class,CustomClass, by extending a built-in class, for example:
```
@tool
extends Path3D
class_name CustomClass
```
### Create a second script to apply to a Path3D node
```
@tool
extends Path3D
```
### Create a 3D scene, add a Node3D.
Add a CustomClass as child node, also add a further child node based on the built-in class (Path3D in this case) and attach the Path3D script. Add the following script to the Node3D to display values of properties:
```
@tool
extends Node3D
@export var path3d:Path3D
@export var custom_class:CustomClass
@export var path3d_set:Path3D:
set(value):
path3d_set = value
print( "Set path3d_set ",path3d_set,"\n")
@export var custom_class_set:CustomClass:
set(value):
custom_class_set = value
print( "Set custom_class_set ",custom_class_set,"\n")
func _init() -> void:
print( "Init .............","\n",
"Path3D ",path3d,"\n",
"CustomClass ",custom_class,"\n",
"Path3D_set ",path3d_set,"\n",
"CustomClass_set ",custom_class_set,"\n")
func _ready() -> void:
print( "Ready .............","\n",
"Path3D ",path3d,"\n",
"CustomClass ",custom_class,"\n",
"Path3D_set ",path3d_set,"\n",
"CustomClass_set ",custom_class_set,"\n")
```
### Assign the CustomClass and Path3D nodes to the respective properties in the editor.
Then reload the scene, this gives the following output, note that the exported property, is defined as expected.
> Init .............
> Path3D \
> CustomClass \
> Path3D_set \
> CustomClass_set \
>
> Set path3d_set Path3D:
>
> Set custom_class_set CustomClass:
>
> Ready .............
> Path3D Path3D:
> CustomClass CustomClass:
> Path3D_set Path3D:
> CustomClass_set CustomClass:
### Duplicate the above node
Either in the GUI, or by attaching the script below to the root node of the scene, saving and running the project
```
@tool
extends Node3D
func _ready() -> void:
var new_node = $Node3D.duplicate()
add_child(new_node)
new_node.set_owner(get_tree().get_edited_scene_root())
```
### The output will be as below
> Init .............
> Path3D \
> CustomClass \
> Path3D_set \
> CustomClass_set \
>
> Set path3d_set Path3D:
>
> Ready .............
> Path3D Path3D:
> CustomClass \
> Path3D_set Path3D:
> CustomClass_set \
### As is demonstrated, the CustomClass setter is not called during the duplicate process
The value of the property remains even though defined in the original node, yet the exported property referencing a built-in class is duplicated correctly
### Minimal reproduction project (MRP)
[CustomClassExportDuplicate.zip](https://github.com/user-attachments/files/17559367/CustomClassExportDuplicate.zip)
Contributor guide
Research direction
Start with the attached CustomClassExportDuplicate.zip and reproduce the behavior using the shown Node3D.duplicate() call. Compare duplication of the exported Path3D and CustomClass properties, then trace the engine path used by duplicate(). Done means the custom-class property receives its duplicated value and its setter is called consistently with the built-in class case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100