Skip to content

Commit 283ce27

Browse files
committed
Add the ability to expose nodes for direct access in instantiated scenes ( godotengine#84018 )
1 parent 7fdec06 commit 283ce27

16 files changed

+558
-64
lines changed

doc/classes/EditorSettings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@
239239
<member name="docks/scene_tree/ask_before_deleting_related_animation_tracks" type="bool" setter="" getter="">
240240
If [code]true[/code], when a node is deleted with animation tracks referencing it, a confirmation dialog appears before the tracks are deleted. The dialog will appear even when using the "Delete (No Confirm)" shortcut.
241241
</member>
242+
<member name="docks/scene_tree/ask_before_revoking_node_exposure" type="bool" setter="" getter="">
243+
If [code]true[/code], displays a confirmation dialog after left-clicking the "exposed" icon next to a node name in the Scene tree dock. When clicked, this icon revokes the node's scene exposure, which can impact the behavior of scripts that rely on this exposed node due to identifiers not being found anymore.
244+
</member>
242245
<member name="docks/scene_tree/ask_before_revoking_unique_name" type="bool" setter="" getter="">
243246
If [code]true[/code], displays a confirmation dialog after left-clicking the "percent" icon next to a node name in the Scene tree dock. When clicked, this icon revokes the node's scene-unique name, which can impact the behavior of scripts that rely on this scene-unique name due to identifiers not being found anymore.
244247
</member>

editor/docks/scene_tree_dock.cpp

Lines changed: 104 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ void SceneTreeDock::shortcut_input(const Ref<InputEvent> &p_event) {
230230
_tool_selected(TOOL_SHOW_IN_FILE_SYSTEM);
231231
} else if (ED_IS_SHORTCUT("scene_tree/toggle_unique_name", p_event)) {
232232
_tool_selected(TOOL_TOGGLE_SCENE_UNIQUE_NAME);
233+
} else if (ED_IS_SHORTCUT("scene_tree/toggle_expose_node", p_event)) {
234+
_tool_selected(TOOL_TOGGLE_SCENE_EXPOSE_NODE);
233235
} else if (ED_IS_SHORTCUT("scene_tree/toggle_editable_children", p_event)) {
234236
_tool_selected(TOOL_SCENE_EDITABLE_CHILDREN);
235237
} else if (ED_IS_SHORTCUT("scene_tree/delete", p_event)) {
@@ -329,6 +331,14 @@ void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, N
329331
instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(p_files[i]));
330332

331333
instances.push_back(instantiated_scene);
334+
Vector<NodePath> exposed_nodes = sdata->get_state()->get_exposed_nodes();
335+
instantiated_scene->set_meta(META_CONTAINS_EXPOSED_NODES, exposed_nodes.size() > 0);
336+
for (const NodePath &e_path : exposed_nodes) {
337+
Node *ei = instantiated_scene->get_node_or_null(e_path);
338+
if (ei) {
339+
ei->set_meta(META_EXPOSED_IN_INSTANCE, true);
340+
}
341+
}
332342
}
333343

334344
if (error) {
@@ -454,6 +464,15 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base)
454464
return;
455465
}
456466

467+
Vector<NodePath> exposed_nodes = sdata->get_state()->get_exposed_nodes();
468+
instantiated_scene->set_meta(META_CONTAINS_EXPOSED_NODES, exposed_nodes.size() > 0);
469+
for (const NodePath &e_path : exposed_nodes) {
470+
Node *ei = instantiated_scene->get_node_or_null(e_path);
471+
if (ei) {
472+
ei->set_meta(META_EXPOSED_IN_INSTANCE, true);
473+
}
474+
}
475+
457476
instantiated_scene->set_unique_name_in_owner(base->is_unique_name_in_owner());
458477

459478
Node2D *copy_2d = Object::cast_to<Node2D>(instantiated_scene);
@@ -1499,6 +1518,57 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
14991518
undo_redo->commit_action();
15001519
}
15011520
} break;
1521+
case TOOL_TOGGLE_SCENE_EXPOSE_NODE: {
1522+
const List<Node *>::Element *first_selected = editor_selection->get_top_selected_node_list().front();
1523+
if (first_selected == nullptr) {
1524+
return;
1525+
}
1526+
if (first_selected->get() == EditorNode::get_singleton()->get_edited_scene()) {
1527+
editor_selection->remove_node(first_selected->get());
1528+
first_selected = editor_selection->get_top_selected_node_list().front();
1529+
if (first_selected == nullptr) {
1530+
return;
1531+
}
1532+
}
1533+
1534+
const List<Node *> full_selection = editor_selection->get_full_selected_node_list();
1535+
bool enabling = !first_selected->get()->has_meta(META_MARKED_FOR_EXPOSURE);
1536+
1537+
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
1538+
if (enabling) {
1539+
undo_redo->create_action(TTR("Expose Node(s) In Scene"));
1540+
} else {
1541+
undo_redo->create_action(TTR("Unexpose Node(s) In Scene"));
1542+
}
1543+
1544+
for (Node *node : full_selection) {
1545+
// Only operate on nodes whose state will actually change
1546+
bool is_exposed = node->has_meta(META_MARKED_FOR_EXPOSURE);
1547+
1548+
if (enabling && !is_exposed) {
1549+
// Only expose nodes that are not already exposed
1550+
if (get_tree()->get_edited_scene_root() == node->get_owner()) {
1551+
undo_redo->add_do_method(node, "set_meta", META_EXPOSED_IN_OWNER, true);
1552+
undo_redo->add_undo_method(node, "remove_meta", META_EXPOSED_IN_OWNER);
1553+
}
1554+
undo_redo->add_do_method(node, "set_meta", META_MARKED_FOR_EXPOSURE, true);
1555+
undo_redo->add_undo_method(node, "remove_meta", META_MARKED_FOR_EXPOSURE);
1556+
undo_redo->add_do_method(scene_tree, "update_tree");
1557+
undo_redo->add_undo_method(scene_tree, "update_tree");
1558+
} else if (!enabling && is_exposed) {
1559+
// Only unexpose nodes that are currently exposed
1560+
undo_redo->add_do_method(node, "remove_meta", META_MARKED_FOR_EXPOSURE);
1561+
undo_redo->add_undo_method(node, "set_meta", META_MARKED_FOR_EXPOSURE, true);
1562+
if (get_tree()->get_edited_scene_root() == node->get_owner()) {
1563+
undo_redo->add_do_method(node, "remove_meta", META_EXPOSED_IN_OWNER);
1564+
undo_redo->add_undo_method(node, "set_meta", META_EXPOSED_IN_OWNER, true);
1565+
}
1566+
undo_redo->add_do_method(scene_tree, "update_tree");
1567+
undo_redo->add_undo_method(scene_tree, "update_tree");
1568+
}
1569+
}
1570+
undo_redo->commit_action();
1571+
} break;
15021572
case TOOL_CREATE_2D_SCENE:
15031573
case TOOL_CREATE_3D_SCENE:
15041574
case TOOL_CREATE_USER_INTERFACE:
@@ -2735,6 +2805,11 @@ void SceneTreeDock::_toggle_editable_children(Node *p_node) {
27352805

27362806
for (Node *owned_node : owned) {
27372807
if (owned_node != p_node && owned_node != edited_scene && owned_node->get_owner() == edited_scene && owned_node->get_parent()->get_owner() != edited_scene) {
2808+
// Preserve children of exposed nodes
2809+
if (owned_node->get_parent()->has_meta(META_EXPOSED_IN_OWNER)) {
2810+
continue;
2811+
}
2812+
27382813
owned_nodes_array.push_back(owned_node);
27392814
paths_array.push_back(p_node->get_path_to(owned_node->get_parent()));
27402815
name_array.push_back(owned_node->get_name());
@@ -3511,7 +3586,7 @@ static bool _is_node_visible(Node *p_node) {
35113586
if (!p_node->get_owner()) {
35123587
return false;
35133588
}
3514-
if (p_node->get_owner() != EditorNode::get_singleton()->get_edited_scene() && !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node->get_owner())) {
3589+
if (p_node->get_owner() != EditorNode::get_singleton()->get_edited_scene() && !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node->get_owner()) && !p_node->has_meta(META_MARKED_FOR_EXPOSURE)) {
35153590
return false;
35163591
}
35173592

@@ -3533,6 +3608,10 @@ static bool _has_visible_children(Node *p_node) {
35333608
return true;
35343609
}
35353610

3611+
if (p_node->has_exposed_nodes()) {
3612+
return true;
3613+
}
3614+
35363615
return false;
35373616
}
35383617

@@ -3545,9 +3624,13 @@ void SceneTreeDock::_normalize_drop(Node *&to_node, int &to_pos, int p_type) {
35453624
to_node = nullptr;
35463625
ERR_FAIL_MSG("Cannot perform drop above the root node!");
35473626
}
3548-
3549-
to_pos = to_node->get_index(false);
3550-
to_node = to_node->get_parent();
3627+
if (to_node->has_meta(META_EXPOSED_IN_INSTANCE)) {
3628+
to_node = to_node->get_owner();
3629+
to_pos = -1;
3630+
} else {
3631+
to_pos = to_node->get_index(false);
3632+
to_node = to_node->get_parent();
3633+
}
35513634

35523635
} else if (p_type == 1) {
35533636
//drop at below selected node
@@ -3560,7 +3643,11 @@ void SceneTreeDock::_normalize_drop(Node *&to_node, int &to_pos, int p_type) {
35603643
Node *lower_sibling = nullptr;
35613644

35623645
if (_has_visible_children(to_node)) {
3563-
to_pos = 0;
3646+
if (to_node->has_exposed_nodes()) {
3647+
to_pos = -1;
3648+
} else {
3649+
to_pos = 0;
3650+
}
35643651
} else {
35653652
for (int i = to_node->get_index(false) + 1; i < to_node->get_parent()->get_child_count(false); i++) {
35663653
Node *c = to_node->get_parent()->get_child(i, false);
@@ -3573,7 +3660,12 @@ void SceneTreeDock::_normalize_drop(Node *&to_node, int &to_pos, int p_type) {
35733660
to_pos = lower_sibling->get_index(false);
35743661
}
35753662

3576-
to_node = to_node->get_parent();
3663+
if (to_node->has_meta(META_EXPOSED_IN_INSTANCE)) {
3664+
to_pos = to_node->get_index(false) + 1;
3665+
to_node = to_node->get_owner();
3666+
} else {
3667+
to_node = to_node->get_parent();
3668+
}
35773669
}
35783670
}
35793671
}
@@ -3944,16 +4036,20 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
39444036
break;
39454037
}
39464038
}
4039+
4040+
Node *node = full_selection.front()->get();
39474041
if (all_owned) {
39484042
// Group "toggle_unique_name" with "copy_node_path", if it is available.
39494043
if (menu->get_item_index(TOOL_COPY_NODE_PATH) == -1) {
39504044
menu->add_separator();
39514045
}
3952-
Node *node = full_selection.front()->get();
39534046
menu->add_icon_check_item(get_editor_theme_icon(SNAME("SceneUniqueName")), TTRC("Access as Unique Name"), TOOL_TOGGLE_SCENE_UNIQUE_NAME);
39544047
menu->set_item_shortcut(menu->get_item_index(TOOL_TOGGLE_SCENE_UNIQUE_NAME), ED_GET_SHORTCUT("scene_tree/toggle_unique_name"));
39554048
menu->set_item_checked(menu->get_item_index(TOOL_TOGGLE_SCENE_UNIQUE_NAME), node->is_unique_name_in_owner());
39564049
}
4050+
menu->add_icon_check_item(get_editor_theme_icon(SNAME("SceneExposedNode")), TTRC("Expose in Instances"), TOOL_TOGGLE_SCENE_EXPOSE_NODE);
4051+
menu->set_item_shortcut(menu->get_item_index(TOOL_TOGGLE_SCENE_EXPOSE_NODE), ED_GET_SHORTCUT("scene_tree/toggle_expose_node"));
4052+
menu->set_item_checked(menu->get_item_index(TOOL_TOGGLE_SCENE_EXPOSE_NODE), node->has_meta(META_MARKED_FOR_EXPOSURE));
39574053
}
39584054

39594055
if (selection.size() == 1) {
@@ -4724,6 +4820,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
47244820
ED_SHORTCUT("scene_tree/copy_node_path", TTRC("Copy Node Path"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::C);
47254821
ED_SHORTCUT("scene_tree/show_in_file_system", TTRC("Show in FileSystem"));
47264822
ED_SHORTCUT("scene_tree/toggle_unique_name", TTRC("Toggle Access as Unique Name"));
4823+
ED_SHORTCUT("scene_tree/toggle_expose_node", TTRC("Toggle Node Exposure"));
47274824
ED_SHORTCUT("scene_tree/toggle_editable_children", TTRC("Toggle Editable Children"));
47284825
ED_SHORTCUT("scene_tree/delete_no_confirm", TTRC("Delete (No Confirm)"), KeyModifierMask::SHIFT | Key::KEY_DELETE);
47294826
ED_SHORTCUT("scene_tree/delete", TTRC("Delete"), Key::KEY_DELETE);

editor/docks/scene_tree_dock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class SceneTreeDock : public VBoxContainer {
8282
TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM,
8383
TOOL_SCENE_OPEN_INHERITED,
8484
TOOL_TOGGLE_SCENE_UNIQUE_NAME,
85+
TOOL_TOGGLE_SCENE_EXPOSE_NODE,
8586
TOOL_CREATE_2D_SCENE,
8687
TOOL_CREATE_3D_SCENE,
8788
TOOL_CREATE_USER_INTERFACE,
@@ -150,6 +151,7 @@ class SceneTreeDock : public VBoxContainer {
150151
Label *delete_dialog_label = nullptr;
151152
CheckBox *delete_tracks_checkbox = nullptr;
152153
ConfirmationDialog *editable_instance_remove_dialog = nullptr;
154+
ConfirmationDialog *revoke_node_exposure_dialog = nullptr;
153155
ConfirmationDialog *placeholder_editable_instance_remove_dialog = nullptr;
154156

155157
ReparentDialog *reparent_dialog = nullptr;

editor/editor_data.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -723,9 +723,17 @@ bool EditorData::check_and_update_scene(int p_idx) {
723723
for (const Node *E : edited_scene.write[p_idx].selection) {
724724
NodePath p = edited_scene[p_idx].root->get_path_to(E);
725725
Node *new_node = new_scene->get_node(p);
726-
if (new_node) {
727-
new_selection.push_back(new_node);
726+
// Node can't be found, skip it.
727+
if (!new_node) {
728+
continue;
728729
}
730+
731+
// Node is no longer exposed, skip it.
732+
if (E->has_meta(META_EXPOSED_IN_OWNER) && !new_node->has_meta(META_EXPOSED_IN_OWNER)) {
733+
continue;
734+
}
735+
736+
new_selection.push_back(new_node);
729737
}
730738

731739
new_scene->set_scene_file_path(edited_scene[p_idx].root->get_scene_file_path());

editor/icons/SceneExposedNode.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

editor/import/3d/resource_importer_scene.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,13 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
14891489
}
14901490
}
14911491

1492+
if (!isroot && node_settings.has("import/exposed")) {
1493+
if (bool(node_settings["import/exposed"])) {
1494+
p_node->set_meta(META_EXPOSED_IN_OWNER, true);
1495+
p_node->get_owner()->set_meta(META_CONTAINS_EXPOSED_NODES, true);
1496+
}
1497+
}
1498+
14921499
if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
14931500
ObjectID node_id = p_node->get_instance_id();
14941501
for (int i = 0; i < post_importer_plugins.size(); i++) {
@@ -2118,10 +2125,12 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
21182125
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "node/node_type", PROPERTY_HINT_TYPE_STRING, "Node"), ""));
21192126
r_options->push_back(ImportOption(PropertyInfo(Variant::OBJECT, "node/script", PROPERTY_HINT_RESOURCE_TYPE, "Script"), Variant()));
21202127
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
2128+
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/exposed", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
21212129
} break;
21222130
case INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE: {
21232131
r_options->push_back(ImportOption(PropertyInfo(Variant::OBJECT, "node/script", PROPERTY_HINT_RESOURCE_TYPE, "Script"), Variant()));
21242132
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
2133+
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/exposed", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
21252134
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate/physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
21262135
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/navmesh", PROPERTY_HINT_ENUM, "Disabled,Mesh + NavMesh,NavMesh Only"), 0));
21272136
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/body_type", PROPERTY_HINT_ENUM, "Static,Dynamic,Area"), 0));
@@ -2203,6 +2212,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
22032212
case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: {
22042213
r_options->push_back(ImportOption(PropertyInfo(Variant::OBJECT, "node/script", PROPERTY_HINT_RESOURCE_TYPE, "Script"), Variant()));
22052214
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
2215+
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/exposed", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
22062216
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "optimizer/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
22072217
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_velocity_error", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.01));
22082218
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angular_error", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.01));
@@ -2216,6 +2226,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
22162226
case INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE: {
22172227
r_options->push_back(ImportOption(PropertyInfo(Variant::OBJECT, "node/script", PROPERTY_HINT_RESOURCE_TYPE, "Script"), Variant()));
22182228
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
2229+
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/exposed", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
22192230
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "rest_pose/load_pose", PROPERTY_HINT_ENUM, "Default Pose,Use AnimationPlayer,Load External Animation", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
22202231
r_options->push_back(ImportOption(PropertyInfo(Variant::OBJECT, "rest_pose/external_animation_library", PROPERTY_HINT_RESOURCE_TYPE, "Animation,AnimationLibrary", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Variant()));
22212232
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "rest_pose/selected_animation", PROPERTY_HINT_ENUM, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), ""));
@@ -2770,7 +2781,12 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_
27702781
mesh_node->set_gi_mode(GeometryInstance3D::GI_MODE_STATIC);
27712782
} break;
27722783
}
2773-
2784+
if (src_mesh_node->has_meta(META_EXPOSED_IN_OWNER)) {
2785+
mesh_node->set_meta(META_EXPOSED_IN_OWNER, true);
2786+
}
2787+
if (mesh_node->get_owner() != nullptr) {
2788+
mesh_node->get_owner()->set_meta(META_CONTAINS_EXPOSED_NODES, src_mesh_node->has_meta(META_EXPOSED_IN_OWNER));
2789+
}
27742790
mesh_node->set_layer_mask(src_mesh_node->get_layer_mask());
27752791
mesh_node->set_cast_shadows_setting(src_mesh_node->get_cast_shadows_setting());
27762792
mesh_node->set_visible(src_mesh_node->is_visible());

editor/scene/3d/node_3d_editor_plugin.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4966,6 +4966,15 @@ bool Node3DEditorViewport::_create_instance(Node *p_parent, const String &p_path
49664966
instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(p_path));
49674967
}
49684968

4969+
Vector<NodePath> exposed_nodes = scene->get_state()->get_exposed_nodes();
4970+
instantiated_scene->set_meta(META_CONTAINS_EXPOSED_NODES, exposed_nodes.size() > 0);
4971+
for (const NodePath &e_path : exposed_nodes) {
4972+
Node *ei = instantiated_scene->get_node_or_null(e_path);
4973+
if (ei) {
4974+
ei->set_meta(META_EXPOSED_IN_INSTANCE, true);
4975+
}
4976+
}
4977+
49694978
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
49704979
undo_redo->add_do_method(p_parent, "add_child", instantiated_scene, true);
49714980
undo_redo->add_do_method(instantiated_scene, "set_owner", EditorNode::get_singleton()->get_edited_scene());

0 commit comments

Comments
 (0)