10internal static class TilesheetFactory
12 #region factory methods
14 internal static Tilesheet FromBitmap(
string name, SKBitmap bitmap) =>
new(name, bitmap);
16 internal static Tilesheet FromStream(
string name, Stream stream) =>
new(name, stream);
18 internal static Tilesheet FromImageFile(
string name,
string imageFilePath) =>
new(name, imageFilePath);
20 internal static Tilesheet FromAssetsFile(AssetsFile assetsFile,
string entryName) =>
new(assetsFile, entryName);
22 internal static Tilesheet FromDefinitionFile(
string gtsPath)
24 if (
string.IsNullOrWhiteSpace(gtsPath))
25 throw new ArgumentException(
"GTS path must be a non-empty string.", nameof(gtsPath));
27 var fullPath = Path.GetFullPath(gtsPath);
28 if (!File.Exists(fullPath))
29 throw new FileNotFoundException($
"GTS file not found: {fullPath}", fullPath);
31 var definition = TilesheetDefinitionSerializer.Load(fullPath);
32 return FromDefinition(definition, Path.GetDirectoryName(fullPath));
36 string? baseDirectory =
null,
37 AssetsFile? defaultAssetsFile =
null)
39 ArgumentNullException.ThrowIfNull(definition);
41 var tilesheet = CreateTilesheet(
43 addDefaultRegion:
false,
47 foreach (var region
in definition.
Regions)
49 var runtimeRegion = tilesheet.AddRegion(
56 region.CollisionAdjust,
57 region.CollisionType);
61 foreach (var frame
in region.Frames ?? [])
63 if (frame.CollisionAdjust is { } adjust)
65 runtimeRegion.SetFrameCollisionAdjust(
71 if (frame.CollisionType is { } collisionType)
73 runtimeRegion.SetFrameCollisionType(
81 if (definition.
Mask is not
null)
93 tilesheet.ApplyPremultiplyAlpha();
96 tilesheet.DefinitionProvenance = definition.LoadStamp?.Materialized(definition,
97 () => TilesheetDefinitionSerializer.FromTilesheet(tilesheet));
101 internal static Tilesheet FromDefinitionAsset(AssetsFile assetsFile,
string gtsEntryName)
103 ArgumentNullException.ThrowIfNull(assetsFile);
105 if (
string.IsNullOrWhiteSpace(gtsEntryName))
107 throw new ArgumentException(
108 "GTS asset entry name must be a non-empty string.",
109 nameof(gtsEntryName));
112 using var stream = assetsFile.
Get(
AssetTypes.TilesheetDefinition, gtsEntryName);
116 throw new InvalidOperationException(
117 $
"Tilesheet definition asset '{gtsEntryName}' could not be found in AssetsFile '{assetsFile.SourcePath}'.");
120 var definition = TilesheetDefinitionSerializer.Load(stream);
122 definition.Source = TilesheetDefinitionSource.None();
123 if (!
string.IsNullOrWhiteSpace(assetsFile.
SourcePath))
125 definition.Source = TilesheetDefinitionSource.PackedDefinitionFile(
130 definition.LoadStamp =
new(definition, assetsFilePath: assetsFile.
SourcePath, entryName: gtsEntryName);
132 var baseDirectory =
string.IsNullOrWhiteSpace(assetsFile.
SourcePath)
134 : Path.GetDirectoryName(Path.GetFullPath(assetsFile.
SourcePath));
136 return FromDefinition(
139 defaultAssetsFile: assetsFile);
142 #endregion factory methods
144 #region private methods
146 private static Tilesheet CreateTilesheet(
148 bool addDefaultRegion,
149 string? baseDirectory =
null,
150 AssetsFile? defaultAssetsFile =
null)
152 var image = definition.Image
153 ??
throw new InvalidOperationException(
154 "TilesheetDefinition must specify an image source.");
156 ValidateImageDefinition(image, defaultAssetsFile);
158 if (!
string.IsNullOrWhiteSpace(image.FilePath))
160 return new Tilesheet(
162 ResolvePath(image.FilePath, baseDirectory),
166 AssetsFile assetsFile;
168 if (!
string.IsNullOrWhiteSpace(image.AssetsFilePath))
170 assetsFile = LoadExistingAssetsFile(
171 ResolvePath(image.AssetsFilePath, baseDirectory));
175 assetsFile = defaultAssetsFile!;
178 var tilesheet =
new Tilesheet(
180 image.AssetEntryName!,
185 tilesheet.Name = definition.
Name;
190 private static void ValidateImageDefinition(TilesheetImageDefinition image, AssetsFile? defaultAssetsFile)
192 var hasFilePath = !
string.IsNullOrWhiteSpace(image.
FilePath);
193 var hasAssetsFilePath = !
string.IsNullOrWhiteSpace(image.
AssetsFilePath);
194 var hasAssetEntryName = !
string.IsNullOrWhiteSpace(image.
AssetEntryName);
196 if (hasFilePath && (hasAssetsFilePath || hasAssetEntryName))
198 throw new InvalidOperationException(
199 "TilesheetDefinition image source is ambiguous. Image.FilePath cannot be combined with Image.AssetsFilePath or Image.AssetEntryName.");
202 if (hasAssetsFilePath && !hasAssetEntryName)
204 throw new InvalidOperationException(
205 "TilesheetDefinition image specifies an AssetsFilePath but does not specify an AssetEntryName.");
211 if (!hasAssetEntryName)
213 throw new InvalidOperationException(
214 "TilesheetDefinition must specify either Image.FilePath or Image.AssetEntryName.");
217 if (!hasAssetsFilePath && defaultAssetsFile is
null)
219 throw new InvalidOperationException(
220 "TilesheetDefinition image specifies an AssetEntryName but does not specify an AssetsFilePath, and no default AssetsFile was provided.");
224 private static AssetsFile LoadExistingAssetsFile(
string path)
226 if (
string.IsNullOrWhiteSpace(path))
227 throw new ArgumentException(
"Assets file path must be a non-empty string.", nameof(path));
229 var fullPath = Path.GetFullPath(path);
230 var loaded = AssetsFile.AllAssetsFiles.FirstOrDefault(file =>
231 !
string.IsNullOrWhiteSpace(file.SourcePath) &&
string.Equals(Path.GetFullPath(file.SourcePath), fullPath,
232 OperatingSystem.IsWindows() ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal));
233 if (loaded is not
null)
return loaded;
234 if (!File.Exists(fullPath))
235 throw new FileNotFoundException($
"Assets file not found: {fullPath}", fullPath);
237 return AssetsFile.LoadOrCreate(fullPath);
240 private static string ResolvePath(
string path,
string? baseDirectory)
242 if (Path.IsPathRooted(path) ||
string.IsNullOrWhiteSpace(baseDirectory))
245 return Path.GetFullPath(Path.Combine(baseDirectory, path));
248 #endregion private methods
string? SourcePath
Gets the archive's reconstructible origin, including an optional stream origin.
Stream? Get(AssetTypes type, string name)
Retrieves a stream for the specified asset type and name.
List< TilesheetRegionDefinition > Regions
Gets or sets the list of region definitions that define subdivisions within the tilesheet.
TilesheetMaskDefinition? Mask
Gets or sets the mask definition for color transparency, or null if no mask is applied.
string Name
Gets or sets the name of the tilesheet.
bool PremultiplyAlpha
Gets or sets a value indicating whether alpha should be premultiplied when loading the tilesheet imag...
string? AssetsFilePath
Gets or sets the path to the assets file containing the tilesheet image.
string? AssetEntryName
Gets or sets the name of the specific entry within an assets file that contains the tilesheet image.
string? FilePath
Gets or sets the direct file path to the tilesheet image.
byte Tolerance
Gets or sets the tolerance value for color matching, allowing colors within a range to be considered ...
byte Alpha
Gets or sets the alpha (opacity) component of the mask color (0-255).
byte Blue
Gets or sets the blue component of the mask color (0-255).
byte Red
Gets or sets the red component of the mask color (0-255).
byte Green
Gets or sets the green component of the mask color (0-255).
AssetTypes
Defines the types of assets that can be stored and managed by the engine.
@ TilesheetDefinition
Represents a tilesheet definition file (.gts) for Gondwana.Drawing.Tilesheets.GTS....