Pixel-Composer/scripts/BBMOD_Resouce/BBMOD_Resouce.gml
2023-04-23 16:47:33 +02:00

286 lines
6.7 KiB
Text

/// @func BBMOD_Resource()
///
/// @extends BBMOD_Class
///
/// @desc Base struct for all BBMOD resources.
function BBMOD_Resource()
: BBMOD_Class() constructor
{
BBMOD_CLASS_GENERATED_BODY;
static Class_destroy = destroy;
/// @var {Bool} If `false` then the resource has not been loaded yet.
/// @readonly
IsLoaded = false;
/// @var {String} The path to the file from which was the resource
/// loaded, or `undefined` if the resource does not come from a file.
/// @readonly
Path = undefined;
/// @var {Bool] If `true` then the resource is persistent and it is not
/// destroyed when method `free` is used. Default value is `false`.
/// @see BBMOD_Resource.free
/// @see BBMOD_ResourceManager.free
Persistent = false;
/// @var {Struct.BBMOD_ResourceManager} The resource manager that loaded
/// the resource.
/// @private
__manager = undefined;
/// @var {Real} Number of resource "lives". If it reaches 0, the resource is
/// destroyed.
/// @private
__counter = 1;
/// @func from_buffer(_buffer)
///
/// @desc Loads the resource from a buffer.
///
/// @param {Id.Buffer} _buffer The buffer to load the resource from.
///
/// @return {Struct.BBMOD_Resource} Returns `self`.
///
/// @throws {BBMOD_NotImplementedException} If the method is not implemented.
static from_buffer = function (_buffer) {
throw new BBMOD_NotImplementedException();
// When implementing this method, do not forget to set IsLoaded to true!
//return self;
};
/// @func to_buffer(_buffer)
///
/// @desc Writes the resource to a buffer.
///
/// @param {Id.Buffer} _buffer The buffer to write the resource to.
///
/// @return {Struct.BBMOD_Resource} Returns `self`.
///
/// @throws {BBMOD_NotImplementedException} If the method is not implemented.
static to_buffer = function (_buffer) {
throw new BBMOD_NotImplementedException();
// When implementing this method, do not forget to set IsLoaded to true!
//return self;
};
/// @func check_file(_file[, _sha1[, _callback]])
///
/// @param {String} _file
/// @param {String} [_sha1]
/// @param {Function} [_callback]
///
/// @return {Bool}
///
/// @throws {BBMOD_Exception}
///
/// @private
static check_file = function (_file, _sha1=undefined, _callback=undefined) {
var _err = undefined;
if (!file_exists(_file))
{
_err = new BBMOD_Exception("File " + _file + " does not exist!");
}
else if (_sha1 != undefined)
{
if (sha1_file(_file) != _sha1)
{
_err = new BBMOD_Exception("SHA1 does not match!");
}
}
if (_err != undefined)
{
if (_callback != undefined)
{
_callback(_err);
return false;
}
else
{
throw _err;
}
}
return true;
};
/// @func from_file(_file[, _sha1])
///
/// @desc Loads the resource from a file.
///
/// @param {String} _file The path to the file.
/// @param {String} [_sha1] Expected SHA1 of the file. If the actual one
/// does not match with this, then the resource will not be loaded. Use
/// `undefined` if you do not want to check the SHA1 of the file.
///
/// @return {Struct.BBMOD_Resource} Returns `self`.
///
/// @throws {BBMOD_Exception} If loading fails.
static from_file = function (_file, _sha1=undefined) {
Path = _file;
check_file(_file, _sha1);
var _buffer = buffer_load(_file);
buffer_seek(_buffer, buffer_seek_start, 0);
try
{
from_buffer(_buffer);
buffer_delete(_buffer);
}
catch (_e)
{
buffer_delete(_buffer);
throw _e;
}
return self;
};
/// @func to_file(_file)
///
/// @desc Writes a resource to a file.
///
/// @param {String} _file The path to the file.
///
/// @return {Struct.BBMOD_Resource} Returns `self`.
///
/// @throws {BBMOD_Exception} If saving fails.
static to_file = function (_file) {
var _buffer = buffer_create(1, buffer_grow, 1);
var _dirname = filename_dir(_file);
if (!directory_exists(_dirname))
{
directory_create(_dirname);
}
try
{
to_buffer(_buffer);
buffer_save(_buffer, _file);
buffer_delete(_buffer);
}
catch (_e)
{
buffer_delete(_buffer);
throw _e;
}
return self;
};
/// @func from_file_async(_file[, _sha1[, _callback]])
///
/// @desc Asynchronnously loads the resource from a file.
///
/// @param {String} _file The path to the file.
/// @param {String} [_sha1] Expected SHA1 of the file. If the actual
/// one does not match with this, then the resource will not be loaded. Use
/// `undefined` if you do not want to check the SHA1 of the file.
/// @param {Function} [_callback] The function to execute when the
/// resource is loaded or if an error occurs or. It must take the error as the
/// first argument and the resource as the second argument. If no error occurs,
/// then `undefined` is passed. Defaults to `undefined`.
///
/// @return {Struct.BBMOD_Resource} Returns `self`.
///
/// @note Do not forget to call {@link bbmod_async_save_load_update} and
/// {@link bbmod_async_image_loaded_update} in appropriate events when using
/// asynchronnous loading! You can also use {@link BBMOD_ResourceManager} for
/// unified asynchronnous loading of resources.
static from_file_async = function (_file, _sha1=undefined, _callback=undefined) {
Path = _file;
if (!check_file(_file, _sha1, _callback ?? bbmod_empty_callback))
{
return self;
}
var _resource = self;
var _struct = {
Resource: _resource,
Callback: _callback,
};
bbmod_buffer_load_async(_file, method(_struct, function (_err, _buffer) {
var _callback = Callback;
if (_err)
{
if (_callback != undefined)
{
_callback(_err, Resource);
}
return;
}
try
{
Resource.from_buffer(_buffer);
}
catch (_err2)
{
if (_callback != undefined)
{
_callback(_err2, Resource);
}
return;
}
if (_callback != undefined)
{
_callback(undefined, Resource);
}
}));
return self;
};
/// @func ref()
///
/// @desc Retrieves a reference to the resource.
///
/// @return {Struct.BBMOD_Resource} Returns `self`.
static ref = function () {
gml_pragma("forceinline");
if (!Persistent)
{
++__counter;
}
return self;
};
/// @func free()
///
/// @desc Releases a reference to the resource.
///
/// @return {Bool} Returns `true` if there are no other references to the
/// resource and the resource is destroyed.
///
/// @note This does not destroy the resource if it is persistent!
///
/// @see BBMOD_Resource.Persistent
static free = function () {
gml_pragma("forceinline");
if (!Persistent && --__counter == 0)
{
destroy();
return true;
}
return false;
};
static destroy = function () {
Class_destroy();
if (__manager != undefined)
{
ds_map_delete(__manager.__resources, Path);
__manager = undefined;
}
return undefined;
};
}