@bscotch/stitch
Version:
Stitch: The GameMaker Studio 2 Asset Pipeline Development Kit.
158 lines • 5.43 kB
JavaScript
import { assert } from '../../../utility/errors.js';
import path from '../../../utility/paths.js';
export class Gms2ResourceBase {
resourceRoot;
io;
data;
storage;
_yyData;
/**
* Create a resource using either the direct YYP-sourced object
* -or- the name of the resource
*/
constructor(resourceRoot, data, io) {
this.resourceRoot = resourceRoot;
this.io = io;
this.storage = io.storage;
if (typeof data == 'string') {
const name = data;
this.data = {
id: { name, path: `${this.resourceRoot}/${name}/${name}.yy` },
order: 0,
};
}
else {
this.data = { ...data };
}
this.io.plugins.forEach((plugin) => plugin.afterResourceCreated?.(this));
}
get yyData() {
this._yyData ??= this.storage.readJsonSync(this.yyPathAbsolute);
return this._yyData;
}
get id() {
return { ...this.data.id };
}
get name() {
return this.data.id.name;
}
/** The type, named by the root folder containing the resource type's .yy files. */
get type() {
return this.resourceRoot;
}
/** The folder containing this resource (as viewed via the IDE) */
get folder() {
return this.yyData.parent.path.replace(/^folders\/(.*)\.yy$/, '$1');
}
/**
* Set the parent folder for this resource. Note that you may
* run into errors if this folder doesn't already exist.
*/
set folder(folderName) {
assert(!['', '/', '\\'].includes(folderName), `Root level folder assignments are not allowed.`);
this.yyData.parent.name = folderName;
this.yyData.parent.path = `folders/${folderName}.yy`;
this.save();
}
get resourceType() {
return this.yyData.resourceType;
}
get yyDirRelative() {
return path.dirname(this.yyPathRelative);
}
get yyDirAbsolute() {
return path.dirname(this.yyPathAbsolute);
}
get yyPathRelative() {
return this.data.id.path;
}
get yyPathAbsolute() {
return path.join(this.storage.yypDirAbsolute, this.data.id.path);
}
/** The list of configurations that apply to this resource in some way. */
get configNames() {
return Object.keys(this.yyData.ConfigValues || {});
}
/**
* Return the paths of all files that collectively make up this
* resource. In *all cases* that inclues a .yy file. The rest is
* resourceType-specific.
*/
get filePathsAbsolute() {
return this.storage.listPathsSync(this.yyDirAbsolute);
}
get filePathsRelative() {
return this.filePathsAbsolute.map((filePath) => path.relative(path.join(this.yyDirAbsolute, '..', '..'), filePath));
}
/**
* Check the name of this Resource against a known name.
* **Important**: The check is *case-insensitive*, returning
* `false` if the name is a complete mismatch and an object
* with the type of match if it at least matches insensitively.
*
* In other words, if the result is *truthy* it's at least a
* case-insensitive match.
*/
isNamed(name) {
const isMatch = this.name.toLowerCase() === name.toLowerCase();
if (!isMatch) {
return false;
}
return {
/** Matches at least case-insensitively. */
isMatch,
/** Exactly matches, including case. */
isExactMatch: this.name === name,
};
}
/**
* Check to see if this resource is in a given folder (recursively).
* For example, for sprite 'sprites/menu/title/logo' both
* 'sprites' and 'sprites/menu' would return `true`.
*/
isInFolder(folderPath, recursive = true) {
folderPath = folderPath.replace(/\/$/, '');
if (!this.folder.startsWith(folderPath)) {
return false;
}
else if (this.folder == folderPath) {
return true;
}
else if (recursive && this.folder.replace(folderPath, '')[0] == '/') {
// Then this.folder is a subdirectory of folderPath
return true;
}
return false;
}
/** Resources typically have one or more companion files
* alongside their .yy file. They often have the same name
* as the resource, but generally have different extension.
* @param name If not provided, defaults to the resource's name
*/
dataFilePathAbsolute(extension, name) {
const basename = `${name || this.name}.${extension}`;
return path.join(this.yyDirAbsolute, basename);
}
/**
* Save any changes made to this resource to disk
* in its `.yy` file.
*
* If `result` is passed in, the `changed` field will
* be updated to reflect whether any changes were made.
*/
save(result) {
// Save the YY data
const changed = this.storage.writeYySync(this.yyPathAbsolute, this.yyData, this.resourceRoot, this.io.project.yypRaw);
if (result)
result.changed = changed;
return this;
}
async replaceYyFile(yyData) {
await this.storage.writeYy(this.yyPathAbsolute, yyData, this.resourceRoot, this.io.project.yypRaw);
return this;
}
toJSON() {
return { ...this.data };
}
}
//# sourceMappingURL=Gms2ResourceBase.js.map