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

Prefab style feature #34

Merged
merged 9 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions LDtk.Codegen/Generators/BaseGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ public void EndBlock()
Line("}");
}

public void EndBlockSeparator()
{
indent--;
Line("},");
}

public void EndCodeBlock()
{
indent--;
Line("};");
}

public static string Call(string functionName, string contents)
{
return $"{functionName}({contents})";
Expand Down
218 changes: 184 additions & 34 deletions LDtk.Codegen/Generators/ClassGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,72 +1,222 @@
namespace LDtk.Codegen.Generators;

using LDtk.Codegen;
using LDtk.Full;
using System.Globalization;
using System.Linq;
using System.Text.Json;

using Full;

public class ClassGenerator(LDtkFileFull ldtkFile, Options options) : BaseGenerator(ldtkFile, options)
{
public void Generate()
{
// Level Classes
GenClass(Options.LevelClassName, LDtkFile.Defs.LevelFields, string.Empty, false);
GenClass(Options.LevelClassName, string.Empty, fieldDefinitions: LDtkFile.Defs.LevelFields);

// Entity Classes
foreach (EntityDefinition e in LDtkFile.Defs.Entities)
{
GenClass(e.Identifier, e.FieldDefs, "Entities", true);
GenClass(e.Identifier, "Entities", e);
}
}

void GenClass(string identifier, FieldDefinition[] fields, string folder, bool isEntity)
void GenClass(string identifier, string folder, EntityDefinition entityDefinition = null,
FieldDefinition[] fieldDefinitions = null)
{
Line($"namespace {Options.Namespace};");
Blank();
Line("// This file was automatically generated, any modifications will be lost!");
Line("#pragma warning disable");
Blank();
Line("using LDtk;");
Line("using Microsoft.Xna.Framework;");
Blank();
GenHeaders();

string classDef = $"public partial class {identifier}";

if (isEntity && Options.EntityInterface)
if (entityDefinition != null && Options.EntityInterface)
{
classDef += " : ILDtkEntity";
}

Line(classDef);

StartBlock();
{
if (entityDefinition != null)
{
GenEntityFields(identifier, entityDefinition);
}
else if (fieldDefinitions != null)
{
GenFieldDefs(fieldDefinitions);
}
}
EndBlock();

Line("#pragma warning restore");
Output(folder, identifier);
}

void GenEntityFields(string identifier, EntityDefinition entityDefinition)
{
//generate the default data for fields.
Line($"public static {identifier} Default() => new()");
StartBlock();
{
if (isEntity)
Line($"Identifier = \"{identifier}\",");
Line($"Uid = {entityDefinition.Uid},");
Line($"Size = new Vector2({entityDefinition.Width}f, {entityDefinition.Height}f),");
Line($"Pivot = new Vector2({entityDefinition.PivotX}f, {entityDefinition.PivotY}f),");
if (entityDefinition.TileRect != null)
{
GenTilesetRectangle("Tile", entityDefinition.TileRect);
}

byte r = entityDefinition.Color.R;
byte g = entityDefinition.Color.G;
byte b = entityDefinition.Color.B;
byte a = entityDefinition.Color.A;

Line($"SmartColor = new Color({r}, {g}, {b}, {a}),");

//generate default data for custom fields
GenCustomFieldDefData(entityDefinition.FieldDefs);
}
EndCodeBlock();
Blank();

//generate the rest of the class
Line("public string Identifier { get; set; }");
Line("public System.Guid Iid { get; set; }");
Line("public int Uid { get; set; }");
Line("public Vector2 Position { get; set; }");
Line("public Vector2 Size { get; set; }");
Line("public Vector2 Pivot { get; set; }");
Line("public Rectangle Tile { get; set; }");
Blank();
Line("public Color SmartColor { get; set; }");

FieldDefinition[] fields = entityDefinition.FieldDefs;
GenFieldDefs(fields);
}

void GenFieldDefs(FieldDefinition[] fields)
{
if (fields.Length > 0)
{
Blank();
}

foreach (FieldDefinition value in fields)
{
string type = Converter.ConvertFieldDefinitionTypes(value._Type, Options.PointAsVector2);

if (value.CanBeNull)
{
type += "?";
}

Line($"public {type} {value.Identifier} {{ get; set; }}");
}
}

void GenCustomFieldDefData(FieldDefinition[] fieldDefs)
{
if (fieldDefs.Length > 0)
{
Blank();
}

foreach (FieldDefinition field in fieldDefs)
{
if (field.DefaultOverride == null)
{
Line("public string Identifier { get; set; }");
Line("public System.Guid Iid { get; set; }");
Line("public int Uid { get; set; }");
Line("public Vector2 Position { get; set; }");
Line("public Vector2 Size { get; set; }");
Line("public Vector2 Pivot { get; set; }");
Line("public Rectangle Tile { get; set; }");
Blank();
Line("public Color SmartColor { get; set; }");
Blank();
continue;
}

foreach (FieldDefinition value in fields)
if (field.DefaultOverride.Params.ValueKind != JsonValueKind.Array)
{
string type = Converter.ConvertFieldDefinitionTypes(value._Type, Options.PointAsVector2);
continue;
}

JsonElement defaultValue = field.DefaultOverride.Params.EnumerateArray().First();

if (field._Type.Contains("Enum"))
{
string enumName = field._Type.Replace("LocalEnum.", "");
string value = defaultValue.GetString();
string enumValue = $"{enumName}.{value}";

Line($"entity.{field.Identifier} = {enumValue};");
}

switch (field._Type)
{
case Field.IntType:
Line($"{field.Identifier} = {defaultValue.GetInt32()},");
break;

case Field.FloatType:
Line($"{field.Identifier} = {defaultValue.GetSingle().ToString(CultureInfo.InvariantCulture)}f,");
break;

case Field.BoolType:
Line($"{field.Identifier} = {defaultValue.GetBoolean().ToString().ToLower()},");
break;

if (value.CanBeNull)
case Field.StringType:
Line($"{field.Identifier} = {defaultValue.GetRawText()},");
break;

case Field.FilePathType:
Line($"{field.Identifier} = {defaultValue.GetString()},");
break;

case Field.TileType:
string[] rectValues = defaultValue.GetString()!.Split(',');
int x = int.Parse(rectValues[0]);
int y = int.Parse(rectValues[1]);
int width = int.Parse(rectValues[2]);
int height = int.Parse(rectValues[3]);
int tilesetUid = (int)field.TilesetUid!;
TilesetRectangle finalRect = new()
{
type += "?";
}
X = x,
Y = y,
W = width,
H = height,
TilesetUid = tilesetUid
};
GenTilesetRectangle(field.Identifier, finalRect);
break;

Line($"public {type} {value.Identifier} {{ get; set; }}");
case Field.ColorType:
int colorValue = defaultValue.GetInt32();
int r = (colorValue >> 16) & 0xFF;
int g = (colorValue >> 8) & 0xFF;
int b = colorValue & 0xFF;
Line($"{field.Identifier} = new Color({r}, {g}, {b}, {1}),");
break;
}
}
EndBlock();
Line("#pragma warning restore");
}

Output(folder, identifier);
void GenHeaders()
{
Line($"namespace {Options.Namespace};");
Blank();
Line("// This file was automatically generated, any modifications will be lost!");
Line("#pragma warning disable");
Blank();
Line("using LDtk;");
Line("using Microsoft.Xna.Framework;");
Blank();
}

void GenTilesetRectangle(string identifier, TilesetRectangle rect)
{
Line($"{identifier} = new TilesetRectangle()");
StartBlock();
{
Line($"X = {rect.X},");
Line($"Y = {rect.Y},");
Line($"W = {rect.W},");
Line($"H = {rect.H}");
}
EndBlockSeparator();
}
}
9 changes: 9 additions & 0 deletions LDtk.Example/Entry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ protected override void Initialize()
_ = renderer.PrerenderLevel(world.Levels[i]);
}

// Default value instance example
var prefab = Enemy.Default();
prefab.Wander = new Vector2[] { Vector2.One * 180, Vector2.One * 120 };
enemies.Add(new EnemyEntity(prefab, spriteSheet, renderer));

var prefab2 = Enemy.Default();
prefab2.Wander = new Vector2[] { Vector2.One * 200, Vector2.One * 100 };
enemies.Add(new EnemyEntity(prefab2, spriteSheet, renderer));

Gun_Pickup gunData = world.GetEntity<Gun_Pickup>();
gun = new GunEntity(gunData, spriteSheet, renderer);

Expand Down
2 changes: 1 addition & 1 deletion LDtk.Example/LDtkTypes/World/CustomLevelDataName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ namespace LDtkTypes;
#pragma warning disable

using LDtk;

using Microsoft.Xna.Framework;

public partial class CustomLevelDataName
{

public float Float { get; set; }
public TilesetRectangle[] Tile { get; set; }
public string? Multilines { get; set; }
Expand Down
19 changes: 18 additions & 1 deletion LDtk.Example/LDtkTypes/World/Entities/Enemy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,28 @@ namespace LDtkTypes;
#pragma warning disable

using LDtk;

using Microsoft.Xna.Framework;

public partial class Enemy : ILDtkEntity
{
public static Enemy Default() => new()
{
Identifier = "Enemy",
Uid = 98,
Size = new Vector2(16f, 16f),
Pivot = new Vector2(0.5f, 0.5f),
Tile = new TilesetRectangle()
{
X = 16,
Y = 16,
W = 16,
H = 16
},
SmartColor = new Color(255, 107, 25, 255),

Color = new Color(166, 80, 80, 1),
};

public string Identifier { get; set; }
public System.Guid Iid { get; set; }
public int Uid { get; set; }
Expand Down
18 changes: 16 additions & 2 deletions LDtk.Example/LDtkTypes/World/Entities/Gun_Pickup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,26 @@ namespace LDtkTypes;
#pragma warning disable

using LDtk;

using Microsoft.Xna.Framework;

public partial class Gun_Pickup : ILDtkEntity
{
public static Gun_Pickup Default() => new()
{
Identifier = "Gun_Pickup",
Uid = 107,
Size = new Vector2(16f, 16f),
Pivot = new Vector2(0.5f, 1f),
Tile = new TilesetRectangle()
{
X = 0,
Y = 16,
W = 16,
H = 16
},
SmartColor = new Color(75, 224, 96, 255),
};

public string Identifier { get; set; }
public System.Guid Iid { get; set; }
public int Uid { get; set; }
Expand All @@ -18,6 +33,5 @@ public partial class Gun_Pickup : ILDtkEntity
public Rectangle Tile { get; set; }

public Color SmartColor { get; set; }

}
#pragma warning restore
Loading