Gondwana Game Engine Development (master) - 2.6.1
Gondwana is a cross-platform 2.5D game and rendering engine written in C#/.NET 8. It provides fine-grained control over rendering, timing, and scene composition, with built-in support for parallax, z-ordering, pixel overhang, collision detection, and particle effects. Gondwana targets desktop and web platforms using SkiaSharp for graphics and pluggable audio backends for desktop and browser targets.
Loading...
Searching...
No Matches
TilesheetDefinitionValidator.cs
2
4
6public static class TilesheetDefinitionValidator
7{
13 public static IReadOnlyList<string> Validate(TilesheetDefinition definition, int? imageWidth = null, int? imageHeight = null)
14 {
15 ArgumentNullException.ThrowIfNull(definition);
16 var errors = new List<string>();
17 var names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
18 foreach (var region in definition.Regions ?? [])
19 {
20 if (region is null) { errors.Add("Regions contains a null entry."); continue; }
21 var label = $"Region '{region.Name}'";
22 if (string.IsNullOrWhiteSpace(region.Name)) errors.Add($"{label}: name is empty.");
23 if (!names.Add(region.Name)) errors.Add($"{label}: duplicate name.");
24 if (region.Area.Width <= 0 || region.Area.Height <= 0 || region.TileSize.Width <= 0 || region.TileSize.Height <= 0)
25 {
26 errors.Add($"{label}: area and tile dimensions must be positive.");
27 continue;
28 }
29 if (region.Area.X < 0 || region.Area.Y < 0 ||
30 (imageWidth.HasValue && (long)region.Area.X + region.Area.Width > imageWidth) ||
31 (imageHeight.HasValue && (long)region.Area.Y + region.Area.Height > imageHeight)) errors.Add($"{label}: area is outside the source image.");
32 if (Negative(region.TilePadding)) errors.Add($"{label}: tile padding cannot be negative.");
33 if (region.RegionMargin.Left < 0 || region.RegionMargin.Top < 0 ||
34 region.RegionMargin.Right < -region.TilePadding.Right ||
35 region.RegionMargin.Bottom < -region.TilePadding.Bottom)
36 errors.Add($"{label}: leading margins cannot be negative; trailing margins may only cancel trailing tile padding.");
37 if (Negative(region.Overhang)) errors.Add($"{label}: overhang cannot be negative.");
38 var (columns, rows) = GridSize(region);
39 if (columns <= 0 || rows <= 0) errors.Add($"{label}: layout contains no complete frames.");
40 CheckCollision(region.CollisionAdjust, region, label, errors);
41 if (!Enum.IsDefined(region.CollisionType)) errors.Add($"{label}: unknown collision type.");
42 var coordinates = new HashSet<(int, int)>();
43 foreach (var frame in region.Frames ?? [])
44 {
45 if (frame is null) { errors.Add($"{label}: null frame metadata."); continue; }
46 var frameLabel = $"{label}, frame ({frame.XTile}, {frame.YTile})";
47 if (!coordinates.Add((frame.XTile, frame.YTile))) errors.Add($"{frameLabel}: duplicate frame metadata.");
48 if (frame.XTile < 0 || frame.YTile < 0 || frame.XTile >= columns || frame.YTile >= rows) errors.Add($"{frameLabel}: coordinates are outside the frame grid.");
49 if (frame.CollisionAdjust is { } adjust) CheckCollision(adjust, region, frameLabel, errors);
50 if (frame.CollisionType is { } type && !Enum.IsDefined(type)) errors.Add($"{frameLabel}: unknown collision type.");
51 }
52 }
53 return errors;
54 }
55
59 public static (long Columns, long Rows) GridSize(TilesheetRegionDefinition region)
60 {
61 long width = (long)region.TileSize.Width + region.TilePadding.Left + region.TilePadding.Right;
62 long height = (long)region.TileSize.Height + region.TilePadding.Top + region.TilePadding.Bottom;
63 return (width <= 0 ? 0 : Math.Max(0, ((long)region.Area.Width - region.RegionMargin.Left - region.RegionMargin.Right) / width),
64 height <= 0 ? 0 : Math.Max(0, ((long)region.Area.Height - region.RegionMargin.Top - region.RegionMargin.Bottom) / height));
65 }
66
67 private static bool Negative(Spacing spacing) => spacing.Left < 0 || spacing.Right < 0 || spacing.Top < 0 || spacing.Bottom < 0;
68 private static void CheckCollision(CollisionAdjust adjust, TilesheetRegionDefinition region, string label, List<string> errors)
69 {
70 // Negative adjustments intentionally expand collision bounds. Only inverted
71 // geometry is impossible; zero-sized collision areas may disable collisions.
72 if ((long)adjust.Left + adjust.Right > region.TileSize.Width || (long)adjust.Top + adjust.Bottom > region.TileSize.Height)
73 errors.Add($"{label}: collision adjustments invert the frame's collision rectangle.");
74 }
75}
record struct Spacing([property:JsonProperty("left")] int Left, [property:JsonProperty("top")] int Top, [property:JsonProperty("right")] int Right, [property:JsonProperty("bottom")] int Bottom)
Represents dimensions in pixels when spacing Tilesheets.
Definition Spacing.cs:12
int Top
Gets or sets the number of pixels by which to inset the top edge.
int Left
Gets or sets the number of pixels by which to inset the left edge.
int Bottom
Gets or sets the number of pixels by which to inset the bottom edge.
int Right
Gets or sets the number of pixels by which to inset the right edge.