-
-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a method to create a new inherited scene from code #3907
Comments
I also want this for a open world terrain addon. Need it for generating a bunch of scenes for each terrain tile (or "chunk"). For the time being, I assume it's possible to write the text for the .tscn file? I actually did something like that for a previous iteration of this project. |
I could not understand the proposal, whats the difference from a instanced scene to a inherited one, when instanced via code? |
Currently you can't create a new scene that inherits from something else via code. You can only instance scenes that you already set up manually in editor. |
but in the end its the same thing, look: var scene = load(existing_scene_path)
add_child(scene)
# do some code here to modify the scene
#save the scene somewhere in res:// Done you have a modified scene from the chosen one. |
Aah, that is what you mean. Yes, that's a solution for the OP |
its because, when you create a In case the statement above isnt true, I can try to implement it. |
If the greyed out nodes behave the same in a scene duplicated that way the same way as they do in an inherited scene, this would indeed be a solution if not, and the inheritance is lost then it's not a functional workaround. |
@lentsius-bark: If you're doing it from code, there is no such thing as the 'greyed out node' since that's only an editor display convention. I've been doing some scene saving recently and the only thing the code cares about is the 'owner', and you can't change the owner on other instanced scenes, but that's a matter for the 'enable editable children in code' proposal, not this one. |
I think Your solution brakes the inheritance . I made a simple scene : which tries to make new inherited scene from code. Without success. Please copy it and use "SaveScene" button in 2D editor, and analize results. Here is the main part of code I used: var _load_path: String = "res://Inheritance.tscn"
var _loaded_scene: PackedScene = load(_load_path)
var _root_node: Node = _loaded_scene.instance(1)
var _new_node: Node2D = Node2D.new()
_new_node.set_name("NewNode2D")
_root_node.add_child(_new_node)
_new_node.set_owner(_root_node)
var _pck: int = _loaded_scene.pack(_root_node)
var _save_path: String = "res://NewInherited.tscn"
var _sv: int = ResourceSaver.save(_save_path, _loaded_scene)
_root_node.free() I still hope the problem is made only by my lack of knowledge. |
Very much looking forward to progress on this. I want to be able to create a new inherited scene from code which will allow the automation of certain gamedev processes, like creating new characters. I'm working on a plugin to procedurally generate new characters for a game, but would prefer to have the generated scenes have inheritance set up from a base scene that will propagate any changes to all characters so that I'm not having to make the changes on every scene individually. I can probably automate something like that, but it would be much smoother and easier to do so via inheritance. Thanks in advance for your work! |
Edit: Updated, but only difference is the "version" property. Important though! Godot 3.x: func create_inherited_scene(inherits: PackedScene, root_name := "Scene") -> PackedScene:
var scene := PackedScene.new()
scene._bundled = { "names": [root_name], "variants": [inherits], "node_count": 1, "nodes": [-1, -1, 2147483647, 0, -1, 0, 0], "conn_count": 0, "conns": [], "node_paths": [], "editable_instances": [], "base_scene": 0, "version": 2 }
return scene Godot 4.0: func create_inherited_scene(inherits: PackedScene, root_name := "Scene") -> PackedScene:
var scene := PackedScene.new()
scene._bundled = { "names": [root_name], "variants": [inherits], "node_count": 1, "nodes": [-1, -1, 2147483647, 0, -1, 0, 0], "conn_count": 0, "conns": [], "node_paths": [], "editable_instances": [], "base_scene": 0, "version": 3 }
return scene Future: The same dictionary probably won't work in a few years. To get a new dictionary, create your inherited scene in the editor, then |
Nice trick, should be documented somewhere. Also what is that magic number in nodes? |
No idea- to get this dictionary I created an inherited scene in the editor and then |
I personally would be in need/want for this. I have certain ingame-objects saved as scenes (Items, Equipment, Armor etc.) and i have hundreds of them. These are ordered in tiers. So when i now want to create a new tier, i have to manually duplicate those scenes of the previous tier and rename them. I tried to write a script that loads items/equipment of a certain tier, changes some values and saves them as a higher tier item, with a new file-name (sword_t1 -> sword_t2). It works at it's core, but i loose my connection to the core-scene its inheriting from, which defines certain defualt values i want to be able to easily change for all inheriting scenes, by just changing it in this parent scene. I found an idea of how to make it work, by using a different kind of instance, but this only works for tool scripts: https://godotengine.org/qa/120127/how-to-edit-inherited-packed-scenes The problem with this is that it requires to run scripts in tool, but that still doesnt work and creates a scene without the inheritance connection: what it does: In the image all those ext_resource are created because it doesnt inherit anymore and the The initial proposal feels like it could help me make it possible for me to duplicate a scene and it's still an inherited scene. Even if i would have to do a workaround like:
|
Hi! I've tried Your way and it works for me. I added line for using root node name of inherited scene. It's useful if You don't want to change root node name in inheriting scene.
|
I managed to find a workaround for this by creating an inherited scene from the editor, then duplicating it from code and saving the duplicate as a new .tscn file. The duplicate scene maintains inheritance. tool
extends EditorScript
const INHERITED_SCENE = preload("res://test/Inherited.tscn")
func _run():
var new_scene = INHERITED_SCENE.duplicate();
var instance = new_scene.instance(PackedScene.GEN_EDIT_STATE_INSTANCE);
instance.name = "AnotherInherited";
new_scene.pack(instance);
ResourceSaver.save("test/AnotherInherited.tscn", new_scene); Anyway I second the proposal for ease of use and moreover this workaround doesn't solve this use case |
This is the same approach I take for an addon I've made, but it really is inelegant and comes with its own set of problems in my experience. I've run into problems where making changes to the new .tscn file after it's been successfully created breaks the inheritance. As it stands, I'm going to have to verify and/or edit the .tscn file's content directly to make this work, which I'd really rather not do because that's so error prone. Here's hoping the pull request gets reviewed and approved soon! |
I submitted a PR that should work: godotengine/godot#90057 Would appreciate a review. |
I had a similar Problem when writing a custom public override void _PostProcess(Node scene)
{
CreateNewInheritedScene(scene);
}
// scenePath is the path of the scene file (fbx, gltf, tscn) that is supposedly inherited into the scene test.tscn
void CreateNewInheritedScene(Node sceneNode)
{
PackedScene scene = new PackedScene();
scene._Bundled = new Dictionary
{
{ "base_scene", 0 },
{ "conn_count", 0 },
{ "conns", new Array() },
{ "editable_instances", new Array() },
{ "names", new Array(new[] { sceneNode.Name }) },
{ "node_count", 1 }, { "node_paths", new Array() },
{ "nodes", new Array(new[] { -1, -1, 2147483647, 0, -1, 0, 0 }.Select(i => Variant.From(i))) },
{ "variants", new Array(new[] { ResourceLoader.Load<PackedScene>(scenePath) }) },
{ "version", 3 }
};
ResourceSaver.Save(scene, "res://test.tscn");
} |
Last January/Feb I was able to get the equivalent of "right click > new inherited scene" on glb files by using the following:
I could run through an arbitrary folder structure with glbs, images, and json with the material info and was able to hack together the little text files Godot likes to use and it all worked. But now, in 4.3, once it hits the first glb it finds, the editor stops executing the script (an anti pattern) and shows the popup you would get if you were doing this manually. But when I was looking into this, I did stumble across the property that Sythelux mentioned, and skipped it because it looks too complicated. Probably will have to revisit it now. |
Describe the project you are working on
2D isometric car race game. currently in Godot 3.4.2
Describe the problem or limitation you are having in your project
In my game I will have to add about 1000-2000 vehicles of 200-400 types (for now i have 256 in 42 types). Each vehicle must be unique beacuse only one instance can be in game scene at once. I have base CarTemplate scene. Then I create default CarType which inherits from CarTemplate. Then I make specific Car scenes (usualy 6- 10) which inherit from CarType and have its unique features. Making one CarType by hand takes me about half an hour.
I designed EditorPlugin which helps with tedious process of making new Car scenes. It takes assets from named folders and creates nessesery Resources (e.g. SpriteFrames, simple scripts inherited from CarTemplate.gd script I have, etc.) and then ataches them to corresponding Car scenes.
Unfortunately whole proccess can not be fully automatic. Car scenes must be made by hand if I want to use benefits of inheritance... It takes time and makes a risk of typing mistakes.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
With ability to create a new inherited scene directly from GDScript, it would be possible to fully automate process of creating inherited scenes inside editor and thus could save a lot of developer's time.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
It could be a new Method added to PackedScene.
The code in GDScript should allow something like:
If this enhancement will not be used often, can it be worked around with a few lines of script?
There is no code for this. Only tedious clicking and typing in the editor.
Is there a reason why this should be core and not an add-on in the asset library?
The proposal looks like core to me. Also I suppose change like that is imposible to do whitout changing base engine code and recompiling it.
The text was updated successfully, but these errors were encountered: