Open yahkr opened 1 year ago
see also:
You're more than welcome to use any of the code from my fork, though I'm not keeping it in topic branches anymore. I'll try to remember to push if I do anything interesting. In particular, you may want to adopt the packed_scene unit test I wrote and adjust it for your needs, since the existing Godot codebase doesn't have any unit tests for the "instantiate a scene with a packed subscene" code path and its behavior is pretty critical for, y'know, running games.
Feel free to tag me and ask if you have any problems you can't figure out a solution to, though I'm not planning to actively follow the discussion here.
ETA: There's also a feature I'm intending to add which is the equivalent of the right-click "create scene from this branch" but more powerful, letting you create a scene from just the intermediary nodes of a branch, collapsing a scene fragment into a subscene with default_child_parent without adjusting the current scene's hierarchy in any way. It could be altered to let you create a subscene with exposed children - I'd always expected that an "exposed in owner" feature was the natural follow-on to "default child parent", though I think I called the feature "forced-visible children" in my comments.
Appreciate it @dmchurch . I'll definitely borrow the unit test . That extra feature of collapsing a branch does sound handy. Will have to explore some more
My current goal is to better understand the scene tree dock structure and how nodes get saved etc.
My current goal is to better understand the scene tree dock structure and how nodes get saved etc.
Take a look at the list of files and methods I've changed - you won't necessarily need to make the same changes I did, but they should provide you a good jumping-off point for exploring the code paths.
Hi, you might be interested by #3248 discussion.
Pushed an update that is somewhat functional, results showing promise. is saved to:
[gd_scene load_steps=2 format=3 uid="uid://bikicvcke5g1o"]
[ext_resource type="PackedScene" uid="uid://bgbfogy57nk63" path="res://control.tscn" id="1_l1gfn"]
[node name="Root" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 0
offset_right = 262.0
offset_bottom = 291.0
[node name="InstantiatedScene" parent="HBoxContainer" instance=ExtResource("1_l1gfn")]
layout_mode = 2
[node name="Button" type="Button" parent="HBoxContainer/InstantiatedScene/%Exposed" index="0"]
layout_mode = 2
text = "test1"
Exposed node inside control.tscn looks like this.
[node name="Exposed" type="VBoxContainer" parent="Panel/PanelContainer/VBoxContainer"]
unique_name_in_owner = true
exposed_in_owner = true
layout_mode = 2
theme_override_constants/separation = 10
It will be awesome to have gltf scene that you can expose meshes in the import window. Sometime I have models that I can drag and drop materials and I have to click on editable children
for all of them before doing so
It will be awesome to have gltf scene that you can expose meshes in the import window. Sometime I have models that I can drag and drop materials and I have to click on
editable children
for all of them before doing so
I did look into this feature this past day or so, and while i can get exposure working on import, since the exposed node isn't saved in the instantiated scene the material override isn't either. So will have to re-think that aspect.
I'm making some semi-advanced UI for my game, where I want to animate in arbitrary children at certain locations. It would make my workflow and project structure way cleaner to be able to build custom Control components that allow predetermined slots. If this was implemented, I think this would become my preferred way to compose control components.
This would be super useful for reducing the amount of boilerplate code you need for editing "composed" nodes. So I think built in nodes should also use this feature to expose their hidden nodes. For example:
MenuButton
& LineEdit
have a hidden PopupMenu
ScrollContainer
& TextEdit
have a hidden HScrollBar
and VScrollBar
SpinBox
has a hidden LineEdit
ColorPickerButton
has a hidden ColorPicker
and Popup
There's likely a bunch more. But in all of these cases, it's a pain to edit properties, connect signals, and add theme overrides because the associated nodes are hidden. Some of these nodes have extra (and redundant) properties to expose some of the hidden attributes, but they're incomplete, and it would just be better to directly access them with this.
Hi all, just to continue the conversation and provide a small update. I've been tinkering with overrides/exposed nodes and have added some features I would love to get feedback on. Work below inspired by #3248 discussion, @jcostello's comment, and @dugramen comment
Overrides: Provides a way to make changes to nodes that are exposed: This is what my exposed_spinner.tscn looks like: The root spinner has a script that simply spins the "$Exposed" node. Exposed is a MeshInstance3D that is marked as exposed, and the "Not Exposed" node is just a decal projector that is a child of the exposed node.
When you instantiate this scene you can apply override materials or other modifications and they will be saved into the tscn file like so: main.tscn
main.tscn
This allows you to have scenes be really flexible. Heres a quick demo of what you can do with this system.
I also worked on .blend imports and can now use "-exp" to define if a node should be exposed or not. The overriding feature also works with this. This is in response to @jcostello's comment about gltf importing (currently only works with .blend but i will make it work with gltf as well), below is a demo of how this system handles .blend file changes and applies the overrides.
Keep in mind all of this is without the pitfalls of 'editable children' being enabled. So when things move around in the instantiated scene, so long as the names are kept the same any children/overrides will remain in-tact. I'll definitely be exploring how to propagate renames to any other scene that uses the tscn, but we shall see. Current implementation is kinda hacky I feel so I havn't committed it to my repo yet. I would love to get some feedback on this overriding feature. Thanks!
@dugramen
This would be super useful for reducing the amount of boilerplate code you need for editing "composed" nodes. So I think built in nodes should also use this feature to expose their hidden nodes. For example:
MenuButton
&LineEdit
have a hiddenPopupMenu
ScrollContainer
&TextEdit
have a hiddenHScrollBar
andVScrollBar
SpinBox
has a hiddenLineEdit
ColorPickerButton
has a hiddenColorPicker
andPopup
There's likely a bunch more. But in all of these cases, it's a pain to edit properties, connect signals, and add theme overrides because the associated nodes are hidden. Some of these nodes have extra (and redundant) properties to expose some of the hidden attributes, but they're incomplete, and it would just be better to directly access them with this.
I was curious about this, so i looked into it. To make this work with the exposed nodes, spin_box.cpp must be modified like so:
405 add_child(line_edit, true, INTERNAL_MODE_FRONT);
406 line_edit->set_exposed_in_owner(true);
Whats really important here is the second param, when false it generates a random id tacked onto the end of the name, this makes it unusable for the exposed node system. so changed it to true, where its forced to be named LineEdit. (This would cause issues if you wanted your own LineEdit child of a SpinBox for some reason...
This does produce the desired results, however it also produces quite a lot of junk in the tscn file when saving, regardless of if you made overrides the engine does after instantiation, so theyre included in the tscn.
Added a right_icon and overwrote the font_size for theme:
[override path="./SpinBox/LineEdit"]
unique_name_in_owner = true
exposed_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = -16.0
mouse_filter = 1
theme_override_font_sizes/font_size = 60
text = "0"
right_icon = ExtResource("4_ce87b")
caret_column = 1
Unedited:
[override path="./SpinBox2/LineEdit"]
unique_name_in_owner = true
exposed_in_owner = true
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = -16.0
mouse_filter = 1
text = "0"
caret_column = 1
All in all i think it's cool that these could be exposed, but im not sure they would benefit from allowing the user to override any of their properties with how they are currently setup in engine.
Whats really important here is the second param, when false it generates a random id tacked onto the end of the name, this makes it unusable for the exposed node system. so changed it to true, where its forced to be named LineEdit. (This would cause issues if you wanted your own LineEdit child of a SpinBox for some reason...
Maybe it could be named more explicitly or in a special way, to avoid conflicts. Like "LineEdit@Internal" or just "_LineEdit_"
All in all i think it's cool that these could be exposed, but im not sure they would benefit from allowing the user to override any of their properties with how they are currently setup in engine.
Do you mean that users wouldn't be able to override, or just that there may be too many drawbacks?
(Also just wanna say this looks awesome already!)
Maybe it could be named more explicitly or in a special way, to avoid conflicts. Like "LineEdit@Internal" or just "LineEdit"
For the naming I agree it could certainly be made to be more predictable when they auto generate internal node names, that way when saving overrides we can trust the name of the internal node matches that of what gets generated at runtime. I'm sure there's a lengthy discussion somewhere that decided the generated uid was best but who knows.
Do you mean that users wouldn't be able to override, or just that there may be too many drawbacks?
Users could still override any property they wanted. Like I do in that example I override the properties:
theme_override_font_sizes/font_size = 60
right_icon = ExtResource("4_ce87b")
But with how these types of nodes are currently implemented in the engine (spinbox etc) they create their own internal children and setup the properties it needs by default, so for spinbox its the following:
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = -16.0
mouse_filter = 1
text = "0"
caret_column = 1
Since how my override system works is looking for modified properties it picks these up as overrides when they really aren't (from a functional standpoint). This isn't necessarily a bad thing, it just clutters the tscn file when you save. Appreciate the kind words :)
relevant and would solve the issues with built-in node references and renaming of nodes within subscenes: https://github.com/godotengine/godot/pull/86960
im working on comprehensive GUI stuff rn, and have a lot of stuff where this would be useful. Would love this to get added
I also had to create tool scripts that duplicate child nodes to replace specific ReferenceRect in packed scenes. This adds a significant amount of editor/runtime branching that this feature would replace.
Describe the project you are working on
This is a hopeful continuation/discussion of https://github.com/godotengine/godot-proposals/issues/8184
A re-usable ui framework that would allow a user to quickly and efficiently create new ui that follows the same formats and styles of the project. The only way to use the current system is to enable "Editable Children" on an instantiated scene.
Describe the problem or limitation you are having in your project
"Editable Children" clutters the scene tree dock and while functional, when modifying the underlying scene (moving/renaming), the child placed on the instantiated version becomes 'corrupt' losing its parent. This prevents the user from creating one scene and reusing it many times while maintaining the abilty to modify the underlying scene. In my case specifically UI related, but can be applied to all areas.
Example of using "Editable Children"
Describe the feature / enhancement and how it helps to overcome the problem or limitation
By allowing the user to expose nodes inside of an instantiated scene you can add children to specific sections of the subscene. This allows the user to re-use scenes as a type of custom container node.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
I propose nodes get an additional bit of data added to them "exposed_in_owner" and related functions
My current thought is having exposed nodes be dependent on also having a unique name within the scene so it's more straightforward when saving a scene to figure out where they should go. Current implementation forces 'unique_name_in_owner' on, but wont force it off if you disable the exposure setting.
Would love to get some feedback/assistance with this. @dmchurch if you see this, would love to work together on a solution :)
Things left to do ( for my implementation ):
(For reference lets assume Scene A instantiates a copy of Scene B, in which Scene B has an exposed node E):
Proof of concept parts done:
https://github.com/godotengine/godot/pull/84018
Visual example of what I have so far:
If this enhancement will not be used often, can it be worked around with a few lines of script?
Would be used throughout a project, but if forced to workaround it could possible be done, not in a few lines of code, but an example of a workaround could be similar to @raulsntos 's suggestion here: @8184. However this approach has a lot of manual work for the user.
Is there a reason why this should be core and not an add-on in the asset library?
I don't currently see a way around this without being able to modify the scene_tree_dock/pack_scene/node code. Giving the user the ability to reuse code like this would increase readability of the Scene hierarchy and remove unnecessary duplication across the project.