xchange-scene
A

Publisher

amopel

xchange-scene

Tools
Scene Child Management Workflow GDScript Instance Hierarchy Indexing

Xchange-scene is a robust, high level interface for manipulating child scenes below a given Node and indexing them.

xchange-scene

xchange-scene

Xchange-scene is a robust, high level interface for manipulating child scenes below a given Node and indexing them.

Disclaimer: In the following, when talking about scenes, often it's about the instance of the scene, which is added as a child scene to the tree, and which is also a Node.

Inspired by this part of the godot docs.

TL;DR

Scenes can be in these states:

state function used consequence
ACTIVE .add_child(Node) running and visible
HIDDEN Node.hide() running and hidden
STOPPED .remove_child(Node) not running, but still in memory
FREE Node.free() no longer in memory and no longer indexed

In the example/main.gd you can see all of the features in action.

Here is a first taste:

var scene1 = preload("scene1.tscn")
# x adds and removes scenes below $World
# adds itself to the tree below $World
var x = XScene.new($World)

# this is a reference to $World
var r = x.root

# add_scene takes a PackedScene or a Node
# without a key specified it indexes automatically with integers starting at 1
# (this can be changed to 0)
# default method is ACTIVE, using add_child()
x.add_scene(scene1)
# uses add_child() and .hide()
x.add_scene(scene1, "a", x.HIDDEN)
# just instances and indexes the scene
x.add_scene(scene1, "stopped_s1", x.STOPPED)

get_node("/root").print_tree_pretty()
# ┖╴root
#    ┖╴Main
#       ┠╴Gui
#       ┃  ┖╴ColorRect
#       ┠╴World
#       ┃  ┠╴Node2D  ACTIVE
# a:{scene:[Node2D:1231], state:1}, -> HIDDEN
# stopped_s1:{scene:[Node2D:1235], state:2}} -> STOPPED

# uses remove_child()
x.remove_scene(1, x.STOPPED)
get_node("/root").print_tree_pretty()
# ┠╴World
# ┃  ┠╴Node2D
# ┃  ┃  ┖╴Node2D
# ┃  ┃     ┖╴Node2D
# ┃  ┃        ┖╴icon
# ┃  ┠╴@@2
# ┃  ┖╴@Node2D@4 
- Download a __.zip__ of this repo and unpack it into your project

The version in the AsserLib is __not__ up to date

For more details, read the [godot docs on installing Plugins
](https://docs.godotengine.org/en/stable/tutorials/plugins/editor/installing_plugins.html)

__Don't forget to enable it in your project settings!__

### Run examples

To run the examples yourself, you can
1. Clone this repo 
`git clone https://github.com/aMOPel/godot-xchange-scene.git xscene`
2. Run godot in it (eg. using linux and bash)
`cd xscene; godot --editor`
3. Comment and uncomment the functions in [__example/main.gd__](https://raw.githubusercontent.com/aMOPel/godot-xchange-scene/main/example/main.gd) `_ready()`
4. Run the main scene in godot

### Usage

In the [__example/main.gd__](https://raw.githubusercontent.com/aMOPel/godot-xchange-scene/main/example/main.gd) you can see how to use it. 
There are little __tutorials__ split in functions with __a lot of comments__ to explain everything in detail.

Also in [__docs/XScene.md__](https://raw.githubusercontent.com/aMOPel/godot-xchange-scene/main/docs/XScene.md) is a full markdown reference built from the docstrings.
However it is hard to read on Github because it merges the linebreaks. Either read it in an editor on read it 
["Raw" on Github](https://raw.githubusercontent.com/aMOPel/godot-xchange-scene/main/docs/XScene.md).

```gdscript
# example/main.gd

# gives an instance of XScene
# it adds itself below $World
# it doesn't index itself
x = XScene.new($World)
# ┖╴root
# 	┖╴Main
# 	   ┠╴Gui
# 	   ┃  ┖╴ColorRect
# 	   ┖╴World <- acts below World
# 	      ┖╴@@2 <- x

This will give you an instance of XScene (the main class), which acts and sits below World.

Transistions

from\to ACTIVE = 0 HIDDEN = 1 STOPPED = 2 FREE = 3
ACTIVE --- remove_scene(key, HIDDEN) remove_scene(key, STOPPED) remove_scene(key, FREE)
HIDDEN show_scene(key) --- remove_scene(key, STOPPED) remove_scene(key, FREE)
STOPPED show_scene(key) --- --- remove_scene(key, FREE)
FREE add_scene(scene, key, ACTIVE) add_scene(scene, key, HIDDEN) add_scene(scene, key, STOPPED) ---

The states are just an enum, so you can also use the integers, but writing out the names helps readability of your code.

Normally the visibility of a node (HIDDEN) and if it's in the tree or not (STOPPED), are unrelated. However, in this plugin it's either or. Meaning, when a hidden scene is stopped, its visibility will be reset to true. And when a stopped scene happened to also be hidden, show_scene will reset its visibility to true.

NOTE: Although this plugin resembles a state machine, it isn't implemented as one.

Caveats

  • This plugin adds an overhead to adding and removing scenes. When you add or remove in high quantities, you should consider using the built-in commands, if you don't have to index the scenes so thoroughly.
  • The sync feature adds more overhead and should also only be used for small quantities of scenes. Mind that this feature checks for every addition in the whole tree. So if you were to have a few XScene instances with sync enabled, every instances will make checks and add even more overhead

Here are some really basic benchmarks taken on my mediocre personal PC.

This benchmark comes from adding (ACTIVE) and removing (FREE) 1000 instances of a scene that consists of 4 nodes below root. Every test was done 10 times and the time was averaged. In example/main.gd test_time() you can see the code used.

X no sync sync
add_child() 0.011148 0.020159
add_scene(ACTIVE) 0.014747 0.017216
free() 0.090902 0.098739
remove_scene(FREE) 0.098556 0.099513

These measurements aren't exactly statistically significant, but they give a good idea of the overhead added by this plugin, especially when using sync. Note that the overhead is more or less independent of sync when removing scenes.

TODO

  • You can open an issue if you're missing a feature

Attributions

Icon made by Freepik from Flaticon