add LdtkFieldInstance and LdtkEntityMap classes; update LdtkSceneBuilder to support entity mapping
This commit is contained in:
11
addons/csharp_ldtk_importer/LdtkEntityMap.cs
Normal file
11
addons/csharp_ldtk_importer/LdtkEntityMap.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace CSharpLdtkImporter;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class LdtkEntityMap : Resource
|
||||
{
|
||||
[Export] public Dictionary<string, PackedScene> EntitySceneMap { get; set; } = new();
|
||||
}
|
1
addons/csharp_ldtk_importer/LdtkEntityMap.cs.uid
Normal file
1
addons/csharp_ldtk_importer/LdtkEntityMap.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c5wadsimbi1re
|
@@ -44,9 +44,11 @@ public partial class LdtkResourceImporter : EditorImportPlugin
|
||||
GD.PushError("Parsed LDTK data is null.");
|
||||
return Error.Failed;
|
||||
}
|
||||
|
||||
var entityMap = options.TryGetValue("entity_map", out var map) ? map.As<LdtkEntityMap>() : null;
|
||||
|
||||
// 3. Use the Scene Builder to generate the Godot scene
|
||||
var builder = new LdtkSceneBuilder(ldtkData, sourceFile);
|
||||
var builder = new LdtkSceneBuilder(ldtkData, sourceFile, entityMap);
|
||||
var rootNode = builder.BuildLdtkProjectRoot();
|
||||
|
||||
var scene = new PackedScene();
|
||||
@@ -78,6 +80,13 @@ public partial class LdtkResourceImporter : EditorImportPlugin
|
||||
{ "name", "import_tilemaps" },
|
||||
{ "default_value", true },
|
||||
{ "usage", (int)(PropertyUsageFlags.Default | PropertyUsageFlags.UpdateAllIfModified) }
|
||||
},
|
||||
new()
|
||||
{
|
||||
{ "name", "entity_map" },
|
||||
{ "default_value", new LdtkEntityMap() },
|
||||
{ "property_hint", (int)PropertyHint.ResourceType },
|
||||
{ "hint_string", "LdtkEntityMap" },
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using CSharpLdtkImporter.Models;
|
||||
using Godot;
|
||||
|
||||
@@ -8,12 +10,14 @@ public class LdtkSceneBuilder
|
||||
{
|
||||
private readonly LdtkData _ldtkData;
|
||||
private readonly string _basePath;
|
||||
private readonly LdtkEntityMap _entityMap;
|
||||
private readonly Godot.Collections.Dictionary<int, TileSet> _tileSetCache = new();
|
||||
|
||||
public LdtkSceneBuilder(LdtkData ldtkData, string sourceFile)
|
||||
public LdtkSceneBuilder(LdtkData ldtkData, string sourceFile, LdtkEntityMap entityMap)
|
||||
{
|
||||
_ldtkData = ldtkData;
|
||||
_basePath = sourceFile.GetBaseDir();
|
||||
_entityMap = entityMap;
|
||||
}
|
||||
|
||||
public Node2D BuildLdtkProjectRoot()
|
||||
@@ -94,17 +98,57 @@ public class LdtkSceneBuilder
|
||||
private Node2D BuildEntityLayer(LdtkLayerInstance layer)
|
||||
{
|
||||
var entityLayerRoot = new Node2D { Name = layer.Identifier };
|
||||
|
||||
foreach (var entity in layer.EntityInstances)
|
||||
{
|
||||
var marker = new Marker2D
|
||||
Node2D instance = null;
|
||||
|
||||
GD.Print($"EntityMap keys: {string.Join(", ", _entityMap?.EntitySceneMap.Keys ?? Array.Empty<string>())}");
|
||||
GD.Print($"Entity Identifier: {entity.Identifier}");
|
||||
GD.Print($"Is Entity Mapped: {_entityMap?.EntitySceneMap.ContainsKey(entity.Identifier)}");
|
||||
|
||||
if (_entityMap?.EntitySceneMap.TryGetValue(entity.Identifier, out var packedScene) == true &&
|
||||
packedScene != null)
|
||||
{
|
||||
Name = entity.Identifier,
|
||||
Position = new Vector2(entity.Px[0], entity.Px[1])
|
||||
};
|
||||
entityLayerRoot.AddChild(marker);
|
||||
GD.Print($"Instantiating entity '{entity.Identifier}' from mapped scene.");
|
||||
instance = packedScene.Instantiate<Node2D>();
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.Print($"Defaulting to Marker2D for unmapped entity '{entity.Identifier}'.");
|
||||
instance = new Marker2D();
|
||||
}
|
||||
|
||||
instance.Name = entity.Identifier;
|
||||
instance.Position = new Vector2(entity.Px[0], entity.Px[1]);
|
||||
|
||||
foreach (var field in entity.FieldInstances)
|
||||
{
|
||||
instance.SetMeta(field.Identifier, ConvertJsonElementToVariant(field.Value));
|
||||
}
|
||||
|
||||
entityLayerRoot.AddChild(instance);
|
||||
}
|
||||
|
||||
return entityLayerRoot;
|
||||
}
|
||||
|
||||
private static Variant ConvertJsonElementToVariant(JsonElement element)
|
||||
{
|
||||
return element.ValueKind switch
|
||||
{
|
||||
JsonValueKind.String => element.GetString(),
|
||||
JsonValueKind.Number => element.GetDouble(),
|
||||
JsonValueKind.True => true,
|
||||
JsonValueKind.False => false,
|
||||
JsonValueKind.Null => default,
|
||||
// For LDTK points (which are objects) or arrays, we can serialize them back to a JSON string.
|
||||
// A more advanced implementation could convert these to Vector2 or Array types.
|
||||
JsonValueKind.Object => Json.Stringify(Json.ParseString(element.GetRawText())),
|
||||
JsonValueKind.Array => Json.Stringify(Json.ParseString(element.GetRawText())),
|
||||
_ => default
|
||||
};
|
||||
}
|
||||
|
||||
private TileSet GetOrCreateTileSet(int tilesetDefUid)
|
||||
{
|
||||
|
@@ -9,4 +9,7 @@ public class LdtkEntityInstance
|
||||
|
||||
[JsonPropertyName("px")]
|
||||
public int[] Px { get; set; }
|
||||
|
||||
[JsonPropertyName("fieldInstances")]
|
||||
public LdtkFieldInstance[] FieldInstances { get; set; }
|
||||
}
|
16
addons/csharp_ldtk_importer/Models/LdtkFieldInstance.cs
Normal file
16
addons/csharp_ldtk_importer/Models/LdtkFieldInstance.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace CSharpLdtkImporter.Models;
|
||||
|
||||
public class LdtkFieldInstance
|
||||
{
|
||||
[JsonPropertyName("__identifier")]
|
||||
public string Identifier { get; set; }
|
||||
|
||||
[JsonPropertyName("__type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonPropertyName("__value")]
|
||||
public JsonElement Value { get; set; }
|
||||
}
|
@@ -0,0 +1 @@
|
||||
uid://dgwt3rdvkdypq
|
11
assets/MyEntityMap.tres
Normal file
11
assets/MyEntityMap.tres
Normal file
@@ -0,0 +1,11 @@
|
||||
[gd_resource type="Resource" script_class="LdtkEntityMap" load_steps=3 format=3 uid="uid://cqu47e7mrbwfr"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://c5wadsimbi1re" path="res://addons/csharp_ldtk_importer/LdtkEntityMap.cs" id="1_0e1w3"]
|
||||
[ext_resource type="PackedScene" uid="uid://bmtfa3t0gbg3e" path="res://assets/square.tscn" id="1_1cxp4"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_0e1w3")
|
||||
EntitySceneMap = Dictionary[String, PackedScene]({
|
||||
"Player": ExtResource("1_1cxp4")
|
||||
})
|
||||
metadata/_custom_type_script = "uid://c5wadsimbi1re"
|
8
assets/square.tscn
Normal file
8
assets/square.tscn
Normal file
@@ -0,0 +1,8 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bmtfa3t0gbg3e"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://dmrfe4r8rw46w" path="res://icon.svg" id="1_a73l4"]
|
||||
|
||||
[node name="Square" type="Node2D"]
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
texture = ExtResource("1_a73l4")
|
167
assets/test.ldtk
167
assets/test.ldtk
@@ -11,7 +11,7 @@
|
||||
"iid": "2c2f2ff0-8560-11f0-9745-f307d35f41a0",
|
||||
"jsonVersion": "1.5.3",
|
||||
"appBuildId": 488493,
|
||||
"nextUid": 25,
|
||||
"nextUid": 27,
|
||||
"identifierStyle": "Capitalize",
|
||||
"toc": [],
|
||||
"worldLayout": "Free",
|
||||
@@ -41,6 +41,41 @@
|
||||
"customCommands": [],
|
||||
"flags": [],
|
||||
"defs": { "layers": [
|
||||
{
|
||||
"__type": "Entities",
|
||||
"identifier": "Entities",
|
||||
"type": "Entities",
|
||||
"uid": 26,
|
||||
"doc": null,
|
||||
"uiColor": null,
|
||||
"gridSize": 16,
|
||||
"guideGridWid": 0,
|
||||
"guideGridHei": 0,
|
||||
"displayOpacity": 1,
|
||||
"inactiveOpacity": 0.6,
|
||||
"hideInList": false,
|
||||
"hideFieldsWhenInactive": true,
|
||||
"canSelectWhenInactive": true,
|
||||
"renderInWorldView": true,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"parallaxFactorX": 0,
|
||||
"parallaxFactorY": 0,
|
||||
"parallaxScaling": true,
|
||||
"requiredTags": [],
|
||||
"excludedTags": [],
|
||||
"autoTilesKilledByOtherLayerUid": null,
|
||||
"uiFilterTags": [],
|
||||
"useAsyncRender": false,
|
||||
"intGridValues": [],
|
||||
"intGridValuesGroups": [],
|
||||
"autoRuleGroups": [],
|
||||
"autoSourceLayerDefUid": null,
|
||||
"tilesetDefUid": null,
|
||||
"tilePivotX": 0,
|
||||
"tilePivotY": 0,
|
||||
"biomeFieldUid": null
|
||||
},
|
||||
{
|
||||
"__type": "IntGrid",
|
||||
"identifier": "IntGrid",
|
||||
@@ -669,7 +704,43 @@
|
||||
"tilePivotY": 0,
|
||||
"biomeFieldUid": null
|
||||
}
|
||||
], "entities": [], "tilesets": [
|
||||
], "entities": [
|
||||
{
|
||||
"identifier": "Player",
|
||||
"uid": 25,
|
||||
"tags": [],
|
||||
"exportToToc": false,
|
||||
"allowOutOfBounds": false,
|
||||
"doc": null,
|
||||
"width": 16,
|
||||
"height": 16,
|
||||
"resizableX": false,
|
||||
"resizableY": false,
|
||||
"minWidth": null,
|
||||
"maxWidth": null,
|
||||
"minHeight": null,
|
||||
"maxHeight": null,
|
||||
"keepAspectRatio": false,
|
||||
"tileOpacity": 1,
|
||||
"fillOpacity": 1,
|
||||
"lineOpacity": 1,
|
||||
"hollow": false,
|
||||
"color": "#BE4A2F",
|
||||
"renderMode": "Rectangle",
|
||||
"showName": true,
|
||||
"tilesetId": null,
|
||||
"tileRenderMode": "FitInside",
|
||||
"tileRect": null,
|
||||
"uiTileRect": null,
|
||||
"nineSliceBorders": [],
|
||||
"maxCount": 0,
|
||||
"limitScope": "PerLevel",
|
||||
"limitBehavior": "MoveLastOne",
|
||||
"pivotX": 0,
|
||||
"pivotY": 0,
|
||||
"fieldDefs": []
|
||||
}
|
||||
], "tilesets": [
|
||||
{
|
||||
"__cWid": 16,
|
||||
"__cHei": 12,
|
||||
@@ -715,6 +786,48 @@
|
||||
"externalRelPath": null,
|
||||
"fieldInstances": [],
|
||||
"layerInstances": [
|
||||
{
|
||||
"__identifier": "Entities",
|
||||
"__type": "Entities",
|
||||
"__cWid": 16,
|
||||
"__cHei": 16,
|
||||
"__gridSize": 16,
|
||||
"__opacity": 1,
|
||||
"__pxTotalOffsetX": 0,
|
||||
"__pxTotalOffsetY": 0,
|
||||
"__tilesetDefUid": null,
|
||||
"__tilesetRelPath": null,
|
||||
"iid": "332d3780-8560-11f0-9745-0103de4db213",
|
||||
"levelId": 0,
|
||||
"layerDefUid": 26,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"visible": true,
|
||||
"optionalRules": [],
|
||||
"intGridCsv": [],
|
||||
"autoLayerTiles": [],
|
||||
"seed": 4277998,
|
||||
"overrideTilesetUid": null,
|
||||
"gridTiles": [],
|
||||
"entityInstances": [
|
||||
{
|
||||
"__identifier": "Player",
|
||||
"__grid": [7,8],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": null,
|
||||
"__smartColor": "#BE4A2F",
|
||||
"iid": "3a675850-8560-11f0-9745-41d5f1b372f4",
|
||||
"width": 16,
|
||||
"height": 16,
|
||||
"defUid": 25,
|
||||
"px": [112,128],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 112,
|
||||
"__worldY": 128
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"__identifier": "IntGrid",
|
||||
"__type": "IntGrid",
|
||||
@@ -915,6 +1028,31 @@
|
||||
"externalRelPath": null,
|
||||
"fieldInstances": [],
|
||||
"layerInstances": [
|
||||
{
|
||||
"__identifier": "Entities",
|
||||
"__type": "Entities",
|
||||
"__cWid": 16,
|
||||
"__cHei": 16,
|
||||
"__gridSize": 16,
|
||||
"__opacity": 1,
|
||||
"__pxTotalOffsetX": 0,
|
||||
"__pxTotalOffsetY": 0,
|
||||
"__tilesetDefUid": null,
|
||||
"__tilesetRelPath": null,
|
||||
"iid": "332d5e90-8560-11f0-9745-d935367db062",
|
||||
"levelId": 23,
|
||||
"layerDefUid": 26,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"visible": true,
|
||||
"optionalRules": [],
|
||||
"intGridCsv": [],
|
||||
"autoLayerTiles": [],
|
||||
"seed": 8641114,
|
||||
"overrideTilesetUid": null,
|
||||
"gridTiles": [],
|
||||
"entityInstances": []
|
||||
},
|
||||
{
|
||||
"__identifier": "IntGrid",
|
||||
"__type": "IntGrid",
|
||||
@@ -1100,6 +1238,31 @@
|
||||
"externalRelPath": null,
|
||||
"fieldInstances": [],
|
||||
"layerInstances": [
|
||||
{
|
||||
"__identifier": "Entities",
|
||||
"__type": "Entities",
|
||||
"__cWid": 16,
|
||||
"__cHei": 16,
|
||||
"__gridSize": 16,
|
||||
"__opacity": 1,
|
||||
"__pxTotalOffsetX": 0,
|
||||
"__pxTotalOffsetY": 0,
|
||||
"__tilesetDefUid": null,
|
||||
"__tilesetRelPath": null,
|
||||
"iid": "332d5e91-8560-11f0-9745-af9a0227805e",
|
||||
"levelId": 24,
|
||||
"layerDefUid": 26,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"visible": true,
|
||||
"optionalRules": [],
|
||||
"intGridCsv": [],
|
||||
"autoLayerTiles": [],
|
||||
"seed": 4469038,
|
||||
"overrideTilesetUid": null,
|
||||
"gridTiles": [],
|
||||
"entityInstances": []
|
||||
},
|
||||
{
|
||||
"__identifier": "IntGrid",
|
||||
"__type": "IntGrid",
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
importer="ldtk.importer"
|
||||
type="PackedScene"
|
||||
uid="uid://c4xhtpmir26ah"
|
||||
uid="uid://ckbephcqvg24h"
|
||||
path="res://.godot/imported/test.ldtk-5da58debf60b2ac4adee332e85c3c4bc.tscn"
|
||||
|
||||
[deps]
|
||||
@@ -14,3 +14,4 @@ dest_files=["res://.godot/imported/test.ldtk-5da58debf60b2ac4adee332e85c3c4bc.ts
|
||||
|
||||
import_entities=true
|
||||
import_tilemaps=true
|
||||
entity_map=Resource("uid://cqu47e7mrbwfr", "res://assets/MyEntityMap.tres")
|
||||
|
Reference in New Issue
Block a user