How to make a deep customized container?

Godot Version

Godot 4.4

Question

How to make a deep customized container?

I’m making some deep customized containers but they can’t work properly. And there’s an example:

I want to make a container called “LabeledPanel” with structure like this:
-LabeledPanel(PanelContainer)
-Container(HBoxContainer)
-Label(Label)
-ChildContainer(HBoxContainer)

I want to make it works like this:

When in scene editor, when I drag a control into scene tree to make it as LabeledPanel’s child control, the control will automatically be placed into UIChildPanel, like any other godot containers. Then I write some code and it’s able to work

using Godot;
using System;
using System.Collections.Generic;

[Tool]
public partial class LabeledTemplate : Container
{
    public HBoxContainer UIContainer;
    public Label Label;
    public HBoxContainer UIChildContainer;
    

    public override void _EnterTree()
    {
        UIContainer = GetNode<HBoxContainer>("Container");
        Label = GetNode<Label>("Container/Label");
        UIChildContainer = GetNode<HBoxContainer>("Container/ChildContainer");
    }

    public override void _ExitTree()
    {
        UIContainer = null;
        Label = null;
        UIChildContainer = null;
    }

    public override void _Ready()
    {
        UIContainer = GetNode<HBoxContainer>("Container");
        Label = GetNode<Label>("Container/Label");
        UIChildContainer = GetNode<HBoxContainer>("Container/ChildContainer");
    }

    public override void _Notification(int what)
    {
        if (what == NotificationSortChildren)
        {
            List<Node> toMove = new List<Node>();
            foreach (Node child in GetChildren())
            {
                if (child != UIContainer &&
                    child != Label &&
                    child != UIChildContainer)
                {
                    toMove.Add(child);
                }
            }

            foreach (Node child in toMove)
            {
                RemoveChild(child);
                UIChildContainer.AddChild(child);
                child.Owner = GetTree().EditedSceneRoot;
                GD.Print(child.Owner);
            }

            if (UIChildContainer is Container container)
            {
                container.QueueSort();
            }
        }
    }
}

But then I met some problem, after the control become a child of UIChildPanel, removing it from the scene treeview is not possible unless selecting Editable Children. Plus, if I haven’t select Editable Children, when I run the scene, the children added will not be added in LabeledPanel.

How can I fix that and is there any potential mistakes in my code? Thanks!

It’s not possible yet. There is a proposal opened for that Allow user to expose nodes within an instantiated scene · Issue #8266 · godotengine/godot-proposals · GitHub

1 Like

Thanks and hope that feature come true soon!