From 2207116d0ac91bcc7e57d52a726e4ae055033138 Mon Sep 17 00:00:00 2001 From: REDCODE Date: Sun, 14 Jun 2026 21:00:14 +0200 Subject: [PATCH] spart to data --- SlaveEngine.Assets/Asset.cs | 4 +- SlaveEngine.Assets/Models/PartAsset.cs | 14 ++ SlaveEngine.Assets/Models/PathData.cs | 11 ++ SlaveEngine.Assets/Models/PathGroup.cs | 14 ++ SlaveEngine.Assets/Models/VariantAsset.cs | 7 + .../Primitives/BezierCommand.cs | 6 + SlaveEngine.Assets/Primitives/CommandType.cs | 8 ++ SlaveEngine.Assets/Primitives/Joint.cs | 6 + .../Processors/PartProcessor.cs | 120 ++++++++++++++++++ SlaveEngine.Assets/SlaveEngine.Assets.csproj | 4 + 10 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 SlaveEngine.Assets/Models/PartAsset.cs create mode 100644 SlaveEngine.Assets/Models/PathData.cs create mode 100644 SlaveEngine.Assets/Models/PathGroup.cs create mode 100644 SlaveEngine.Assets/Models/VariantAsset.cs create mode 100644 SlaveEngine.Assets/Primitives/BezierCommand.cs create mode 100644 SlaveEngine.Assets/Primitives/CommandType.cs create mode 100644 SlaveEngine.Assets/Primitives/Joint.cs create mode 100644 SlaveEngine.Assets/Processors/PartProcessor.cs diff --git a/SlaveEngine.Assets/Asset.cs b/SlaveEngine.Assets/Asset.cs index 93baf03..187fc51 100644 --- a/SlaveEngine.Assets/Asset.cs +++ b/SlaveEngine.Assets/Asset.cs @@ -1,6 +1,6 @@ namespace SlaveEngine.Assets; public abstract class Asset { - public Guid Guid { get; private set; } - public AssetFileInfo FileInfo { get; private set; } + public Guid Guid { get; init; } + public AssetFileInfo FileInfo { get; init; } } \ No newline at end of file diff --git a/SlaveEngine.Assets/Models/PartAsset.cs b/SlaveEngine.Assets/Models/PartAsset.cs new file mode 100644 index 0000000..c37b446 --- /dev/null +++ b/SlaveEngine.Assets/Models/PartAsset.cs @@ -0,0 +1,14 @@ +using SlaveEngine.Assets.Primitives; + +namespace SlaveEngine.Assets.Models; + +public sealed class PartAsset : Asset { + public required string Id { get; init; } + public required string OriginalKey { get; init; } + public required string Resource { get; init; } + public int MorphX { get; init; } + public int MorphY { get; init; } + public required string[] Fields { get; init; } + public required Joint[] Joints { get; init; } + public required VariantAsset[] Variants { get; init; } +} diff --git a/SlaveEngine.Assets/Models/PathData.cs b/SlaveEngine.Assets/Models/PathData.cs new file mode 100644 index 0000000..6ce536b --- /dev/null +++ b/SlaveEngine.Assets/Models/PathData.cs @@ -0,0 +1,11 @@ +using SlaveEngine.Assets.Primitives; + +namespace SlaveEngine.Assets.Models; + +public sealed class PathData { + public required string Fill { get; init; } + public required string Stroke { get; init; } + public float StrokeWidth { get; init; } + public bool IsClosed { get; init; } + public required BezierCommand[] Commands { get; init; } +} diff --git a/SlaveEngine.Assets/Models/PathGroup.cs b/SlaveEngine.Assets/Models/PathGroup.cs new file mode 100644 index 0000000..bc6f746 --- /dev/null +++ b/SlaveEngine.Assets/Models/PathGroup.cs @@ -0,0 +1,14 @@ +namespace SlaveEngine.Assets.Models; + +public sealed class PathGroup { + public required string Name { get; init; } + public bool HasTransform { get; init; } + public float Tx { get; init; } + public float Ty { get; init; } + public float Angle { get; init; } + public float Sx { get; init; } + public float Sy { get; init; } + public float Bx { get; init; } + public float By { get; init; } + public required PathData[] Paths { get; init; } +} diff --git a/SlaveEngine.Assets/Models/VariantAsset.cs b/SlaveEngine.Assets/Models/VariantAsset.cs new file mode 100644 index 0000000..de27ad6 --- /dev/null +++ b/SlaveEngine.Assets/Models/VariantAsset.cs @@ -0,0 +1,7 @@ +namespace SlaveEngine.Assets.Models; + +public sealed class VariantAsset { + public int X { get; init; } + public int Y { get; init; } + public required PathGroup[] Groups { get; init; } +} diff --git a/SlaveEngine.Assets/Primitives/BezierCommand.cs b/SlaveEngine.Assets/Primitives/BezierCommand.cs new file mode 100644 index 0000000..de81815 --- /dev/null +++ b/SlaveEngine.Assets/Primitives/BezierCommand.cs @@ -0,0 +1,6 @@ +namespace SlaveEngine.Assets.Primitives; + +public readonly struct BezierCommand { + public CommandType Type { get; init; } + public float[] Args { get; init; } +} diff --git a/SlaveEngine.Assets/Primitives/CommandType.cs b/SlaveEngine.Assets/Primitives/CommandType.cs new file mode 100644 index 0000000..a74b3d3 --- /dev/null +++ b/SlaveEngine.Assets/Primitives/CommandType.cs @@ -0,0 +1,8 @@ +namespace SlaveEngine.Assets.Primitives; + +public enum CommandType : byte { + MoveTo = 0, + LineTo = 1, + CubicBezierTo = 2, + Close = 3 +} diff --git a/SlaveEngine.Assets/Primitives/Joint.cs b/SlaveEngine.Assets/Primitives/Joint.cs new file mode 100644 index 0000000..117403f --- /dev/null +++ b/SlaveEngine.Assets/Primitives/Joint.cs @@ -0,0 +1,6 @@ +namespace SlaveEngine.Assets.Primitives; + +public readonly struct Joint { + public float X { get; init; } + public float Y { get; init; } +} diff --git a/SlaveEngine.Assets/Processors/PartProcessor.cs b/SlaveEngine.Assets/Processors/PartProcessor.cs new file mode 100644 index 0000000..a2740a4 --- /dev/null +++ b/SlaveEngine.Assets/Processors/PartProcessor.cs @@ -0,0 +1,120 @@ +using System.Text; +using SlaveEngine.Assets.Models; +using SlaveEngine.Assets.Primitives; + +namespace SlaveEngine.Assets.Processors; + +[AssetProcessor(typeof(PartAsset), managedExtensions: [".spart"])] +public sealed class PartProcessor : AssetProcessor { + public override Asset Process(AssetFileInfo fileInfo, byte[] data) { + using var stream = new MemoryStream(data); + using var reader = new BinaryReader(stream); + + var magic = reader.ReadBytes(4); + if (magic[0] != 'S' || magic[1] != 'P' || magic[2] != 'R' || magic[3] != 'T') + throw new InvalidDataException("Invalid .spart file magic"); + + var version = reader.ReadInt32(); + if (version != 1) + throw new InvalidDataException($"Unsupported .spart version: {version}"); + + var id = ReadString(reader); + var originalKey = ReadString(reader); + var resource = ReadString(reader); + var morphX = reader.ReadInt32(); + var morphY = reader.ReadInt32(); + + var fieldCount = reader.ReadInt32(); + var fields = new string[fieldCount]; + for (var i = 0; i < fieldCount; i++) + fields[i] = ReadString(reader); + + var jointCount = reader.ReadInt32(); + var joints = new Joint[jointCount]; + for (var i = 0; i < jointCount; i++) + joints[i] = new Joint { X = reader.ReadSingle(), Y = reader.ReadSingle() }; + + var variantCount = reader.ReadInt32(); + var variants = new VariantAsset[variantCount]; + for (var v = 0; v < variantCount; v++) { + var vx = reader.ReadInt32(); + var vy = reader.ReadInt32(); + + var groupCount = reader.ReadInt32(); + var groups = new PathGroup[groupCount]; + for (var g = 0; g < groupCount; g++) { + var groupName = ReadString(reader); + var hasTransform = reader.ReadBoolean(); + float tx = 0, ty = 0, angle = 0, sx = 1, sy = 1, bx = 0, by = 0; + if (hasTransform) { + tx = reader.ReadSingle(); + ty = reader.ReadSingle(); + angle = reader.ReadSingle(); + sx = reader.ReadSingle(); + sy = reader.ReadSingle(); + bx = reader.ReadSingle(); + by = reader.ReadSingle(); + } + + var pathCount = reader.ReadInt32(); + var paths = new PathData[pathCount]; + for (var p = 0; p < pathCount; p++) { + var fill = ReadString(reader); + var stroke = ReadString(reader); + var strokeWidth = reader.ReadSingle(); + var isClosed = reader.ReadBoolean(); + + var cmdCount = reader.ReadInt32(); + var cmds = new BezierCommand[cmdCount]; + for (var c = 0; c < cmdCount; c++) { + var cmdType = (CommandType)reader.ReadByte(); + var argCount = reader.ReadInt32(); + var args = new float[argCount]; + for (var a = 0; a < argCount; a++) + args[a] = reader.ReadSingle(); + cmds[c] = new BezierCommand { Type = cmdType, Args = args }; + } + + paths[p] = new PathData { + Fill = fill, + Stroke = stroke, + StrokeWidth = strokeWidth, + IsClosed = isClosed, + Commands = cmds + }; + } + + groups[g] = new PathGroup { + Name = groupName, + HasTransform = hasTransform, + Tx = tx, Ty = ty, Angle = angle, + Sx = sx, Sy = sy, Bx = bx, By = by, + Paths = paths + }; + } + + variants[v] = new VariantAsset { + X = vx, Y = vy, Groups = groups + }; + } + + return new PartAsset { + Guid = Guid.NewGuid(), + FileInfo = fileInfo, + Id = id, + OriginalKey = originalKey, + Resource = resource, + MorphX = morphX, + MorphY = morphY, + Fields = fields, + Joints = joints, + Variants = variants + }; + } + + private static string ReadString(BinaryReader reader) { + var len = reader.ReadInt32(); + var bytes = reader.ReadBytes(len); + return Encoding.UTF8.GetString(bytes); + } +} diff --git a/SlaveEngine.Assets/SlaveEngine.Assets.csproj b/SlaveEngine.Assets/SlaveEngine.Assets.csproj index 3a63532..d2df1de 100644 --- a/SlaveEngine.Assets/SlaveEngine.Assets.csproj +++ b/SlaveEngine.Assets/SlaveEngine.Assets.csproj @@ -6,4 +6,8 @@ enable + + + +