0 votes

I have a custom node which holds a resource. When I duplicate the node in the scene tab, I would like the cloned node to hold a copy of that resource, not a reference to the same resource.

Is there a simple way to achieve this? Here is what my custom node look like:

tool
extends Node

# I am avoiding using export so that it doesn't
# show in the inspector, hence the _get, _set
# and _get_property_list methods below
var my_resource: MyCustomResourceType


func _ready():
    if not self.my_resource:
        self.my_resource = MyCustomResourceType.new()


func _set(property, value):
    match property:
        "custom_resource":
            my_resource = value
            return true
    return false


func _get(property):
    match property:
        "custom_resource":
            return my_resource
    return null


func _get_property_list() -> Array:
    return [
        {
            "name": "custom_resource",
            "type": TYPE_OBJECT,
            "hint": PROPERTY_HINT_RESOURCE_TYPE,
            "hint_string": "MyCustomResourceType",
            "usage": PROPERTY_USAGE_NOEDITOR
        }
    ]

Thanks a bunch!

in Engine by (1,094 points)

Have you already tried using the duplicate() method on the resource?

No I haven't, but how would I go about it? I would need to somehow react to the "duplicate" function in the scene tree. How do I know when my node is being copied?

I tried replacing my_resource = value with my_resource = value.duplicate(true), but I get the error Trying to assign value of type '' to a variable of type 'my_custom_resource_type.gd'

I tried casting: my_resource = value.duplicate(true) as MyCustomResourceType, but then my_resource ends up null. It kinda looks like an engine issue. I know support for custom resources is a bit lacking.

Doing my_resource = value works fine, I don't really understand why my_resource = value.duplicate() wouldn't.

Maybe first try checking the value of value in the _set() function? If it's null, then try creating a duplicate resource? Set it up to check for a null value, and return false on such a value? Maybe also check for the intended datatype?

func _set(property, value):
    if not value:
        return false
    match property:
        "custom_resource":
            if value is Resource:
                 my_resource = value
                 return true
    return false

I'm also wondering about your datatype, MyCustomResourceType. Aren't custom datatypes usually defined in a class?

The value is not null. Thanks for the help, I'll try some more debugging tomorrow and I'll get back if I make any advance.

I'm also wondering about your datatype, MyCustomResourceType. Aren't custom datatypes usually defined in a class?

I have a need for custom resources, like the one shown in this tutotial: https://docs.godotengine.org/en/stable/getting_started/step_by_step/resources.html#creating-your-own-resources

Thanks for trying to help, but unfortunately this seems to be a known issue: https://github.com/godotengine/godot/pull/41924

My resource does contain custom scripts, and those seem to cause problemes when using duplicate.

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.