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

Loading Tileset Overrides fails when LDtk Project saves Levels to separate files #45

Closed
miketvo opened this issue Dec 4, 2024 · 1 comment · Fixed by #46
Closed

Comments

@miketvo
Copy link
Contributor

miketvo commented Dec 4, 2024

Description

My team is working on a private project that imports LDtk levels using the Godot LDtk Importer plugin. At the moment, our LDtk project is set to export each level to separate files.

The import process works as intended, but for every re-import, this error message shows up in Godot output:

res://addons/ldtk-importer/src/tileset.gd:319 - Unable to iterate on object of type 'Nil'.
Full log:

Godot Engine v4.3.stable.official (c) 2007-present Juan Linietsky, Ariel Manzur & Godot Contributors.
--- Debug adapter server started on port 6006 ---
--- GDScript language server started on port 6005 ---
Add Autoload
Godot-LDtk-Importer 2.0.1 (c) 2023 Andrew Gleeson.
  res://addons/ldtk-importer/src/tileset.gd:319 - Unable to iterate on object of type 'Nil'.
[LDTK] Start Import: 'res://world/world.ldtk'
• LDTK VERSION (1.5.3) OK ✔
	• Saving Tilesets: ["tileset_16px"] 
			‣ Entity Post-Import: Level0.Player
			‣ Entity Post-Import: Level0.DynamicEnvironment
			‣ Entity Post-Import: Level0.Collectibles
			‣ Entity Post-Import: Level0.Locations
				‣ Generated Locations
		‣ Level Post-Import: Level0
			‣ Processing Level
			‣ Excluded layer 'FloorMapInvalids'
			‣ Excluded layer 'FloorMap'
	• Could not resolve 3 references, most likely non-existent entities. 
	• Saving Levels: [&"Level0"] 
	• Saving World 'res://.godot/imported/world.ldtk-a3a9fb77576c8abcabc7332360bd86e9' 
[LDTK] Finished Import. (Total Time: 215ms)

On further investigation, I realized that the function get_tileset_overrides() in addons\ldtk-importer\src\tileset.gd is trying to access the JSON field world_data.levels->layerInstances in the .ldtk project file. This is returning Nil, because the actual data for each level is saved externally for my project. So the data in layerInstances still exists, but it is just saved in an external file.

Since I saw that the plugin has the capability to check for external levels (var external_level at func _import() in addons\ldtk-importer\ldtk-importer.gd:200) and parse external levels with LevelUtil.get_external_level(), I suppose it could be expected that loading tileset overrides would behave the same way for separated level files.

To Reproduce

  1. Clone the plugin's repository.
  2. Open the example GridVania project under examples/gridvania/example_gridvania.ldtk with LDtk, go into Project Settings, check "Save levels to separate files":
  1. Save the LDtk project (Ctrl+S).
  2. Open the repository in Godot, in FileSystem (1) with the examples/gridvania/example_gridvania.ldtk file selected (2), go to the Import (3) dock and press Reimport (4):
  1. Expected output in Godot:
  res://addons/ldtk-importer/src/tileset.gd:319 - Unable to iterate on object of type 'Nil'.
[LDTK] Start Import: 'res://examples/gridvania/example_gridvania.ldtk'
• LDTK VERSION (1.5.3) OK ✔
	‣ Tileset Post-Import: { 16: <TileSet#-9223370286370328518> }
Tileset: <TileSet#-9223370286370328518>(16, 16)
	• Saving Tilesets: ["tileset_16px"] 
			‣ Entity Post-Import: Level_0.Entities
EntityLayer: Entities | Count: 7
		‣ Level Post-Import: Level_0
Level: Level_0:<Node2D#2436286706377>
			‣ Entity Post-Import: Level_1.Entities
EntityLayer: Entities | Count: 4
		‣ Level Post-Import: Level_1
Level: Level_1:<Node2D#2436941017830>
			‣ Entity Post-Import: Level_2.Entities
EntityLayer: Entities | Count: 4
		‣ Level Post-Import: Level_2
Level: Level_2:<Node2D#2437511443385>
			‣ Entity Post-Import: Level_3.Entities
EntityLayer: Entities | Count: 1
		‣ Level Post-Import: Level_3
Level: Level_3:<Node2D#2437964428942>
			‣ Entity Post-Import: Level_4.Entities
EntityLayer: Entities | Count: 1
		‣ Level Post-Import: Level_4
Level: Level_4:<Node2D#2438266418860>
			‣ Entity Post-Import: Level_5.Entities
EntityLayer: Entities | Count: 0
		‣ Level Post-Import: Level_5
Level: Level_5:<Node2D#2438568407965>
	• Saving Levels: [&"Level_0", &"Level_1", &"Level_2", &"Level_3", &"Level_4", &"Level_5"] 
	‣ World Post-Import: example_gridvania
World: example_gridvania:<Node2D#2443215697417>
	• Saving World 'res://.godot/imported/example_gridvania.ldtk-2c2bfddda6d6598db19492e019e8ae49' 
[LDTK] Finished Import. (Total Time: 271ms)

Potential Solution

Modify get_tileset_overrides() to accept base_dir and external_levels as arguments, then load the level data accordingly:

# Collect all layer tileset overrides. Later we'll ensure these sources are included in TileSet resources.
static func get_tileset_overrides(
		world_data: Dictionary,
		base_dir: String,
		external_levels: bool
) -> Dictionary:
	var overrides := {}
	for level_index in range(world_data.levels.size()):
		var level_data
		level_data = world_data.levels[level_index]

		if external_levels:
			level_data = LevelUtil.get_external_level(level_data, base_dir)

		for layer in level_data.layerInstances:
			if layer.overrideTilesetUid == null:
				continue
			var gridSize: int = layer.__gridSize
			var overrideUid: int = layer.overrideTilesetUid
			if overrideUid != null:
				if not overrides.has(gridSize):
					overrides[gridSize] = []
				var gridsize_overrides: Array = overrides[gridSize]
				if not gridsize_overrides.has(overrideUid):
					gridsize_overrides.append(overrideUid)
	return overrides

This would need some additional modifications to addons\ldtk-importer\ldtk-importer.gd to pass in base_dir and external_levels as parameters.

This is the current fix I am using in my project. Please let me know if this is the intended design for the plugin. If so, I can create a fork and make a PR for this.

System Information

  • Windows 10/11
  • Godot v4.3.stable.official [77dcf97d8] (x86_64) installed via scoop
  • LDtk 1.5.3-64bits
  • Godot LDtk Importer 2.0.1

(Btw, thanks for the amazing work on this plugin!)

miketvo added a commit to miketvo/godot-ldtk-importer that referenced this issue Dec 4, 2024
@miketvo
Copy link
Contributor Author

miketvo commented Dec 4, 2024

Since I have some extra time today, I've decided to go ahead and fork the repository and made the fix in #46. Please feel free to dismiss this if it is not the intended behavior of the plugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant