Skip to content
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

Allow strong access to each loaded resource #12

Open
clm805 opened this issue Oct 8, 2024 · 4 comments
Open

Allow strong access to each loaded resource #12

clm805 opened this issue Oct 8, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@clm805
Copy link

clm805 commented Oct 8, 2024

I wrote the following code generation tool using your library:

@tool
extends EditorScript

func _run() -> void:
	var items = preload("res://data/items.tres").load_all()
	var items_str = "\n".join(items.map(func(item: Item):
		return 'static var {id}: Item = load("{path}")'.format({"id": item.id, "path": item.resource_path})))
	var all_str = ", ".join(items.map(func(item: Item): return item.id))

	var script_content = \
"""
# This file was auto-generated
class_name Items
extends RefCounted

{items}

static var all: Array[Item] = [{all}]

""".format({"items": items_str, "all": all_str})

	print(script_content)

	var script = GDScript.new()
	script.source_code = script_content
	ResourceSaver.save(script, 'res://scripts/data/items.gd')

where res://data/items.tres is a ResourceGroup. It's been very helpful for referencing specific resources by (in this case) their id field. I was wondering if you might incorporate this into your library, perhaps have each ResourceGroup export at least a file path, which, if set, would make the resource group generate a file similar to the one above, where the details (class_name, the field that becomes the var names, etc..) could be additional exports.

@clm805
Copy link
Author

clm805 commented Oct 8, 2024

The generated file looks like this:

# This file was auto-generated
class_name Items
extends RefCounted

static var apple: Item = load("res://data/items/apple.tres")
static var axe: Item = load("res://data/items/axe.tres")
static var carrot: Item = load("res://data/items/carrot.tres")
static var carrot_seed: Item = load("res://data/items/carrot_seed.tres")
static var chair: Item = load("res://data/items/chair.tres")
static var clock: Item = load("res://data/items/clock.tres")
static var hoe: Item = load("res://data/items/hoe.tres")
static var orange: Item = load("res://data/items/orange.tres")
static var peach: Item = load("res://data/items/peach.tres")
static var pear: Item = load("res://data/items/pear.tres")
static var stick: Item = load("res://data/items/stick.tres")
static var stone: Item = load("res://data/items/stone.tres")
static var table: Item = load("res://data/items/table.tres")
static var watering_can: Item = load("res://data/items/watering_can.tres")
static var wood: Item = load("res://data/items/wood.tres")

static var all: Array[Item] = [apple, axe, carrot, carrot_seed, chair, clock, hoe, orange, peach, pear, stick, stone, table, watering_can, wood]

where I can easily access each item from anywhere using e.g. Items.axe or Items.all.

@derkork
Copy link
Owner

derkork commented Oct 9, 2024

Actually, when I started making this library, this was the original thing I wanted to build - a code generator. However, I was not able to come up with an output that would have been universally useful. Some projects would benefit from a list of variables like you have suggested, others would probably benefit more from a database-like structure, where you can ask things like "give me a random fruit" or "give me all tools sorted by price", yet others would like to have a dictionary of enemies grouped by element type or cards grouped into decks or upgrade levels, etc, etc.

So whatever output I decided for, would work only for some games and at the same time would not work for a substantial amount of other games. Another problem with a code generator is that this introduces a good amount of edge cases where variable or function names clash with other data or Godot's built-in functions (e.g. if for some reason you name an item all in your example, this will break the generated code). This is ok if you build the generator for your own game and can live with some limitations but a library should be robust enough to handle this kind of stuff and more. So in the end I scrapped the code generator idea and rather went for a simple but universally useful interface that would allow game developers to build their own system on top of the resource groups - like you did with your implementation. Right now I still think that this was the right call.

But if you have some ideas on how to generate a universally useful output and handle the other problems I mentioned, I'd very much like to know about it!

@derkork derkork added enhancement New feature or request question Further information is requested labels Oct 9, 2024
@clm805
Copy link
Author

clm805 commented Oct 22, 2024

I think individual references to each resource is almost universally useful (and in the rare cases it isn't you can just not opt in). Regarding the all var (see below paragraph for naming conflict solution), this is merely in keeping with your existing provided use case of load_all().

Amending my earlier suggestion, export an optional string name for the all var, set the class name to the resource name of the resource group (properly cased), set the var names to the resource names of the resources. As before, allow the path to the script file to be set, where if left empty then no script is generated.

I'm guessing this would cover 90+% of the use cases for your tool, which I understand to be not having to preload each resources by hand, which I'm presently still needing to do in order to reference them individually. If people want different/more functionality they can create their own tool script (or maybe have your generator only write its own part of the script between two comment lines and let people add additional code (if you do this then maybe drop the all var, it would be easy to add manually).

@derkork
Copy link
Owner

derkork commented Oct 24, 2024

Thanks for taking the time to write this up. I think if it's optional and configurable to some extent it could indeed be a good 80/20 solution. I'll have a deeper look at it, but it will be a few days as I'm currently fully engaged in another thing that needs doing :-).

@derkork derkork removed the question Further information is requested label Oct 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants