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
TilesheetRegistry.cs
1using System.Collections.Immutable;
4using Microsoft.Extensions.Logging;
5using SkiaSharp;
6
8
12public sealed class TilesheetRegistry : IDisposable
13{
14 private readonly object _gate = new();
15 private readonly Dictionary<string, Tilesheet> _sheets = new(StringComparer.Ordinal);
16
17 // --- Singleton setup ---
18 private static readonly Lazy<TilesheetRegistry> _instance =
19 new(() => new TilesheetRegistry());
20
25 public static TilesheetRegistry Instance => _instance.Value;
26
27 // Private ctor ensures no one else can new this up
28 private TilesheetRegistry()
29 { }
30
40 internal void Register(Tilesheet sheet, bool disposeReplaced = true)
41 {
42 if (sheet is null)
43 {
44 Engine.Logger.LogError("TilesheetRegistry: Attempt to register a null Tilesheet.");
45 return;
46 }
47
48 Tilesheet? replaced = null;
49
50 lock (_gate)
51 {
52 if (_sheets.TryGetValue(sheet.Name, out var existing) && !ReferenceEquals(existing, sheet))
53 {
54 _sheets[sheet.Name] = sheet;
55 replaced = existing;
56 }
57 else
58 {
59 _sheets[sheet.Name] = sheet;
60 }
61
62 // Avoid duplicate subscriptions if the same instance is registered again.
63 sheet.Disposed -= OnTilesheetDisposed;
64 sheet.Disposed += OnTilesheetDisposed;
65 }
66
67 if (replaced is not null)
68 {
69 replaced.Disposed -= OnTilesheetDisposed;
70
71 if (disposeReplaced)
72 replaced.Dispose();
73 }
74 }
75
87 public bool TryGet(string name, out Tilesheet? sheet)
88 {
89 if (name is null)
90 {
91 Engine.Logger.LogWarning("TilesheetRegistry: Attempt to look up a null name.");
92 sheet = null;
93 return false;
94 }
95
96 lock (_gate)
97 return _sheets.TryGetValue(name, out sheet!);
98 }
99
109 public Tilesheet? GetOrNull(string name)
110 {
111 return TryGet(name, out var s) ? s : null;
112 }
113
126 public Tilesheet this[string name]
127 {
128 get
129 {
130 if (name is null)
131 throw new ArgumentNullException(nameof(name));
132
133 lock (_gate)
134 {
135 if (_sheets.TryGetValue(name, out var sheet))
136 return sheet;
137
138 throw new KeyNotFoundException($"Tilesheet with name '{name}' was not found in the registry.");
139 }
140 }
141 }
142
152 public bool Remove(string name, bool dispose = false)
153 {
154 if (name is null)
155 {
156 Engine.Logger.LogWarning("TilesheetRegistry: Attempt to remove a null name.");
157 return false;
158 }
159
160 Tilesheet? removed = null;
161
162 lock (_gate)
163 {
164 if (!_sheets.TryGetValue(name, out removed))
165 return false;
166
167 _sheets.Remove(name);
168 }
169
170 removed.Disposed -= OnTilesheetDisposed;
171
172 if (dispose)
173 removed.Dispose();
174
175 return true;
176 }
177
189 internal bool Remove(string name, Tilesheet expected, bool dispose = false)
190 {
191 if (name is null)
192 {
193 Engine.Logger.LogWarning("TilesheetRegistry: Attempt to remove a null name.");
194 return false;
195 }
196
197 if (expected is null)
198 {
199 Engine.Logger.LogWarning("TilesheetRegistry: Attempt to remove a null Tilesheet.");
200 return false;
201 }
202
203 Tilesheet? removed = null;
204
205 lock (_gate)
206 {
207 if (_sheets.TryGetValue(name, out var current) && ReferenceEquals(current, expected))
208 {
209 _sheets.Remove(name);
210 removed = current;
211 }
212 else
213 {
214 return false;
215 }
216 }
217
218 removed.Disposed -= OnTilesheetDisposed;
219
220 if (dispose)
221 removed.Dispose();
222
223 return true;
224 }
225
233 public void Clear()
234 {
235 List<Tilesheet> copy;
236
237 lock (_gate)
238 {
239 copy = _sheets.Values.ToList();
240 _sheets.Clear();
241 }
242
243 foreach (var ts in copy)
244 {
245 ts.Disposed -= OnTilesheetDisposed;
246 ts.Dispose();
247 }
248 }
249
257 public IReadOnlyList<string> Names
258 {
259 get
260 {
261 lock (_gate)
262 return _sheets.Keys.ToList();
263 }
264 }
265
274 public IImmutableDictionary<string, Tilesheet> GetAll()
275 {
276 lock (_gate)
277 {
278 return _sheets.ToImmutableDictionary(kv => kv.Key, kv => kv.Value, _sheets.Comparer);
279 }
280 }
281
289 public int Count
290 {
291 get
292 {
293 lock (_gate)
294 return _sheets.Count;
295 }
296 }
297
309 internal void OnTilesheetRenamed(string oldName, string newName, Tilesheet sheet, bool disposeReplaced = true)
310 {
311 if (oldName is null)
312 throw new ArgumentNullException(nameof(oldName));
313
314 if (newName is null)
315 throw new ArgumentNullException(nameof(newName));
316
317 if (sheet is null)
318 throw new ArgumentNullException(nameof(sheet));
319
320 Tilesheet? replaced = null;
321
322 lock (_gate)
323 {
324 // If old mapping points to this sheet, remove it.
325 if (_sheets.TryGetValue(oldName, out var existingAtOld) && ReferenceEquals(existingAtOld, sheet))
326 _sheets.Remove(oldName);
327
328 // If something else is already at newName, warn and replace.
329 if (_sheets.TryGetValue(newName, out var existingAtNew) && !ReferenceEquals(existingAtNew, sheet))
330 {
331 Engine.Logger.LogWarning(
332 "TilesheetRegistry: Renaming '{Old}'→'{New}' replaced a different registered Tilesheet instance.",
333 oldName, newName);
334 replaced = existingAtNew;
335 }
336
337 _sheets[newName] = sheet;
338 }
339
340 if (replaced is not null)
341 {
342 replaced.Disposed -= OnTilesheetDisposed;
343
344 if (disposeReplaced)
345 replaced.Dispose();
346 }
347 }
348
349 private void OnTilesheetDisposed(Tilesheet sheet)
350 {
351 if (sheet is null)
352 return;
353
354 Remove(sheet.Name, sheet, dispose: false);
355 }
356
360 public void Dispose()
361 {
362 Clear();
363 }
364
365 #region public shims to TilesheetFactory
366
373 public Tilesheet LoadFromBitmap(string name, SKBitmap bitmap)
374 {
375 var tilesheet = TilesheetFactory.FromBitmap(name, bitmap);
376 Register(tilesheet);
377 return tilesheet;
378 }
379
386 public Tilesheet LoadFromStream(string name, Stream stream)
387 {
388 var tilesheet = TilesheetFactory.FromStream(name, stream);
389 Register(tilesheet);
390 return tilesheet;
391 }
392
399 public Tilesheet LoadFromImageFile(string name, string imageFilePath)
400 {
401 var tilesheet = TilesheetFactory.FromImageFile(name, imageFilePath);
402 Register(tilesheet);
403 return tilesheet;
404 }
405
412 public Tilesheet LoadFromAssetsFile(AssetsFile assetsFile, string entryName)
413 {
414 var tilesheet = TilesheetFactory.FromAssetsFile(assetsFile, entryName);
415 Register(tilesheet);
416 return tilesheet;
417 }
418
424 public Tilesheet LoadFromDefinitionFile(string gtsPath)
425 {
426 var tilesheet = TilesheetFactory.FromDefinitionFile(gtsPath);
427 Register(tilesheet);
428 return tilesheet;
429 }
430
437 public Tilesheet LoadFromDefinition(TilesheetDefinition definition, string? baseDirectory = null)
438 {
439 var tilesheet = TilesheetFactory.FromDefinition(definition, baseDirectory);
440 Register(tilesheet);
441 return tilesheet;
442 }
443
450 public Tilesheet LoadFromDefinitionAsset(AssetsFile assetsFile, string gtsEntryName)
451 {
452 var tilesheet = TilesheetFactory.FromDefinitionAsset(assetsFile, gtsEntryName);
453 Register(tilesheet);
454
455 return tilesheet;
456 }
457
458 #endregion public shims to TilesheetFactory
459}
Represents an asset file used by the engine, providing functionality to load, manage,...
Definition AssetsFile.cs:18
Represents the root definition of a tilesheet in the GTS (Gondwana Tilesheet) file format.
Tilesheet LoadFromDefinition(TilesheetDefinition definition, string? baseDirectory=null)
Creates a new tilesheet from a tilesheet definition object and registers it in the registry.
Tilesheet LoadFromDefinitionFile(string gtsPath)
Creates a new tilesheet from a GTS definition file and registers it in the registry.
bool TryGet(string name, out Tilesheet? sheet)
Attempts to retrieve a Tilesheet by its name from the registry.
int Count
Gets the number of tilesheets currently registered in the registry.
static TilesheetRegistry Instance
Gets the singleton instance of the TilesheetRegistry.
void Clear()
Removes all tilesheets from the registry and disposes them.
Tilesheet LoadFromImageFile(string name, string imageFilePath)
Creates a new tilesheet from an image file and registers it in the registry.
bool Remove(string name, bool dispose=false)
Removes the tilesheet with the specified name from the collection.
Tilesheet LoadFromAssetsFile(AssetsFile assetsFile, string entryName)
Creates a new tilesheet from an entry in an assets file and registers it in the registry.
Tilesheet LoadFromBitmap(string name, SKBitmap bitmap)
Creates a new tilesheet from an existing SKBitmap and registers it in the registry.
Tilesheet LoadFromDefinitionAsset(AssetsFile assetsFile, string gtsEntryName)
Creates a new tilesheet from a GTS definition stored as an entry in an assets file and registers it i...
void Dispose()
Releases all resources used by the TilesheetRegistry by clearing and disposing all registered tileshe...
Tilesheet? GetOrNull(string name)
Retrieves a Tilesheet by its name from the registry, or null if not found.
Tilesheet LoadFromStream(string name, Stream stream)
Creates a new tilesheet from a stream and registers it in the registry.
IReadOnlyList< string > Names
Gets a read-only list of all tilesheet names currently registered in the registry.
IImmutableDictionary< string, Tilesheet > GetAll()
Gets an immutable snapshot of all registered tilesheets as a dictionary.
Represents a tilesheet image and metadata for rendering tiles.
Definition Tilesheet.cs:14
void Dispose()
Releases the resources owned by this instance.
Definition Tilesheet.cs:554
Represents the core game engine singleton responsible for managing the main update loop,...
Definition Engine.cs:36
static ILogger< Engine > Logger
Gets the logger instance used by the engine for diagnostic and informational messages.
Definition Engine.cs:59