mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00

* This adds two new settings, available in the Project Properties and in the Scene Properties dialog, to allow to specify the strategy for preloading resources of the scenes and unloading them. By default, a game will preload in background the resources of all scenes. It will never unload these resources (so scene switching is fast). * You can now choose to unload the resources of a scene when the scene is left using the "Resources unloading" field. If the scene is launched again later, it will load its resources again. * You can also choose to change the preloading to disable it for all scenes (by modifying the setting in the project properties) or enable it/disable it on a scene by scene basis. This can be useful for large or modular games where you anticipate the player to only play some scenes, or if you want to reduce the resources that needs to be loaded on a web game.
148 lines
4.6 KiB
TypeScript
148 lines
4.6 KiB
TypeScript
/*
|
|
* GDevelop JS Platform
|
|
* Copyright 2013-present Florian Rival (Florian.Rival@gmail.com). All rights reserved.
|
|
* This project is released under the MIT License.
|
|
*/
|
|
namespace gdjs {
|
|
const logger = new gdjs.Logger('Spine Manager');
|
|
|
|
const resourceKinds: ResourceKind[] = ['spine'];
|
|
|
|
/**
|
|
* SpineManager manages pixi spine skeleton data.
|
|
*/
|
|
export class SpineManager implements gdjs.ResourceManager {
|
|
private _spineAtlasManager: SpineAtlasManager;
|
|
private _resourceLoader: ResourceLoader;
|
|
private _loadedSpines = new gdjs.ResourceCache<pixi_spine.ISkeletonData>();
|
|
|
|
/**
|
|
* @param resourceLoader The resources loader of the game.
|
|
* @param spineAtlasManager The resources data of the game.
|
|
*/
|
|
constructor(
|
|
resourceLoader: gdjs.ResourceLoader,
|
|
spineAtlasManager: SpineAtlasManager
|
|
) {
|
|
this._resourceLoader = resourceLoader;
|
|
this._spineAtlasManager = spineAtlasManager;
|
|
}
|
|
|
|
getResourceKinds(): ResourceKind[] {
|
|
return resourceKinds;
|
|
}
|
|
|
|
async processResource(resourceName: string): Promise<void> {
|
|
// Do nothing because pixi-spine parses resources by itself.
|
|
}
|
|
|
|
async loadResource(resourceName: string): Promise<void> {
|
|
const resource = this._getSpineResource(resourceName);
|
|
|
|
if (!resource) {
|
|
return logger.error(
|
|
`Unable to find spine json for resource ${resourceName}.`
|
|
);
|
|
}
|
|
|
|
try {
|
|
const game = this._resourceLoader.getRuntimeGame();
|
|
const embeddedResourcesNames = game.getEmbeddedResourcesNames(
|
|
resource.name
|
|
);
|
|
|
|
// there should be exactly one file which is pointing to atlas
|
|
if (embeddedResourcesNames.length !== 1) {
|
|
return logger.error(
|
|
`Unable to find atlas metadata for resource spine json ${resourceName}.`
|
|
);
|
|
}
|
|
|
|
const atlasResourceName = game.resolveEmbeddedResource(
|
|
resource.name,
|
|
embeddedResourcesNames[0]
|
|
);
|
|
const spineAtlas =
|
|
await this._spineAtlasManager.getOrLoad(atlasResourceName);
|
|
const url = this._resourceLoader.getFullUrl(resource.file);
|
|
PIXI.Assets.setPreferences({
|
|
preferWorkers: false,
|
|
crossOrigin: this._resourceLoader.checkIfCredentialsRequired(url)
|
|
? 'use-credentials'
|
|
: 'anonymous',
|
|
});
|
|
PIXI.Assets.add({
|
|
alias: resource.name,
|
|
src: url,
|
|
data: { spineAtlas },
|
|
});
|
|
const loadedJson = await PIXI.Assets.load(resource.name);
|
|
|
|
if (loadedJson.spineData) {
|
|
this._loadedSpines.set(resource, loadedJson.spineData);
|
|
} else {
|
|
logger.error(
|
|
`Loader cannot process spine resource ${resource.name} correctly.`
|
|
);
|
|
}
|
|
} catch (error) {
|
|
logger.error(
|
|
`Error while preloading spine resource ${resource.name}: ${error}`
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the object for the given resource that is already loaded (preloaded or loaded with `loadJson`).
|
|
* If the resource is not loaded, `null` will be returned.
|
|
*
|
|
* @param resourceName The name of the spine skeleton.
|
|
* @returns the spine skeleton if loaded, `null` otherwise.
|
|
*/
|
|
getSpine(resourceName: string): pixi_spine.ISkeletonData | null {
|
|
return this._loadedSpines.getFromName(resourceName);
|
|
}
|
|
|
|
/**
|
|
* Check if the given spine skeleton was loaded.
|
|
* @param resourceName The name of the spine skeleton.
|
|
* @returns true if the content of the spine skeleton is loaded, false otherwise.
|
|
*/
|
|
isSpineLoaded(resourceName: string): boolean {
|
|
return !!this._loadedSpines.getFromName(resourceName);
|
|
}
|
|
|
|
private _getSpineResource(resourceName: string): ResourceData | null {
|
|
const resource = this._resourceLoader.getResource(resourceName);
|
|
return resource && this.getResourceKinds().includes(resource.kind)
|
|
? resource
|
|
: null;
|
|
}
|
|
|
|
/**
|
|
* To be called when the game is disposed.
|
|
* Clear the Spine skeleton data loaded in this manager.
|
|
*/
|
|
dispose(): void {
|
|
this._loadedSpines.clear();
|
|
}
|
|
|
|
/**
|
|
* Unload the specified list of resources:
|
|
* this clears the Spine skeleton data loaded in this manager.
|
|
*
|
|
* Usually called when scene resoures are unloaded.
|
|
*
|
|
* @param resourcesList The list of specific resources
|
|
*/
|
|
unloadResourcesList(resourcesList: ResourceData[]): void {
|
|
resourcesList.forEach((resourceData) => {
|
|
const loadedSpine = this._loadedSpines.get(resourceData);
|
|
if (loadedSpine) {
|
|
this._loadedSpines.delete(resourceData);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|