godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Expose `Node.set_scene_inherited_state()` method to set child node as inherited #8522

Open ducklin5 opened 11 months ago

ducklin5 commented 11 months ago

Describe the project you are working on

I'm working on a GdExt library that defines common classes that GdScript classes can extend from. Specifically, these GdExt classes could be large scenes with many children.

Describe the problem or limitation you are having in your project

I would like the child nodes added by a superclass to show up as "inherited" nodes in the editor. Note: I'm already able to get gdscript/gdext child nodes to show up in the editor by setting the owner. The issue is there is no distinction between nodes added manually to the scene and nodes added programmatically by the superclass. I also want nodes added by the superclass to be immutable in the editor similar to nodes in sub-scenes (cant be renamed deleted or reordered)

Describe the feature / enhancement and how it helps to overcome the problem or limitation

To solve the above-mentioned issues. I'm proposing that we expose a function to set a child node as inherited.

In the engine code, this is where the editor determines if a node is a subscene: scene_tree_editor.cpp#L208 So in order to mark a node as inherited, we need to be able to call Node::set_scene_inherited_state() from gdext code: node.h#L585

The enhancement is simply to expose the above Node::set_scene_inherited_state method to gdext and gdscript, or a new method which internally modifies the SceneState.

Finally, we could have something like a Node::set_editor_mutable() to prevent editing sub-nodes added by the superclass.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

@tool
class_name SuperClass
extends Node

func _ready():
    var child_node = Node.new()
        child_node.name = "Test"
    add_child(child_node)
    child_node.set_owner(self)
        self.set_node_is_inherited(child_node, true)
        child_node.is_mutable(false)
@tool
class_name SubClass
extends SuperClass

func _ready():
    super._ready()
    var node = Sprite2D.new()
    node.name = "Sprite"
    add_child(node)

When a SubClass scene is created in the Editor, the "Test" node should show up in the editor but it should have a different colour in the scene tree similar to inherited nodes

Changes to the yellow node should not be savable by the editor:

image

If this enhancement will not be used often, can it be worked around with a few lines of script?

I don't think this is possible without an engine/editor enhancement

Is there a reason why this should be core and not an add-on in the asset library?

This is about improving the interface between gdscript and gdext. If I build a scene in gdext via code. I should be able to see the scene when the class is extended in an editor tool scene. differentiate which child nodes where added by the parent class and which ones were manually added via the scene editor

### Tasks
ducklin5 commented 11 months ago

I explored the scene tree editor logic a bit and found a pretty straightforward way to achieve the desired effect: https://github.com/godotengine/godot/pull/85691 The above PR only adds a single branch of logic to determine part_of_subscene. PR is still a draft as I'm not sure if metadata is the way to go or if this is even the best approach.