godot icon indicating copy to clipboard operation
godot copied to clipboard

Expose scene unique id functionality in Resource

Open Ryan-000 opened this issue 2 years ago • 1 comments

There is no current way to set the embedded resource ID before or when saving a resource. Also, the only way to get the ID is after saving the scene (id generated during save and is based on time!) and splitting the resource path to get the ID.

In my situation, I am making a Multiset plugin for collaborative scene editing, and this is a massive road blocker when creating and keeping track of resources over the network. When the host creates a new embedded resource in a scene, I cannot keep track of it at all across clients, because the scene unique id is created at save time, so for each client the resource will actually have a different scene unique id, or not one at all. Which makes it practically impossible to keep all the changes synced, and will mess up git history as everyone's will be slightly different.

I tested this, and it works well, if there are duplicate ids in a scene (but on different resources) at save time, only the first resource will get the id, and the other ones will have regenerated ids.

  • Bugsquad edit, closes: https://github.com/godotengine/godot-proposals/issues/9057

Ryan-000 avatar Feb 08 '24 19:02 Ryan-000

Please open a proposal to track the support and details of this feature :)

AThousandShips avatar Feb 08 '24 19:02 AThousandShips

Is there an example I can use to check this is working?

fire avatar Feb 09 '24 03:02 fire

Is there an example I can use to check this is working?

Create a new scene with 3 world environments to test this with. image

@tool
extends Node

@onready var world_environment: WorldEnvironment = $WorldEnvironment
@onready var world_environment_2: WorldEnvironment = $WorldEnvironment2
@onready var world_environment_3: WorldEnvironment = $WorldEnvironment3

@export var run: bool:
	set(v):
		if !is_inside_tree(): return
		run_impl()

func run_impl() -> void:
	var id := Resource.generate_scene_unique_id();
	# create some different resource instances, with the same id.
	var env1 := make_new_resource_with(id)
	var env2 := make_new_resource_with(id)
	var env3 := make_new_resource_with(id)
	
	print("1: " + env1.resource_scene_unique_id)
	print("2: " + env2.resource_scene_unique_id)
	print("3: " + env3.resource_scene_unique_id)
	
	# after saving, you will notice that the world enviroment higher in the scene (in my case WorldEnviroment3)
	# will have retained the id we generated, while the other two,
	# will have a random id assigned to them at save time 
	# (which is a good thing) because no scene corruption
	# use the inspector to check
	world_environment.environment = env1
	world_environment_2.environment = env2
	world_environment_3.environment = env3

func make_new_resource_with(id: String) -> Environment:
	var env := Environment.new();
	env.resource_scene_unique_id = id
	return env

Ryan-000 avatar Feb 09 '24 06:02 Ryan-000

While I'm reviewing and gather reviewers can you apply the documentation changes?

fire avatar Feb 09 '24 08:02 fire

Makes sense, but please add the documentation in doc/classes/Resource.xml you need to run Godot with --doctool . argument so the xmls get updated.

reduz avatar Feb 09 '24 08:02 reduz

While adding documentation, please also squash the commits. See PR workflow for instructions.

akien-mga avatar Feb 09 '24 10:02 akien-mga

Skeptical myself on exposing this full in the Inspector. I have many thoughts but to make it brief: It would be a property not many would modify among others that are arguably more useful. This adds to clutter, bloat, noise, however one may want to call it. It may sound like an exaggeration but... yeah.

But if it has to be exposed it needs better documentation.

Yeah, I'm not too familiar with how Godot does things on a code level. But exposing it to the editor inspector (and to be saved as a property in the resource, as I just found out) was definitely not my intention. I just wanted to be able to use it as a property in code. So ill make a quick change in a moment to fix that.

Ryan-000 avatar Feb 09 '24 23:02 Ryan-000

If this were a property defined in a script it would usually be assigned PROPERTY_USAGE_DEFAULT, so that it is not exposed to the Inspector and saved at all, yet still documented. For built-in properties I'm struggling to find any that actually do this, and this may be entirely by design.

In fact, for these kinds of properties what other Objects do is only keeping the setter and getter. For example, all of Node's set_process and is_processing methods. They could be interpreted as setting a process property that is not actually exposed.

Mickeon avatar Feb 10 '24 00:02 Mickeon

If this were a property defined in a script it would usually be assigned PROPERTY_USAGE_DEFAULT, so that it is not exposed to the Inspector and saved at all, yet still documented. For built-in properties I'm struggling to find any that actually do this, and this may be entirely by design.

In fact, for these kinds of properties what other Objects do is only keeping the setter and getter. For example, all of Node's set_process and is_processing methods. They could be interpreted as setting a process property that is not actually exposed.

turns out changing it from

ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_scene_unique_id"), "set_scene_unique_id", "get_scene_unique_id");

to

ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_scene_unique_id", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_scene_unique_id", "get_scene_unique_id");

does the trick

Ryan-000 avatar Feb 10 '24 00:02 Ryan-000

By the way, the most I've used git is to back up my projects, so all this advanced git stuff is new to me. If you asked me yesterday what git squash is, I'd be thinking about butternut squash soup.

Ryan-000 avatar Feb 10 '24 01:02 Ryan-000

You need to run godot --doctool as mentioned earlier so that the github actions pass and we can merge.

fire avatar Feb 10 '24 06:02 fire

If you asked me yesterday what git squash is, I'd be thinking about butternut squash soup.

This is our fault actually. We should have linked you to the Pull request workflow page sooner.

Mickeon avatar Feb 10 '24 13:02 Mickeon

hang on i have to regenerate the docs then ill do the git squashing things

Ryan-000 avatar Feb 10 '24 19:02 Ryan-000

You can squash at the same time or just update the original commit :)

AThousandShips avatar Feb 10 '24 19:02 AThousandShips

Do I delete all the other commits except for the one that I just put now?

Ryan-000 avatar Feb 10 '24 20:02 Ryan-000

You use fixup by them, if you delete them you lose all the information

AThousandShips avatar Feb 10 '24 20:02 AThousandShips

You need to push with --force, you added merge commits instead

AThousandShips avatar Feb 10 '24 20:02 AThousandShips

Please do the following:

git reset --hard 1887211
git push --force

Or if you like I can help fix this for you

AThousandShips avatar Feb 10 '24 20:02 AThousandShips

There we go :)

In the future remember to create your changes on a separate branch to avoid a lot of these problems, and to use rebase to update your branch and not merges

AThousandShips avatar Feb 10 '24 20:02 AThousandShips

Ok, thank you for your help and understanding.

Ryan-000 avatar Feb 10 '24 20:02 Ryan-000

No worries!

AThousandShips avatar Feb 10 '24 20:02 AThousandShips

Okay, I added some documentation and a check before being able to set it, also if the check fails it will default to a randomly generated one.

Ryan-000 avatar Feb 12 '24 04:02 Ryan-000

Please remove the body of the commit message, it's just a lot of notes on what was changed and just clutters :)

AThousandShips avatar Feb 12 '24 17:02 AThousandShips

Please remove the body of the commit message, it's just a lot of notes on what was changed and just clutters :)

Force pushed an amend to do this, and rebased on latest master.

akien-mga avatar Mar 07 '24 13:03 akien-mga

Thanks! And congrats for your ~first~ second merged Godot contribution :tada:

akien-mga avatar Mar 08 '24 12:03 akien-mga