mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-09-24 09:47:55 +00:00
初始化
This commit is contained in:
836
engine/cocos2d/core/asset-manager/CCAssetManager.js
Normal file
836
engine/cocos2d/core/asset-manager/CCAssetManager.js
Normal file
@@ -0,0 +1,836 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
const preprocess = require('./preprocess');
|
||||
const fetch = require('./fetch');
|
||||
const Cache = require('./cache');
|
||||
const helper = require('./helper');
|
||||
const releaseManager = require('./releaseManager');
|
||||
const dependUtil = require('./depend-util');
|
||||
const load = require('./load');
|
||||
const Pipeline = require('./pipeline');
|
||||
const Task = require('./task');
|
||||
const RequestItem = require('./request-item');
|
||||
const downloader = require('./downloader');
|
||||
const parser = require('./parser');
|
||||
const packManager = require('./pack-manager');
|
||||
const Bundle = require('./bundle');
|
||||
const builtins = require('./builtins');
|
||||
const factory = require('./factory');
|
||||
const { parse, combine } = require('./urlTransformer');
|
||||
const { parseParameters, asyncify } = require('./utilities');
|
||||
const { assets, files, parsed, pipeline, transformPipeline, fetchPipeline, RequestType, bundles, BuiltinBundleName } = require('./shared');
|
||||
|
||||
|
||||
/**
|
||||
* @module cc
|
||||
*/
|
||||
/**
|
||||
* !#en
|
||||
* This module controls asset's behaviors and information, include loading, releasing etc. it is a singleton
|
||||
* All member can be accessed with `cc.assetManager`.
|
||||
*
|
||||
* !#zh
|
||||
* 此模块管理资源的行为和信息,包括加载,释放等,这是一个单例,所有成员能够通过 `cc.assetManager` 调用
|
||||
*
|
||||
* @class AssetManager
|
||||
*/
|
||||
function AssetManager () {
|
||||
|
||||
this._preprocessPipe = preprocess;
|
||||
|
||||
this._fetchPipe = fetch;
|
||||
|
||||
this._loadPipe = load;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Normal loading pipeline
|
||||
*
|
||||
* !#zh
|
||||
* 正常加载管线
|
||||
*
|
||||
* @property pipeline
|
||||
* @type {Pipeline}
|
||||
*/
|
||||
this.pipeline = pipeline.append(preprocess).append(load);
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Fetching pipeline
|
||||
*
|
||||
* !#zh
|
||||
* 下载管线
|
||||
*
|
||||
* @property fetchPipeline
|
||||
* @type {Pipeline}
|
||||
*/
|
||||
this.fetchPipeline = fetchPipeline.append(preprocess).append(fetch);
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Url transformer
|
||||
*
|
||||
* !#zh
|
||||
* Url 转换器
|
||||
*
|
||||
* @property transformPipeline
|
||||
* @type {Pipeline}
|
||||
*/
|
||||
this.transformPipeline = transformPipeline.append(parse).append(combine);
|
||||
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The collection of bundle which is already loaded, you can remove cache with {{#crossLink "AssetManager/removeBundle:method"}}{{/crossLink}}
|
||||
*
|
||||
* !#zh
|
||||
* 已加载 bundle 的集合, 你能通过 {{#crossLink "AssetManager/removeBundle:method"}}{{/crossLink}} 来移除缓存
|
||||
*
|
||||
* @property bundles
|
||||
* @type {Cache}
|
||||
* @typescript
|
||||
* bundles: AssetManager.Cache<AssetManager.Bundle>
|
||||
*/
|
||||
this.bundles = bundles;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The collection of asset which is already loaded, you can remove cache with {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}}
|
||||
*
|
||||
* !#zh
|
||||
* 已加载资源的集合, 你能通过 {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}} 来移除缓存
|
||||
*
|
||||
* @property assets
|
||||
* @type {Cache}
|
||||
* @typescript
|
||||
* assets: AssetManager.Cache<cc.Asset>
|
||||
*/
|
||||
this.assets = assets;
|
||||
|
||||
this._files = files;
|
||||
|
||||
this._parsed = parsed;
|
||||
|
||||
this.generalImportBase = '';
|
||||
|
||||
this.generalNativeBase = '';
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Manage relationship between asset and its dependencies
|
||||
*
|
||||
* !#zh
|
||||
* 管理资源依赖关系
|
||||
*
|
||||
* @property dependUtil
|
||||
* @type {DependUtil}
|
||||
*/
|
||||
this.dependUtil = dependUtil;
|
||||
|
||||
this._releaseManager = releaseManager;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Whether or not cache the loaded asset
|
||||
*
|
||||
* !#zh
|
||||
* 是否缓存已加载的资源
|
||||
*
|
||||
* @property cacheAsset
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.cacheAsset = true;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Whether or not load asset forcely, if it is true, asset will be loaded regardless of error
|
||||
*
|
||||
* !#zh
|
||||
* 是否强制加载资源, 如果为 true ,加载资源将会忽略报错
|
||||
*
|
||||
* @property force
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.force = false;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Some useful function
|
||||
*
|
||||
* !#zh
|
||||
* 一些有用的方法
|
||||
*
|
||||
* @property utils
|
||||
* @type {Helper}
|
||||
*/
|
||||
this.utils = helper;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Manage all downloading task
|
||||
*
|
||||
* !#zh
|
||||
* 管理所有下载任务
|
||||
*
|
||||
* @property downloader
|
||||
* @type {Downloader}
|
||||
*/
|
||||
this.downloader = downloader;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Manage all parsing task
|
||||
*
|
||||
* !#zh
|
||||
* 管理所有解析任务
|
||||
*
|
||||
* @property parser
|
||||
* @type {Parser}
|
||||
*/
|
||||
this.parser = parser;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Manage internal asset
|
||||
*
|
||||
* !#zh
|
||||
* 管理内置资源
|
||||
*
|
||||
* @property builtins
|
||||
* @type {Builtins}
|
||||
*/
|
||||
this.builtins = builtins;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Manage all packed asset
|
||||
*
|
||||
* !#zh
|
||||
* 管理所有合并后的资源
|
||||
*
|
||||
* @property packManager
|
||||
* @type {PackManager}
|
||||
*/
|
||||
this.packManager = packManager;
|
||||
|
||||
this.factory = factory;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Cache manager is a module which controls all caches downloaded from server in non-web platform.
|
||||
*
|
||||
* !#zh
|
||||
* 缓存管理器是一个模块,在非 WEB 平台上,用于管理所有从服务器上下载下来的缓存
|
||||
*
|
||||
* @property cacheManager
|
||||
* @type {cc.AssetManager.CacheManager}
|
||||
* @typescript
|
||||
* cacheManager: cc.AssetManager.CacheManager|null
|
||||
*/
|
||||
this.cacheManager = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The preset of options
|
||||
*
|
||||
* !#zh
|
||||
* 可选参数的预设集
|
||||
*
|
||||
* @property presets
|
||||
* @type {Object}
|
||||
* @typescript
|
||||
* presets: Record<string, Record<string, any>>
|
||||
*/
|
||||
this.presets = {
|
||||
'default': {
|
||||
priority: 0,
|
||||
},
|
||||
|
||||
'preload': {
|
||||
maxConcurrency: 2,
|
||||
maxRequestsPerFrame: 2,
|
||||
priority: -1,
|
||||
},
|
||||
|
||||
'scene': {
|
||||
maxConcurrency: 8,
|
||||
maxRequestsPerFrame: 8,
|
||||
priority: 1,
|
||||
},
|
||||
|
||||
'bundle': {
|
||||
maxConcurrency: 8,
|
||||
maxRequestsPerFrame: 8,
|
||||
priority: 2,
|
||||
},
|
||||
|
||||
'remote': {
|
||||
maxRetryCount: 4
|
||||
},
|
||||
|
||||
'script': {
|
||||
maxConcurrency: 1024,
|
||||
maxRequestsPerFrame: 1024,
|
||||
priority: 2
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AssetManager.Pipeline = Pipeline;
|
||||
AssetManager.Task = Task;
|
||||
AssetManager.Cache = Cache;
|
||||
AssetManager.RequestItem = RequestItem;
|
||||
AssetManager.Bundle = Bundle;
|
||||
AssetManager.BuiltinBundleName = BuiltinBundleName;
|
||||
|
||||
AssetManager.prototype = {
|
||||
|
||||
constructor: AssetManager,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The builtin 'main' bundle
|
||||
*
|
||||
* !#zh
|
||||
* 内置 main 包
|
||||
*
|
||||
* @property main
|
||||
* @readonly
|
||||
* @type {Bundle}
|
||||
*/
|
||||
get main () {
|
||||
return bundles.get(BuiltinBundleName.MAIN);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The builtin 'resources' bundle
|
||||
*
|
||||
* !#zh
|
||||
* 内置 resources 包
|
||||
*
|
||||
* @property resources
|
||||
* @readonly
|
||||
* @type {Bundle}
|
||||
*/
|
||||
get resources () {
|
||||
return bundles.get(BuiltinBundleName.RESOURCES);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The builtin 'internal' bundle
|
||||
*
|
||||
* !#zh
|
||||
* 内置 internal 包
|
||||
*
|
||||
* @property internal
|
||||
* @readonly
|
||||
* @type {Bundle}
|
||||
*/
|
||||
get internal () {
|
||||
return bundles.get(BuiltinBundleName.INTERNAL);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Initialize assetManager with options
|
||||
*
|
||||
* !#zh
|
||||
* 初始化资源管理器
|
||||
*
|
||||
* @method init
|
||||
* @param {Object} options
|
||||
*
|
||||
* @typescript
|
||||
* init(options: Record<string, any>): void
|
||||
*/
|
||||
init (options) {
|
||||
options = options || Object.create(null);
|
||||
this._files.clear();
|
||||
this._parsed.clear();
|
||||
this._releaseManager.init();
|
||||
this.assets.clear();
|
||||
this.bundles.clear();
|
||||
this.packManager.init();
|
||||
this.downloader.init(options.bundleVers, options.server);
|
||||
this.parser.init();
|
||||
this.dependUtil.init();
|
||||
this.generalImportBase = options.importBase;
|
||||
this.generalNativeBase = options.nativeBase;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get the bundle which has been loaded
|
||||
*
|
||||
* !#zh
|
||||
* 获取已加载的分包
|
||||
*
|
||||
* @method getBundle
|
||||
* @param {String} name - The name of bundle
|
||||
* @return {Bundle} - The loaded bundle
|
||||
*
|
||||
* @example
|
||||
* // ${project}/assets/test1
|
||||
* cc.assetManager.getBundle('test1');
|
||||
*
|
||||
* cc.assetManager.getBundle('resources');
|
||||
*
|
||||
* @typescript
|
||||
* getBundle (name: string): cc.AssetManager.Bundle
|
||||
*/
|
||||
getBundle (name) {
|
||||
return bundles.get(name);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Remove this bundle. NOTE: The asset whthin this bundle will not be released automatically, you can call {{#crossLink "Bundle/releaseAll:method"}}{{/crossLink}} manually before remove it if you need
|
||||
*
|
||||
* !#zh
|
||||
* 移除此包, 注意:这个包内的资源不会自动释放, 如果需要的话你可以在摧毁之前手动调用 {{#crossLink "Bundle/releaseAll:method"}}{{/crossLink}} 进行释放
|
||||
*
|
||||
* @method removeBundle
|
||||
* @param {Bundle} bundle - The bundle to be removed
|
||||
*
|
||||
* @typescript
|
||||
* removeBundle(bundle: cc.AssetManager.Bundle): void
|
||||
*/
|
||||
removeBundle (bundle) {
|
||||
bundle._destroy();
|
||||
bundles.remove(bundle.name);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* General interface used to load assets with a progression callback and a complete callback. You can achieve almost all effect you want with combination of `requests` and `options`.
|
||||
* It is highly recommended that you use more simple API, such as `load`, `loadDir` etc. Every custom parameter in `options` will be distribute to each of `requests`.
|
||||
* if request already has same one, the parameter in request will be given priority. Besides, if request has dependencies, `options` will distribute to dependencies too.
|
||||
* Every custom parameter in `requests` will be tranfered to handler of `downloader` and `parser` as `options`.
|
||||
* You can register you own handler downloader or parser to collect these custom parameters for some effect.
|
||||
*
|
||||
* Reserved Keyword: `uuid`, `url`, `path`, `dir`, `scene`, `type`, `priority`, `preset`, `audioLoadMode`, `ext`, `bundle`, `onFileProgress`, `maxConcurrency`, `maxRequestsPerFrame`
|
||||
* `maxRetryCount`, `version`, `responseType`, `withCredentials`, `mimeType`, `timeout`, `header`, `reload`, `cacheAsset`, `cacheEnabled`,
|
||||
* Please DO NOT use these words as custom options!
|
||||
*
|
||||
* !#zh
|
||||
* 通用加载资源接口,可传入进度回调以及完成回调,通过组合 `request` 和 `options` 参数,几乎可以实现和扩展所有想要的加载效果。非常建议你使用更简单的API,例如 `load`、`loadDir` 等。
|
||||
* `options` 中的自定义参数将会分发到 `requests` 的每一项中,如果request中已存在同名的参数则以 `requests` 中为准,同时如果有其他
|
||||
* 依赖资源,则 `options` 中的参数会继续向依赖项中分发。request中的自定义参数都会以 `options` 形式传入加载流程中的 `downloader`, `parser` 的方法中, 你可以
|
||||
* 扩展 `downloader`, `parser` 收集参数完成想实现的效果。
|
||||
*
|
||||
* 保留关键字: `uuid`, `url`, `path`, `dir`, `scene`, `type`, `priority`, `preset`, `audioLoadMode`, `ext`, `bundle`, `onFileProgress`, `maxConcurrency`, `maxRequestsPerFrame`
|
||||
* `maxRetryCount`, `version`, `responseType`, `withCredentials`, `mimeType`, `timeout`, `header`, `reload`, `cacheAsset`, `cacheEnabled`,
|
||||
* 请不要使用这些字段为自定义参数!
|
||||
*
|
||||
* @method loadAny
|
||||
* @param {string|string[]|Object|Object[]} requests - The request you want to load
|
||||
* @param {Object} [options] - Optional parameters
|
||||
* @param {Function} [onProgress] - Callback invoked when progression change
|
||||
* @param {Number} onProgress.finished - The number of the items that are already completed
|
||||
* @param {Number} onProgress.total - The total number of the items
|
||||
* @param {RequestItem} onProgress.item - The current request item
|
||||
* @param {Function} [onComplete] - Callback invoked when finish loading
|
||||
* @param {Error} onComplete.err - The error occured in loading process.
|
||||
* @param {Object} onComplete.data - The loaded content
|
||||
*
|
||||
* @example
|
||||
* cc.assetManager.loadAny({url: 'http://example.com/a.png'}, (err, img) => cc.log(img));
|
||||
* cc.assetManager.loadAny(['60sVXiTH1D/6Aft4MRt9VC'], (err, assets) => cc.log(assets));
|
||||
* cc.assetManager.loadAny([{ uuid: '0cbZa5Y71CTZAccaIFluuZ'}, {url: 'http://example.com/a.png'}], (err, assets) => cc.log(assets));
|
||||
* cc.assetManager.downloader.register('.asset', (url, options, onComplete) => {
|
||||
* url += '?userName=' + options.userName + "&password=" + options.password;
|
||||
* cc.assetManager.downloader.downloadFile(url, null, onComplete);
|
||||
* });
|
||||
* cc.assetManager.parser.register('.asset', (file, options, onComplete) => {
|
||||
* var json = JSON.parse(file);
|
||||
* var skin = json[options.skin];
|
||||
* var model = json[options.model];
|
||||
* onComplete(null, {skin, model});
|
||||
* });
|
||||
* cc.assetManager.loadAny({ url: 'http://example.com/my.asset', skin: 'xxx', model: 'xxx', userName: 'xxx', password: 'xxx' });
|
||||
*
|
||||
* @typescript
|
||||
* loadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], options: Record<string, any>, onProgress: (finished: number, total: number, item: cc.AssetManager.RequestItem) => void, onComplete: (err: Error, data: any) => void): void
|
||||
* loadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], onProgress: (finished: number, total: number, item: cc.AssetManager.RequestItem) => void, onComplete: (err: Error, data: any) => void): void
|
||||
* loadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], options: Record<string, any>, onComplete: (err: Error, data: any) => void): void
|
||||
* loadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], onComplete: (err: Error, data: any) => void): void
|
||||
* loadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], options: Record<string, any>): void
|
||||
* loadAny(requests: string | string[] | Record<string, any> | Record<string, any>[]): void
|
||||
*/
|
||||
loadAny (requests, options, onProgress, onComplete) {
|
||||
var { options, onProgress, onComplete } = parseParameters(options, onProgress, onComplete);
|
||||
|
||||
options.preset = options.preset || 'default';
|
||||
requests = Array.isArray(requests) ? requests.concat() : requests;
|
||||
let task = new Task({input: requests, onProgress, onComplete: asyncify(onComplete), options});
|
||||
pipeline.async(task);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* General interface used to preload assets with a progression callback and a complete callback.It is highly recommended that you use more simple API, such as `preloadRes`, `preloadResDir` etc.
|
||||
* Everything about preload is just likes `cc.assetManager.loadAny`, the difference is `cc.assetManager.preloadAny` will only download asset but not parse asset. You need to invoke `cc.assetManager.loadAny(preloadTask)`
|
||||
* to finish loading asset
|
||||
*
|
||||
* !#zh
|
||||
* 通用预加载资源接口,可传入进度回调以及完成回调,非常建议你使用更简单的 API ,例如 `preloadRes`, `preloadResDir` 等。`preloadAny` 和 `loadAny` 几乎一样,区别在于 `preloadAny` 只会下载资源,不会去解析资源,你需要调用 `cc.assetManager.loadAny(preloadTask)`
|
||||
* 来完成资源加载。
|
||||
*
|
||||
* @method preloadAny
|
||||
* @param {string|string[]|Object|Object[]} requests - The request you want to preload
|
||||
* @param {Object} [options] - Optional parameters
|
||||
* @param {Function} [onProgress] - Callback invoked when progression change
|
||||
* @param {Number} onProgress.finished - The number of the items that are already completed
|
||||
* @param {Number} onProgress.total - The total number of the items
|
||||
* @param {RequestItem} onProgress.item - The current request item
|
||||
* @param {Function} [onComplete] - Callback invoked when finish preloading
|
||||
* @param {Error} onComplete.err - The error occured in preloading process.
|
||||
* @param {RequestItem[]} onComplete.items - The preloaded content
|
||||
*
|
||||
* @example
|
||||
* cc.assetManager.preloadAny('0cbZa5Y71CTZAccaIFluuZ', (err) => cc.assetManager.loadAny('0cbZa5Y71CTZAccaIFluuZ'));
|
||||
*
|
||||
* @typescript
|
||||
* preloadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], options: Record<string, any>, onProgress: (finished: number, total: number, item: cc.AssetManager.RequestItem) => void, onComplete: (err: Error, items: cc.AssetManager.RequestItem[]) => void): void
|
||||
* preloadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], onProgress: (finished: number, total: number, item: cc.AssetManager.RequestItem) => void, onComplete: (err: Error, items: cc.AssetManager.RequestItem[]) => void): void
|
||||
* preloadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], options: Record<string, any>, onComplete: (err: Error, items: cc.AssetManager.RequestItem[]) => void): void
|
||||
* preloadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], onComplete: (err: Error, items: cc.AssetManager.RequestItem[]) => void): void
|
||||
* preloadAny(requests: string | string[] | Record<string, any> | Record<string, any>[], options: Record<string, any>): void
|
||||
* preloadAny(requests: string | string[] | Record<string, any> | Record<string, any>[]): void
|
||||
*/
|
||||
preloadAny (requests, options, onProgress, onComplete) {
|
||||
var { options, onProgress, onComplete } = parseParameters(options, onProgress, onComplete);
|
||||
|
||||
options.preset = options.preset || 'preload';
|
||||
requests = Array.isArray(requests) ? requests.concat() : requests;
|
||||
var task = new Task({input: requests, onProgress, onComplete: asyncify(onComplete), options});
|
||||
fetchPipeline.async(task);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Load native file of asset, if you check the option 'Async Load Assets', you may need to load native file with this before you use the asset
|
||||
*
|
||||
* !#zh
|
||||
* 加载资源的原生文件,如果你勾选了'延迟加载资源'选项,你可能需要在使用资源之前调用此方法来加载原生文件
|
||||
*
|
||||
* @method postLoadNative
|
||||
* @param {Asset} asset - The asset
|
||||
* @param {Object} [options] - Some optional parameters
|
||||
* @param {Function} [onComplete] - Callback invoked when finish loading
|
||||
* @param {Error} onComplete.err - The error occured in loading process.
|
||||
*
|
||||
* @example
|
||||
* cc.assetManager.postLoadNative(texture, (err) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* postLoadNative(asset: cc.Asset, options: Record<string, any>, onComplete: (err: Error) => void): void
|
||||
* postLoadNative(asset: cc.Asset, onComplete: (err: Error) => void): void
|
||||
* postLoadNative(asset: cc.Asset, options: Record<string, any>): void
|
||||
* postLoadNative(asset: cc.Asset): void
|
||||
*/
|
||||
postLoadNative (asset, options, onComplete) {
|
||||
if (!(asset instanceof cc.Asset)) throw new Error('input is not asset');
|
||||
var { options, onComplete } = parseParameters(options, undefined, onComplete);
|
||||
|
||||
if (!asset._native || asset._nativeAsset) {
|
||||
return asyncify(onComplete)(null);
|
||||
}
|
||||
|
||||
var depend = dependUtil.getNativeDep(asset._uuid);
|
||||
if (depend) {
|
||||
if (!bundles.has(depend.bundle)) {
|
||||
var bundle = bundles.find(function (bundle) {
|
||||
return bundle.getAssetInfo(asset._uuid);
|
||||
});
|
||||
if (bundle) {
|
||||
depend.bundle = bundle.name;
|
||||
}
|
||||
}
|
||||
|
||||
this.loadAny(depend, options, function (err, native) {
|
||||
if (!err) {
|
||||
if (asset.isValid && !asset._nativeAsset) {
|
||||
asset._nativeAsset = native
|
||||
}
|
||||
}
|
||||
else {
|
||||
cc.error(err.message, err.stack);
|
||||
}
|
||||
onComplete && onComplete(err);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Load remote asset with url, such as audio, image, text and so on.
|
||||
*
|
||||
* !#zh
|
||||
* 使用 url 加载远程资源,例如音频,图片,文本等等。
|
||||
*
|
||||
* @method loadRemote
|
||||
* @param {string} url - The url of asset
|
||||
* @param {Object} [options] - Some optional parameters
|
||||
* @param {cc.AudioClip.LoadMode} [options.audioLoadMode] - Indicate which mode audio you want to load
|
||||
* @param {string} [options.ext] - If the url does not have a extension name, you can specify one manually.
|
||||
* @param {Function} [onComplete] - Callback invoked when finish loading
|
||||
* @param {Error} onComplete.err - The error occured in loading process.
|
||||
* @param {Asset} onComplete.asset - The loaded texture
|
||||
*
|
||||
* @example
|
||||
* cc.assetManager.loadRemote('http://www.cloud.com/test1.jpg', (err, texture) => console.log(err));
|
||||
* cc.assetManager.loadRemote('http://www.cloud.com/test2.mp3', (err, audioClip) => console.log(err));
|
||||
* cc.assetManager.loadRemote('http://www.cloud.com/test3', { ext: '.png' }, (err, texture) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* loadRemote<T extends cc.Asset>(url: string, options: Record<string, any>, onComplete: (err: Error, asset: T) => void): void
|
||||
* loadRemote<T extends cc.Asset>(url: string, onComplete: (err: Error, asset: T) => void): void
|
||||
* loadRemote<T extends cc.Asset>(url: string, options: Record<string, any>): void
|
||||
* loadRemote<T extends cc.Asset>(url: string): void
|
||||
*/
|
||||
loadRemote (url, options, onComplete) {
|
||||
var { options, onComplete } = parseParameters(options, undefined, onComplete);
|
||||
|
||||
if (this.assets.has(url)) {
|
||||
return asyncify(onComplete)(null, this.assets.get(url));
|
||||
}
|
||||
|
||||
options.__isNative__ = true;
|
||||
options.preset = options.preset || 'remote';
|
||||
this.loadAny({url}, options, null, function (err, data) {
|
||||
if (err) {
|
||||
cc.error(err.message, err.stack);
|
||||
onComplete && onComplete(err, null);
|
||||
}
|
||||
else {
|
||||
factory.create(url, data, options.ext || cc.path.extname(url), options, function (err, out) {
|
||||
onComplete && onComplete(err, out);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Load script
|
||||
*
|
||||
* !#zh
|
||||
* 加载脚本
|
||||
*
|
||||
* @method loadScript
|
||||
* @param {string|string[]} url - Url of the script
|
||||
* @param {Object} [options] - Some optional paramters
|
||||
* @param {boolean} [options.async] - Indicate whether or not loading process should be async
|
||||
* @param {Function} [onComplete] - Callback when script loaded or failed
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
*
|
||||
* @example
|
||||
* loadScript('http://localhost:8080/index.js', null, (err) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* loadScript(url: string|string[], options: Record<string, any>, onComplete: (err: Error) => void): void
|
||||
* loadScript(url: string|string[], onComplete: (err: Error) => void): void
|
||||
* loadScript(url: string|string[], options: Record<string, any>): void
|
||||
* loadScript(url: string|string[]): void
|
||||
*/
|
||||
loadScript (url, options, onComplete) {
|
||||
var { options, onComplete } = parseParameters(options, undefined, onComplete);
|
||||
options.__requestType__ = RequestType.URL;
|
||||
options.preset = options.preset || 'script';
|
||||
this.loadAny(url, options, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* load bundle
|
||||
*
|
||||
* !#zh
|
||||
* 加载资源包
|
||||
*
|
||||
* @method loadBundle
|
||||
* @param {string} nameOrUrl - The name or root path of bundle
|
||||
* @param {Object} [options] - Some optional paramter, same like downloader.downloadFile
|
||||
* @param {string} [options.version] - The version of this bundle, you can check config.json in this bundle
|
||||
* @param {Function} [onComplete] - Callback when bundle loaded or failed
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {Bundle} onComplete.bundle - The loaded bundle
|
||||
*
|
||||
* @example
|
||||
* loadBundle('http://localhost:8080/test', null, (err, bundle) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* loadBundle(nameOrUrl: string, options: Record<string, any>, onComplete: (err: Error, bundle: cc.AssetManager.Bundle) => void): void
|
||||
* loadBundle(nameOrUrl: string, onComplete: (err: Error, bundle: cc.AssetManager.Bundle) => void): void
|
||||
* loadBundle(nameOrUrl: string, options: Record<string, any>): void
|
||||
* loadBundle(nameOrUrl: string): void
|
||||
*/
|
||||
loadBundle (nameOrUrl, options, onComplete) {
|
||||
var { options, onComplete } = parseParameters(options, undefined, onComplete);
|
||||
|
||||
let bundleName = cc.path.basename(nameOrUrl);
|
||||
|
||||
if (this.bundles.has(bundleName)) {
|
||||
return asyncify(onComplete)(null, this.getBundle(bundleName));
|
||||
}
|
||||
|
||||
options.preset = options.preset || 'bundle';
|
||||
options.ext = 'bundle';
|
||||
this.loadRemote(nameOrUrl, options, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Release asset and it's dependencies.
|
||||
* This method will not only remove the cache of the asset in assetManager, but also clean up its content.
|
||||
* For example, if you release a texture, the texture asset and its gl texture data will be freed up.
|
||||
* Notice, this method may cause the texture to be unusable, if there are still other nodes use the same texture, they may turn to black and report gl errors.
|
||||
*
|
||||
* !#zh
|
||||
* 释放资源以及其依赖资源, 这个方法不仅会从 assetManager 中删除资源的缓存引用,还会清理它的资源内容。
|
||||
* 比如说,当你释放一个 texture 资源,这个 texture 和它的 gl 贴图数据都会被释放。
|
||||
* 注意,这个函数可能会导致资源贴图或资源所依赖的贴图不可用,如果场景中存在节点仍然依赖同样的贴图,它们可能会变黑并报 GL 错误。
|
||||
*
|
||||
* @method releaseAsset
|
||||
* @param {Asset} asset - The asset to be released
|
||||
*
|
||||
* @example
|
||||
* // release a texture which is no longer need
|
||||
* cc.assetManager.releaseAsset(texture);
|
||||
*
|
||||
* @typescript
|
||||
* releaseAsset(asset: cc.Asset): void
|
||||
*/
|
||||
releaseAsset (asset) {
|
||||
releaseManager.tryRelease(asset, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Release all unused assets. Refer to {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}} for detailed informations.
|
||||
*
|
||||
* !#zh
|
||||
* 释放所有没有用到的资源。详细信息请参考 {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}}
|
||||
*
|
||||
* @method releaseUnusedAssets
|
||||
* @private
|
||||
*
|
||||
* @typescript
|
||||
* releaseUnusedAssets(): void
|
||||
*/
|
||||
releaseUnusedAssets () {
|
||||
assets.forEach(function (asset) {
|
||||
releaseManager.tryRelease(asset);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Release all assets. Refer to {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}} for detailed informations.
|
||||
*
|
||||
* !#zh
|
||||
* 释放所有资源。详细信息请参考 {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}}
|
||||
*
|
||||
* @method releaseAll
|
||||
*
|
||||
* @typescript
|
||||
* releaseAll(): void
|
||||
*/
|
||||
releaseAll () {
|
||||
assets.forEach(function (asset) {
|
||||
releaseManager.tryRelease(asset, true);
|
||||
});
|
||||
if (CC_EDITOR) {
|
||||
dependUtil._depends.clear();
|
||||
}
|
||||
},
|
||||
|
||||
_transform (input, options) {
|
||||
var subTask = Task.create({input, options});
|
||||
var urls = [];
|
||||
try {
|
||||
var result = transformPipeline.sync(subTask);
|
||||
for (var i = 0, l = result.length; i < l; i++) {
|
||||
var item = result[i];
|
||||
var url = item.url;
|
||||
item.recycle();
|
||||
urls.push(url);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
for (var i = 0, l = subTask.output.length; i < l; i++) {
|
||||
subTask.output[i].recycle();
|
||||
}
|
||||
cc.error(e.message, e.stack);
|
||||
}
|
||||
subTask.recycle();
|
||||
return urls.length > 1 ? urls : urls[0];
|
||||
}
|
||||
};
|
||||
|
||||
cc.AssetManager = AssetManager;
|
||||
/**
|
||||
* @module cc
|
||||
*/
|
||||
/**
|
||||
* @property assetManager
|
||||
* @type {AssetManager}
|
||||
*/
|
||||
cc.assetManager = new AssetManager();
|
||||
|
||||
Object.defineProperty(cc, 'resources', {
|
||||
/**
|
||||
* !#en
|
||||
* cc.resources is a bundle and controls all asset under assets/resources
|
||||
*
|
||||
* !#zh
|
||||
* cc.resources 是一个 bundle,用于管理所有在 assets/resources 下的资源
|
||||
*
|
||||
* @property resources
|
||||
* @readonly
|
||||
* @type {AssetManager.Bundle}
|
||||
*/
|
||||
get () {
|
||||
return bundles.get(BuiltinBundleName.RESOURCES);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
module.exports = cc.assetManager;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* This module controls asset's behaviors and information, include loading, releasing etc.
|
||||
* All member can be accessed with `cc.assetManager`. All class or enum can be accessed with `cc.AssetManager`
|
||||
*
|
||||
* !#zh
|
||||
* 此模块管理资源的行为和信息,包括加载,释放等,所有成员能够通过 `cc.assetManager` 调用. 所有类型或枚举能通过 `cc.AssetManager` 访问
|
||||
*
|
||||
* @module cc.AssetManager
|
||||
*/
|
133
engine/cocos2d/core/asset-manager/builtins.js
Normal file
133
engine/cocos2d/core/asset-manager/builtins.js
Normal file
@@ -0,0 +1,133 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const Cache = require('./cache');
|
||||
const releaseManager = require('./releaseManager');
|
||||
const { BuiltinBundleName } = require('./shared');
|
||||
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
/**
|
||||
* !#en
|
||||
* This module contains the builtin asset, it's a singleton, all member can be accessed with `cc.assetManager.builtins`
|
||||
*
|
||||
* !#zh
|
||||
* 此模块包含内建资源,这是一个单例,所有成员能通过 `cc.assetManager.builtins` 访问
|
||||
*
|
||||
* @class Builtins
|
||||
*/
|
||||
var builtins = {
|
||||
|
||||
_assets: new Cache({ material: new Cache(), effect: new Cache() }), // builtin assets
|
||||
|
||||
_loadBuiltins (name, cb) {
|
||||
let dirname = name + 's';
|
||||
let builtin = this._assets.get(name);
|
||||
return cc.assetManager.internal.loadDir(dirname, null, null, (err, assets) => {
|
||||
if (err) {
|
||||
cc.error(err.message, err.stack);
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < assets.length; i++) {
|
||||
var asset = assets[i];
|
||||
builtin.add(asset.name, asset.addRef());
|
||||
}
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Initialize
|
||||
*
|
||||
* !#zh
|
||||
* 初始化
|
||||
*
|
||||
* @method init
|
||||
* @param {Function} cb - Callback when finish loading built-in assets
|
||||
*
|
||||
* @typescript
|
||||
* init (cb: () => void): void
|
||||
*/
|
||||
init (cb) {
|
||||
this.clear();
|
||||
if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS || !cc.assetManager.bundles.has(BuiltinBundleName.INTERNAL)) {
|
||||
return cb && cb();
|
||||
}
|
||||
|
||||
this._loadBuiltins('effect', () => {
|
||||
this._loadBuiltins('material', cb);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get the built-in asset using specific type and name.
|
||||
*
|
||||
* !#zh
|
||||
* 通过特定的类型和名称获取内建资源
|
||||
*
|
||||
* @method getBuiltin
|
||||
* @param {string} [type] - The type of asset, such as `effect`
|
||||
* @param {string} [name] - The name of asset, such as `phong`
|
||||
* @return {Asset|Cache} Builtin-assets
|
||||
*
|
||||
* @example
|
||||
* cc.assetManaer.builtins.getBuiltin('effect', 'phone');
|
||||
*
|
||||
* @typescript
|
||||
* getBuiltin(type?: string, name?: string): cc.Asset | Cache<cc.Asset>
|
||||
*/
|
||||
getBuiltin (type, name) {
|
||||
if (arguments.length === 0) return this._assets;
|
||||
else if (arguments.length === 1) return this._assets.get(type);
|
||||
else return this._assets.get(type).get(name);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Clear all builtin assets
|
||||
*
|
||||
* !#zh
|
||||
* 清空所有内置资源
|
||||
*
|
||||
* @method clear
|
||||
*
|
||||
* @typescript
|
||||
* clear(): void
|
||||
*/
|
||||
clear () {
|
||||
this._assets.forEach(function (assets) {
|
||||
assets.forEach(function (asset) {
|
||||
releaseManager.tryRelease(asset, true);
|
||||
});
|
||||
assets.clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = builtins;
|
614
engine/cocos2d/core/asset-manager/bundle.js
Normal file
614
engine/cocos2d/core/asset-manager/bundle.js
Normal file
@@ -0,0 +1,614 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const Config = require('./config');
|
||||
const releaseManager = require('./releaseManager');
|
||||
const { parseParameters, parseLoadResArgs } = require('./utilities');
|
||||
const { RequestType, assets, bundles } = require('./shared');
|
||||
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* A bundle contains an amount of assets(includes scene), you can load, preload, release asset which is in this bundle
|
||||
*
|
||||
* !#zh
|
||||
* 一个包含一定数量资源(包括场景)的包,你可以加载,预加载,释放此包内的资源
|
||||
*
|
||||
* @class Bundle
|
||||
*/
|
||||
function Bundle () {
|
||||
this._config = new Config();
|
||||
}
|
||||
|
||||
Bundle.prototype = {
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Create a bundle
|
||||
*
|
||||
* !#zh
|
||||
* 创建一个 bundle
|
||||
*
|
||||
* @method constructor
|
||||
*
|
||||
* @typescript
|
||||
* constructor()
|
||||
*/
|
||||
constructor: Bundle,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The name of this bundle
|
||||
*
|
||||
* !#zh
|
||||
* 此 bundle 的名称
|
||||
*
|
||||
* @property name
|
||||
* @type {string}
|
||||
*/
|
||||
get name () {
|
||||
return this._config.name;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The dependency of this bundle
|
||||
*
|
||||
* !#zh
|
||||
* 此 bundle 的依赖
|
||||
*
|
||||
* @property deps
|
||||
* @type {string[]}
|
||||
*/
|
||||
get deps () {
|
||||
return this._config.deps;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The root path of this bundle, such like 'http://example.com/bundle1'
|
||||
*
|
||||
* !#zh
|
||||
* 此 bundle 的根路径, 例如 'http://example.com/bundle1'
|
||||
*
|
||||
* @property base
|
||||
* @type {string}
|
||||
*/
|
||||
get base () {
|
||||
return this._config.base;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get asset's info using path, only valid when asset is in bundle folder.
|
||||
*
|
||||
* !#zh
|
||||
* 使用 path 获取资源的配置信息
|
||||
*
|
||||
* @method getInfoWithPath
|
||||
* @param {string} path - The relative path of asset, such as 'images/a'
|
||||
* @param {Function} [type] - The constructor of asset, such as `cc.Texture2D`
|
||||
* @returns {Object} The asset info
|
||||
*
|
||||
* @example
|
||||
* var info = bundle.getInfoWithPath('image/a', cc.Texture2D);
|
||||
*
|
||||
* @typescript
|
||||
* getInfoWithPath (path: string, type?: typeof cc.Asset): Record<string, any>
|
||||
*/
|
||||
getInfoWithPath (path, type) {
|
||||
return this._config.getInfoWithPath(path, type);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get all asset's info within specific folder
|
||||
*
|
||||
* !#zh
|
||||
* 获取在某个指定文件夹下的所有资源信息
|
||||
*
|
||||
* @method getDirWithPath
|
||||
* @param {string} path - The relative path of folder, such as 'images'
|
||||
* @param {Function} [type] - The constructor should be used to filter paths
|
||||
* @param {Array} [out] - The output array
|
||||
* @returns {Object[]} Infos
|
||||
*
|
||||
* @example
|
||||
* var infos = [];
|
||||
* bundle.getDirWithPath('images', cc.Texture2D, infos);
|
||||
*
|
||||
* @typescript
|
||||
* getDirWithPath (path: string, type: typeof cc.Asset, out: Array<Record<string, any>>): Array<Record<string, any>>
|
||||
* getDirWithPath (path: string, type: typeof cc.Asset): Array<Record<string, any>>
|
||||
* getDirWithPath (path: string): Array<Record<string, any>>
|
||||
*/
|
||||
getDirWithPath (path, type, out) {
|
||||
return this._config.getDirWithPath(path, type, out);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get asset's info with uuid
|
||||
*
|
||||
* !#zh
|
||||
* 通过 uuid 获取资源信息
|
||||
*
|
||||
* @method getAssetInfo
|
||||
* @param {string} uuid - The asset's uuid
|
||||
* @returns {Object} info
|
||||
*
|
||||
* @example
|
||||
* var info = bundle.getAssetInfo('fcmR3XADNLgJ1ByKhqcC5Z');
|
||||
*
|
||||
* @typescript
|
||||
* getAssetInfo (uuid: string): Record<string, any>
|
||||
*/
|
||||
getAssetInfo (uuid) {
|
||||
return this._config.getAssetInfo(uuid);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get scene'info with name
|
||||
*
|
||||
* !#zh
|
||||
* 通过场景名获取场景信息
|
||||
*
|
||||
* @method getSceneInfo
|
||||
* @param {string} name - The name of scene
|
||||
* @return {Object} info
|
||||
*
|
||||
* @example
|
||||
* var info = bundle.getSceneInfo('first.fire');
|
||||
*
|
||||
* @typescript
|
||||
* getSceneInfo(name: string): Record<string, any>
|
||||
*/
|
||||
getSceneInfo (name) {
|
||||
return this._config.getSceneInfo(name);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Initialize this bundle with options
|
||||
*
|
||||
* !#zh
|
||||
* 初始化此 bundle
|
||||
*
|
||||
* @method init
|
||||
* @param {Object} options
|
||||
*
|
||||
* @typescript
|
||||
* init(options: Record<string, any>): void
|
||||
*/
|
||||
init (options) {
|
||||
this._config.init(options);
|
||||
bundles.add(options.name, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Load the asset within this bundle by the path which is relative to bundle's path
|
||||
*
|
||||
* !#zh
|
||||
* 通过相对路径加载分包中的资源。路径是相对分包文件夹路径的相对路径
|
||||
*
|
||||
* @method load
|
||||
* @param {String|String[]} paths - Paths of the target assets.The path is relative to the bundle's folder, extensions must be omitted.
|
||||
* @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.
|
||||
* @param {Function} [onProgress] - Callback invoked when progression change.
|
||||
* @param {Number} onProgress.finish - The number of the items that are already completed.
|
||||
* @param {Number} onProgress.total - The total number of the items.
|
||||
* @param {RequestItem} onProgress.item - The finished request item.
|
||||
* @param {Function} [onComplete] - Callback invoked when all assets loaded.
|
||||
* @param {Error} onComplete.error - The error info or null if loaded successfully.
|
||||
* @param {Asset|Asset[]} onComplete.assets - The loaded assets.
|
||||
*
|
||||
* @example
|
||||
* // load the texture (${project}/assets/resources/textures/background.jpg) from resources
|
||||
* cc.resources.load('textures/background', cc.Texture2D, (err, texture) => console.log(err));
|
||||
*
|
||||
* // load the audio (${project}/assets/resources/music/hit.mp3) from resources
|
||||
* cc.resources.load('music/hit', cc.AudioClip, (err, audio) => console.log(err));
|
||||
*
|
||||
* // load the prefab (${project}/assets/bundle1/misc/character/cocos) from bundle1 folder
|
||||
* bundle1.load('misc/character/cocos', cc.Prefab, (err, prefab) => console.log(err));
|
||||
*
|
||||
* // load the sprite frame (${project}/assets/some/xxx/bundle2/imgs/cocos.png) from bundle2 folder
|
||||
* bundle2.load('imgs/cocos', cc.SpriteFrame, null, (err, spriteFrame) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* load<T extends cc.Asset>(paths: string, type: { prototype: T } onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, assets: T) => void): void
|
||||
* load<T extends cc.Asset>(paths: string[], type: { prototype: T }, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, assets: Array<T>) => void): void
|
||||
* load<T extends cc.Asset>(paths: string, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, assets: T) => void): void
|
||||
* load<T extends cc.Asset>(paths: string[], onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, assets: Array<T>) => void): void
|
||||
* load<T extends cc.Asset>(paths: string, type: { prototype: T }, onComplete?: (error: Error, assets: T) => void): void
|
||||
* load<T extends cc.Asset>(paths: string[], type: { prototype: T }, onComplete?: (error: Error, assets: Array<T>) => void): void
|
||||
* load<T extends cc.Asset>(paths: string, onComplete?: (error: Error, assets: T) => void): void
|
||||
* load<T extends cc.Asset>(paths: string[], onComplete?: (error: Error, assets: Array<T>) => void): void
|
||||
*/
|
||||
load (paths, type, onProgress, onComplete) {
|
||||
var { type, onProgress, onComplete } = parseLoadResArgs(type, onProgress, onComplete);
|
||||
cc.assetManager.loadAny(paths, { __requestType__: RequestType.PATH, type: type, bundle: this.name, __outputAsArray__: Array.isArray(paths) }, onProgress, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Preload the asset within this bundle by the path which is relative to bundle's path.
|
||||
* After calling this method, you still need to finish loading by calling `Bundle.load`.
|
||||
* It will be totally fine to call `Bundle.load` at any time even if the preloading is not
|
||||
* yet finished
|
||||
*
|
||||
* !#zh
|
||||
* 通过相对路径预加载分包中的资源。路径是相对分包文件夹路径的相对路径。调用完后,你仍然需要通过 `Bundle.load` 来完成加载。
|
||||
* 就算预加载还没完成,你也可以直接调用 `Bundle.load`。
|
||||
*
|
||||
* @method preload
|
||||
* @param {String|String[]} paths - Paths of the target asset.The path is relative to bundle folder, extensions must be omitted.
|
||||
* @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.
|
||||
* @param {Function} [onProgress] - Callback invoked when progression change.
|
||||
* @param {Number} onProgress.finish - The number of the items that are already completed.
|
||||
* @param {Number} onProgress.total - The total number of the items.
|
||||
* @param {RequestItem} onProgress.item - The finished request item.
|
||||
* @param {Function} [onComplete] - Callback invoked when the resource loaded.
|
||||
* @param {Error} onComplete.error - The error info or null if loaded successfully.
|
||||
* @param {RequestItem[]} onComplete.items - The preloaded items.
|
||||
*
|
||||
* @example
|
||||
* // preload the texture (${project}/assets/resources/textures/background.jpg) from resources
|
||||
* cc.resources.preload('textures/background', cc.Texture2D);
|
||||
*
|
||||
* // preload the audio (${project}/assets/resources/music/hit.mp3) from resources
|
||||
* cc.resources.preload('music/hit', cc.AudioClip);
|
||||
* // wait for while
|
||||
* cc.resources.load('music/hit', cc.AudioClip, (err, audioClip) => {});
|
||||
*
|
||||
* * // preload the prefab (${project}/assets/bundle1/misc/character/cocos) from bundle1 folder
|
||||
* bundle1.preload('misc/character/cocos', cc.Prefab);
|
||||
*
|
||||
* // load the sprite frame of (${project}/assets/bundle2/imgs/cocos.png) from bundle2 folder
|
||||
* bundle2.preload('imgs/cocos', cc.SpriteFrame);
|
||||
* // wait for while
|
||||
* bundle2.load('imgs/cocos', cc.SpriteFrame, (err, spriteFrame) => {});
|
||||
*
|
||||
* @typescript
|
||||
* preload(paths: string|string[], type: typeof cc.Asset, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, items: RequestItem[]) => void): void
|
||||
* preload(paths: string|string[], onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, items: RequestItem[]) => void): void
|
||||
* preload(paths: string|string[], type: typeof cc.Asset, onComplete: (error: Error, items: RequestItem[]) => void): void
|
||||
* preload(paths: string|string[], type: typeof cc.Asset): void
|
||||
* preload(paths: string|string[], onComplete: (error: Error, items: RequestItem[]) => void): void
|
||||
* preload(paths: string|string[]): void
|
||||
*/
|
||||
preload (paths, type, onProgress, onComplete) {
|
||||
var { type, onProgress, onComplete } = parseLoadResArgs(type, onProgress, onComplete);
|
||||
cc.assetManager.preloadAny(paths, { __requestType__: RequestType.PATH, type: type, bundle: this.name }, onProgress, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Load all assets under a folder inside the bundle folder.<br>
|
||||
* <br>
|
||||
* Note: All asset paths in Creator use forward slashes, paths using backslashes will not work.
|
||||
*
|
||||
* !#zh
|
||||
* 加载目标文件夹中的所有资源, 注意:路径中只能使用斜杠,反斜杠将停止工作
|
||||
*
|
||||
* @method loadDir
|
||||
* @param {string} dir - path of the target folder.The path is relative to the bundle folder, extensions must be omitted.
|
||||
* @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.
|
||||
* @param {Function} [onProgress] - Callback invoked when progression change.
|
||||
* @param {Number} onProgress.finish - The number of the items that are already completed.
|
||||
* @param {Number} onProgress.total - The total number of the items.
|
||||
* @param {Object} onProgress.item - The latest request item
|
||||
* @param {Function} [onComplete] - A callback which is called when all assets have been loaded, or an error occurs.
|
||||
* @param {Error} onComplete.error - If one of the asset failed, the complete callback is immediately called with the error. If all assets are loaded successfully, error will be null.
|
||||
* @param {Asset[]|Asset} onComplete.assets - An array of all loaded assets.
|
||||
*
|
||||
* @example
|
||||
* // load all audios (resources/audios/)
|
||||
* cc.resources.loadDir('audios', cc.AudioClip, (err, audios) => {});
|
||||
*
|
||||
* // load all textures in "resources/imgs/"
|
||||
* cc.resources.loadDir('imgs', cc.Texture2D, null, function (err, textures) {
|
||||
* var texture1 = textures[0];
|
||||
* var texture2 = textures[1];
|
||||
* });
|
||||
*
|
||||
* // load all prefabs (${project}/assets/bundle1/misc/characters/) from bundle1 folder
|
||||
* bundle1.loadDir('misc/characters', cc.Prefab, (err, prefabs) => console.log(err));
|
||||
*
|
||||
* // load all sprite frame (${project}/assets/some/xxx/bundle2/skills/) from bundle2 folder
|
||||
* bundle2.loadDir('skills', cc.SpriteFrame, null, (err, spriteFrames) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* loadDir<T extends cc.Asset>(dir: string, type: { prototype: T }, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, assets: Array<T>) => void): void
|
||||
* loadDir<T extends cc.Asset>(dir: string, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, assets: Array<T>) => void): void
|
||||
* loadDir<T extends cc.Asset>(dir: string, type: { prototype: T }, onComplete: (error: Error, assets: Array<T>) => void): void
|
||||
* loadDir<T extends cc.Asset>(dir: string, type: { prototype: T }): void
|
||||
* loadDir<T extends cc.Asset>(dir: string, onComplete: (error: Error, assets: Array<T>) => void): void
|
||||
* loadDir<T extends cc.Asset>(dir: string): void
|
||||
*/
|
||||
loadDir (dir, type, onProgress, onComplete) {
|
||||
var { type, onProgress, onComplete } = parseLoadResArgs(type, onProgress, onComplete);
|
||||
cc.assetManager.loadAny(dir, { __requestType__: RequestType.DIR, type: type, bundle: this.name, __outputAsArray__: true }, onProgress, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Preload all assets under a folder inside the bundle folder.<br> After calling this method, you still need to finish loading by calling `Bundle.loadDir`.
|
||||
* It will be totally fine to call `Bundle.loadDir` at any time even if the preloading is not yet finished
|
||||
*
|
||||
* !#zh
|
||||
* 预加载目标文件夹中的所有资源。调用完后,你仍然需要通过 `Bundle.loadDir` 来完成加载。
|
||||
* 就算预加载还没完成,你也可以直接调用 `Bundle.loadDir`。
|
||||
*
|
||||
* @method preloadDir
|
||||
* @param {string} dir - path of the target folder.The path is relative to the bundle folder, extensions must be omitted.
|
||||
* @param {Function} [type] - Only asset of type will be preloaded if this argument is supplied.
|
||||
* @param {Function} [onProgress] - Callback invoked when progression change.
|
||||
* @param {Number} onProgress.finish - The number of the items that are already completed.
|
||||
* @param {Number} onProgress.total - The total number of the items.
|
||||
* @param {Object} onProgress.item - The latest request item
|
||||
* @param {Function} [onComplete] - A callback which is called when all assets have been loaded, or an error occurs.
|
||||
* @param {Error} onComplete.error - If one of the asset failed, the complete callback is immediately called with the error. If all assets are preloaded successfully, error will be null.
|
||||
* @param {RequestItem[]} onComplete.items - An array of all preloaded items.
|
||||
*
|
||||
* @example
|
||||
* // preload all audios (resources/audios/)
|
||||
* cc.resources.preloadDir('audios', cc.AudioClip);
|
||||
*
|
||||
* // preload all textures in "resources/imgs/"
|
||||
* cc.resources.preloadDir('imgs', cc.Texture2D);
|
||||
* // wait for while
|
||||
* cc.resources.loadDir('imgs', cc.Texture2D, (err, textures) => {});
|
||||
*
|
||||
* // preload all prefabs (${project}/assets/bundle1/misc/characters/) from bundle1 folder
|
||||
* bundle1.preloadDir('misc/characters', cc.Prefab);
|
||||
*
|
||||
* // preload all sprite frame (${project}/assets/some/xxx/bundle2/skills/) from bundle2 folder
|
||||
* bundle2.preloadDir('skills', cc.SpriteFrame);
|
||||
* // wait for while
|
||||
* bundle2.loadDir('skills', cc.SpriteFrame, (err, spriteFrames) => {});
|
||||
*
|
||||
* @typescript
|
||||
* preloadDir(dir: string, type: typeof cc.Asset, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, items: RequestItem[]) => void): void
|
||||
* preloadDir(dir: string, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, items: RequestItem[]) => void): void
|
||||
* preloadDir(dir: string, type: typeof cc.Asset, onComplete: (error: Error, items: RequestItem[]) => void): void
|
||||
* preloadDir(dir: string, type: typeof cc.Asset): void
|
||||
* preloadDir(dir: string, onComplete: (error: Error, items: RequestItem[]) => void): void
|
||||
* preloadDir(dir: string): void
|
||||
*/
|
||||
preloadDir (dir, type, onProgress, onComplete) {
|
||||
var { type, onProgress, onComplete } = parseLoadResArgs(type, onProgress, onComplete);
|
||||
cc.assetManager.preloadAny(dir, { __requestType__: RequestType.DIR, type: type, bundle: this.name }, onProgress, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Loads the scene within this bundle by its name.
|
||||
*
|
||||
* !#zh
|
||||
* 通过场景名称加载分包中的场景。
|
||||
*
|
||||
* @method loadScene
|
||||
* @param {String} sceneName - The name of the scene to load.
|
||||
* @param {Object} [options] - Some optional parameters
|
||||
* @param {Function} [onProgress] - Callback invoked when progression change.
|
||||
* @param {Number} onProgress.finish - The number of the items that are already completed.
|
||||
* @param {Number} onProgress.total - The total number of the items.
|
||||
* @param {Object} onProgress.item - The latest request item
|
||||
* @param {Function} [onComplete] - callback, will be called after scene launched.
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {SceneAsset} onComplete.sceneAsset - The scene asset
|
||||
*
|
||||
* @example
|
||||
* bundle1.loadScene('first', (err, sceneAsset) => cc.director.runScene(sceneAsset));
|
||||
*
|
||||
* @typescript
|
||||
* loadScene(sceneName: string, options: Record<string, any>, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, sceneAsset: cc.SceneAsset) => void): void
|
||||
* loadScene(sceneName: string, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error, sceneAsset: cc.SceneAsset) => void): void
|
||||
* loadScene(sceneName: string, options: Record<string, any>, onComplete: (error: Error, sceneAsset: cc.SceneAsset) => void): void
|
||||
* loadScene(sceneName: string, onComplete: (error: Error, sceneAsset: cc.SceneAsset) => void): void
|
||||
* loadScene(sceneName: string, options: Record<string, any>): void
|
||||
* loadScene(sceneName: string): void
|
||||
*/
|
||||
loadScene (sceneName, options, onProgress, onComplete) {
|
||||
var { options, onProgress, onComplete } = parseParameters(options, onProgress, onComplete);
|
||||
|
||||
options.preset = options.preset || 'scene';
|
||||
options.bundle = this.name;
|
||||
cc.assetManager.loadAny({ 'scene': sceneName }, options, onProgress, function (err, sceneAsset) {
|
||||
if (err) {
|
||||
cc.error(err.message, err.stack);
|
||||
onComplete && onComplete(err);
|
||||
}
|
||||
else if (sceneAsset instanceof cc.SceneAsset) {
|
||||
var scene = sceneAsset.scene;
|
||||
scene._id = sceneAsset._uuid;
|
||||
scene._name = sceneAsset._name;
|
||||
onComplete && onComplete(null, sceneAsset);
|
||||
}
|
||||
else {
|
||||
onComplete && onComplete(new Error('The asset ' + sceneAsset._uuid + ' is not a scene'));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Preloads the scene within this bundle by its name. After calling this method, you still need to finish loading by calling `Bundle.loadScene` or `cc.director.loadScene`.
|
||||
* It will be totally fine to call `Bundle.loadDir` at any time even if the preloading is not yet finished
|
||||
*
|
||||
* !#zh
|
||||
* 通过场景名称预加载分包中的场景.调用完后,你仍然需要通过 `Bundle.loadScene` 或 `cc.director.loadScene` 来完成加载。
|
||||
* 就算预加载还没完成,你也可以直接调用 `Bundle.loadScene` 或 `cc.director.loadScene`。
|
||||
*
|
||||
* @method preloadScene
|
||||
* @param {String} sceneName - The name of the scene to preload.
|
||||
* @param {Object} [options] - Some optional parameters
|
||||
* @param {Function} [onProgress] - callback, will be called when the load progression change.
|
||||
* @param {Number} onProgress.finish - The number of the items that are already completed
|
||||
* @param {Number} onProgress.total - The total number of the items
|
||||
* @param {RequestItem} onProgress.item The latest request item
|
||||
* @param {Function} [onComplete] - callback, will be called after scene loaded.
|
||||
* @param {Error} onComplete.error - null or the error object.
|
||||
*
|
||||
* @example
|
||||
* bundle1.preloadScene('first');
|
||||
* // wait for a while
|
||||
* bundle1.loadScene('first', (err, scene) => cc.director.runScene(scene));
|
||||
*
|
||||
* @typescript
|
||||
* preloadScene(sceneName: string, options: Record<string, any>, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error) => void): void
|
||||
* preloadScene(sceneName: string, onProgress: (finish: number, total: number, item: RequestItem) => void, onComplete: (error: Error) => void): void
|
||||
* preloadScene(sceneName: string, options: Record<string, any>, onComplete: (error: Error) => void): void
|
||||
* preloadScene(sceneName: string, onComplete: (error: Error) => void): void
|
||||
* preloadScene(sceneName: string, options: Record<string, any>): void
|
||||
* preloadScene(sceneName: string): void
|
||||
*/
|
||||
preloadScene (sceneName, options, onProgress, onComplete) {
|
||||
var { options, onProgress, onComplete } = parseParameters(options, onProgress, onComplete);
|
||||
|
||||
options.bundle = this.name;
|
||||
cc.assetManager.preloadAny({'scene': sceneName}, options, onProgress, function (err) {
|
||||
if (err) {
|
||||
cc.errorID(1210, sceneName, err.message);
|
||||
}
|
||||
onComplete && onComplete(err);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get asset within this bundle by path and type. <br>
|
||||
* After you load asset with {{#crossLink "Bundle/load:method"}}{{/crossLink}} or {{#crossLink "Bundle/loadDir:method"}}{{/crossLink}},
|
||||
* you can acquire them by passing the path to this API.
|
||||
*
|
||||
* !#zh
|
||||
* 通过路径与类型获取资源。在你使用 {{#crossLink "Bundle/load:method"}}{{/crossLink}} 或者 {{#crossLink "Bundle/loadDir:method"}}{{/crossLink}} 之后,
|
||||
* 你能通过传路径通过这个 API 获取到这些资源。
|
||||
*
|
||||
* @method get
|
||||
* @param {String} path - The path of asset
|
||||
* @param {Function} [type] - Only asset of type will be returned if this argument is supplied.
|
||||
* @returns {Asset}
|
||||
*
|
||||
* @example
|
||||
* bundle1.get('music/hit', cc.AudioClip);
|
||||
*
|
||||
* @typescript
|
||||
* get<T extends cc.Asset> (path: string, type?: { prototype: T }): T
|
||||
*/
|
||||
get (path, type) {
|
||||
var info = this.getInfoWithPath(path, type);
|
||||
return assets.get(info && info.uuid);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Release the asset loaded by {{#crossLink "Bundle/load:method"}}{{/crossLink}} or {{#crossLink "Bundle/loadDir:method"}}{{/crossLink}} and it's dependencies.
|
||||
* Refer to {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}} for detailed informations.
|
||||
*
|
||||
* !#zh
|
||||
* 释放通过 {{#crossLink "Bundle/load:method"}}{{/crossLink}} 或者 {{#crossLink "Bundle/loadDir:method"}}{{/crossLink}} 加载的资源。详细信息请参考 {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}}
|
||||
*
|
||||
* @method release
|
||||
* @param {String} path - The path of asset
|
||||
* @param {Function} [type] - Only asset of type will be released if this argument is supplied.
|
||||
*
|
||||
* @example
|
||||
* // release a texture which is no longer need
|
||||
* bundle1.release('misc/character/cocos');
|
||||
*
|
||||
* @typescript
|
||||
* release(path: string, type: typeof cc.Asset): void
|
||||
* release(path: string): void
|
||||
*/
|
||||
release (path, type) {
|
||||
releaseManager.tryRelease(this.get(path, type), true);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Release all unused assets within this bundle. Refer to {{#crossLink "AssetManager/releaseAll:method"}}{{/crossLink}} for detailed informations.
|
||||
*
|
||||
* !#zh
|
||||
* 释放此包中的所有没有用到的资源。详细信息请参考 {{#crossLink "AssetManager/releaseAll:method"}}{{/crossLink}}
|
||||
*
|
||||
* @method releaseUnusedAssets
|
||||
* @private
|
||||
*
|
||||
* @example
|
||||
* // release all unused asset within bundle1
|
||||
* bundle1.releaseUnusedAssets();
|
||||
*
|
||||
* @typescript
|
||||
* releaseUnusedAssets(): void
|
||||
*/
|
||||
releaseUnusedAssets () {
|
||||
var self = this;
|
||||
assets.forEach(function (asset) {
|
||||
let info = self.getAssetInfo(asset._uuid);
|
||||
if (info && !info.redirect) {
|
||||
releaseManager.tryRelease(asset);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Release all assets within this bundle. Refer to {{#crossLink "AssetManager/releaseAll:method"}}{{/crossLink}} for detailed informations.
|
||||
*
|
||||
* !#zh
|
||||
* 释放此包中的所有资源。详细信息请参考 {{#crossLink "AssetManager/releaseAll:method"}}{{/crossLink}}
|
||||
*
|
||||
* @method releaseAll
|
||||
*
|
||||
* @example
|
||||
* // release all asset within bundle1
|
||||
* bundle1.releaseAll();
|
||||
*
|
||||
* @typescript
|
||||
* releaseAll(): void
|
||||
*/
|
||||
releaseAll () {
|
||||
var self = this;
|
||||
assets.forEach(function (asset) {
|
||||
let info = self.getAssetInfo(asset._uuid);
|
||||
if (info && !info.redirect) {
|
||||
releaseManager.tryRelease(asset, true);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_destroy () {
|
||||
this._config.destroy();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = Bundle;
|
154
engine/cocos2d/core/asset-manager/cache-manager.ts
Normal file
154
engine/cocos2d/core/asset-manager/cache-manager.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import Cache from './cache';
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Cache manager is a module which controls all caches downloaded from server in non-web platform, it is a singleton
|
||||
* All member can be accessed with `cc.assetManager.cacheManager`.
|
||||
*
|
||||
* !#zh
|
||||
* 缓存管理器是一个模块,在非 WEB 平台上,用于管理所有从服务器上下载下来的缓存,这是一个单例,所有成员能通过 `cc.assetManager.cacheManager` 访问。
|
||||
*
|
||||
* @class CacheManager
|
||||
*/
|
||||
export abstract class CacheManager {
|
||||
/**
|
||||
* !#en
|
||||
* The name of cacheDir
|
||||
*
|
||||
* !#zh
|
||||
* 缓存目录的名称
|
||||
*
|
||||
* @property cacheDir
|
||||
* @type {String}
|
||||
* @default 'gamecaches'
|
||||
*/
|
||||
public abstract cacheDir: String;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Whether or not cache asset into user's storage space, this property only works on mini-game platforms
|
||||
*
|
||||
* !#zh
|
||||
* 是否缓存资源到用户存储空间,此属性只在小游戏平台有效
|
||||
*
|
||||
* @property cacheEnabled
|
||||
* @type {Boolean}
|
||||
* @default true
|
||||
*/
|
||||
public abstract cacheEnabled: Boolean;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Whether or not auto clear cache when storage ran out, this property only works on mini-game platforms
|
||||
*
|
||||
* !#zh
|
||||
* 是否在存储空间满了后自动清理缓存,此属性只在小游戏平台有效
|
||||
*
|
||||
* @property autoClear
|
||||
* @type {Boolean}
|
||||
* @default true
|
||||
*/
|
||||
public abstract autoClear: Boolean;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The interval between caching resources, this property only works on mini-game platforms, unit: ms
|
||||
*
|
||||
* !#zh
|
||||
* 缓存资源的间隔时间,此属性只在小游戏平台有效,单位:ms
|
||||
*
|
||||
* @property cacheInterval
|
||||
* @type {Number}
|
||||
* @default 500
|
||||
*/
|
||||
public abstract cacheInterval: Number;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The interval between deleting resources, when you use `cleanLRU`, the resources will be deleted as this interval, unit: ms
|
||||
*
|
||||
* !#zh
|
||||
* 清理资源的间隔时间,当你使用 `cleanLRU` 时,资源将以此间隔被删除,单位:ms
|
||||
*
|
||||
* @property deleteInterval
|
||||
* @type {Number}
|
||||
* @default 500
|
||||
*/
|
||||
public abstract deleteInterval: Number;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* List of all cached files
|
||||
*
|
||||
* !#zh
|
||||
* 所有缓存文件列表
|
||||
*
|
||||
* @property cachedFiles
|
||||
* @type {Cache}
|
||||
* @typescript
|
||||
* cachedFiles: Cache<{ bundle: string, url: string, lastTime: number }>
|
||||
*/
|
||||
public abstract cachedFiles: Cache;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get cached path with origin url
|
||||
*
|
||||
* !#zh
|
||||
* 通过原始 url 获取缓存后的路径
|
||||
*
|
||||
* @method getCache
|
||||
* @param {string} originUrl
|
||||
* @returns {String} The cached path
|
||||
*/
|
||||
public abstract getCache (originUrl: string): string;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get temporary path with origin url, this method only works on mini-game platforms
|
||||
*
|
||||
* !#zh
|
||||
* 通过原始 url 获取临时文件的路径,此方法只在小游戏平台有效
|
||||
*
|
||||
* @method getTemp
|
||||
* @param {string} originUrl
|
||||
* @returns {String} The temp path
|
||||
*/
|
||||
public abstract getTemp (originUrl: string): string;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Clear all caches, please use with caution, If necessary, we recommend using it before the game is launched
|
||||
*
|
||||
* !#zh
|
||||
* 清空所有缓存,请谨慎使用,如果必要的话,我们建议在游戏启动之前使用
|
||||
*
|
||||
* @method clearCache
|
||||
*/
|
||||
public abstract clearCache (): void;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Clear part of caches with LRU strategy
|
||||
*
|
||||
* !#zh
|
||||
* 使用 LRU 策略清空部分缓存
|
||||
*
|
||||
* @method clearLRU
|
||||
*/
|
||||
public abstract clearLRU (): void;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Remove cache with origin url
|
||||
*
|
||||
* !#zh
|
||||
* 通过原始 url 移除缓存
|
||||
*
|
||||
* @method removeCache
|
||||
*/
|
||||
public abstract removeCache (originUrl: string): void;
|
||||
}
|
267
engine/cocos2d/core/asset-manager/cache.js
Normal file
267
engine/cocos2d/core/asset-manager/cache.js
Normal file
@@ -0,0 +1,267 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
|
||||
const js = require('../platform/js');
|
||||
/**
|
||||
* !#en
|
||||
* use to cache something
|
||||
*
|
||||
* !#zh
|
||||
* 用于缓存某些内容
|
||||
*
|
||||
* @class Cache
|
||||
* @typescript Cache<T = any>
|
||||
*/
|
||||
function Cache (map) {
|
||||
if (map) {
|
||||
this._map = map;
|
||||
this._count = Object.keys(map).length;
|
||||
}
|
||||
else {
|
||||
this._map = js.createMap(true);
|
||||
this._count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Cache.prototype = {
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Create a cache
|
||||
*
|
||||
* !#zh
|
||||
* 创建一个 cache
|
||||
*
|
||||
* @method constructor
|
||||
* @param {Object} [map] - An object used to initialize
|
||||
*
|
||||
* @typescript
|
||||
* constructor(map?: Record<string, T>)
|
||||
*/
|
||||
constructor: Cache,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Add Key-Value to cache
|
||||
*
|
||||
* !#zh
|
||||
* 增加键值对到缓存中
|
||||
*
|
||||
* @method add
|
||||
* @param {String} key - The key
|
||||
* @param {*} val - The value
|
||||
* @returns {*} The value
|
||||
*
|
||||
* @example
|
||||
* var cache = new Cache();
|
||||
* cache.add('test', null);
|
||||
*
|
||||
* @typescript
|
||||
* add(key: string, val: T): T
|
||||
*/
|
||||
add (key, val) {
|
||||
if (!(key in this._map)) this._count++;
|
||||
return this._map[key] = val;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get the cached content by key
|
||||
*
|
||||
* !#zh
|
||||
* 通过 key 获取对应的 value
|
||||
*
|
||||
* @method get
|
||||
* @param {string} key - The key
|
||||
* @returns {*} The corresponding content
|
||||
*
|
||||
* @example
|
||||
* var cache = new Cache();
|
||||
* var test = cache.get('test');
|
||||
*
|
||||
* @typescript
|
||||
* get(key: string): T
|
||||
*/
|
||||
get (key) {
|
||||
return this._map[key];
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Check whether or not content exists by key
|
||||
*
|
||||
* !#zh
|
||||
* 通过 Key 判断是否存在对应的内容
|
||||
*
|
||||
* @method has
|
||||
* @param {string} key - The key
|
||||
* @returns {boolean} True indecates that content of the key exists
|
||||
*
|
||||
* @example
|
||||
* var cache = new Cache();
|
||||
* var exist = cache.has('test');
|
||||
*
|
||||
* @typescript
|
||||
* has(key: string): boolean
|
||||
*/
|
||||
has (key) {
|
||||
return key in this._map;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Remove the cached content by key
|
||||
*
|
||||
* !#zh
|
||||
* 通过 Key 移除对应的内容
|
||||
*
|
||||
* @method remove
|
||||
* @param {string} key - The key
|
||||
* @returns {*} The removed content
|
||||
*
|
||||
* @example
|
||||
* var cache = new Cache();
|
||||
* var content = cache.remove('test');
|
||||
*
|
||||
* @typescript
|
||||
* remove(key: string): T
|
||||
*/
|
||||
remove (key) {
|
||||
var out = this._map[key];
|
||||
if (key in this._map) {
|
||||
delete this._map[key];
|
||||
this._count--;
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Clear all content
|
||||
*
|
||||
* !#zh
|
||||
* 清除所有内容
|
||||
*
|
||||
* @method clear
|
||||
*
|
||||
* @example
|
||||
* var cache = new Cache();
|
||||
* cache.clear();
|
||||
*
|
||||
* @typescript
|
||||
* clear():void
|
||||
*/
|
||||
clear () {
|
||||
if (this._count !== 0) {
|
||||
this._map = js.createMap(true);
|
||||
this._count = 0;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Enumerate all content and invoke function
|
||||
*
|
||||
* !#zh
|
||||
* 枚举所有内容并执行方法
|
||||
*
|
||||
* @method forEach
|
||||
* @param {Function} func - Function to be invoked
|
||||
* @param {*} func.val - The value
|
||||
* @param {String} func.key - The corresponding key
|
||||
*
|
||||
* @example
|
||||
* var cache = new Cache();
|
||||
* cache.forEach((val, key) => console.log(key));
|
||||
*
|
||||
* @typescript
|
||||
* forEach(func: (val: T, key: string) => void): void
|
||||
*/
|
||||
forEach (func) {
|
||||
for (var key in this._map) {
|
||||
func(this._map[key], key);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Enumerate all content to find one element which can fulfill condition
|
||||
*
|
||||
* !#zh
|
||||
* 枚举所有内容,找到一个可以满足条件的元素
|
||||
*
|
||||
* @method find
|
||||
* @param {Function} predicate - The condition
|
||||
* @returns {*} content
|
||||
*
|
||||
* @example
|
||||
* var cache = new Cache();
|
||||
* var val = cache.find((val, key) => key === 'test');
|
||||
*
|
||||
* @typescript
|
||||
* find(predicate: (val: T, key: string) => boolean): T
|
||||
*/
|
||||
find (predicate) {
|
||||
for (var key in this._map) {
|
||||
if (predicate(this._map[key], key)) return this._map[key];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The count of cached content
|
||||
*
|
||||
* !#zh
|
||||
* 缓存数量
|
||||
*
|
||||
* @property count
|
||||
* @type {Number}
|
||||
*/
|
||||
get count () {
|
||||
return this._count;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Destroy this cache
|
||||
*
|
||||
* !#zh
|
||||
* 销毁这个 cache
|
||||
*
|
||||
* @method destroy
|
||||
*
|
||||
* @typescript
|
||||
* destroy(): void
|
||||
*/
|
||||
destroy () {
|
||||
this._map = null;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Cache;
|
257
engine/cocos2d/core/asset-manager/config.js
Normal file
257
engine/cocos2d/core/asset-manager/config.js
Normal file
@@ -0,0 +1,257 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const js = require('../platform/js');
|
||||
const Cache = require('./cache');
|
||||
const { normalize } = require('./helper');
|
||||
const { processOptions } = require('./utilities');
|
||||
|
||||
function Config () {
|
||||
|
||||
this.name = '';
|
||||
|
||||
this.base = '';
|
||||
|
||||
this.importBase = '';
|
||||
|
||||
this.nativeBase = '';
|
||||
|
||||
this.deps = null;
|
||||
|
||||
this.assetInfos = new Cache();
|
||||
|
||||
this.scenes = new Cache();
|
||||
|
||||
this.paths = new Cache();
|
||||
}
|
||||
|
||||
Config.prototype = {
|
||||
|
||||
constructor: Config,
|
||||
|
||||
init: function (options) {
|
||||
processOptions(options);
|
||||
|
||||
this.importBase = options.importBase || '';
|
||||
this.nativeBase = options.nativeBase || '';
|
||||
this.base = options.base || '';
|
||||
this.name = options.name || '';
|
||||
this.deps = options.deps || [];
|
||||
// init
|
||||
this._initUuid(options.uuids);
|
||||
this._initPath(options.paths);
|
||||
this._initScene(options.scenes);
|
||||
this._initPackage(options.packs);
|
||||
this._initVersion(options.versions);
|
||||
this._initRedirect(options.redirect);
|
||||
},
|
||||
|
||||
_initUuid: function (uuidList) {
|
||||
if (!uuidList) return;
|
||||
this.assetInfos.clear();
|
||||
for (var i = 0, l = uuidList.length; i < l; i++) {
|
||||
var uuid = uuidList[i];
|
||||
this.assetInfos.add(uuid, {uuid});
|
||||
}
|
||||
},
|
||||
|
||||
_initPath: function (pathList) {
|
||||
if (!pathList) return;
|
||||
var paths = this.paths;
|
||||
paths.clear();
|
||||
for (var uuid in pathList) {
|
||||
var info = pathList[uuid];
|
||||
var path = info[0];
|
||||
var type = info[1];
|
||||
var isSubAsset = info.length === 3;
|
||||
|
||||
var assetInfo = this.assetInfos.get(uuid);
|
||||
assetInfo.path = path;
|
||||
assetInfo.ctor = js._getClassById(type);
|
||||
if (paths.has(path)) {
|
||||
if (isSubAsset) {
|
||||
paths.get(path).push(assetInfo);
|
||||
}
|
||||
else {
|
||||
paths.get(path).unshift(assetInfo);
|
||||
}
|
||||
}
|
||||
else {
|
||||
paths.add(path, [assetInfo]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_initScene: function (sceneList) {
|
||||
if (!sceneList) return;
|
||||
var scenes = this.scenes;
|
||||
scenes.clear();
|
||||
var assetInfos = this.assetInfos;
|
||||
for (var sceneName in sceneList) {
|
||||
var uuid = sceneList[sceneName];
|
||||
var assetInfo = assetInfos.get(uuid);
|
||||
assetInfo.url = sceneName;
|
||||
scenes.add(sceneName, assetInfo);
|
||||
}
|
||||
},
|
||||
|
||||
_initPackage: function (packageList) {
|
||||
if (!packageList) return;
|
||||
var assetInfos = this.assetInfos;
|
||||
for (var packUuid in packageList) {
|
||||
var uuids = packageList[packUuid];
|
||||
var pack = {uuid: packUuid, packs: uuids, ext:'.json'};
|
||||
assetInfos.add(packUuid, pack);
|
||||
|
||||
for (var i = 0, l = uuids.length; i < l; i++) {
|
||||
var uuid = uuids[i];
|
||||
var assetInfo = assetInfos.get(uuid);
|
||||
var assetPacks = assetInfo.packs;
|
||||
if (assetPacks) {
|
||||
if (l === 1) {
|
||||
assetPacks.unshift(pack);
|
||||
}
|
||||
else {
|
||||
assetPacks.push(pack);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assetInfo.packs = [pack];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_initVersion: function (versions) {
|
||||
if (!versions) return;
|
||||
var assetInfos = this.assetInfos;
|
||||
var entries = versions.import;
|
||||
if (entries) {
|
||||
for (var i = 0, l = entries.length; i < l; i += 2) {
|
||||
var uuid = entries[i];
|
||||
var assetInfo = assetInfos.get(uuid);
|
||||
assetInfo.ver = entries[i + 1];
|
||||
}
|
||||
}
|
||||
entries = versions.native;
|
||||
if (entries) {
|
||||
for (var i = 0, l = entries.length; i < l; i += 2) {
|
||||
var uuid = entries[i];
|
||||
var assetInfo = assetInfos.get(uuid);
|
||||
assetInfo.nativeVer = entries[i + 1];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_initRedirect: function (redirect) {
|
||||
if (!redirect) return;
|
||||
var assetInfos = this.assetInfos;
|
||||
for (var i = 0, l = redirect.length; i < l; i += 2) {
|
||||
var uuid = redirect[i];
|
||||
var assetInfo = assetInfos.get(uuid);
|
||||
assetInfo.redirect = redirect[i + 1];
|
||||
}
|
||||
},
|
||||
|
||||
getInfoWithPath: function (path, type) {
|
||||
|
||||
if (!path) {
|
||||
return null;
|
||||
}
|
||||
path = normalize(path);
|
||||
var items = this.paths.get(path);
|
||||
if (items) {
|
||||
if (type) {
|
||||
for (var i = 0, l = items.length; i < l; i++) {
|
||||
var assetInfo = items[i];
|
||||
if (js.isChildClassOf(assetInfo.ctor, type)) {
|
||||
return assetInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return items[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
getDirWithPath: function (path, type, out) {
|
||||
path = normalize(path);
|
||||
if (path[path.length - 1] === '/') {
|
||||
path = path.slice(0, -1);
|
||||
}
|
||||
|
||||
var infos = out || [];
|
||||
function isMatchByWord (path, test) {
|
||||
if (path.length > test.length) {
|
||||
var nextAscii = path.charCodeAt(test.length);
|
||||
return nextAscii === 47; // '/'
|
||||
}
|
||||
return true;
|
||||
}
|
||||
this.paths.forEach(function (items, p) {
|
||||
if ((p.startsWith(path) && isMatchByWord(p, path)) || !path) {
|
||||
for (var i = 0, l = items.length; i < l; i++) {
|
||||
var entry = items[i];
|
||||
if (!type || js.isChildClassOf(entry.ctor, type)) {
|
||||
infos.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return infos;
|
||||
},
|
||||
|
||||
getAssetInfo: function (uuid) {
|
||||
return this.assetInfos.get(uuid);
|
||||
},
|
||||
|
||||
getSceneInfo: function (name) {
|
||||
if (!name.endsWith('.fire')) {
|
||||
name += '.fire';
|
||||
}
|
||||
if (name[0] !== '/' && !name.startsWith('db://')) {
|
||||
name = '/' + name; // 使用全名匹配
|
||||
}
|
||||
// search scene
|
||||
var info = this.scenes.find(function (val, key) {
|
||||
return key.endsWith(name);
|
||||
});
|
||||
return info;
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.paths.destroy();
|
||||
this.scenes.destroy();
|
||||
this.assetInfos.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
if (CC_TEST) {
|
||||
cc._Test.Config = Config;
|
||||
}
|
||||
|
||||
module.exports = Config;
|
246
engine/cocos2d/core/asset-manager/depend-util.js
Normal file
246
engine/cocos2d/core/asset-manager/depend-util.js
Normal file
@@ -0,0 +1,246 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const Cache = require('./cache');
|
||||
const deserialize = require('./deserialize');
|
||||
const { files, parsed } = require('./shared');
|
||||
import { hasNativeDep , getDependUuidList } from '../platform/deserialize-compiled';
|
||||
import deserializeForCompiled from '../platform/deserialize-compiled';
|
||||
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
/**
|
||||
* !#en
|
||||
* Control asset's dependency list, it is a singleton. All member can be accessed with `cc.assetManager.dependUtil`
|
||||
*
|
||||
* !#zh
|
||||
* 控制资源的依赖列表,这是一个单例, 所有成员能通过 `cc.assetManager.dependUtil` 访问
|
||||
*
|
||||
* @class DependUtil
|
||||
*/
|
||||
var dependUtil = {
|
||||
_depends: new Cache(),
|
||||
|
||||
init () {
|
||||
this._depends.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get asset's native dependency. For example, Texture's native dependency is image.
|
||||
*
|
||||
* !#zh
|
||||
* 获取资源的原生依赖,例如 Texture 的原生依赖是图片
|
||||
*
|
||||
* @method getNativeDep
|
||||
* @param {string} uuid - asset's uuid
|
||||
* @returns {Object} native dependency
|
||||
*
|
||||
* @example
|
||||
* var dep = dependUtil.getNativeDep('fcmR3XADNLgJ1ByKhqcC5Z');
|
||||
*
|
||||
* @typescript
|
||||
* getNativeDep(uuid: string): Record<string, any>
|
||||
*/
|
||||
getNativeDep (uuid) {
|
||||
let depend = this._depends.get(uuid);
|
||||
if (depend) return depend.nativeDep && Object.assign({}, depend.nativeDep);
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get asset's direct referencing non-native dependency list. For example, Material's non-native dependencies are Texture.
|
||||
*
|
||||
* !#zh
|
||||
* 获取资源直接引用的非原生依赖列表,例如,材质的非原生依赖是 Texture
|
||||
*
|
||||
* @method getDeps
|
||||
* @param {string} uuid - asset's uuid
|
||||
* @returns {string[]} direct referencing non-native dependency list
|
||||
*
|
||||
* @example
|
||||
* var deps = dependUtil.getDeps('fcmR3XADNLgJ1ByKhqcC5Z');
|
||||
*
|
||||
* @typescript
|
||||
* getDeps(uuid: string): string[]
|
||||
*/
|
||||
getDeps (uuid) {
|
||||
if (this._depends.has(uuid)) {
|
||||
return this._depends.get(uuid).deps;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get non-native dependency list of the loaded asset, include indirect reference.
|
||||
* The returned array stores the dependencies with their uuid, after retrieve dependencies,
|
||||
*
|
||||
* !#zh
|
||||
* 获取某个已经加载好的资源的所有非原生依赖资源列表,包括间接引用的资源,并保存在数组中返回。
|
||||
* 返回的数组将仅保存依赖资源的 uuid。
|
||||
*
|
||||
* @method getDependsRecursively
|
||||
* @param {String} uuid - The asset's uuid
|
||||
* @returns {string[]} non-native dependency list
|
||||
*
|
||||
* @example
|
||||
* var deps = dependUtil.getDepsRecursively('fcmR3XADNLgJ1ByKhqcC5Z');
|
||||
*
|
||||
* @typescript
|
||||
* getDepsRecursively(uuid: string): string[]
|
||||
*/
|
||||
getDepsRecursively (uuid) {
|
||||
var exclude = Object.create(null), depends = [];
|
||||
this._descend(uuid, exclude, depends);
|
||||
return depends;
|
||||
},
|
||||
|
||||
_descend (uuid, exclude, depends) {
|
||||
var deps = this.getDeps(uuid);
|
||||
for (var i = 0; i < deps.length; i++) {
|
||||
var depend = deps[i];
|
||||
if ( !exclude[depend] ) {
|
||||
exclude[depend] = true;
|
||||
depends.push(depend);
|
||||
this._descend(depend, exclude, depends);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
remove (uuid) {
|
||||
this._depends.remove(uuid);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Extract dependency list from serialized data or asset and then store in cache.
|
||||
*
|
||||
* !#zh
|
||||
* 从序列化数据或资源中提取出依赖列表,并且存储在缓存中。
|
||||
*
|
||||
* @param {string} uuid - The uuid of serialized data or asset
|
||||
* @param {Object} json - Serialized data or asset
|
||||
* @returns {Object} dependency list, include non-native and native dependency
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('test.json', {responseType: 'json'}, null, (err, file) => {
|
||||
* var dependencies = parse('fcmR3XADNLgJ1ByKhqcC5Z', file);
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* parse(uuid: string, json: any): { deps?: string[], nativeDep?: any }
|
||||
*/
|
||||
parse (uuid, json) {
|
||||
var out = null;
|
||||
if (Array.isArray(json) || json.__type__) {
|
||||
|
||||
if (out = this._depends.get(uuid)) return out;
|
||||
|
||||
if (Array.isArray(json) && (!(CC_BUILD || deserializeForCompiled.isCompiledJson(json)) || !hasNativeDep(json))) {
|
||||
out = {
|
||||
deps: this._parseDepsFromJson(json),
|
||||
};
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var asset = deserialize(json);
|
||||
out = this._parseDepsFromAsset(asset);
|
||||
out.nativeDep && (out.nativeDep.uuid = uuid);
|
||||
parsed.add(uuid + '@import', asset);
|
||||
}
|
||||
catch (e) {
|
||||
files.remove(uuid + '@import');
|
||||
out = { deps: [] };
|
||||
}
|
||||
}
|
||||
}
|
||||
// get deps from an existing asset
|
||||
else {
|
||||
if (!CC_EDITOR && (out = this._depends.get(uuid)) && out.parsedFromExistAsset) return out;
|
||||
out = this._parseDepsFromAsset(json);
|
||||
}
|
||||
// cache dependency list
|
||||
this._depends.add(uuid, out);
|
||||
return out;
|
||||
},
|
||||
|
||||
_parseDepsFromAsset: function (asset) {
|
||||
var out = {
|
||||
deps: [],
|
||||
parsedFromExistAsset: true,
|
||||
preventPreloadNativeObject: asset.constructor.preventPreloadNativeObject,
|
||||
preventDeferredLoadDependents: asset.constructor.preventDeferredLoadDependents
|
||||
};
|
||||
let deps = asset.__depends__;
|
||||
for (var i = 0, l = deps.length; i < l; i++) {
|
||||
var dep = deps[i].uuid;
|
||||
out.deps.push(dep);
|
||||
}
|
||||
|
||||
if (asset.__nativeDepend__) {
|
||||
out.nativeDep = asset._nativeDep;
|
||||
}
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
_parseDepsFromJson: CC_EDITOR || CC_PREVIEW ? function (json) {
|
||||
|
||||
if (deserializeForCompiled.isCompiledJson(json)) {
|
||||
let depends = getDependUuidList(json);
|
||||
depends.forEach((uuid, index) => depends[index] = cc.assetManager.utils.decodeUuid(uuid));
|
||||
return depends;
|
||||
}
|
||||
|
||||
var depends = [];
|
||||
function parseDependRecursively (data, out) {
|
||||
if (!data || typeof data !== 'object' || data.__id__) return;
|
||||
var uuid = data.__uuid__;
|
||||
if (Array.isArray(data)) {
|
||||
for (let i = 0, l = data.length; i < l; i++) {
|
||||
parseDependRecursively(data[i], out);
|
||||
}
|
||||
}
|
||||
else if (uuid) {
|
||||
out.push(cc.assetManager.utils.decodeUuid(uuid));
|
||||
}
|
||||
else {
|
||||
for (var prop in data) {
|
||||
parseDependRecursively(data[prop], out);
|
||||
}
|
||||
}
|
||||
}
|
||||
parseDependRecursively(json, depends);
|
||||
return depends;
|
||||
} : function (json) {
|
||||
let depends = getDependUuidList(json);
|
||||
depends.forEach((uuid, index) => depends[index] = cc.assetManager.utils.decodeUuid(uuid));
|
||||
return depends;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = dependUtil;
|
793
engine/cocos2d/core/asset-manager/deprecated.js
Normal file
793
engine/cocos2d/core/asset-manager/deprecated.js
Normal file
@@ -0,0 +1,793 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
const js = require('../platform/js');
|
||||
require('../CCDirector');
|
||||
const utilities = require('./utilities');
|
||||
const dependUtil = require('./depend-util');
|
||||
const releaseManager = require('./releaseManager');
|
||||
const downloader = require('./downloader');
|
||||
const factory = require('./factory');
|
||||
const helper = require('./helper');
|
||||
|
||||
const ImageFmts = ['.png', '.jpg', '.bmp', '.jpeg', '.gif', '.ico', '.tiff', '.webp', '.image', '.pvr', '.pkm'];
|
||||
const AudioFmts = ['.mp3', '.ogg', '.wav', '.m4a'];
|
||||
|
||||
function GetTrue () { return true; }
|
||||
|
||||
const md5Pipe = {
|
||||
transformURL (url) {
|
||||
let uuid = helper.getUuidFromURL(url);
|
||||
if (!uuid) { return url; }
|
||||
let bundle = cc.assetManager.bundles.find((b) => {
|
||||
return !!b.getAssetInfo(uuid);
|
||||
});
|
||||
if (!bundle) { return url; }
|
||||
let hashValue = '';
|
||||
let info = bundle.getAssetInfo(uuid);
|
||||
if (url.startsWith(bundle.base + bundle._config.nativeBase)) {
|
||||
hashValue = info.nativeVer || '';
|
||||
}
|
||||
else {
|
||||
hashValue = info.ver || '';
|
||||
}
|
||||
if (!hashValue || url.indexOf(hashValue) !== -1) { return url; }
|
||||
let hashPatchInFolder = false;
|
||||
if (cc.path.extname(url) === '.ttf') {
|
||||
hashPatchInFolder = true;
|
||||
}
|
||||
if (hashPatchInFolder) {
|
||||
let dirname = cc.path.dirname(url);
|
||||
let basename = cc.path.basename(url);
|
||||
url = `${dirname}.${hashValue}/${basename}`;
|
||||
} else {
|
||||
url = url.replace(/.*[/\\][0-9a-fA-F]{2}[/\\]([0-9a-fA-F-]{8,})/, (match, uuid) => {
|
||||
return match + '.' + hashValue;
|
||||
});
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* `cc.loader` is deprecated, please backup your project and upgrade to {{#crossLink "AssetManager"}}{{/crossLink}}
|
||||
*
|
||||
* @class loader
|
||||
* @static
|
||||
* @deprecated cc.loader is deprecated, please backup your project and upgrade to cc.assetManager
|
||||
*/
|
||||
const loader = {
|
||||
/**
|
||||
* `cc.loader.onProgress` is deprecated, please transfer onProgress to API as a parameter
|
||||
* @property onProgress
|
||||
* @deprecated cc.loader.onProgress is deprecated, please transfer onProgress to API as a parameter
|
||||
*/
|
||||
onProgress: null,
|
||||
_autoReleaseSetting: Object.create(null),
|
||||
|
||||
get _cache () {
|
||||
return cc.assetManager.assets._map;
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.load` is deprecated, please use {{#crossLink "AssetManager/loadAny:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.load is deprecated, please use cc.assetManager.loadAny instead
|
||||
*
|
||||
* @method load
|
||||
* @param {String|String[]|Object} resources - Url list in an array
|
||||
* @param {Function} [progressCallback] - Callback invoked when progression change
|
||||
* @param {Number} progressCallback.completedCount - The number of the items that are already completed
|
||||
* @param {Number} progressCallback.totalCount - The total number of the items
|
||||
* @param {Object} progressCallback.item - The latest item which flow out the pipeline
|
||||
* @param {Function} [completeCallback] - Callback invoked when all resources loaded
|
||||
* @typescript
|
||||
* load(resources: string|string[]|{uuid?: string, url?: string, type?: string}, completeCallback?: Function): void
|
||||
* load(resources: string|string[]|{uuid?: string, url?: string, type?: string}, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: Function|null): void
|
||||
*/
|
||||
load (resources, progressCallback, completeCallback) {
|
||||
if (completeCallback === undefined) {
|
||||
if (progressCallback !== undefined) {
|
||||
completeCallback = progressCallback;
|
||||
progressCallback = null;
|
||||
}
|
||||
}
|
||||
resources = Array.isArray(resources) ? resources : [resources];
|
||||
for (var i = 0; i < resources.length; i++) {
|
||||
var item = resources[i];
|
||||
if (typeof item === 'string') {
|
||||
resources[i] = { url: item, __isNative__: true};
|
||||
}
|
||||
else {
|
||||
if (item.type) {
|
||||
item.ext = '.' + item.type;
|
||||
item.type = undefined;
|
||||
}
|
||||
|
||||
if (item.url) {
|
||||
item.__isNative__ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
var images = [];
|
||||
var audios = [];
|
||||
cc.assetManager.loadAny(resources, null, (finish, total, item) => {
|
||||
if (item.content) {
|
||||
if (ImageFmts.includes(item.ext)) {
|
||||
images.push(item.content);
|
||||
}
|
||||
else if (AudioFmts.includes(item.ext)) {
|
||||
audios.push(item.content);
|
||||
}
|
||||
}
|
||||
progressCallback && progressCallback(finish, total, item);
|
||||
}, (err, native) => {
|
||||
var res = null;
|
||||
if (!err) {
|
||||
native = Array.isArray(native) ? native : [native];
|
||||
for (var i = 0; i < native.length; i++) {
|
||||
var item = native[i];
|
||||
if (!(item instanceof cc.Asset)) {
|
||||
var asset = item;
|
||||
var url = resources[i].url;
|
||||
if (images.includes(asset)) {
|
||||
factory.create(url, item, '.png', null, (err, image) => {
|
||||
asset = native[i] = image;
|
||||
});
|
||||
}
|
||||
else if (audios.includes(asset)) {
|
||||
factory.create(url, item, '.mp3', null, (err, audio) => {
|
||||
asset = native[i] = audio;
|
||||
});
|
||||
}
|
||||
cc.assetManager.assets.add(url, asset);
|
||||
}
|
||||
}
|
||||
if (native.length > 1) {
|
||||
var map = Object.create(null);
|
||||
native.forEach(function (asset) {
|
||||
map[asset._uuid] = asset;
|
||||
});
|
||||
res = { isCompleted: GetTrue, _map: map };
|
||||
}
|
||||
else {
|
||||
res = native[0];
|
||||
}
|
||||
}
|
||||
completeCallback && completeCallback(err, res);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.getXMLHttpRequest` is deprecated, please use `XMLHttpRequest` directly
|
||||
*
|
||||
* @method getXMLHttpRequest
|
||||
* @deprecated cc.loader.getXMLHttpRequest is deprecated, please use XMLHttpRequest directly
|
||||
* @returns {XMLHttpRequest}
|
||||
*/
|
||||
getXMLHttpRequest () {
|
||||
return new XMLHttpRequest();
|
||||
},
|
||||
|
||||
_parseLoadResArgs: utilities.parseLoadResArgs,
|
||||
|
||||
/**
|
||||
* `cc.loader.getItem` is deprecated, please use `cc.assetManager.asset.get` instead
|
||||
*
|
||||
* @method getItem
|
||||
* @param {Object} id The id of the item
|
||||
* @return {Object}
|
||||
* @deprecated cc.loader.getItem is deprecated, please use cc.assetManager.assets.get instead
|
||||
*/
|
||||
getItem (key) {
|
||||
return cc.assetManager.assets.has(key) ? { content: cc.assetManager.assets.get(key) } : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.loadRes` is deprecated, please use {{#crossLink "Bundle/load:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.loadRes is deprecated, please use cc.resources.load instead
|
||||
* @method loadRes
|
||||
* @param {String} url - Url of the target resource.
|
||||
* The url is relative to the "resources" folder, extensions must be omitted.
|
||||
* @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.
|
||||
* @param {Function} [progressCallback] - Callback invoked when progression change.
|
||||
* @param {Number} progressCallback.completedCount - The number of the items that are already completed.
|
||||
* @param {Number} progressCallback.totalCount - The total number of the items.
|
||||
* @param {Object} progressCallback.item - The latest item which flow out the pipeline.
|
||||
* @param {Function} [completeCallback] - Callback invoked when the resource loaded.
|
||||
* @param {Error} completeCallback.error - The error info or null if loaded successfully.
|
||||
* @param {Object} completeCallback.resource - The loaded resource if it can be found otherwise returns null.
|
||||
*
|
||||
* @typescript
|
||||
* loadRes(url: string, type: typeof cc.Asset, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any) => void)|null): void
|
||||
* loadRes(url: string, type: typeof cc.Asset, completeCallback: (error: Error, resource: any) => void): void
|
||||
* loadRes(url: string, type: typeof cc.Asset): void
|
||||
* loadRes(url: string, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any) => void)|null): void
|
||||
* loadRes(url: string, completeCallback: (error: Error, resource: any) => void): void
|
||||
* loadRes(url: string): void
|
||||
*/
|
||||
loadRes (url, type, progressCallback, completeCallback) {
|
||||
var { type, onProgress, onComplete } = this._parseLoadResArgs(type, progressCallback, completeCallback);
|
||||
var extname = cc.path.extname(url);
|
||||
if (extname) {
|
||||
// strip extname
|
||||
url = url.slice(0, - extname.length);
|
||||
}
|
||||
cc.resources.load(url, type, onProgress, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.loadResArray` is deprecated, please use {{#crossLink "Bundle/load:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.loadResArray is deprecated, please use cc.resources.load instead
|
||||
* @method loadResArray
|
||||
* @param {String[]} urls - Array of URLs of the target resource.
|
||||
* The url is relative to the "resources" folder, extensions must be omitted.
|
||||
* @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.
|
||||
* @param {Function} [progressCallback] - Callback invoked when progression change.
|
||||
* @param {Number} progressCallback.completedCount - The number of the items that are already completed.
|
||||
* @param {Number} progressCallback.totalCount - The total number of the items.
|
||||
* @param {Object} progressCallback.item - The latest item which flow out the pipeline.
|
||||
* @param {Function} [completeCallback] - A callback which is called when all assets have been loaded, or an error occurs.
|
||||
* @param {Error} completeCallback.error - If one of the asset failed, the complete callback is immediately called
|
||||
* with the error. If all assets are loaded successfully, error will be null.
|
||||
* @param {Asset[]|Array} completeCallback.assets - An array of all loaded assets.
|
||||
* If nothing to load, assets will be an empty array.
|
||||
* @typescript
|
||||
* loadResArray(url: string[], type: typeof cc.Asset, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any[]) => void)|null): void
|
||||
* loadResArray(url: string[], type: typeof cc.Asset, completeCallback: (error: Error, resource: any[]) => void): void
|
||||
* loadResArray(url: string[], type: typeof cc.Asset): void
|
||||
* loadResArray(url: string[], progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any[]) => void)|null): void
|
||||
* loadResArray(url: string[], completeCallback: (error: Error, resource: any[]) => void): void
|
||||
* loadResArray(url: string[]): void
|
||||
* loadResArray(url: string[], type: typeof cc.Asset[]): void
|
||||
*/
|
||||
loadResArray (urls, type, progressCallback, completeCallback) {
|
||||
var { type, onProgress, onComplete } = this._parseLoadResArgs(type, progressCallback, completeCallback);
|
||||
urls.forEach((url, i) => {
|
||||
var extname = cc.path.extname(url);
|
||||
if (extname) {
|
||||
// strip extname
|
||||
urls[i] = url.slice(0, - extname.length);
|
||||
}
|
||||
})
|
||||
cc.resources.load(urls, type, onProgress, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.loadResDir` is deprecated, please use {{#crossLink "Bundle/loadDir:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.loadResDir is deprecated, please use cc.resources.loadDir instead
|
||||
* @method loadResDir
|
||||
* @param {String} url - Url of the target folder.
|
||||
* The url is relative to the "resources" folder, extensions must be omitted.
|
||||
* @param {Function} [type] - Only asset of type will be loaded if this argument is supplied.
|
||||
* @param {Function} [progressCallback] - Callback invoked when progression change.
|
||||
* @param {Number} progressCallback.completedCount - The number of the items that are already completed.
|
||||
* @param {Number} progressCallback.totalCount - The total number of the items.
|
||||
* @param {Object} progressCallback.item - The latest item which flow out the pipeline.
|
||||
* @param {Function} [completeCallback] - A callback which is called when all assets have been loaded, or an error occurs.
|
||||
* @param {Error} completeCallback.error - If one of the asset failed, the complete callback is immediately called
|
||||
* with the error. If all assets are loaded successfully, error will be null.
|
||||
* @param {Asset[]|Array} completeCallback.assets - An array of all loaded assets.
|
||||
* If nothing to load, assets will be an empty array.
|
||||
* @param {String[]} completeCallback.urls - An array that lists all the URLs of loaded assets.
|
||||
*
|
||||
* @typescript
|
||||
* loadResDir(url: string, type: typeof cc.Asset, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any[], urls: string[]) => void)|null): void
|
||||
* loadResDir(url: string, type: typeof cc.Asset, completeCallback: (error: Error, resource: any[], urls: string[]) => void): void
|
||||
* loadResDir(url: string, type: typeof cc.Asset): void
|
||||
* loadResDir(url: string, progressCallback: (completedCount: number, totalCount: number, item: any) => void, completeCallback: ((error: Error, resource: any[], urls: string[]) => void)|null): void
|
||||
* loadResDir(url: string, completeCallback: (error: Error, resource: any[], urls: string[]) => void): void
|
||||
* loadResDir(url: string): void
|
||||
*/
|
||||
loadResDir (url, type, progressCallback, completeCallback) {
|
||||
var { type, onProgress, onComplete } = this._parseLoadResArgs(type, progressCallback, completeCallback);
|
||||
cc.resources.loadDir(url, type, onProgress, function (err, assets) {
|
||||
var urls = [];
|
||||
if (!err) {
|
||||
var infos = cc.resources.getDirWithPath(url, type);
|
||||
urls = infos.map(function (info) {
|
||||
return info.path;
|
||||
});
|
||||
}
|
||||
onComplete && onComplete(err, assets, urls);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.getRes` is deprecated, please use {{#crossLink "Bundle/get:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @method getRes
|
||||
* @param {String} url
|
||||
* @param {Function} [type] - Only asset of type will be returned if this argument is supplied.
|
||||
* @returns {*}
|
||||
* @deprecated cc.loader.getRes is deprecated, please use cc.resources.get instead
|
||||
*/
|
||||
getRes (url, type) {
|
||||
return cc.assetManager.assets.has(url) ? cc.assetManager.assets.get(url) : cc.resources.get(url, type);
|
||||
},
|
||||
|
||||
getResCount () {
|
||||
return cc.assetManager.assets.count;
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.getDependsRecursively` is deprecated, please use use {{#crossLink "DependUtil/getDepsRecursively:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.getDependsRecursively is deprecated, please use use cc.assetManager.dependUtil.getDepsRecursively instead
|
||||
* @method getDependsRecursively
|
||||
* @param {Asset|String} owner - The owner asset or the resource url or the asset's uuid
|
||||
* @returns {Array}
|
||||
*/
|
||||
getDependsRecursively (owner) {
|
||||
if (!owner) return [];
|
||||
return dependUtil.getDepsRecursively(typeof owner === 'string' ? owner : owner._uuid).concat([ owner._uuid ]);
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.assetLoader` was removed, assetLoader and md5Pipe were merged into {{#crossLink "AssetManager/transformPipeline:property"}}{{/crossLink}}
|
||||
*
|
||||
* @property assetLoader
|
||||
* @deprecated cc.loader.assetLoader was removed, assetLoader and md5Pipe were merged into cc.assetManager.transformPipeline
|
||||
* @type {Object}
|
||||
*/
|
||||
get assetLoader () {
|
||||
if (CC_DEBUG) {
|
||||
cc.error('cc.loader.assetLoader was removed, assetLoader and md5Pipe were merged into cc.assetManager.transformPipeline');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.md5Pipe` is deprecated, assetLoader and md5Pipe were merged into {{#crossLink "AssetManager/transformPipeline:property"}}{{/crossLink}}
|
||||
*
|
||||
* @property md5Pipe
|
||||
* @deprecated cc.loader.md5Pipe is deprecated, assetLoader and md5Pipe were merged into cc.assetManager.transformPipeline
|
||||
* @type {Object}
|
||||
*/
|
||||
get md5Pipe () {
|
||||
return md5Pipe;
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.downloader` is deprecated, please use {{#crossLink "AssetManager/downloader:property"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.downloader is deprecated, please use cc.assetManager.downloader instead
|
||||
* @property downloader
|
||||
* @type {Object}
|
||||
*/
|
||||
get downloader () {
|
||||
return cc.assetManager.downloader;
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.loader` is deprecated, please use {{#crossLink "AssetManager/parser:property"}}{{/crossLink}} instead
|
||||
*
|
||||
* @property loader
|
||||
* @type {Object}
|
||||
* @deprecated cc.loader.loader is deprecated, please use cc.assetManager.parser instead
|
||||
*/
|
||||
get loader () {
|
||||
return cc.assetManager.parser;
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.addDownloadHandlers` is deprecated, please use `cc.assetManager.downloader.register` instead
|
||||
*
|
||||
* @method addDownloadHandlers
|
||||
* @param {Object} extMap Custom supported types with corresponded handler
|
||||
* @deprecated cc.loader.addDownloadHandlers is deprecated, please use cc.assetManager.downloader.register instead
|
||||
*/
|
||||
addDownloadHandlers (extMap) {
|
||||
if (CC_DEBUG) {
|
||||
cc.warn('`cc.loader.addDownloadHandlers` is deprecated, please use `cc.assetManager.downloader.register` instead');
|
||||
}
|
||||
var handler = Object.create(null);
|
||||
for (var type in extMap) {
|
||||
var func = extMap[type];
|
||||
handler['.' + type] = function (url, options, onComplete) {
|
||||
func({url}, onComplete);
|
||||
};
|
||||
}
|
||||
cc.assetManager.downloader.register(handler);
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.addLoadHandlers` is deprecated, please use `cc.assetManager.parser.register` instead
|
||||
*
|
||||
* @method addLoadHandlers
|
||||
* @param {Object} extMap Custom supported types with corresponded handler
|
||||
* @deprecated cc.loader.addLoadHandlers is deprecated, please use cc.assetManager.parser.register instead
|
||||
*/
|
||||
addLoadHandlers (extMap) {
|
||||
if (CC_DEBUG) {
|
||||
cc.warn('`cc.loader.addLoadHandlers` is deprecated, please use `cc.assetManager.parser.register` instead');
|
||||
}
|
||||
var handler = Object.create(null);
|
||||
for (var type in extMap) {
|
||||
var func = extMap[type];
|
||||
handler['.' + type] = function (file, options, onComplete) {
|
||||
func({content: file}, onComplete);
|
||||
};
|
||||
}
|
||||
cc.assetManager.parser.register(handler);
|
||||
},
|
||||
|
||||
flowInDeps () {
|
||||
if (CC_DEBUG) {
|
||||
cc.error('cc.loader.flowInDeps was removed');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.release` is deprecated, please use {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @method release
|
||||
* @param {Asset|String|Array} asset
|
||||
* @deprecated cc.loader.release is deprecated, please use cc.assetManager.releaseAsset instead
|
||||
*/
|
||||
release (asset) {
|
||||
if (Array.isArray(asset)) {
|
||||
for (let i = 0; i < asset.length; i++) {
|
||||
var key = asset[i];
|
||||
if (typeof key === 'string') key = cc.assetManager.assets.get(key);
|
||||
let isBuiltin = cc.assetManager.builtins._assets.find(function (assets) {
|
||||
return assets.find(builtinAsset => builtinAsset === key);
|
||||
});
|
||||
if (isBuiltin) continue;
|
||||
cc.assetManager.releaseAsset(key);
|
||||
}
|
||||
}
|
||||
else if (asset) {
|
||||
if (typeof asset === 'string') asset = cc.assetManager.assets.get(asset);
|
||||
let isBuiltin = cc.assetManager.builtins._assets.find(function (assets) {
|
||||
return assets.find(builtinAsset => builtinAsset === asset);
|
||||
});
|
||||
if (isBuiltin) return;
|
||||
cc.assetManager.releaseAsset(asset);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.releaseAsset` is deprecated, please use {{#crossLink "AssetManager/releaseAsset:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.releaseAsset is deprecated, please use cc.assetManager.releaseAsset instead
|
||||
* @method releaseAsset
|
||||
* @param {Asset} asset
|
||||
*/
|
||||
releaseAsset (asset) {
|
||||
cc.assetManager.releaseAsset(asset);
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.releaseRes` is deprecated, please use {{#crossLink "AssetManager/releaseRes:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.releaseRes is deprecated, please use cc.assetManager.releaseRes instead
|
||||
* @method releaseRes
|
||||
* @param {String} url
|
||||
* @param {Function} [type] - Only asset of type will be released if this argument is supplied.
|
||||
*/
|
||||
releaseRes (url, type) {
|
||||
cc.resources.release(url, type);
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.releaseResDir` was removed, please use {{#crossLink "AssetManager/releaseRes:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.releaseResDir was removed, please use cc.assetManager.releaseRes instead
|
||||
* @method releaseResDir
|
||||
*/
|
||||
releaseResDir () {
|
||||
if (CC_DEBUG) {
|
||||
cc.error('cc.loader.releaseResDir was removed, please use cc.assetManager.releaseAsset instead');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.releaseAll` is deprecated, please use {{#crossLink "AssetManager/releaseAll:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.releaseAll is deprecated, please use cc.assetManager.releaseAll instead
|
||||
* @method releaseAll
|
||||
*/
|
||||
releaseAll () {
|
||||
cc.assetManager.releaseAll();
|
||||
cc.assetManager.assets.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.removeItem` is deprecated, please use `cc.assetManager.assets.remove` instead
|
||||
*
|
||||
* @deprecated cc.loader.removeItem is deprecated, please use cc.assetManager.assets.remove instead
|
||||
* @method removeItem
|
||||
* @param {Object} id The id of the item
|
||||
* @return {Boolean} succeed or not
|
||||
*/
|
||||
removeItem (key) {
|
||||
cc.assetManager.assets.remove(key);
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.setAutoRelease` is deprecated, if you want to prevent some asset from auto releasing, please use {{#crossLink "Asset/addRef:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.setAutoRelease is deprecated, if you want to prevent some asset from auto releasing, please use cc.Asset.addRef instead
|
||||
* @method setAutoRelease
|
||||
* @param {Asset|String} assetOrUrlOrUuid - asset object or the raw asset's url or uuid
|
||||
* @param {Boolean} autoRelease - indicates whether should release automatically
|
||||
*/
|
||||
setAutoRelease (asset, autoRelease) {
|
||||
if (typeof asset === 'object') asset = asset._uuid;
|
||||
this._autoReleaseSetting[asset] = !!autoRelease;
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.setAutoReleaseRecursively` is deprecated, if you want to prevent some asset from auto releasing, please use {{#crossLink "Asset/addRef:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @method setAutoReleaseRecursively
|
||||
* @param {Asset|String} assetOrUrlOrUuid - asset object or the raw asset's url or uuid
|
||||
* @param {Boolean} autoRelease - indicates whether should release automatically
|
||||
* @deprecated cc.loader.setAutoReleaseRecursively is deprecated, if you want to prevent some asset from auto releasing, please use cc.Asset.addRef instead
|
||||
*/
|
||||
setAutoReleaseRecursively (asset, autoRelease) {
|
||||
if (typeof asset === 'object') asset = asset._uuid;
|
||||
autoRelease = !!autoRelease;
|
||||
this._autoReleaseSetting[asset] = autoRelease;
|
||||
var depends = dependUtil.getDepsRecursively(asset);
|
||||
for (var i = 0; i < depends.length; i++) {
|
||||
var depend = depends[i];
|
||||
this._autoReleaseSetting[depend] = autoRelease;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.loader.isAutoRelease` is deprecated
|
||||
*
|
||||
* @method isAutoRelease
|
||||
* @param {Asset|String} assetOrUrl - asset object or the raw asset's url
|
||||
* @returns {Boolean}
|
||||
* @deprecated cc.loader.isAutoRelease is deprecated
|
||||
*/
|
||||
isAutoRelease (asset) {
|
||||
if (typeof asset === 'object') asset = asset._uuid;
|
||||
return !!this._autoReleaseSetting[asset];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Downloader
|
||||
*/
|
||||
/**
|
||||
* `cc.loader.downloader.loadSubpackage` is deprecated, please use {{#crossLink "AssetManager/loadBundle:method"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.loader.downloader.loadSubpackage is deprecated, please use AssetManager.loadBundle instead
|
||||
* @method loadSubpackage
|
||||
* @param {String} name - Subpackage name
|
||||
* @param {Function} [completeCallback] - Callback invoked when subpackage loaded
|
||||
* @param {Error} completeCallback.error - error information
|
||||
*/
|
||||
downloader.loadSubpackage = function (name, completeCallback) {
|
||||
cc.assetManager.loadBundle(name, null, completeCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated cc.AssetLibrary is deprecated, please backup your project and upgrade to cc.assetManager
|
||||
*/
|
||||
var AssetLibrary = {
|
||||
|
||||
/**
|
||||
* @deprecated cc.AssetLibrary.init is deprecated, please use cc.assetManager.init instead
|
||||
*/
|
||||
init (options) {
|
||||
options.importBase = options.libraryPath;
|
||||
options.nativeBase = CC_BUILD ? options.rawAssetsBase : options.libraryPath;
|
||||
cc.assetManager.init(options);
|
||||
if (options.rawAssets) {
|
||||
var resources = new cc.AssetManager.Bundle();
|
||||
resources.init({
|
||||
name: cc.AssetManager.BuiltinBundleName.RESOURCES,
|
||||
importBase: options.importBase,
|
||||
nativeBase: options.nativeBase,
|
||||
paths: options.rawAssets.assets,
|
||||
uuids: Object.keys(options.rawAssets.assets),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated cc.AssetLibrary is deprecated, please use cc.assetManager.loadAny instead
|
||||
*/
|
||||
loadAsset (uuid, onComplete) {
|
||||
cc.assetManager.loadAny(uuid, onComplete);
|
||||
},
|
||||
|
||||
getLibUrlNoExt () {
|
||||
if (CC_DEBUG) {
|
||||
cc.error('cc.AssetLibrary.getLibUrlNoExt was removed, if you want to transform url, please use cc.assetManager.utils.getUrlWithUuid instead');
|
||||
}
|
||||
},
|
||||
|
||||
queryAssetInfo () {
|
||||
if (CC_DEBUG) {
|
||||
cc.error('cc.AssetLibrary.queryAssetInfo was removed, only available in the editor by using cc.assetManager.editorExtend.queryAssetInfo');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* `cc.url` is deprecated
|
||||
*
|
||||
* @deprecated cc.url is deprecated
|
||||
* @class url
|
||||
* @static
|
||||
*/
|
||||
cc.url = {
|
||||
normalize (url) {
|
||||
cc.warnID(1400, 'cc.url.normalize', 'cc.assetManager.utils.normalize');
|
||||
return cc.assetManager.utils.normalize(url);
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.url.raw` is deprecated, please use `cc.resources.load` directly, or use `Asset.nativeUrl` instead.
|
||||
*
|
||||
* @deprecated cc.url.raw is deprecated, please use cc.resources.load directly, or use Asset.nativeUrl instead.
|
||||
* @method raw
|
||||
* @param {String} url
|
||||
* @return {String}
|
||||
*/
|
||||
raw (url) {
|
||||
cc.warnID(1400, 'cc.url.raw', 'cc.resources.load');
|
||||
if (url.startsWith('resources/')) {
|
||||
return cc.assetManager._transform({'path': cc.path.changeExtname(url.substr(10)), bundle: cc.AssetManager.BuiltinBundleName.RESOURCES, __isNative__: true, ext: cc.path.extname(url)});
|
||||
}
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
let onceWarns = {
|
||||
loader: true,
|
||||
assetLibrary: true,
|
||||
};
|
||||
|
||||
Object.defineProperties(cc, {
|
||||
loader: {
|
||||
get () {
|
||||
if (CC_DEBUG) {
|
||||
if (onceWarns.loader) {
|
||||
onceWarns.loader = false;
|
||||
cc.log('cc.loader is deprecated, use cc.assetManager instead please. See https://docs.cocos.com/creator/manual/zh/release-notes/asset-manager-upgrade-guide.html');
|
||||
}
|
||||
}
|
||||
return loader;
|
||||
}
|
||||
},
|
||||
|
||||
AssetLibrary: {
|
||||
get () {
|
||||
if (CC_DEBUG) {
|
||||
if (onceWarns.assetLibrary) {
|
||||
onceWarns.assetLibrary = false;
|
||||
cc.log('cc.AssetLibrary is deprecated, use cc.assetManager instead please. See https://docs.cocos.com/creator/manual/zh/release-notes/asset-manager-upgrade-guide.html');
|
||||
}
|
||||
}
|
||||
return AssetLibrary;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* `cc.LoadingItems` was removed, please use {{#crossLink "Task"}}{{/crossLink}} instead
|
||||
*
|
||||
* @deprecated cc.LoadingItems was removed, please use cc.AssetManager.Task instead
|
||||
* @class LoadingItems
|
||||
*/
|
||||
LoadingItems: {
|
||||
get () {
|
||||
cc.warnID(1400, 'cc.LoadingItems', 'cc.AssetManager.Task');
|
||||
return cc.AssetManager.Task;
|
||||
}
|
||||
},
|
||||
|
||||
Pipeline: {
|
||||
get () {
|
||||
cc.warnID(1400, 'cc.Pipeline', 'cc.AssetManager.Pipeline');
|
||||
return cc.AssetManager.Pipeline;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
js.obsolete(cc, 'cc.RawAsset', 'cc.Asset');
|
||||
|
||||
/**
|
||||
* @class Asset
|
||||
*/
|
||||
/**
|
||||
* `cc.Asset.url` is deprecated, please use {{#crossLink "Asset/nativeUrl:property"}}{{/crossLink}} instead
|
||||
* @property url
|
||||
* @type {String}
|
||||
* @deprecated cc.Asset.url is deprecated, please use cc.Asset.nativeUrl instead
|
||||
*/
|
||||
js.obsolete(cc.Asset.prototype, 'cc.Asset.url', 'nativeUrl');
|
||||
|
||||
/**
|
||||
* @class macro
|
||||
* @static
|
||||
*/
|
||||
Object.defineProperties(cc.macro, {
|
||||
/**
|
||||
* `cc.macro.DOWNLOAD_MAX_CONCURRENT` is deprecated now, please use {{#crossLink "Downloader/maxConcurrency:property"}}{{/crossLink}} instead
|
||||
*
|
||||
* @property DOWNLOAD_MAX_CONCURRENT
|
||||
* @type {Number}
|
||||
* @deprecated cc.macro.DOWNLOAD_MAX_CONCURRENT is deprecated now, please use cc.assetManager.downloader.maxConcurrency instead
|
||||
*/
|
||||
DOWNLOAD_MAX_CONCURRENT: {
|
||||
get () {
|
||||
return cc.assetManager.downloader.maxConcurrency;
|
||||
},
|
||||
|
||||
set (val) {
|
||||
cc.assetManager.downloader.maxConcurrency = val;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Object.assign(cc.director, {
|
||||
_getSceneUuid (sceneName) {
|
||||
cc.assetManager.main.getSceneInfo(sceneName);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperties(cc.game, {
|
||||
_sceneInfos: {
|
||||
get () {
|
||||
var scenes = [];
|
||||
cc.assetManager.main._config.scenes.forEach(function (val) {
|
||||
scenes.push(val);
|
||||
});
|
||||
return scenes;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var parseParameters = utilities.parseParameters;
|
||||
utilities.parseParameters = function (options, onProgress, onComplete) {
|
||||
var result = parseParameters(options, onProgress, onComplete);
|
||||
result.onProgress = result.onProgress || loader.onProgress;
|
||||
return result;
|
||||
};
|
||||
|
||||
var autoRelease = releaseManager._autoRelease;
|
||||
releaseManager._autoRelease = function () {
|
||||
autoRelease.apply(this, arguments);
|
||||
var releaseSettings = loader._autoReleaseSetting;
|
||||
var keys = Object.keys(releaseSettings);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
let key = keys[i];
|
||||
if (releaseSettings[key] === true) {
|
||||
var asset = cc.assetManager.assets.get(key);
|
||||
asset && releaseManager.tryRelease(asset);
|
||||
}
|
||||
}
|
||||
};
|
103
engine/cocos2d/core/asset-manager/deserialize.js
Normal file
103
engine/cocos2d/core/asset-manager/deserialize.js
Normal file
@@ -0,0 +1,103 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
const helper = require('./helper');
|
||||
const MissingClass = CC_EDITOR && Editor.require('app://editor/page/scene-utils/missing-class-reporter').MissingClass;
|
||||
require('../platform/deserialize');
|
||||
|
||||
function deserialize (json, options) {
|
||||
var classFinder, missingClass;
|
||||
if (CC_EDITOR) {
|
||||
missingClass = MissingClass;
|
||||
classFinder = function (type, data, owner, propName) {
|
||||
var res = missingClass.classFinder(type, data, owner, propName);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
return cc._MissingScript;
|
||||
};
|
||||
classFinder.onDereferenced = missingClass.classFinder.onDereferenced;
|
||||
}
|
||||
else {
|
||||
classFinder = cc._MissingScript.safeFindClass;
|
||||
}
|
||||
|
||||
let pool = null;
|
||||
if (!CC_PREVIEW) {
|
||||
pool = cc.deserialize.Details.pool;
|
||||
}
|
||||
else {
|
||||
let { default: deserializeForCompiled } = require('../platform/deserialize-compiled');
|
||||
let deserializeForEditor = require('../platform/deserialize-editor');
|
||||
if (deserializeForCompiled.isCompiledJson(json)) {
|
||||
pool = deserializeForCompiled.Details.pool;
|
||||
}
|
||||
else {
|
||||
pool = deserializeForEditor.Details.pool;
|
||||
}
|
||||
}
|
||||
var tdInfo = pool.get();
|
||||
|
||||
var asset;
|
||||
try {
|
||||
asset = cc.deserialize(json, tdInfo, {
|
||||
classFinder: classFinder,
|
||||
customEnv: options
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
pool.put(tdInfo);
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (CC_EDITOR && missingClass) {
|
||||
missingClass.reportMissingClass(asset);
|
||||
missingClass.reset();
|
||||
}
|
||||
|
||||
var uuidList = tdInfo.uuidList;
|
||||
var objList = tdInfo.uuidObjList;
|
||||
var propList = tdInfo.uuidPropList;
|
||||
var depends = [];
|
||||
|
||||
for (var i = 0; i < uuidList.length; i++) {
|
||||
var dependUuid = uuidList[i];
|
||||
depends[i] = {
|
||||
uuid: helper.decodeUuid(dependUuid),
|
||||
owner: objList[i],
|
||||
prop: propList[i]
|
||||
};
|
||||
}
|
||||
|
||||
// non-native deps
|
||||
asset.__depends__ = depends;
|
||||
// native dep
|
||||
asset._native && (asset.__nativeDepend__ = true);
|
||||
pool.put(tdInfo);
|
||||
return asset;
|
||||
|
||||
}
|
||||
|
||||
module.exports = deserialize;
|
68
engine/cocos2d/core/asset-manager/download-dom-audio.js
Normal file
68
engine/cocos2d/core/asset-manager/download-dom-audio.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
var __audioSupport = cc.sys.__audioSupport;
|
||||
const { parseParameters } = require('./utilities');
|
||||
|
||||
function downloadDomAudio (url, options, onComplete) {
|
||||
var { options, onComplete } = parseParameters(options, undefined, onComplete);
|
||||
|
||||
var dom = document.createElement('audio');
|
||||
dom.src = url;
|
||||
|
||||
var clearEvent = function () {
|
||||
clearTimeout(timer);
|
||||
dom.removeEventListener("canplaythrough", success, false);
|
||||
dom.removeEventListener("error", failure, false);
|
||||
if(__audioSupport.USE_LOADER_EVENT)
|
||||
dom.removeEventListener(__audioSupport.USE_LOADER_EVENT, success, false);
|
||||
};
|
||||
|
||||
var timer = setTimeout(function () {
|
||||
if (dom.readyState === 0)
|
||||
failure();
|
||||
else
|
||||
success();
|
||||
}, 8000);
|
||||
|
||||
var success = function () {
|
||||
clearEvent();
|
||||
onComplete && onComplete(null, dom);
|
||||
};
|
||||
|
||||
var failure = function () {
|
||||
clearEvent();
|
||||
var message = 'load audio failure - ' + url;
|
||||
cc.log(message);
|
||||
onComplete && onComplete(new Error(message));
|
||||
};
|
||||
|
||||
dom.addEventListener("canplaythrough", success, false);
|
||||
dom.addEventListener("error", failure, false);
|
||||
if(__audioSupport.USE_LOADER_EVENT)
|
||||
dom.addEventListener(__audioSupport.USE_LOADER_EVENT, success, false);
|
||||
return dom;
|
||||
}
|
||||
|
||||
module.exports = downloadDomAudio;
|
56
engine/cocos2d/core/asset-manager/download-dom-image.js
Normal file
56
engine/cocos2d/core/asset-manager/download-dom-image.js
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
const { parseParameters } = require('./utilities');
|
||||
|
||||
function downloadDomImage (url, options, onComplete) {
|
||||
var { options, onComplete } = parseParameters(options, undefined, onComplete);
|
||||
|
||||
var img = new Image();
|
||||
|
||||
if (window.location.protocol !== 'file:') {
|
||||
img.crossOrigin = 'anonymous';
|
||||
}
|
||||
|
||||
function loadCallback () {
|
||||
img.removeEventListener('load', loadCallback);
|
||||
img.removeEventListener('error', errorCallback);
|
||||
onComplete && onComplete(null, img);
|
||||
}
|
||||
|
||||
function errorCallback () {
|
||||
img.removeEventListener('load', loadCallback);
|
||||
img.removeEventListener('error', errorCallback);
|
||||
onComplete && onComplete(new Error(cc.debug.getError(4930, url)));
|
||||
}
|
||||
|
||||
img.addEventListener('load', loadCallback);
|
||||
img.addEventListener('error', errorCallback);
|
||||
img.src = url;
|
||||
return img;
|
||||
}
|
||||
|
||||
module.exports = downloadDomImage;
|
79
engine/cocos2d/core/asset-manager/download-file.js
Normal file
79
engine/cocos2d/core/asset-manager/download-file.js
Normal file
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const { parseParameters } = require('./utilities');
|
||||
|
||||
function downloadFile (url, options, onProgress, onComplete) {
|
||||
var { options, onProgress, onComplete } = parseParameters(options, onProgress, onComplete);
|
||||
|
||||
var xhr = new XMLHttpRequest(), errInfo = 'download failed: ' + url + ', status: ';
|
||||
|
||||
xhr.open('GET', url, true);
|
||||
|
||||
if (options.responseType !== undefined) xhr.responseType = options.responseType;
|
||||
if (options.withCredentials !== undefined) xhr.withCredentials = options.withCredentials;
|
||||
if (options.mimeType !== undefined && xhr.overrideMimeType ) xhr.overrideMimeType(options.mimeType);
|
||||
if (options.timeout !== undefined) xhr.timeout = options.timeout;
|
||||
|
||||
if (options.header) {
|
||||
for (var header in options.header) {
|
||||
xhr.setRequestHeader(header, options.header[header]);
|
||||
}
|
||||
}
|
||||
|
||||
xhr.onload = function () {
|
||||
if ( xhr.status === 200 || xhr.status === 0 ) {
|
||||
onComplete && onComplete(null, xhr.response);
|
||||
} else {
|
||||
onComplete && onComplete(new Error(errInfo + xhr.status + '(no response)'));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (onProgress) {
|
||||
xhr.onprogress = function (e) {
|
||||
if (e.lengthComputable) {
|
||||
onProgress(e.loaded, e.total);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
xhr.onerror = function(){
|
||||
onComplete && onComplete(new Error(errInfo + xhr.status + '(error)'));
|
||||
};
|
||||
|
||||
xhr.ontimeout = function(){
|
||||
onComplete && onComplete(new Error(errInfo + xhr.status + '(time out)'));
|
||||
};
|
||||
|
||||
xhr.onabort = function(){
|
||||
onComplete && onComplete(new Error(errInfo + xhr.status + '(abort)'));
|
||||
};
|
||||
|
||||
xhr.send(null);
|
||||
|
||||
return xhr;
|
||||
}
|
||||
|
||||
module.exports = downloadFile;
|
66
engine/cocos2d/core/asset-manager/download-script.js
Normal file
66
engine/cocos2d/core/asset-manager/download-script.js
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const { parseParameters } = require('./utilities');
|
||||
|
||||
const downloaded = {};
|
||||
|
||||
function downloadScript (url, options, onComplete) {
|
||||
var { options, onComplete } = parseParameters(options, undefined, onComplete);
|
||||
|
||||
// no need to load script again
|
||||
if (downloaded[url]) {
|
||||
return onComplete && onComplete(null);
|
||||
}
|
||||
|
||||
var d = document, s = document.createElement('script');
|
||||
|
||||
if (window.location.protocol !== 'file:') {
|
||||
s.crossOrigin = 'anonymous';
|
||||
}
|
||||
|
||||
s.async = options.async;
|
||||
s.src = url;
|
||||
function loadHandler () {
|
||||
s.parentNode.removeChild(s);
|
||||
s.removeEventListener('load', loadHandler, false);
|
||||
s.removeEventListener('error', errorHandler, false);
|
||||
downloaded[url] = true;
|
||||
onComplete && onComplete(null);
|
||||
}
|
||||
|
||||
function errorHandler() {
|
||||
s.parentNode.removeChild(s);
|
||||
s.removeEventListener('load', loadHandler, false);
|
||||
s.removeEventListener('error', errorHandler, false);
|
||||
onComplete && onComplete(new Error(cc.debug.getError(4928, url)));
|
||||
}
|
||||
|
||||
s.addEventListener('load', loadHandler, false);
|
||||
s.addEventListener('error', errorHandler, false);
|
||||
d.body.appendChild(s);
|
||||
}
|
||||
|
||||
module.exports = downloadScript;
|
601
engine/cocos2d/core/asset-manager/downloader.js
Normal file
601
engine/cocos2d/core/asset-manager/downloader.js
Normal file
@@ -0,0 +1,601 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
const js = require('../platform/js');
|
||||
const debug = require('../CCDebug');
|
||||
const { loadFont } = require('./font-loader');
|
||||
const callInNextTick = require('../platform/utils').callInNextTick;
|
||||
const downloadDomImage = require('./download-dom-image');
|
||||
const downloadDomAudio = require('./download-dom-audio');
|
||||
const downloadFile = require('./download-file');
|
||||
const downloadScript = require('./download-script.js');
|
||||
const Cache = require('./cache');
|
||||
const { files } = require('./shared');
|
||||
const { __audioSupport, capabilities } = require('../platform/CCSys');
|
||||
const { urlAppendTimestamp, retry } = require('./utilities');
|
||||
|
||||
const REGEX = /^(?:\w+:\/\/|\.+\/).+/;
|
||||
|
||||
|
||||
var formatSupport = __audioSupport.format || [];
|
||||
|
||||
var unsupported = function (url, options, onComplete) {
|
||||
onComplete(new Error(debug.getError(4927)));
|
||||
}
|
||||
|
||||
var downloadAudio = function (url, options, onComplete) {
|
||||
// web audio need to download file as arrayBuffer
|
||||
if (options.audioLoadMode !== cc.AudioClip.LoadMode.DOM_AUDIO) {
|
||||
downloadArrayBuffer(url, options, onComplete);
|
||||
}
|
||||
else {
|
||||
downloadDomAudio(url, options, onComplete);
|
||||
}
|
||||
};
|
||||
|
||||
var downloadAudio = (!CC_EDITOR || !Editor.isMainProcess) ? (formatSupport.length === 0 ? unsupported : (__audioSupport.WEB_AUDIO ? downloadAudio : downloadDomAudio)) : null;
|
||||
|
||||
var downloadImage = function (url, options, onComplete) {
|
||||
// if createImageBitmap is valid, we can transform blob to ImageBitmap. Otherwise, just use HTMLImageElement to load
|
||||
var func = capabilities.imageBitmap && cc.macro.ALLOW_IMAGE_BITMAP ? downloadBlob : downloadDomImage;
|
||||
func.apply(this, arguments);
|
||||
};
|
||||
|
||||
var downloadBlob = function (url, options, onComplete) {
|
||||
options.responseType = "blob";
|
||||
downloadFile(url, options, options.onFileProgress, onComplete);
|
||||
};
|
||||
|
||||
var downloadJson = function (url, options, onComplete) {
|
||||
options.responseType = "json";
|
||||
downloadFile(url, options, options.onFileProgress, function (err, data) {
|
||||
if (!err && typeof data === 'string') {
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
}
|
||||
onComplete && onComplete(err, data);
|
||||
});
|
||||
};
|
||||
|
||||
var downloadArrayBuffer = function (url, options, onComplete) {
|
||||
options.responseType = "arraybuffer";
|
||||
downloadFile(url, options, options.onFileProgress, onComplete);
|
||||
};
|
||||
|
||||
var downloadText = function (url, options, onComplete) {
|
||||
options.responseType = "text";
|
||||
downloadFile(url, options, options.onFileProgress, onComplete);
|
||||
};
|
||||
|
||||
var downloadVideo = function (url, options, onComplete) {
|
||||
onComplete(null, url);
|
||||
};
|
||||
|
||||
var downloadBundle = function (nameOrUrl, options, onComplete) {
|
||||
let bundleName = cc.path.basename(nameOrUrl);
|
||||
let url = nameOrUrl;
|
||||
if (!REGEX.test(url)) url = 'assets/' + bundleName;
|
||||
var version = options.version || downloader.bundleVers[bundleName];
|
||||
var count = 0;
|
||||
var config = `${url}/config.${version ? version + '.' : ''}json`;
|
||||
let out = null, error = null;
|
||||
downloadJson(config, options, function (err, response) {
|
||||
if (err) {
|
||||
error = err;
|
||||
}
|
||||
out = response;
|
||||
out && (out.base = url + '/');
|
||||
count++;
|
||||
if (count === 2) {
|
||||
onComplete(error, out);
|
||||
}
|
||||
});
|
||||
|
||||
var js = `${url}/index.${version ? version + '.' : ''}js`;
|
||||
downloadScript(js, options, function (err) {
|
||||
if (err) {
|
||||
error = err;
|
||||
}
|
||||
count++;
|
||||
if (count === 2) {
|
||||
onComplete(error, out);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _downloading = new Cache();
|
||||
var _queue = [];
|
||||
var _queueDirty = false;
|
||||
|
||||
// the number of loading thread
|
||||
var _totalNum = 0;
|
||||
|
||||
// the number of request that launched in this period
|
||||
var _totalNumThisPeriod = 0;
|
||||
|
||||
// last time, if now - lastTime > period, refresh _totalNumThisPeriod.
|
||||
var _lastDate = -1;
|
||||
|
||||
// if _totalNumThisPeriod equals max, move request to next period using setTimeOut.
|
||||
var _checkNextPeriod = false;
|
||||
|
||||
var updateTime = function () {
|
||||
var now = Date.now();
|
||||
// use deltaTime as interval
|
||||
let interval = cc.director._deltaTime > downloader._maxInterval ? downloader._maxInterval : cc.director._deltaTime;
|
||||
if (now - _lastDate > interval * 1000) {
|
||||
_totalNumThisPeriod = 0;
|
||||
_lastDate = now;
|
||||
}
|
||||
};
|
||||
|
||||
// handle the rest request in next period
|
||||
var handleQueue = function (maxConcurrency, maxRequestsPerFrame) {
|
||||
_checkNextPeriod = false;
|
||||
updateTime();
|
||||
while (_queue.length > 0 && _totalNum < maxConcurrency && _totalNumThisPeriod < maxRequestsPerFrame) {
|
||||
if (_queueDirty) {
|
||||
_queue.sort(function (a, b) {
|
||||
return a.priority - b.priority;
|
||||
});
|
||||
_queueDirty = false;
|
||||
}
|
||||
var nextOne = _queue.pop();
|
||||
if (!nextOne) {
|
||||
break;
|
||||
}
|
||||
_totalNum++;
|
||||
_totalNumThisPeriod++;
|
||||
nextOne.invoke();
|
||||
}
|
||||
|
||||
if (_queue.length > 0 && _totalNum < maxConcurrency) {
|
||||
callInNextTick(handleQueue, maxConcurrency, maxRequestsPerFrame);
|
||||
_checkNextPeriod = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Control all download process, it is a singleton. All member can be accessed with `cc.assetManager.downloader` , it can download several types of files:
|
||||
* 1. Text
|
||||
* 2. Image
|
||||
* 3. Audio
|
||||
* 4. Assets
|
||||
* 5. Scripts
|
||||
*
|
||||
* !#zh
|
||||
* 管理所有下载过程,downloader 是个单例,所有成员能通过 `cc.assetManager.downloader` 访问,它能下载以下几种类型的文件:
|
||||
* 1. 文本
|
||||
* 2. 图片
|
||||
* 3. 音频
|
||||
* 4. 资源
|
||||
* 5. 脚本
|
||||
*
|
||||
* @class Downloader
|
||||
*/
|
||||
var downloader = {
|
||||
|
||||
_remoteServerAddress: '',
|
||||
_maxInterval: 1 / 30,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The address of remote server
|
||||
*
|
||||
* !#zh
|
||||
* 远程服务器地址
|
||||
*
|
||||
* @property remoteServerAddress
|
||||
* @type {string}
|
||||
* @default ''
|
||||
*/
|
||||
get remoteServerAddress () {
|
||||
return this._remoteServerAddress;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The maximum number of concurrent when downloading
|
||||
*
|
||||
* !#zh
|
||||
* 下载时的最大并发数
|
||||
*
|
||||
* @property maxConcurrency
|
||||
* @type {number}
|
||||
* @default 6
|
||||
*/
|
||||
maxConcurrency: 6,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The maximum number of request can be launched per frame when downloading
|
||||
*
|
||||
* !#zh
|
||||
* 下载时每帧可以启动的最大请求数
|
||||
*
|
||||
* @property maxRequestsPerFrame
|
||||
* @type {number}
|
||||
* @default 6
|
||||
*/
|
||||
maxRequestsPerFrame: 6,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The max number of retries when fail
|
||||
*
|
||||
* !#zh
|
||||
* 失败重试次数
|
||||
*
|
||||
* @property maxRetryCount
|
||||
* @type {Number}
|
||||
*/
|
||||
maxRetryCount: 3,
|
||||
|
||||
appendTimeStamp: false,
|
||||
|
||||
limited: true,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Wait for while before another retry, unit: ms
|
||||
*
|
||||
* !#zh
|
||||
* 重试的间隔时间
|
||||
*
|
||||
* @property retryInterval
|
||||
* @type {Number}
|
||||
*/
|
||||
retryInterval: 2000,
|
||||
|
||||
bundleVers: null,
|
||||
|
||||
/*
|
||||
* !#en
|
||||
* Use Image element to download image
|
||||
*
|
||||
* !#zh
|
||||
* 使用 Image 元素来下载图片
|
||||
*
|
||||
* @method downloadDomImage
|
||||
* @param {string} url - Url of the image
|
||||
* @param {Object} [options] - Some optional paramters
|
||||
* @param {Function} [onComplete] - Callback when image loaded or failed
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {HTMLImageElement} onComplete.img - The loaded Image element, null if error occurred
|
||||
* @returns {HTMLImageElement} The image element
|
||||
*
|
||||
* @example
|
||||
* downloadDomImage('http://example.com/test.jpg', null, (err, img) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* downloadDomImage(url: string, options?: Record<string, any> , onComplete?: (err: Error, img: HTMLImageElement) => void): HTMLImageElement
|
||||
* downloadDomImage(url: string, onComplete?: (err: Error, img: HTMLImageElement) => void): HTMLImageElement
|
||||
*/
|
||||
downloadDomImage: downloadDomImage,
|
||||
|
||||
/*
|
||||
* !#en
|
||||
* Use audio element to download audio
|
||||
*
|
||||
* !#zh
|
||||
* 使用 Audio 元素来下载音频
|
||||
*
|
||||
* @method downloadDomAudio
|
||||
* @param {string} url - Url of the audio
|
||||
* @param {Object} [options] - Some optional paramters
|
||||
* @param {Function} [onComplete] - Callback invoked when audio loaded or failed
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {HTMLAudioElement} onComplete.audio - The loaded audio element, null if error occurred
|
||||
* @returns {HTMLAudioElement} The audio element
|
||||
*
|
||||
* @example
|
||||
* downloadDomAudio('http://example.com/test.mp3', null, (err, audio) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* downloadDomAudio(url: string, options?: Record<string, any>, onComplete?: (err: Error, audio: HTMLAudioElement) => void): HTMLAudioElement
|
||||
* downloadDomAudio(url: string, onComplete?: (err: Error, audio: HTMLAudioElement) => void): HTMLAudioElement
|
||||
*/
|
||||
downloadDomAudio: downloadDomAudio,
|
||||
|
||||
/*
|
||||
* !#en
|
||||
* Use XMLHttpRequest to download file
|
||||
*
|
||||
* !#zh
|
||||
* 使用 XMLHttpRequest 来下载文件
|
||||
*
|
||||
* @method downloadFile
|
||||
* @param {string} url - Url of the file
|
||||
* @param {Object} [options] - Some optional paramters
|
||||
* @param {string} [options.responseType] - Indicate which type of content should be returned
|
||||
* @param {boolean} [options.withCredentials] - Indicate whether or not cross-site Access-Contorl requests should be made using credentials
|
||||
* @param {string} [options.mimeType] - Indicate which type of content should be returned. In some browsers, responseType does't work, you can use mimeType instead
|
||||
* @param {Number} [options.timeout] - Represent the number of ms a request can take before being terminated.
|
||||
* @param {Object} [options.header] - The header should be tranferred to server
|
||||
* @param {Function} [onFileProgress] - Callback continuously during download is processing
|
||||
* @param {Number} onFileProgress.loaded - Size of downloaded content.
|
||||
* @param {Number} onFileProgress.total - Total size of content.
|
||||
* @param {Function} [onComplete] - Callback when file loaded or failed
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {*} onComplete.response - The loaded content, null if error occurred, type of content can be indicated by options.responseType
|
||||
* @returns {XMLHttpRequest} The xhr to be send
|
||||
*
|
||||
* @example
|
||||
* downloadFile('http://example.com/test.bin', {responseType: 'arraybuffer'}, null, (err, arrayBuffer) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* downloadFile(url: string, options?: Record<string, any>, onFileProgress?: (loaded: Number, total: Number) => void, onComplete?: (err: Error, response: any) => void): XMLHttpRequest
|
||||
* downloadFile(url: string, onFileProgress?: (loaded: Number, total: Number) => void, onComplete?: (err: Error, response: any) => void): XMLHttpRequest
|
||||
* downloadFile(url: string, options?: Record<string, any>, onComplete?: (err: Error, response: any) => void): XMLHttpRequest
|
||||
* downloadFile(url: string, onComplete?: (err: Error, response: any) => void): XMLHttpRequest
|
||||
*/
|
||||
downloadFile: downloadFile,
|
||||
|
||||
/*
|
||||
* !#en
|
||||
* Load script
|
||||
*
|
||||
* !#zh
|
||||
* 加载脚本
|
||||
*
|
||||
* @method downloadScript
|
||||
* @param {string} url - Url of the script
|
||||
* @param {Object} [options] - Some optional paramters
|
||||
* @param {boolean} [options.isAsync] - Indicate whether or not loading process should be async
|
||||
* @param {Function} [onComplete] - Callback when script loaded or failed
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
*
|
||||
* @example
|
||||
* downloadScript('http://localhost:8080/index.js', null, (err) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* downloadScript(url: string, options?: Record<string, any>, onComplete?: (err: Error) => void): void
|
||||
* downloadScript(url: string, onComplete?: (err: Error) => void): void
|
||||
*/
|
||||
downloadScript: downloadScript,
|
||||
|
||||
init (bundleVers, remoteServerAddress) {
|
||||
_downloading.clear();
|
||||
_queue.length = 0;
|
||||
this._remoteServerAddress = remoteServerAddress || '';
|
||||
this.bundleVers = bundleVers || Object.create(null);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Register custom handler if you want to change default behavior or extend downloader to download other format file
|
||||
*
|
||||
* !#zh
|
||||
* 当你想修改默认行为或者拓展 downloader 来下载其他格式文件时可以注册自定义的 handler
|
||||
*
|
||||
* @method register
|
||||
* @param {string|Object} type - Extension likes '.jpg' or map likes {'.jpg': jpgHandler, '.png': pngHandler}
|
||||
* @param {Function} [handler] - handler
|
||||
* @param {string} handler.url - url
|
||||
* @param {Object} handler.options - some optional paramters will be transferred to handler.
|
||||
* @param {Function} handler.onComplete - callback when finishing downloading
|
||||
*
|
||||
* @example
|
||||
* downloader.register('.tga', (url, options, onComplete) => onComplete(null, null));
|
||||
* downloader.register({'.tga': (url, options, onComplete) => onComplete(null, null), '.ext': (url, options, onComplete) => onComplete(null, null)});
|
||||
*
|
||||
* @typescript
|
||||
* register(type: string, handler: (url: string, options: Record<string, any>, onComplete: (err: Error, content: any) => void) => void): void
|
||||
* register(map: Record<string, (url: string, options: Record<string, any>, onComplete: (err: Error, content: any) => void) => void>): void
|
||||
*/
|
||||
register (type, handler) {
|
||||
if (typeof type === 'object') {
|
||||
js.mixin(downloaders, type);
|
||||
}
|
||||
else {
|
||||
downloaders[type] = handler;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Use corresponding handler to download file under limitation
|
||||
*
|
||||
* !#zh
|
||||
* 在限制下使用对应的 handler 来下载文件
|
||||
*
|
||||
* @method download
|
||||
* @param {string} url - The url should be downloaded
|
||||
* @param {string} type - The type indicates that which handler should be used to download, such as '.jpg'
|
||||
* @param {Object} options - some optional paramters will be transferred to the corresponding handler.
|
||||
* @param {Function} [options.onFileProgress] - progressive callback will be transferred to handler.
|
||||
* @param {Number} [options.maxRetryCount] - How many times should retry when download failed
|
||||
* @param {Number} [options.maxConcurrency] - The maximum number of concurrent when downloading
|
||||
* @param {Number} [options.maxRequestsPerFrame] - The maximum number of request can be launched per frame when downloading
|
||||
* @param {Number} [options.priority] - The priority of this url, default is 0, the greater number is higher priority.
|
||||
* @param {Function} onComplete - callback when finishing downloading
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {*} onComplete.contetnt - The downloaded file
|
||||
*
|
||||
* @example
|
||||
* download('http://example.com/test.tga', '.tga', {onFileProgress: (loaded, total) => console.lgo(loaded/total)}, onComplete: (err) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* download(id: string, url: string, type: string, options: Record<string, any>, onComplete: (err: Error, content: any) => void): void
|
||||
*/
|
||||
download (id, url, type, options, onComplete) {
|
||||
let func = downloaders[type] || downloaders['default'];
|
||||
let self = this;
|
||||
// if it is downloaded, don't download again
|
||||
let file, downloadCallbacks;
|
||||
if (file = files.get(id)) {
|
||||
onComplete(null, file);
|
||||
}
|
||||
else if (downloadCallbacks = _downloading.get(id)) {
|
||||
downloadCallbacks.push(onComplete);
|
||||
for (let i = 0, l = _queue.length; i < l; i++) {
|
||||
var item = _queue[i];
|
||||
if (item.id === id) {
|
||||
var priority = options.priority || 0;
|
||||
if (item.priority < priority) {
|
||||
item.priority = priority;
|
||||
_queueDirty = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if download fail, should retry
|
||||
var maxRetryCount = typeof options.maxRetryCount !== 'undefined' ? options.maxRetryCount : this.maxRetryCount;
|
||||
var maxConcurrency = typeof options.maxConcurrency !== 'undefined' ? options.maxConcurrency : this.maxConcurrency;
|
||||
var maxRequestsPerFrame = typeof options.maxRequestsPerFrame !== 'undefined' ? options.maxRequestsPerFrame : this.maxRequestsPerFrame;
|
||||
|
||||
function process (index, callback) {
|
||||
if (index === 0) {
|
||||
_downloading.add(id, [onComplete]);
|
||||
}
|
||||
|
||||
if (!self.limited) return func(urlAppendTimestamp(url), options, callback);
|
||||
|
||||
// refresh
|
||||
updateTime();
|
||||
|
||||
function invoke () {
|
||||
func(urlAppendTimestamp(url), options, function () {
|
||||
// when finish downloading, update _totalNum
|
||||
_totalNum--;
|
||||
if (!_checkNextPeriod && _queue.length > 0) {
|
||||
callInNextTick(handleQueue, maxConcurrency, maxRequestsPerFrame);
|
||||
_checkNextPeriod = true;
|
||||
}
|
||||
callback.apply(this, arguments);
|
||||
});
|
||||
}
|
||||
|
||||
if (_totalNum < maxConcurrency && _totalNumThisPeriod < maxRequestsPerFrame) {
|
||||
invoke();
|
||||
_totalNum++;
|
||||
_totalNumThisPeriod++;
|
||||
}
|
||||
else {
|
||||
// when number of request up to limitation, cache the rest
|
||||
_queue.push({ id, priority: options.priority || 0, invoke });
|
||||
_queueDirty = true;
|
||||
|
||||
if (!_checkNextPeriod && _totalNum < maxConcurrency) {
|
||||
callInNextTick(handleQueue, maxConcurrency, maxRequestsPerFrame);
|
||||
_checkNextPeriod = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// when retry finished, invoke callbacks
|
||||
function finale (err, result) {
|
||||
if (!err) files.add(id, result);
|
||||
var callbacks = _downloading.remove(id);
|
||||
for (let i = 0, l = callbacks.length; i < l; i++) {
|
||||
callbacks[i](err, result);
|
||||
}
|
||||
}
|
||||
|
||||
retry(process, maxRetryCount, this.retryInterval, finale);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// dafault handler map
|
||||
var downloaders = {
|
||||
// Images
|
||||
'.png' : downloadImage,
|
||||
'.jpg' : downloadImage,
|
||||
'.bmp' : downloadImage,
|
||||
'.jpeg' : downloadImage,
|
||||
'.gif' : downloadImage,
|
||||
'.ico' : downloadImage,
|
||||
'.tiff' : downloadImage,
|
||||
'.webp' : downloadImage,
|
||||
'.image' : downloadImage,
|
||||
'.pvr': downloadArrayBuffer,
|
||||
'.pkm': downloadArrayBuffer,
|
||||
|
||||
// Audio
|
||||
'.mp3' : downloadAudio,
|
||||
'.ogg' : downloadAudio,
|
||||
'.wav' : downloadAudio,
|
||||
'.m4a' : downloadAudio,
|
||||
|
||||
// Txt
|
||||
'.txt' : downloadText,
|
||||
'.xml' : downloadText,
|
||||
'.vsh' : downloadText,
|
||||
'.fsh' : downloadText,
|
||||
'.atlas' : downloadText,
|
||||
|
||||
'.tmx' : downloadText,
|
||||
'.tsx' : downloadText,
|
||||
|
||||
'.json' : downloadJson,
|
||||
'.ExportJson' : downloadJson,
|
||||
'.plist' : downloadText,
|
||||
|
||||
'.fnt' : downloadText,
|
||||
|
||||
// font
|
||||
'.font' : loadFont,
|
||||
'.eot' : loadFont,
|
||||
'.ttf' : loadFont,
|
||||
'.woff' : loadFont,
|
||||
'.svg' : loadFont,
|
||||
'.ttc' : loadFont,
|
||||
|
||||
// Video
|
||||
'.mp4': downloadVideo,
|
||||
'.avi': downloadVideo,
|
||||
'.mov': downloadVideo,
|
||||
'.mpg': downloadVideo,
|
||||
'.mpeg': downloadVideo,
|
||||
'.rm': downloadVideo,
|
||||
'.rmvb': downloadVideo,
|
||||
|
||||
// Binary
|
||||
'.binary' : downloadArrayBuffer,
|
||||
'.bin': downloadArrayBuffer,
|
||||
'.dbbin': downloadArrayBuffer,
|
||||
'.skel': downloadArrayBuffer,
|
||||
|
||||
'.js': downloadScript,
|
||||
|
||||
'bundle': downloadBundle,
|
||||
|
||||
'default': downloadText
|
||||
|
||||
};
|
||||
|
||||
downloader._downloaders = downloaders;
|
||||
module.exports = downloader;
|
201
engine/cocos2d/core/asset-manager/factory.js
Normal file
201
engine/cocos2d/core/asset-manager/factory.js
Normal file
@@ -0,0 +1,201 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const Bundle = require('./bundle');
|
||||
const Cache = require('./cache');
|
||||
const { assets, bundles } = require('./shared');
|
||||
|
||||
const _creating = new Cache();
|
||||
|
||||
function createTexture (id, data, options, onComplete) {
|
||||
let out = null, err = null;
|
||||
try {
|
||||
out = new cc.Texture2D();
|
||||
out._nativeUrl = id;
|
||||
out._nativeAsset = data;
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
onComplete && onComplete(err, out);
|
||||
}
|
||||
|
||||
function createAudioClip (id, data, options, onComplete) {
|
||||
let out = new cc.AudioClip();
|
||||
out._nativeUrl = id;
|
||||
out._nativeAsset = data;
|
||||
out.duration = data.duration;
|
||||
onComplete && onComplete(null, out);
|
||||
}
|
||||
|
||||
function createVideoClip (id, data, options, onComplete) {
|
||||
let out = new cc.VideoClip();
|
||||
out._nativeUrl = id;
|
||||
out._nativeAsset = data;
|
||||
onComplete && onComplete(null, out);
|
||||
}
|
||||
|
||||
function createJsonAsset (id, data, options, onComplete) {
|
||||
let out = new cc.JsonAsset();
|
||||
out.json = data;
|
||||
onComplete && onComplete(null, out);
|
||||
}
|
||||
|
||||
function createTextAsset (id, data, options, onComplete) {
|
||||
let out = new cc.TextAsset();
|
||||
out.text = data;
|
||||
onComplete && onComplete(null, out);
|
||||
}
|
||||
|
||||
function createFont (id, data, options, onComplete) {
|
||||
let out = new cc.TTFFont();
|
||||
out._nativeUrl = id;
|
||||
out._nativeAsset = data;
|
||||
onComplete && onComplete(null, out);
|
||||
}
|
||||
|
||||
function createBufferAsset (id, data, options, onComplete) {
|
||||
let out = new cc.BufferAsset();
|
||||
out._nativeUrl = id;
|
||||
out._nativeAsset = data;
|
||||
onComplete && onComplete(null, out);
|
||||
}
|
||||
|
||||
function createAsset (id, data, options, onComplete) {
|
||||
let out = new cc.Asset();
|
||||
out._nativeUrl = id;
|
||||
out._nativeAsset = data;
|
||||
onComplete && onComplete(null, out);
|
||||
}
|
||||
|
||||
function createBundle (id, data, options, onComplete) {
|
||||
let bundle = bundles.get(data.name);
|
||||
if (!bundle) {
|
||||
bundle = new Bundle();
|
||||
data.base = data.base || id + '/';
|
||||
bundle.init(data);
|
||||
}
|
||||
onComplete && onComplete(null, bundle);
|
||||
}
|
||||
|
||||
const factory = {
|
||||
|
||||
register (type, handler) {
|
||||
if (typeof type === 'object') {
|
||||
cc.js.mixin(producers, type);
|
||||
}
|
||||
else {
|
||||
producers[type] = handler;
|
||||
}
|
||||
},
|
||||
|
||||
create (id, data, type, options, onComplete) {
|
||||
var func = producers[type] || producers['default'];
|
||||
let asset, creating;
|
||||
if (asset = assets.get(id)) {
|
||||
onComplete(null, asset);
|
||||
}
|
||||
else if (creating = _creating.get(id)) {
|
||||
creating.push(onComplete);
|
||||
}
|
||||
else {
|
||||
_creating.add(id, [onComplete]);
|
||||
func(id, data, options, function (err, data) {
|
||||
if (!err && data instanceof cc.Asset) {
|
||||
data._uuid = id;
|
||||
assets.add(id, data);
|
||||
}
|
||||
let callbacks = _creating.remove(id);
|
||||
for (let i = 0, l = callbacks.length; i < l; i++) {
|
||||
callbacks[i](err, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const producers = {
|
||||
// Images
|
||||
'.png' : createTexture,
|
||||
'.jpg' : createTexture,
|
||||
'.bmp' : createTexture,
|
||||
'.jpeg' : createTexture,
|
||||
'.gif' : createTexture,
|
||||
'.ico' : createTexture,
|
||||
'.tiff' : createTexture,
|
||||
'.webp' : createTexture,
|
||||
'.image' : createTexture,
|
||||
'.pvr': createTexture,
|
||||
'.pkm': createTexture,
|
||||
|
||||
// Audio
|
||||
'.mp3' : createAudioClip,
|
||||
'.ogg' : createAudioClip,
|
||||
'.wav' : createAudioClip,
|
||||
'.m4a' : createAudioClip,
|
||||
|
||||
// Video
|
||||
'.mp4' : createVideoClip,
|
||||
'.avi' : createVideoClip,
|
||||
'.mov' : createVideoClip,
|
||||
'.mpg' : createVideoClip,
|
||||
'.mpeg': createVideoClip,
|
||||
'.rm' : createVideoClip,
|
||||
'.rmvb': createVideoClip,
|
||||
|
||||
// Txt
|
||||
'.txt' : createTextAsset,
|
||||
'.xml' : createTextAsset,
|
||||
'.vsh' : createTextAsset,
|
||||
'.fsh' : createTextAsset,
|
||||
'.atlas' : createTextAsset,
|
||||
|
||||
'.tmx' : createTextAsset,
|
||||
'.tsx' : createTextAsset,
|
||||
'.fnt' : createTextAsset,
|
||||
|
||||
'.json' : createJsonAsset,
|
||||
'.ExportJson' : createJsonAsset,
|
||||
|
||||
// font
|
||||
'.font' : createFont,
|
||||
'.eot' : createFont,
|
||||
'.ttf' : createFont,
|
||||
'.woff' : createFont,
|
||||
'.svg' : createFont,
|
||||
'.ttc' : createFont,
|
||||
|
||||
// Binary
|
||||
'.binary': createBufferAsset,
|
||||
'.bin': createBufferAsset,
|
||||
'.dbbin': createBufferAsset,
|
||||
'.skel': createBufferAsset,
|
||||
|
||||
'bundle': createBundle,
|
||||
|
||||
'default': createAsset
|
||||
|
||||
};
|
||||
|
||||
module.exports = factory;
|
129
engine/cocos2d/core/asset-manager/fetch.js
Normal file
129
engine/cocos2d/core/asset-manager/fetch.js
Normal file
@@ -0,0 +1,129 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const packManager = require('./pack-manager');
|
||||
const Task = require('./task');
|
||||
const { getDepends, clear, forEach } = require('./utilities');
|
||||
const { assets, fetchPipeline } = require('./shared');
|
||||
|
||||
function fetch (task, done) {
|
||||
|
||||
let firstTask = false;
|
||||
if (!task.progress) {
|
||||
task.progress = { finish: 0, total: task.input.length, canInvoke: true };
|
||||
firstTask = true;
|
||||
}
|
||||
|
||||
let options = task.options, depends = [], progress = task.progress, total = progress.total;
|
||||
options.__exclude__ = options.__exclude__ || Object.create(null);
|
||||
|
||||
task.output = [];
|
||||
|
||||
forEach(task.input, function (item, cb) {
|
||||
|
||||
if (!item.isNative && assets.has(item.uuid)) {
|
||||
var asset = assets.get(item.uuid);
|
||||
asset.addRef();
|
||||
handle(item, task, asset, null, asset.__asyncLoadAssets__, depends, total, done);
|
||||
return cb();
|
||||
}
|
||||
|
||||
packManager.load(item, task.options, function (err, data) {
|
||||
if (err) {
|
||||
if (!task.isFinish) {
|
||||
if (!cc.assetManager.force || firstTask) {
|
||||
cc.error(err.message, err.stack);
|
||||
progress.canInvoke = false;
|
||||
done(err);
|
||||
}
|
||||
else {
|
||||
handle(item, task, null, null, false, depends, total, done);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!task.isFinish) handle(item, task, null, data, !item.isNative, depends, total, done);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
|
||||
}, function () {
|
||||
|
||||
if (task.isFinish) {
|
||||
clear(task, true);
|
||||
return task.dispatch('error');
|
||||
}
|
||||
if (depends.length > 0) {
|
||||
|
||||
// stage 2 , download depend asset
|
||||
let subTask = Task.create({
|
||||
name: task.name + ' dependencies',
|
||||
input: depends,
|
||||
progress,
|
||||
options,
|
||||
onProgress: task.onProgress,
|
||||
onError: Task.prototype.recycle,
|
||||
onComplete: function (err) {
|
||||
if (!err) {
|
||||
task.output.push.apply(task.output, this.output);
|
||||
subTask.recycle();
|
||||
}
|
||||
if (firstTask) decreaseRef(task);
|
||||
done(err);
|
||||
},
|
||||
});
|
||||
fetchPipeline.async(subTask);
|
||||
return;
|
||||
}
|
||||
if (firstTask) decreaseRef(task);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
function decreaseRef (task) {
|
||||
let output = task.output;
|
||||
for (let i = 0, l = output.length; i < l; i++) {
|
||||
output[i].content && output[i].content.decRef(false);
|
||||
}
|
||||
}
|
||||
|
||||
function handle (item, task, content, file, loadDepends, depends, last, done) {
|
||||
|
||||
var exclude = task.options.__exclude__;
|
||||
var progress = task.progress;
|
||||
|
||||
item.content = content;
|
||||
item.file = file;
|
||||
task.output.push(item);
|
||||
|
||||
if (loadDepends) {
|
||||
exclude[item.uuid] = true;
|
||||
getDepends(item.uuid, file || content, exclude, depends, true, false, item.config);
|
||||
progress.total = last + depends.length;
|
||||
}
|
||||
|
||||
progress.canInvoke && task.dispatch('progress', ++progress.finish, progress.total, item);
|
||||
}
|
||||
|
||||
module.exports = fetch;
|
226
engine/cocos2d/core/asset-manager/font-loader.js
Normal file
226
engine/cocos2d/core/asset-manager/font-loader.js
Normal file
@@ -0,0 +1,226 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
const textUtils = require('../utils/text-utils');
|
||||
|
||||
let _canvasContext = null;
|
||||
// letter symbol number CJK
|
||||
let _testString = "BES bswy:->@123\u4E01\u3041\u1101";
|
||||
|
||||
let _fontFaces = Object.create(null);
|
||||
let _intervalId = -1;
|
||||
let _loadingFonts = [];
|
||||
// 3 seconds timeout
|
||||
let _timeout = 3000;
|
||||
|
||||
// Refer to https://github.com/typekit/webfontloader/blob/master/src/core/fontwatcher.js
|
||||
let useNativeCheck = (function () {
|
||||
var nativeCheck = undefined;
|
||||
return function () {
|
||||
if (nativeCheck === undefined) {
|
||||
if (!!window.FontFace) {
|
||||
var match = /Gecko.*Firefox\/(\d+)/.exec(window.navigator.userAgent);
|
||||
var safari10Match = /OS X.*Version\/10\..*Safari/.exec(window.navigator.userAgent) && /Apple/.exec(window.navigator.vendor);
|
||||
|
||||
if (match) {
|
||||
nativeCheck = parseInt(match[1], 10) > 42;
|
||||
}
|
||||
else if (safari10Match) {
|
||||
nativeCheck = false;
|
||||
}
|
||||
else {
|
||||
nativeCheck = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
nativeCheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
return nativeCheck;
|
||||
|
||||
}
|
||||
})();
|
||||
|
||||
function _checkFontLoaded () {
|
||||
let allFontsLoaded = true;
|
||||
let now = Date.now();
|
||||
|
||||
for (let i = _loadingFonts.length - 1; i >= 0; i--) {
|
||||
let fontLoadHandle = _loadingFonts[i];
|
||||
let fontFamily = fontLoadHandle.fontFamilyName;
|
||||
// load timeout
|
||||
if (now - fontLoadHandle.startTime > _timeout) {
|
||||
cc.warnID(4933, fontFamily);
|
||||
fontLoadHandle.onComplete(null, fontFamily);
|
||||
_loadingFonts.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
let oldWidth = fontLoadHandle.refWidth;
|
||||
let fontDesc = '40px ' + fontFamily;
|
||||
_canvasContext.font = fontDesc;
|
||||
let newWidth = textUtils.safeMeasureText(_canvasContext, _testString, fontDesc);
|
||||
// loaded successfully
|
||||
if (oldWidth !== newWidth) {
|
||||
_loadingFonts.splice(i, 1);
|
||||
fontLoadHandle.onComplete(null, fontFamily);
|
||||
}
|
||||
else {
|
||||
allFontsLoaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (allFontsLoaded) {
|
||||
clearInterval(_intervalId);
|
||||
_intervalId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// refer to https://github.com/typekit/webfontloader/blob/master/src/core/nativefontwatchrunner.js
|
||||
function nativeCheckFontLoaded (start, font, callback) {
|
||||
var loader = new Promise(function (resolve, reject) {
|
||||
var check = function () {
|
||||
var now = Date.now();
|
||||
|
||||
if (now - start >= _timeout) {
|
||||
reject();
|
||||
}
|
||||
else {
|
||||
document.fonts.load('40px ' + font).then(function (fonts) {
|
||||
if (fonts.length >= 1) {
|
||||
resolve();
|
||||
}
|
||||
else {
|
||||
setTimeout(check, 100);
|
||||
}
|
||||
}, function () {
|
||||
reject();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
check();
|
||||
});
|
||||
|
||||
var timeoutId = null,
|
||||
timer = new Promise(function (resolve, reject) {
|
||||
timeoutId = setTimeout(reject, _timeout);
|
||||
});
|
||||
|
||||
Promise.race([timer, loader]).then(function () {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
}
|
||||
|
||||
callback(null, font);
|
||||
}, function () {
|
||||
cc.warnID(4933, font);
|
||||
callback(null, font);
|
||||
});
|
||||
}
|
||||
|
||||
var fontLoader = {
|
||||
loadFont: function (url, options, onComplete) {
|
||||
let fontFamilyName = fontLoader._getFontFamily(url);
|
||||
|
||||
// Already loaded fonts
|
||||
if (_fontFaces[fontFamilyName]) {
|
||||
return onComplete(null, fontFamilyName);
|
||||
}
|
||||
|
||||
if (!_canvasContext) {
|
||||
let labelCanvas = document.createElement('canvas');
|
||||
labelCanvas.width = 100;
|
||||
labelCanvas.height = 100;
|
||||
_canvasContext = labelCanvas.getContext('2d');
|
||||
}
|
||||
|
||||
// Default width reference to test whether new font is loaded correctly
|
||||
let fontDesc = '40px ' + fontFamilyName;
|
||||
_canvasContext.font = fontDesc;
|
||||
let refWidth = textUtils.safeMeasureText(_canvasContext, _testString, fontDesc);
|
||||
|
||||
// Setup font face style
|
||||
let fontStyle = document.createElement("style");
|
||||
fontStyle.type = "text/css";
|
||||
let fontStr = "";
|
||||
if (isNaN(fontFamilyName - 0))
|
||||
fontStr += "@font-face { font-family:" + fontFamilyName + "; src:";
|
||||
else
|
||||
fontStr += "@font-face { font-family:'" + fontFamilyName + "'; src:";
|
||||
fontStr += "url('" + url + "');";
|
||||
fontStyle.textContent = fontStr + "}";
|
||||
document.body.appendChild(fontStyle);
|
||||
|
||||
// Preload font with div
|
||||
let preloadDiv = document.createElement("div");
|
||||
let divStyle = preloadDiv.style;
|
||||
divStyle.fontFamily = fontFamilyName;
|
||||
preloadDiv.innerHTML = ".";
|
||||
divStyle.position = "absolute";
|
||||
divStyle.left = "-100px";
|
||||
divStyle.top = "-100px";
|
||||
document.body.appendChild(preloadDiv);
|
||||
|
||||
if (useNativeCheck()) {
|
||||
nativeCheckFontLoaded(Date.now(), fontFamilyName, onComplete);
|
||||
}
|
||||
else {
|
||||
// Save loading font
|
||||
let fontLoadHandle = {
|
||||
fontFamilyName,
|
||||
refWidth,
|
||||
onComplete,
|
||||
startTime: Date.now()
|
||||
}
|
||||
_loadingFonts.push(fontLoadHandle);
|
||||
if (_intervalId === -1) {
|
||||
_intervalId = setInterval(_checkFontLoaded, 100);
|
||||
}
|
||||
}
|
||||
_fontFaces[fontFamilyName] = fontStyle;
|
||||
},
|
||||
|
||||
_getFontFamily: function (fontHandle) {
|
||||
var ttfIndex = fontHandle.lastIndexOf(".ttf");
|
||||
if (ttfIndex === -1) return fontHandle;
|
||||
|
||||
var slashPos = fontHandle.lastIndexOf("/");
|
||||
var fontFamilyName;
|
||||
if (slashPos === -1) {
|
||||
fontFamilyName = fontHandle.substring(0, ttfIndex) + "_LABEL";
|
||||
} else {
|
||||
fontFamilyName = fontHandle.substring(slashPos + 1, ttfIndex) + "_LABEL";
|
||||
}
|
||||
if (fontFamilyName.indexOf(' ') !== -1) {
|
||||
fontFamilyName = '"' + fontFamilyName + '"';
|
||||
}
|
||||
return fontFamilyName;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = fontLoader
|
174
engine/cocos2d/core/asset-manager/helper.js
Normal file
174
engine/cocos2d/core/asset-manager/helper.js
Normal file
@@ -0,0 +1,174 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const { bundles } = require('./shared');
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
/**
|
||||
* !#en
|
||||
* Provide some helpful function, it is a singleton. All member can be accessed with `cc.assetManager.utils`
|
||||
*
|
||||
* !#zh
|
||||
* 提供一些辅助方法,helper 是一个单例, 所有成员能通过 `cc.assetManager.utils` 访问
|
||||
*
|
||||
* @class Helper
|
||||
*/
|
||||
var helper = {
|
||||
/**
|
||||
* !#en
|
||||
* Decode uuid, returns the original uuid
|
||||
*
|
||||
* !#zh
|
||||
* 解码 uuid,返回原始 uuid
|
||||
*
|
||||
* @method decodeUuid
|
||||
* @param {String} base64 - the encoded uuid
|
||||
* @returns {String} the original uuid
|
||||
*
|
||||
* @example
|
||||
* var uuid = 'fcmR3XADNLgJ1ByKhqcC5Z';
|
||||
* var originalUuid = decodeUuid(uuid); // fc991dd7-0033-4b80-9d41-c8a86a702e59
|
||||
*
|
||||
* @typescript
|
||||
* decodeUuid(base64: string): string
|
||||
*/
|
||||
decodeUuid: require('../utils/decode-uuid'),
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Extract uuid from url
|
||||
*
|
||||
* !#zh
|
||||
* 从 url 中提取 uuid
|
||||
*
|
||||
* @method getUuidFromURL
|
||||
* @param {String} url - url
|
||||
* @returns {String} the uuid parsed from url
|
||||
*
|
||||
* @example
|
||||
* var url = 'assets/main/import/fc/fc991dd7-0033-4b80-9d41-c8a86a702e59.json';
|
||||
* var uuid = getUuidFromURL(url); // fc991dd7-0033-4b80-9d41-c8a86a702e59
|
||||
*
|
||||
* @typescript
|
||||
* getUuidFromURL(url: string): string
|
||||
*/
|
||||
getUuidFromURL: (function () {
|
||||
var _uuidRegex = /.*[/\\][0-9a-fA-F]{2}[/\\]([0-9a-fA-F-]{8,})/;
|
||||
return function (url) {
|
||||
var matches = url.match(_uuidRegex);
|
||||
if (matches) {
|
||||
return matches[1];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
})(),
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Transform uuid to url
|
||||
*
|
||||
* !#zh
|
||||
* 转换 uuid 为 url
|
||||
*
|
||||
* @method getUrlWithUuid
|
||||
* @param {string} uuid - The uuid of asset
|
||||
* @param {Object} [options] - Some optional parameters
|
||||
* @param {Boolean} [options.isNative] - Indicates whether the path you want is a native resource path
|
||||
* @param {string} [options.nativeExt] - Extension of the native resource path, it is required when isNative is true
|
||||
* @returns {string} url
|
||||
*
|
||||
* @example
|
||||
* // json path, 'assets/main/import/fc/fc991dd7-0033-4b80-9d41-c8a86a702e59.json';
|
||||
* var url = getUrlWithUuid('fcmR3XADNLgJ1ByKhqcC5Z', {isNative: false});
|
||||
*
|
||||
* // png path, 'assets/main/native/fc/fc991dd7-0033-4b80-9d41-c8a86a702e59.png';
|
||||
* var url = getUrlWithUuid('fcmR3XADNLgJ1ByKhqcC5Z', {isNative: true, nativeExt: '.png'});
|
||||
*
|
||||
* @typescript
|
||||
* getUrlWithUuid(uuid: string, options?: Record<string, any>): string
|
||||
*/
|
||||
getUrlWithUuid: function (uuid, options) {
|
||||
options = options || Object.create(null);
|
||||
options.__isNative__ = options.isNative;
|
||||
options.ext = options.nativeExt;
|
||||
var bundle = bundles.find(function (bundle) {
|
||||
return bundle.getAssetInfo(uuid);
|
||||
});
|
||||
|
||||
if (bundle) {
|
||||
options.bundle = bundle.name;
|
||||
}
|
||||
|
||||
return cc.assetManager._transform(uuid, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Check if the type of asset is scene
|
||||
*
|
||||
* !#zh
|
||||
* 检查资源类型是否是场景
|
||||
*
|
||||
* @method isScene
|
||||
* @param {*} asset - asset
|
||||
* @returns {boolean} - whether or not type is cc.SceneAsset
|
||||
*
|
||||
* @typescript
|
||||
* isScene(asset: any): boolean
|
||||
*/
|
||||
isScene: function (asset) {
|
||||
return asset && (asset.constructor === cc.SceneAsset || asset instanceof cc.Scene);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Normalize url, strip './' and '/'
|
||||
*
|
||||
* !#zh
|
||||
* 标准化 url ,去除 './' 和 '/'
|
||||
*
|
||||
* @method normalize
|
||||
* @param {string} url - url
|
||||
* @returns {string} - The normalized url
|
||||
*
|
||||
* @typescript
|
||||
* normalize(url: string): string
|
||||
*/
|
||||
normalize: function (url) {
|
||||
if (url) {
|
||||
if (url.charCodeAt(0) === 46 && url.charCodeAt(1) === 47) {
|
||||
// strip './'
|
||||
url = url.slice(2);
|
||||
}
|
||||
else if (url.charCodeAt(0) === 47) {
|
||||
// strip '/'
|
||||
url = url.slice(1);
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = helper;
|
27
engine/cocos2d/core/asset-manager/index.js
Normal file
27
engine/cocos2d/core/asset-manager/index.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
require('./deprecated');
|
||||
require('./CCAssetManager');
|
||||
|
244
engine/cocos2d/core/asset-manager/load.js
Normal file
244
engine/cocos2d/core/asset-manager/load.js
Normal file
@@ -0,0 +1,244 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const packManager = require('./pack-manager');
|
||||
const Pipeline = require('./pipeline');
|
||||
const parser = require('./parser');
|
||||
const { getDepends, cache, gatherAsset, setProperties, forEach, clear, checkCircleReference } = require('./utilities');
|
||||
const { assets, files, parsed, pipeline } = require('./shared');
|
||||
const Task = require('./task');
|
||||
|
||||
function load (task, done) {
|
||||
|
||||
let firstTask = false;
|
||||
if (!task.progress) {
|
||||
task.progress = { finish: 0, total: task.input.length, canInvoke: true };
|
||||
firstTask = true;
|
||||
}
|
||||
|
||||
var options = task.options, progress = task.progress;
|
||||
|
||||
options.__exclude__ = options.__exclude__ || Object.create(null);
|
||||
|
||||
task.output = [];
|
||||
|
||||
forEach(task.input, function (item, cb) {
|
||||
|
||||
let subTask = Task.create({
|
||||
input: item,
|
||||
onProgress: task.onProgress,
|
||||
options,
|
||||
progress,
|
||||
onComplete: function (err, item) {
|
||||
if (err && !task.isFinish) {
|
||||
if (!cc.assetManager.force || firstTask) {
|
||||
if (!CC_EDITOR) {
|
||||
cc.error(err.message, err.stack);
|
||||
}
|
||||
progress.canInvoke = false;
|
||||
done(err);
|
||||
}
|
||||
else {
|
||||
progress.canInvoke && task.dispatch('progress', ++progress.finish, progress.total, item);
|
||||
}
|
||||
}
|
||||
task.output.push(item);
|
||||
subTask.recycle();
|
||||
cb();
|
||||
}
|
||||
});
|
||||
|
||||
loadOneAssetPipeline.async(subTask);
|
||||
|
||||
}, function () {
|
||||
|
||||
options.__exclude__ = null;
|
||||
|
||||
if (task.isFinish) {
|
||||
clear(task, true);
|
||||
return task.dispatch('error');
|
||||
}
|
||||
|
||||
gatherAsset(task);
|
||||
clear(task, true);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
var loadOneAssetPipeline = new Pipeline('loadOneAsset', [
|
||||
|
||||
function fetch (task, done) {
|
||||
var item = task.output = task.input;
|
||||
var { options, isNative, uuid, file } = item;
|
||||
var { reload } = options;
|
||||
|
||||
if (file || (!reload && !isNative && assets.has(uuid))) return done();
|
||||
|
||||
packManager.load(item, task.options, function (err, data) {
|
||||
item.file = data;
|
||||
done(err);
|
||||
});
|
||||
},
|
||||
|
||||
function parse (task, done) {
|
||||
|
||||
var item = task.output = task.input, progress = task.progress, exclude = task.options.__exclude__;
|
||||
var { id, file, options } = item;
|
||||
|
||||
if (item.isNative) {
|
||||
parser.parse(id, file, item.ext, options, function (err, asset) {
|
||||
if (err) return done(err);
|
||||
item.content = asset;
|
||||
progress.canInvoke && task.dispatch('progress', ++progress.finish, progress.total, item);
|
||||
files.remove(id);
|
||||
parsed.remove(id);
|
||||
done();
|
||||
});
|
||||
}
|
||||
else {
|
||||
var { uuid } = item;
|
||||
if (uuid in exclude) {
|
||||
|
||||
var { finish, content, err, callbacks } = exclude[uuid];
|
||||
progress.canInvoke && task.dispatch('progress', ++progress.finish, progress.total, item);
|
||||
|
||||
if (finish || checkCircleReference(uuid, uuid, exclude) ) {
|
||||
content && content.addRef && content.addRef();
|
||||
item.content = content;
|
||||
done(err);
|
||||
}
|
||||
else {
|
||||
callbacks.push({ done, item });
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!options.reload && assets.has(uuid)) {
|
||||
var asset = assets.get(uuid);
|
||||
if (options.__asyncLoadAssets__ || !asset.__asyncLoadAssets__) {
|
||||
item.content = asset.addRef();
|
||||
progress.canInvoke && task.dispatch('progress', ++progress.finish, progress.total, item);
|
||||
done();
|
||||
}
|
||||
else {
|
||||
loadDepends(task, asset, done, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
parser.parse(id, file, 'import', options, function (err, asset) {
|
||||
if (err) return done(err);
|
||||
asset._uuid = uuid;
|
||||
loadDepends(task, asset, done, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
function loadDepends (task, asset, done, init) {
|
||||
|
||||
var item = task.input, progress = task.progress;
|
||||
var { uuid, id, options, config } = item;
|
||||
var { __asyncLoadAssets__, cacheAsset } = options;
|
||||
|
||||
var depends = [];
|
||||
// add reference avoid being released during loading dependencies
|
||||
asset.addRef && asset.addRef();
|
||||
getDepends(uuid, asset, Object.create(null), depends, false, __asyncLoadAssets__, config);
|
||||
progress.canInvoke && task.dispatch('progress', ++progress.finish, progress.total += depends.length, item);
|
||||
|
||||
var repeatItem = task.options.__exclude__[uuid] = { content: asset, finish: false, callbacks: [{ done, item }] };
|
||||
|
||||
let subTask = Task.create({
|
||||
input: depends,
|
||||
options: task.options,
|
||||
onProgress: task.onProgress,
|
||||
onError: Task.prototype.recycle,
|
||||
progress,
|
||||
onComplete: function (err) {
|
||||
asset.decRef && asset.decRef(false);
|
||||
asset.__asyncLoadAssets__ = __asyncLoadAssets__;
|
||||
repeatItem.finish = true;
|
||||
repeatItem.err = err;
|
||||
|
||||
if (!err) {
|
||||
|
||||
var assets = Array.isArray(subTask.output) ? subTask.output : [subTask.output];
|
||||
var map = Object.create(null);
|
||||
for (let i = 0, l = assets.length; i < l; i++) {
|
||||
var dependAsset = assets[i];
|
||||
dependAsset && (map[dependAsset instanceof cc.Asset ? dependAsset._uuid + '@import' : uuid + '@native'] = dependAsset);
|
||||
}
|
||||
|
||||
if (!init) {
|
||||
if (asset.__nativeDepend__ && !asset._nativeAsset) {
|
||||
var missingAsset = setProperties(uuid, asset, map);
|
||||
if (!missingAsset && !asset.__onLoadInvoked__) {
|
||||
try {
|
||||
asset.onLoad && asset.onLoad();
|
||||
asset.__onLoadInvoked__ = true;
|
||||
}
|
||||
catch (e) {
|
||||
cc.error(e.message, e.stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var missingAsset = setProperties(uuid, asset, map);
|
||||
if (!missingAsset && !asset.__onLoadInvoked__) {
|
||||
try {
|
||||
asset.onLoad && asset.onLoad();
|
||||
asset.__onLoadInvoked__ = true;
|
||||
}
|
||||
catch (e) {
|
||||
cc.error(e.message, e.stack);
|
||||
}
|
||||
}
|
||||
files.remove(id);
|
||||
parsed.remove(id);
|
||||
cache(uuid, asset, cacheAsset !== undefined ? cacheAsset : cc.assetManager.cacheAsset);
|
||||
}
|
||||
subTask.recycle();
|
||||
}
|
||||
|
||||
var callbacks = repeatItem.callbacks;
|
||||
|
||||
for (var i = 0, l = callbacks.length; i < l; i++) {
|
||||
|
||||
var cb = callbacks[i];
|
||||
asset.addRef && asset.addRef();
|
||||
cb.item.content = asset;
|
||||
cb.done(err);
|
||||
|
||||
}
|
||||
|
||||
callbacks.length = 0;
|
||||
}
|
||||
});
|
||||
|
||||
pipeline.async(subTask);
|
||||
}
|
||||
|
||||
module.exports = load;
|
266
engine/cocos2d/core/asset-manager/pack-manager.js
Normal file
266
engine/cocos2d/core/asset-manager/pack-manager.js
Normal file
@@ -0,0 +1,266 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
import { unpackJSONs, packCustomObjData } from '../platform/deserialize-compiled';
|
||||
|
||||
const downloader = require('./downloader');
|
||||
const Cache = require('./cache');
|
||||
const js = require('../platform/js');
|
||||
const { files } = require('./shared');
|
||||
|
||||
var _loading = new Cache();
|
||||
|
||||
function isLoading (val) {
|
||||
return _loading.has(val.uuid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
/**
|
||||
* !#en
|
||||
* Handle the packed asset, include unpacking, loading, cache and so on. It is a singleton. All member can be accessed with `cc.assetManager.packManager`
|
||||
*
|
||||
* !#zh
|
||||
* 处理打包资源,包括拆包,加载,缓存等等,这是一个单例, 所有成员能通过 `cc.assetManager.packManager` 访问
|
||||
*
|
||||
* @class PackManager
|
||||
*/
|
||||
var packManager = {
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Unpack the json, revert to what it was before packing
|
||||
*
|
||||
* !#zh
|
||||
* 拆解 json 包,恢复为打包之前的内容
|
||||
*
|
||||
* @method unpackJson
|
||||
* @param {String[]} pack - The pack
|
||||
* @param {Object} json - The content of pack
|
||||
* @param {Object} options - Some optional parameters
|
||||
* @param {Function} onComplete - Callback when finish unpacking
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {Object} onComplete.content - The unpacked assets
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('pack.json', {responseType: 'json'}, null, (err, file) => {
|
||||
* packManager.unpackJson(['a', 'b'], file, null, (err, data) => console.log(err));
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* unpackJson(pack: string[], json: any, options: Record<string, any>, onComplete?: (err: Error, content: any) => void): void
|
||||
*/
|
||||
unpackJson (pack, json, options, onComplete) {
|
||||
|
||||
var out = js.createMap(true), err = null;
|
||||
|
||||
if (Array.isArray(json)) {
|
||||
|
||||
json = unpackJSONs(json);
|
||||
|
||||
if (json.length !== pack.length) {
|
||||
cc.errorID(4915);
|
||||
}
|
||||
for (let i = 0; i < pack.length; i++) {
|
||||
var key = pack[i] + '@import';
|
||||
out[key] = json[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
const textureType = js._getClassId(cc.Texture2D);
|
||||
if (json.type === textureType) {
|
||||
if (json.data) {
|
||||
var datas = json.data.split('|');
|
||||
if (datas.length !== pack.length) {
|
||||
cc.errorID(4915);
|
||||
}
|
||||
for (let i = 0; i < pack.length; i++) {
|
||||
out[pack[i] + '@import'] = packCustomObjData(textureType, datas[i], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
err = new Error('unmatched type pack!');
|
||||
out = null;
|
||||
}
|
||||
}
|
||||
onComplete && onComplete(err, out);
|
||||
},
|
||||
|
||||
init () {
|
||||
_loading.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Register custom handler if you want to change default behavior or extend packManager to unpack other format pack
|
||||
*
|
||||
* !#zh
|
||||
* 当你想修改默认行为或者拓展 packManager 来拆分其他格式的包时可以注册自定义的 handler
|
||||
*
|
||||
* @method register
|
||||
* @param {string|Object} type - Extension likes '.bin' or map likes {'.bin': binHandler, '.ab': abHandler}
|
||||
* @param {Function} [handler] - handler
|
||||
* @param {string} handler.packUuid - The uuid of pack
|
||||
* @param {*} handler.data - The content of pack
|
||||
* @param {Object} handler.options - Some optional parameters
|
||||
* @param {Function} handler.onComplete - Callback when finishing unpacking
|
||||
*
|
||||
* @example
|
||||
* packManager.register('.bin', (packUuid, file, options, onComplete) => onComplete(null, null));
|
||||
* packManager.register({'.bin': (packUuid, file, options, onComplete) => onComplete(null, null), '.ab': (packUuid, file, options, onComplete) => onComplete(null, null)});
|
||||
*
|
||||
* @typescript
|
||||
* register(type: string, handler: (packUuid: string, data: any, options: Record<string, any>, onComplete: (err: Error, content: any) => void) => void): void
|
||||
* register(map: Record<string, (packUuid: string, data: any, options: Record<string, any>, onComplete: (err: Error, content: any) => void) => void>): void
|
||||
*/
|
||||
register (type, handler) {
|
||||
if (typeof type === 'object') {
|
||||
js.mixin(unpackers, type);
|
||||
}
|
||||
else {
|
||||
unpackers[type] = handler;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Use corresponding handler to unpack package
|
||||
*
|
||||
* !#zh
|
||||
* 用对应的 handler 来进行解包
|
||||
*
|
||||
* @method unpack
|
||||
* @param {String[]} pack - The uuid of packed assets
|
||||
* @param {*} data - The packed data
|
||||
* @param {string} type - The type indicates that which handler should be used to download, such as '.jpg'
|
||||
* @param {Object} options - Some optional parameter
|
||||
* @param {Function} onComplete - callback when finishing unpacking
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {*} onComplete.data - Original assets
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('pack.json', {responseType: 'json'}, null, (err, file) => {
|
||||
* packManager.unpack(['2fawq123d', '1zsweq23f'], file, '.json', null, (err, data) => console.log(err));
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* unpack(pack: string[], data: any, type: string, options: Record<string, any>, onComplete?: (err: Error, data: any) => void): void
|
||||
*/
|
||||
unpack (pack, data, type, options, onComplete) {
|
||||
if (!data) {
|
||||
onComplete && onComplete(new Error('package data is wrong!'));
|
||||
return;
|
||||
}
|
||||
var unpacker = unpackers[type];
|
||||
unpacker(pack, data, options, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Download request item, If item is not in any package, download as usual. Otherwise, download the corresponding package and unpack it.
|
||||
* And then retrieve the corresponding content form it.
|
||||
*
|
||||
* !#zh
|
||||
* 下载请求对象,如果请求对象不在任何包内,则正常下载,否则下载对应的 package 并进行拆解,并取回包内对应的内容
|
||||
*
|
||||
* @method load
|
||||
* @param {RequestItem} item - Some item you want to download
|
||||
* @param {Object} options - Some optional parameters
|
||||
* @param {Function} onComplete - Callback when finished
|
||||
* @param {Err} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {*} onComplete.data - The unpacked data retrieved from package
|
||||
*
|
||||
* @example
|
||||
* var requestItem = cc.AssetManager.RequestItem.create();
|
||||
* requestItem.uuid = 'fcmR3XADNLgJ1ByKhqcC5Z';
|
||||
* requestItem.info = config.getAssetInfo('fcmR3XADNLgJ1ByKhqcC5Z');
|
||||
* packManager.load(requestItem, null, (err, data) => console.log(err));
|
||||
*
|
||||
* @typescript
|
||||
* load(item: RequestItem, options: Record<string, any>, onComplete: (err: Error, data: any) => void): void
|
||||
*
|
||||
*/
|
||||
load (item, options, onComplete) {
|
||||
// if not in any package, download as uausl
|
||||
if (item.isNative || !item.info || !item.info.packs) return downloader.download(item.id, item.url, item.ext, item.options, onComplete);
|
||||
|
||||
if (files.has(item.id)) return onComplete(null, files.get(item.id));
|
||||
|
||||
var packs = item.info.packs;
|
||||
|
||||
// find a loading package
|
||||
var pack = packs.find(isLoading);
|
||||
|
||||
if (pack) return _loading.get(pack.uuid).push({ onComplete, id: item.id });
|
||||
|
||||
// download a new package
|
||||
pack = packs[0];
|
||||
_loading.add(pack.uuid, [{ onComplete, id: item.id }]);
|
||||
|
||||
let url = cc.assetManager._transform(pack.uuid, {ext: pack.ext, bundle: item.config.name});
|
||||
|
||||
downloader.download(pack.uuid, url, pack.ext, item.options, function (err, data) {
|
||||
files.remove(pack.uuid);
|
||||
if (err) {
|
||||
cc.error(err.message, err.stack);
|
||||
}
|
||||
// unpack package
|
||||
packManager.unpack(pack.packs, data, pack.ext, item.options, function (err, result) {
|
||||
if (!err) {
|
||||
for (var id in result) {
|
||||
files.add(id, result[id]);
|
||||
}
|
||||
} else {
|
||||
err.message = `unpack ${url} failed! details: ${err.message}`;
|
||||
}
|
||||
var callbacks = _loading.remove(pack.uuid);
|
||||
for (var i = 0, l = callbacks.length; i < l; i++) {
|
||||
var cb = callbacks[i];
|
||||
if (err) {
|
||||
cb.onComplete(err);
|
||||
continue;
|
||||
}
|
||||
|
||||
var data = result[cb.id];
|
||||
if (!data) {
|
||||
cb.onComplete(new Error('can not retrieve data from package'));
|
||||
}
|
||||
else {
|
||||
cb.onComplete(null, data);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var unpackers = {
|
||||
'.json': packManager.unpackJson
|
||||
};
|
||||
|
||||
module.exports = packManager;
|
440
engine/cocos2d/core/asset-manager/parser.js
Normal file
440
engine/cocos2d/core/asset-manager/parser.js
Normal file
@@ -0,0 +1,440 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
|
||||
const plistParser = require('../platform/CCSAXParser').plistParser;
|
||||
const js = require('../platform/js');
|
||||
const deserialize = require('./deserialize');
|
||||
const Cache = require('./cache');
|
||||
const { isScene } = require('./helper');
|
||||
const { parsed, files } = require('./shared');
|
||||
const { __audioSupport, capabilities } = require('../platform/CCSys');
|
||||
|
||||
var _parsing = new Cache();
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Parse the downloaded file, it's a singleton, all member can be accessed with `cc.assetManager.parser`
|
||||
*
|
||||
* !#zh
|
||||
* 解析已下载的文件,parser 是一个单例, 所有成员能通过 `cc.assetManaager.parser` 访问
|
||||
*
|
||||
* @class Parser
|
||||
*/
|
||||
var parser = {
|
||||
/*
|
||||
* !#en
|
||||
* Parse image file
|
||||
*
|
||||
* !#zh
|
||||
* 解析图片文件
|
||||
*
|
||||
* @method parseImage
|
||||
* @param {Blob} file - The downloaded file
|
||||
* @param {Object} options - Some optional paramters
|
||||
* @param {Function} [onComplete] - callback when finish parsing.
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {ImageBitmap|HTMLImageElement} onComplete.img - The parsed content
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('test.jpg', {responseType: 'blob'}, null, (err, file) => {
|
||||
* parser.parseImage(file, null, (err, img) => console.log(err));
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* parseImage(file: Blob, options: Record<string, any>, onComplete?: (err: Error, img: ImageBitmap|HTMLImageElement) => void): void
|
||||
*/
|
||||
parseImage (file, options, onComplete) {
|
||||
if (capabilities.imageBitmap && file instanceof Blob) {
|
||||
let imageOptions = {};
|
||||
imageOptions.imageOrientation = options.__flipY__ ? 'flipY' : 'none';
|
||||
imageOptions.premultiplyAlpha = options.__premultiplyAlpha__ ? 'premultiply' : 'none';
|
||||
createImageBitmap(file, imageOptions).then(function (result) {
|
||||
result.flipY = !!options.__flipY__;
|
||||
result.premultiplyAlpha = !!options.__premultiplyAlpha__;
|
||||
onComplete && onComplete(null, result);
|
||||
}, function (err) {
|
||||
onComplete && onComplete(err, null);
|
||||
});
|
||||
}
|
||||
else {
|
||||
onComplete && onComplete(null, file);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* !#en
|
||||
* Parse audio file
|
||||
*
|
||||
* !#zh
|
||||
* 解析音频文件
|
||||
*
|
||||
* @method parseAudio
|
||||
* @param {ArrayBuffer|HTMLAudioElement} file - The downloaded file
|
||||
* @param {Object} options - Some optional paramters
|
||||
* @param {Function} onComplete - Callback when finish parsing.
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {AudioBuffer|HTMLAudioElement} onComplete.audio - The parsed content
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('test.mp3', {responseType: 'arraybuffer'}, null, (err, file) => {
|
||||
* parser.parseAudio(file, null, (err, audio) => console.log(err));
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* parseAudio(file: ArrayBuffer|HTMLAudioElement, options: Record<string, any>, onComplete?: (err: Error, audio: AudioBuffer|HTMLAudioElement) => void): void
|
||||
*/
|
||||
parseAudio (file, options, onComplete) {
|
||||
if (file instanceof ArrayBuffer) {
|
||||
__audioSupport.context.decodeAudioData(file, function (buffer) {
|
||||
onComplete && onComplete(null, buffer);
|
||||
}, function(e){
|
||||
onComplete && onComplete(e, null);
|
||||
});
|
||||
}
|
||||
else {
|
||||
onComplete && onComplete(null, file);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* !#en
|
||||
* Parse pvr file
|
||||
*
|
||||
* !#zh
|
||||
* 解析压缩纹理格式 pvr 文件
|
||||
*
|
||||
* @method parsePVRTex
|
||||
* @param {ArrayBuffer|ArrayBufferView} file - The downloaded file
|
||||
* @param {Object} options - Some optional paramters
|
||||
* @param {Function} onComplete - Callback when finish parsing.
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {Object} onComplete.pvrAsset - The parsed content
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('test.pvr', {responseType: 'arraybuffer'}, null, (err, file) => {
|
||||
* parser.parsePVRTex(file, null, (err, pvrAsset) => console.log(err));
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* parsePVRTex(file: ArrayBuffer|ArrayBufferView, options: Record<string, any>, onComplete: (err: Error, pvrAsset: {_data: Uint8Array, _compressed: boolean, width: number, height: number}) => void): void
|
||||
*/
|
||||
parsePVRTex : (function () {
|
||||
//===============//
|
||||
// PVR constants //
|
||||
//===============//
|
||||
// https://github.com/toji/texture-tester/blob/master/js/webgl-texture-util.js#L424
|
||||
const PVR_HEADER_LENGTH = 13; // The header length in 32 bit ints.
|
||||
const PVR_MAGIC = 0x03525650; //0x50565203;
|
||||
|
||||
// Offsets into the header array.
|
||||
const PVR_HEADER_MAGIC = 0;
|
||||
const PVR_HEADER_FORMAT = 2;
|
||||
const PVR_HEADER_HEIGHT = 6;
|
||||
const PVR_HEADER_WIDTH = 7;
|
||||
const PVR_HEADER_MIPMAPCOUNT = 11;
|
||||
const PVR_HEADER_METADATA = 12;
|
||||
|
||||
return function (file, options, onComplete) {
|
||||
let err = null, out = null;
|
||||
try {
|
||||
let buffer = file instanceof ArrayBuffer ? file : file.buffer;
|
||||
// Get a view of the arrayBuffer that represents the DDS header.
|
||||
let header = new Int32Array(buffer, 0, PVR_HEADER_LENGTH);
|
||||
|
||||
// Do some sanity checks to make sure this is a valid DDS file.
|
||||
if(header[PVR_HEADER_MAGIC] != PVR_MAGIC) {
|
||||
throw new Error("Invalid magic number in PVR header");
|
||||
}
|
||||
|
||||
// Gather other basic metrics and a view of the raw the DXT data.
|
||||
let width = header[PVR_HEADER_WIDTH];
|
||||
let height = header[PVR_HEADER_HEIGHT];
|
||||
let dataOffset = header[PVR_HEADER_METADATA] + 52;
|
||||
let pvrtcData = new Uint8Array(buffer, dataOffset);
|
||||
|
||||
out = {
|
||||
_data: pvrtcData,
|
||||
_compressed: true,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
onComplete && onComplete(err, out);
|
||||
};
|
||||
})(),
|
||||
|
||||
/*
|
||||
* !#en
|
||||
* Parse pkm file
|
||||
*
|
||||
* !#zh
|
||||
* 解析压缩纹理格式 pkm 文件
|
||||
*
|
||||
* @method parsePKMTex
|
||||
* @param {ArrayBuffer|ArrayBufferView} file - The downloaded file
|
||||
* @param {Object} options - Some optional paramters
|
||||
* @param {Function} onComplete - Callback when finish parsing.
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {Object} onComplete.etcAsset - The parsed content
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('test.pkm', {responseType: 'arraybuffer'}, null, (err, file) => {
|
||||
* parser.parsePKMTex(file, null, (err, etcAsset) => console.log(err));
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* parsePKMTex(file: ArrayBuffer|ArrayBufferView, options: Record<string, any>, onComplete: (err: Error, etcAsset: {_data: Uint8Array, _compressed: boolean, width: number, height: number}) => void): void
|
||||
*/
|
||||
parsePKMTex: (function () {
|
||||
//===============//
|
||||
// ETC constants //
|
||||
//===============//
|
||||
const ETC_PKM_HEADER_SIZE = 16;
|
||||
|
||||
const ETC_PKM_FORMAT_OFFSET = 6;
|
||||
const ETC_PKM_ENCODED_WIDTH_OFFSET = 8;
|
||||
const ETC_PKM_ENCODED_HEIGHT_OFFSET = 10;
|
||||
const ETC_PKM_WIDTH_OFFSET = 12;
|
||||
const ETC_PKM_HEIGHT_OFFSET = 14;
|
||||
|
||||
const ETC1_RGB_NO_MIPMAPS = 0;
|
||||
const ETC2_RGB_NO_MIPMAPS = 1;
|
||||
const ETC2_RGBA_NO_MIPMAPS = 3;
|
||||
|
||||
function readBEUint16(header, offset) {
|
||||
return (header[offset] << 8) | header[offset+1];
|
||||
}
|
||||
return function (file, options, onComplete) {
|
||||
let err = null, out = null;
|
||||
try {
|
||||
let buffer = file instanceof ArrayBuffer ? file : file.buffer;
|
||||
let header = new Uint8Array(buffer);
|
||||
let format = readBEUint16(header, ETC_PKM_FORMAT_OFFSET);
|
||||
if (format !== ETC1_RGB_NO_MIPMAPS && format !== ETC2_RGB_NO_MIPMAPS && format !== ETC2_RGBA_NO_MIPMAPS) {
|
||||
return new Error("Invalid magic number in ETC header");
|
||||
}
|
||||
let width = readBEUint16(header, ETC_PKM_WIDTH_OFFSET);
|
||||
let height = readBEUint16(header, ETC_PKM_HEIGHT_OFFSET);
|
||||
let encodedWidth = readBEUint16(header, ETC_PKM_ENCODED_WIDTH_OFFSET);
|
||||
let encodedHeight = readBEUint16(header, ETC_PKM_ENCODED_HEIGHT_OFFSET);
|
||||
let etcData = new Uint8Array(buffer, ETC_PKM_HEADER_SIZE);
|
||||
out = {
|
||||
_data: etcData,
|
||||
_compressed: true,
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
onComplete && onComplete(err, out);
|
||||
}
|
||||
})(),
|
||||
|
||||
/*
|
||||
* !#en
|
||||
* Parse plist file
|
||||
*
|
||||
* !#zh
|
||||
* 解析 plist 文件
|
||||
*
|
||||
* @method parsePlist
|
||||
* @param {string} file - The downloaded file
|
||||
* @param {Object} options - Some optional paramters
|
||||
* @param {Function} onComplete - Callback when finish parsing
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {*} onComplete.data - The parsed content
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('test.plist', {responseType: 'text'}, null, (err, file) => {
|
||||
* parser.parsePlist(file, null, (err, data) => console.log(err));
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* parsePlist(file: string, options: Record<string, any>, onComplete?: (err: Error, data: any) => void): void
|
||||
*/
|
||||
parsePlist (file, options, onComplete) {
|
||||
var err = null;
|
||||
var result = plistParser.parse(file);
|
||||
if (!result) err = new Error('parse failed');
|
||||
onComplete && onComplete(err, result);
|
||||
},
|
||||
|
||||
/*
|
||||
* !#en
|
||||
* Deserialize asset file
|
||||
*
|
||||
* !#zh
|
||||
* 反序列化资源文件
|
||||
*
|
||||
* @method parseImport
|
||||
* @param {Object} file - The serialized json
|
||||
* @param {Object} options - Some optional paramters
|
||||
* @param {Function} onComplete - Callback when finish parsing
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {Asset} onComplete.asset - The parsed content
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('test.json', {responseType: 'json'}, null, (err, file) => {
|
||||
* parser.parseImport(file, null, (err, data) => console.log(err));
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* parseImport (file: any, options: Record<string, any>, onComplete?: (err: Error, asset: cc.Asset) => void): void
|
||||
*/
|
||||
parseImport (file, options, onComplete) {
|
||||
if (!file) return onComplete && onComplete(new Error('Json is empty'));
|
||||
var result, err = null;
|
||||
try {
|
||||
result = deserialize(file, options);
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
onComplete && onComplete(err, result);
|
||||
},
|
||||
|
||||
init () {
|
||||
_parsing.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Register custom handler if you want to change default behavior or extend parser to parse other format file
|
||||
*
|
||||
* !#zh
|
||||
* 当你想修改默认行为或者拓展 parser 来解析其他格式文件时可以注册自定义的handler
|
||||
*
|
||||
* @method register
|
||||
* @param {string|Object} type - Extension likes '.jpg' or map likes {'.jpg': jpgHandler, '.png': pngHandler}
|
||||
* @param {Function} [handler] - The corresponding handler
|
||||
* @param {*} handler.file - File
|
||||
* @param {Object} handler.options - Some optional paramter
|
||||
* @param {Function} handler.onComplete - callback when finishing parsing
|
||||
*
|
||||
* @example
|
||||
* parser.register('.tga', (file, options, onComplete) => onComplete(null, null));
|
||||
* parser.register({'.tga': (file, options, onComplete) => onComplete(null, null), '.ext': (file, options, onComplete) => onComplete(null, null)});
|
||||
*
|
||||
* @typescript
|
||||
* register(type: string, handler: (file: any, options: Record<string, any>, onComplete: (err: Error, data: any) => void) => void): void
|
||||
* register(map: Record<string, (file: any, options: Record<string, any>, onComplete: (err: Error, data: any) => void) => void>): void
|
||||
*/
|
||||
register (type, handler) {
|
||||
if (typeof type === 'object') {
|
||||
js.mixin(parsers, type);
|
||||
}
|
||||
else {
|
||||
parsers[type] = handler;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Use corresponding handler to parse file
|
||||
*
|
||||
* !#zh
|
||||
* 使用对应的handler来解析文件
|
||||
*
|
||||
* @method parse
|
||||
* @param {string} id - The id of file
|
||||
* @param {*} file - File
|
||||
* @param {string} type - The corresponding type of file, likes '.jpg'.
|
||||
* @param {Object} options - Some optional paramters will be transferred to the corresponding handler.
|
||||
* @param {Function} onComplete - callback when finishing downloading
|
||||
* @param {Error} onComplete.err - The occurred error, null indicetes success
|
||||
* @param {*} onComplete.contetnt - The parsed file
|
||||
*
|
||||
* @example
|
||||
* downloader.downloadFile('test.jpg', {responseType: 'blob'}, null, (err, file) => {
|
||||
* parser.parse('test.jpg', file, '.jpg', null, (err, img) => console.log(err));
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* parse(id: string, file: any, type: string, options: Record<string, any>, onComplete: (err: Error, content: any) => void): void
|
||||
*/
|
||||
parse (id, file, type, options, onComplete) {
|
||||
let parsedAsset, parsing, parseHandler;
|
||||
if (parsedAsset = parsed.get(id)) {
|
||||
onComplete(null, parsedAsset);
|
||||
}
|
||||
else if (parsing = _parsing.get(id)){
|
||||
parsing.push(onComplete);
|
||||
}
|
||||
else if (parseHandler = parsers[type]){
|
||||
_parsing.add(id, [onComplete]);
|
||||
parseHandler(file, options, function (err, data) {
|
||||
if (err) {
|
||||
files.remove(id);
|
||||
}
|
||||
else if (!isScene(data)){
|
||||
parsed.add(id, data);
|
||||
}
|
||||
let callbacks = _parsing.remove(id);
|
||||
for (let i = 0, l = callbacks.length; i < l; i++) {
|
||||
callbacks[i](err, data);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
onComplete(null, file);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var parsers = {
|
||||
'.png' : parser.parseImage,
|
||||
'.jpg' : parser.parseImage,
|
||||
'.bmp' : parser.parseImage,
|
||||
'.jpeg' : parser.parseImage,
|
||||
'.gif' : parser.parseImage,
|
||||
'.ico' : parser.parseImage,
|
||||
'.tiff' : parser.parseImage,
|
||||
'.webp' : parser.parseImage,
|
||||
'.image' : parser.parseImage,
|
||||
'.pvr' : parser.parsePVRTex,
|
||||
'.pkm' : parser.parsePKMTex,
|
||||
// Audio
|
||||
'.mp3' : parser.parseAudio,
|
||||
'.ogg' : parser.parseAudio,
|
||||
'.wav' : parser.parseAudio,
|
||||
'.m4a' : parser.parseAudio,
|
||||
|
||||
// plist
|
||||
'.plist' : parser.parsePlist,
|
||||
'import' : parser.parseImport
|
||||
};
|
||||
|
||||
module.exports = parser;
|
330
engine/cocos2d/core/asset-manager/pipeline.js
Normal file
330
engine/cocos2d/core/asset-manager/pipeline.js
Normal file
@@ -0,0 +1,330 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
|
||||
const Task = require('./task');
|
||||
|
||||
var _pipelineId = 0;
|
||||
/**
|
||||
* !#en
|
||||
* Pipeline can execute the task for some effect.
|
||||
*
|
||||
* !#zh
|
||||
* 管线能执行任务达到某个效果
|
||||
*
|
||||
* @class Pipeline
|
||||
*/
|
||||
function Pipeline (name, funcs) {
|
||||
if (!Array.isArray(funcs)) {
|
||||
cc.warn('funcs must be an array');
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The id of pipeline
|
||||
*
|
||||
* !#zh
|
||||
* 管线的 id
|
||||
*
|
||||
* @property id
|
||||
* @type {Number}
|
||||
*/
|
||||
this.id = _pipelineId++;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The name of pipeline
|
||||
*
|
||||
* !#zh
|
||||
* 管线的名字
|
||||
*
|
||||
* @property name
|
||||
* @type {String}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* All pipes of pipeline
|
||||
*
|
||||
* !#zh
|
||||
* 所有的管道
|
||||
*
|
||||
* @property pipes
|
||||
* @type {Function[]}
|
||||
*/
|
||||
this.pipes = [];
|
||||
|
||||
for (var i = 0, l = funcs.length; i < l; i++) {
|
||||
if (typeof funcs[i] === 'function') {
|
||||
this.pipes.push(funcs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Pipeline.prototype = {
|
||||
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Create a new pipeline
|
||||
*
|
||||
* !#zh
|
||||
* 创建一个管线
|
||||
*
|
||||
* @method constructor
|
||||
* @param {string} name - The name of pipeline
|
||||
* @param {Function[]} funcs - The array of pipe, every pipe must be function which take two parameters, the first is a `Task` flowed in pipeline, the second is complete callback
|
||||
*
|
||||
* @example
|
||||
* var pipeline = new Pipeline('download', [
|
||||
* (task, done) => {
|
||||
* var url = task.input;
|
||||
* cc.assetManager.downloader.downloadFile(url, null, null, (err, result) => {
|
||||
* task.output = result;
|
||||
* done(err);
|
||||
* });
|
||||
* },
|
||||
* (task, done) => {
|
||||
* var text = task.input;
|
||||
* var json = JSON.stringify(text);
|
||||
* task.output = json;
|
||||
* done();
|
||||
* }
|
||||
* ]);
|
||||
*
|
||||
* @typescript
|
||||
* constructor(name: string, funcs: Array<(task: Task, done?: (err: Error) => void) => void>)
|
||||
*/
|
||||
constructor: Pipeline,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* At specific point insert a new pipe to pipeline
|
||||
*
|
||||
* !#zh
|
||||
* 在某个特定的点为管线插入一个新的 pipe
|
||||
*
|
||||
* @method insert
|
||||
* @param {Function} func - The new pipe
|
||||
* @param {Task} func.task - The task handled with pipeline will be transferred to this function
|
||||
* @param {Function} [func.callback] - Callback you need to invoke manually when this pipe is finished. if the pipeline is synchronous, callback is unnecessary.
|
||||
* @param {number} index - The specific point you want to insert at.
|
||||
* @return {Pipeline} pipeline
|
||||
*
|
||||
* @example
|
||||
* var pipeline = new Pipeline('test', []);
|
||||
* pipeline.insert((task, done) => {
|
||||
* // do something
|
||||
* done();
|
||||
* }, 0);
|
||||
*
|
||||
* @typescript
|
||||
* insert(func: (task: Task, callback?: (err: Error) => void) => void, index: number): Pipeline
|
||||
*/
|
||||
insert (func, index) {
|
||||
if (typeof func !== 'function' || index > this.pipes.length) {
|
||||
cc.warnID(4921);
|
||||
return;
|
||||
}
|
||||
|
||||
this.pipes.splice(index, 0, func);
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Append a new pipe to the pipeline
|
||||
*
|
||||
* !#zh
|
||||
* 添加一个管道到管线中
|
||||
*
|
||||
* @method append
|
||||
* @param {Function} func - The new pipe
|
||||
* @param {Task} func.task - The task handled with pipeline will be transferred to this function
|
||||
* @param {Function} [func.callback] - Callback you need to invoke manually when this pipe is finished. if the pipeline is synchronous, callback is unnecessary.
|
||||
* @return {Pipeline} pipeline
|
||||
*
|
||||
* @example
|
||||
* var pipeline = new Pipeline('test', []);
|
||||
* pipeline.append((task, done) => {
|
||||
* // do something
|
||||
* done();
|
||||
* });
|
||||
*
|
||||
* @typescript
|
||||
* append(func: (task: Task, callback?: (err: Error) => void) => void): Pipeline
|
||||
*/
|
||||
append (func) {
|
||||
if (typeof func !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.pipes.push(func);
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Remove pipe which at specific point
|
||||
*
|
||||
* !#zh
|
||||
* 移除特定位置的管道
|
||||
*
|
||||
* @method remove
|
||||
* @param {number} index - The specific point
|
||||
* @return {Pipeline} pipeline
|
||||
*
|
||||
* @example
|
||||
* var pipeline = new Pipeline('test', (task, done) => {
|
||||
* // do something
|
||||
* done();
|
||||
* });
|
||||
* pipeline.remove(0);
|
||||
*
|
||||
* @typescript
|
||||
* remove(index: number): Pipeline
|
||||
*/
|
||||
remove (index) {
|
||||
if (typeof index !== 'number') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.pipes.splice(index, 1);
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Execute task synchronously
|
||||
*
|
||||
* !#zh
|
||||
* 同步执行任务
|
||||
*
|
||||
* @method sync
|
||||
* @param {Task} task - The task will be executed
|
||||
* @returns {*} result
|
||||
*
|
||||
* @example
|
||||
* var pipeline = new Pipeline('sync', [(task) => {
|
||||
* let input = task.input;
|
||||
* task.output = doSomething(task.input);
|
||||
* }]);
|
||||
*
|
||||
* var task = new Task({input: 'test'});
|
||||
* console.log(pipeline.sync(task));
|
||||
*
|
||||
* @typescript
|
||||
* sync(task: Task): any
|
||||
*/
|
||||
sync (task) {
|
||||
var pipes = this.pipes;
|
||||
if (!(task instanceof Task) || pipes.length === 0) return;
|
||||
if (task.output != null) {
|
||||
task.input = task.output;
|
||||
task.output = null;
|
||||
}
|
||||
task._isFinish = false;
|
||||
for (var i = 0, l = pipes.length; i < l;) {
|
||||
var pipe = pipes[i];
|
||||
var result = pipe(task);
|
||||
if (result) {
|
||||
task._isFinish = true;
|
||||
return result;
|
||||
}
|
||||
i++;
|
||||
if (i !== l) {
|
||||
task.input = task.output;
|
||||
task.output = null;
|
||||
}
|
||||
}
|
||||
task._isFinish = true;
|
||||
return task.output;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Execute task asynchronously
|
||||
*
|
||||
* !#zh
|
||||
* 异步执行任务
|
||||
*
|
||||
* @method async
|
||||
* @param {Task} task - The task will be executed
|
||||
*
|
||||
* @example
|
||||
* var pipeline = new Pipeline('sync', [(task, done) => {
|
||||
* let input = task.input;
|
||||
* task.output = doSomething(task.input);
|
||||
* done();
|
||||
* }]);
|
||||
* var task = new Task({input: 'test', onComplete: (err, result) => console.log(result)});
|
||||
* pipeline.async(task);
|
||||
*
|
||||
* @typescript
|
||||
* async(task: Task): void
|
||||
*/
|
||||
async (task) {
|
||||
var pipes = this.pipes;
|
||||
if (!(task instanceof Task) || pipes.length === 0) return;
|
||||
if (task.output != null) {
|
||||
task.input = task.output;
|
||||
task.output = null;
|
||||
}
|
||||
task._isFinish = false;
|
||||
this._flow(0, task);
|
||||
},
|
||||
|
||||
_flow (index, task) {
|
||||
var self = this;
|
||||
var pipe = this.pipes[index];
|
||||
pipe(task, function (result) {
|
||||
if (result) {
|
||||
task._isFinish = true;
|
||||
task.onComplete && task.onComplete(result);
|
||||
}
|
||||
else {
|
||||
index++;
|
||||
if (index < self.pipes.length) {
|
||||
// move output to input
|
||||
task.input = task.output;
|
||||
task.output = null;
|
||||
self._flow(index, task);
|
||||
}
|
||||
else {
|
||||
task._isFinish = true;
|
||||
task.onComplete && task.onComplete(result, task.output);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Pipeline;
|
78
engine/cocos2d/core/asset-manager/preprocess.js
Normal file
78
engine/cocos2d/core/asset-manager/preprocess.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const Task = require('./task');
|
||||
const { transformPipeline, RequestType } = require('./shared');
|
||||
|
||||
function preprocess (task, done) {
|
||||
var options = task.options, subOptions = Object.create(null), leftOptions = Object.create(null);
|
||||
|
||||
for (var op in options) {
|
||||
switch (op) {
|
||||
// can't set these attributes in options
|
||||
case RequestType.PATH:
|
||||
case RequestType.UUID:
|
||||
case RequestType.DIR:
|
||||
case RequestType.SCENE:
|
||||
case RequestType.URL : break;
|
||||
// only need these attributes to transform url
|
||||
case '__requestType__':
|
||||
case '__isNative__':
|
||||
case 'ext' :
|
||||
case 'type':
|
||||
case '__nativeName__':
|
||||
case 'audioLoadMode':
|
||||
case 'bundle':
|
||||
subOptions[op] = options[op];
|
||||
break;
|
||||
// other settings, left to next pipe
|
||||
case '__exclude__':
|
||||
case '__outputAsArray__':
|
||||
leftOptions[op] = options[op];
|
||||
break;
|
||||
default:
|
||||
subOptions[op] = options[op];
|
||||
leftOptions[op] = options[op];
|
||||
break;
|
||||
}
|
||||
}
|
||||
task.options = leftOptions;
|
||||
|
||||
// transform url
|
||||
let subTask = Task.create({input: task.input, options: subOptions});
|
||||
var err = null;
|
||||
try {
|
||||
task.output = task.source = transformPipeline.sync(subTask);
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
for (var i = 0, l = subTask.output.length; i < l; i++) {
|
||||
subTask.output[i].recycle();
|
||||
}
|
||||
}
|
||||
subTask.recycle();
|
||||
done(err);
|
||||
}
|
||||
|
||||
module.exports = preprocess;
|
239
engine/cocos2d/core/asset-manager/releaseManager.js
Normal file
239
engine/cocos2d/core/asset-manager/releaseManager.js
Normal file
@@ -0,0 +1,239 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const dependUtil = require('./depend-util');
|
||||
const Cache = require('./cache');
|
||||
require('../assets/CCAsset');
|
||||
const { assets } = require('./shared');
|
||||
const { callInNextTick } = require('../platform/utils');
|
||||
|
||||
function visitAsset (asset, deps) {
|
||||
// Skip assets generated programmatically or by user (e.g. label texture)
|
||||
if (!asset._uuid) {
|
||||
return;
|
||||
}
|
||||
deps.push(asset._uuid);
|
||||
}
|
||||
|
||||
function visitComponent (comp, deps) {
|
||||
var props = Object.getOwnPropertyNames(comp);
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
var propName = props[i];
|
||||
if (propName === 'node' || propName === '__eventTargets') continue;
|
||||
var value = comp[propName];
|
||||
if (typeof value === 'object' && value) {
|
||||
if (Array.isArray(value)) {
|
||||
for (let j = 0; j < value.length; j++) {
|
||||
let val = value[j];
|
||||
if (val instanceof cc.Asset) {
|
||||
visitAsset(val, deps);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!value.constructor || value.constructor === Object) {
|
||||
let keys = Object.getOwnPropertyNames(value);
|
||||
for (let j = 0; j < keys.length; j++) {
|
||||
let val = value[keys[j]];
|
||||
if (val instanceof cc.Asset) {
|
||||
visitAsset(val, deps);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value instanceof cc.Asset) {
|
||||
visitAsset(value, deps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _temp = [];
|
||||
|
||||
function visitNode (node, deps) {
|
||||
for (let i = 0; i < node._components.length; i++) {
|
||||
visitComponent(node._components[i], deps);
|
||||
}
|
||||
for (let i = 0; i < node._children.length; i++) {
|
||||
visitNode(node._children[i], deps);
|
||||
}
|
||||
}
|
||||
|
||||
function descendOpRef (asset, refs, exclude, op) {
|
||||
exclude.push(asset._uuid);
|
||||
var depends = dependUtil.getDeps(asset._uuid);
|
||||
for (let i = 0, l = depends.length; i < l; i++) {
|
||||
var dependAsset = assets.get(depends[i]);
|
||||
if (dependAsset) {
|
||||
let uuid = dependAsset._uuid;
|
||||
if (!(uuid in refs)) {
|
||||
refs[uuid] = dependAsset.refCount + op;
|
||||
}
|
||||
else {
|
||||
refs[uuid] += op;
|
||||
}
|
||||
if (exclude.includes(uuid)) continue;
|
||||
descendOpRef(dependAsset, refs, exclude, op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkCircularReference (asset) {
|
||||
// check circular reference
|
||||
var refs = Object.create(null);
|
||||
refs[asset._uuid] = asset.refCount;
|
||||
descendOpRef(asset, refs, _temp, -1);
|
||||
_temp.length = 0;
|
||||
if (refs[asset._uuid] !== 0) return refs[asset._uuid];
|
||||
|
||||
for (let uuid in refs) {
|
||||
if (refs[uuid] !== 0) {
|
||||
descendOpRef(assets.get(uuid), refs, _temp, 1);
|
||||
}
|
||||
}
|
||||
_temp.length = 0;
|
||||
|
||||
return refs[asset._uuid];
|
||||
}
|
||||
|
||||
var _persistNodeDeps = new Cache();
|
||||
var _toDelete = new Cache();
|
||||
var eventListener = false;
|
||||
|
||||
function freeAssets () {
|
||||
eventListener = false;
|
||||
_toDelete.forEach(function (asset) {
|
||||
releaseManager._free(asset);
|
||||
});
|
||||
_toDelete.clear();
|
||||
}
|
||||
|
||||
var releaseManager = {
|
||||
init () {
|
||||
_persistNodeDeps.clear();
|
||||
_toDelete.clear();
|
||||
},
|
||||
|
||||
_addPersistNodeRef (node) {
|
||||
var deps = [];
|
||||
visitNode(node, deps);
|
||||
for (let i = 0, l = deps.length; i < l; i++) {
|
||||
var dependAsset = assets.get(deps[i]);
|
||||
if (dependAsset) {
|
||||
dependAsset.addRef();
|
||||
}
|
||||
}
|
||||
_persistNodeDeps.add(node.uuid, deps);
|
||||
},
|
||||
|
||||
_removePersistNodeRef (node) {
|
||||
if (_persistNodeDeps.has(node.uuid)) {
|
||||
var deps = _persistNodeDeps.get(node.uuid);
|
||||
for (let i = 0, l = deps.length; i < l; i++) {
|
||||
var dependAsset = assets.get(deps[i]);
|
||||
if (dependAsset) {
|
||||
dependAsset.decRef();
|
||||
}
|
||||
}
|
||||
_persistNodeDeps.remove(node.uuid);
|
||||
}
|
||||
},
|
||||
|
||||
// do auto release
|
||||
_autoRelease (oldScene, newScene, persistNodes) {
|
||||
|
||||
if (oldScene) {
|
||||
var childs = dependUtil.getDeps(oldScene._id);
|
||||
for (let i = 0, l = childs.length; i < l; i++) {
|
||||
let asset = assets.get(childs[i]);
|
||||
asset && asset.decRef(CC_TEST || oldScene.autoReleaseAssets);
|
||||
}
|
||||
var dependencies = dependUtil._depends.get(oldScene._id);
|
||||
if (dependencies && dependencies.persistDeps) {
|
||||
var persistDeps = dependencies.persistDeps;
|
||||
for (let i = 0, l = persistDeps.length; i < l; i++) {
|
||||
let asset = assets.get(persistDeps[i]);
|
||||
asset && asset.decRef(CC_TEST || oldScene.autoReleaseAssets);
|
||||
}
|
||||
}
|
||||
oldScene._id !== newScene._id && dependUtil.remove(oldScene._id);
|
||||
}
|
||||
|
||||
var sceneDeps = dependUtil._depends.get(newScene._id);
|
||||
sceneDeps && (sceneDeps.persistDeps = []);
|
||||
// transfer refs from persist nodes to new scene
|
||||
for (let key in persistNodes) {
|
||||
var node = persistNodes[key];
|
||||
var deps = _persistNodeDeps.get(node.uuid);
|
||||
for (let i = 0, l = deps.length; i < l; i++) {
|
||||
var dependAsset = assets.get(deps[i]);
|
||||
if (dependAsset) {
|
||||
dependAsset.addRef();
|
||||
}
|
||||
}
|
||||
if (sceneDeps) {
|
||||
sceneDeps.persistDeps.push.apply(sceneDeps.persistDeps, deps);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_free (asset, force) {
|
||||
_toDelete.remove(asset._uuid);
|
||||
|
||||
if (!cc.isValid(asset, true)) return;
|
||||
|
||||
if (!force) {
|
||||
if (asset.refCount > 0) {
|
||||
if (checkCircularReference(asset) > 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
// remove from cache
|
||||
assets.remove(asset._uuid);
|
||||
var depends = dependUtil.getDeps(asset._uuid);
|
||||
for (let i = 0, l = depends.length; i < l; i++) {
|
||||
var dependAsset = assets.get(depends[i]);
|
||||
if (dependAsset) {
|
||||
dependAsset.decRef(false);
|
||||
releaseManager._free(dependAsset, false);
|
||||
}
|
||||
}
|
||||
asset.destroy();
|
||||
dependUtil.remove(asset._uuid);
|
||||
},
|
||||
|
||||
tryRelease (asset, force) {
|
||||
if (!(asset instanceof cc.Asset)) return;
|
||||
if (force) {
|
||||
releaseManager._free(asset, force);
|
||||
}
|
||||
else {
|
||||
_toDelete.add(asset._uuid, asset);
|
||||
if (!eventListener) {
|
||||
eventListener = true;
|
||||
callInNextTick(freeAssets);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = releaseManager;
|
232
engine/cocos2d/core/asset-manager/request-item.js
Normal file
232
engine/cocos2d/core/asset-manager/request-item.js
Normal file
@@ -0,0 +1,232 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
|
||||
var MAX_DEAD_NUM = 500;
|
||||
var _deadPool = [];
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* A collection of information about a request
|
||||
*
|
||||
* !#zh
|
||||
* 请求的相关信息集合
|
||||
*
|
||||
* @class RequestItem
|
||||
*/
|
||||
function RequestItem () {
|
||||
|
||||
this._id = '';
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The uuid of request
|
||||
*
|
||||
* !#zh
|
||||
* 请求资源的uuid
|
||||
*
|
||||
* @property uuid
|
||||
* @type {String}
|
||||
*/
|
||||
this.uuid = '';
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The final url of request
|
||||
*
|
||||
* !#zh
|
||||
* 请求的最终url
|
||||
*
|
||||
* @property url
|
||||
* @type {String}
|
||||
*/
|
||||
this.url = '';
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The extension name of asset
|
||||
*
|
||||
* !#zh
|
||||
* 资源的扩展名
|
||||
*
|
||||
* @property ext
|
||||
* @type {String}
|
||||
*/
|
||||
this.ext = '.json';
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The content of asset
|
||||
*
|
||||
* !#zh
|
||||
* 资源的内容
|
||||
*
|
||||
* @property content
|
||||
* @type {*}
|
||||
*/
|
||||
this.content = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The file of asset
|
||||
*
|
||||
* !#zh
|
||||
* 资源的文件
|
||||
*
|
||||
* @property file
|
||||
* @type {*}
|
||||
*/
|
||||
this.file = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The information of asset
|
||||
*
|
||||
* !#zh
|
||||
* 资源的相关信息
|
||||
*
|
||||
* @property info
|
||||
* @type {Object}
|
||||
*/
|
||||
this.info = null;
|
||||
|
||||
this.config = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Whether or not it is native asset
|
||||
*
|
||||
* !#zh
|
||||
* 资源是否是原生资源
|
||||
*
|
||||
* @property isNative
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isNative = false;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Custom options
|
||||
*
|
||||
* !#zh
|
||||
* 自定义参数
|
||||
*
|
||||
* @property options
|
||||
* @type {Object}
|
||||
*/
|
||||
this.options = Object.create(null);
|
||||
}
|
||||
|
||||
RequestItem.prototype = {
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Create a request item
|
||||
*
|
||||
* !#zh
|
||||
* 创建一个 request item
|
||||
*
|
||||
* @method constructor
|
||||
*
|
||||
* @typescript
|
||||
* constructor()
|
||||
*/
|
||||
constructor: RequestItem,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The id of request, combined from uuid and isNative
|
||||
*
|
||||
* !#zh
|
||||
* 请求的 id, 由 uuid 和 isNative 组合而成
|
||||
*
|
||||
* @property id
|
||||
* @type {String}
|
||||
*/
|
||||
get id () {
|
||||
if (!this._id) {
|
||||
this._id = this.uuid + '@' + (this.isNative ? 'native' : 'import');
|
||||
}
|
||||
return this._id;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Recycle this for reuse
|
||||
*
|
||||
* !#zh
|
||||
* 回收 requestItem 用于复用
|
||||
*
|
||||
* @method recycle
|
||||
*
|
||||
* @typescript
|
||||
* recycle(): void
|
||||
*/
|
||||
recycle () {
|
||||
if (_deadPool.length === MAX_DEAD_NUM) return;
|
||||
this._id = '';
|
||||
this.uuid = '';
|
||||
this.url = '';
|
||||
this.ext = '.json';
|
||||
this.content = null;
|
||||
this.file = null;
|
||||
this.info = null;
|
||||
this.config = null;
|
||||
this.isNative = false;
|
||||
this.options = Object.create(null);
|
||||
_deadPool.push(this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Create a new request item from pool
|
||||
*
|
||||
* !#zh
|
||||
* 从对象池中创建 requestItem
|
||||
*
|
||||
* @static
|
||||
* @method create
|
||||
* @returns {RequestItem} requestItem
|
||||
*
|
||||
* @typescript
|
||||
* create(): RequestItem
|
||||
*/
|
||||
RequestItem.create = function () {
|
||||
var out = null;
|
||||
if (_deadPool.length !== 0) {
|
||||
out = _deadPool.pop();
|
||||
}
|
||||
else {
|
||||
out = new RequestItem();
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
module.exports = RequestItem;
|
116
engine/cocos2d/core/asset-manager/shared.js
Normal file
116
engine/cocos2d/core/asset-manager/shared.js
Normal file
@@ -0,0 +1,116 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const Cache = require('./cache');
|
||||
const Pipeline = require('./pipeline');
|
||||
|
||||
var assets = new Cache();
|
||||
var files = new Cache();
|
||||
var parsed = new Cache();
|
||||
var bundles = new Cache();
|
||||
var pipeline = new Pipeline('normal load', []);
|
||||
var fetchPipeline = new Pipeline('fetch', []);
|
||||
var transformPipeline = new Pipeline('transform url', []);
|
||||
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
|
||||
var RequestType = {
|
||||
|
||||
UUID: 'uuid',
|
||||
|
||||
PATH: 'path',
|
||||
|
||||
DIR: 'dir',
|
||||
|
||||
URL: 'url',
|
||||
|
||||
SCENE: 'scene'
|
||||
};
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The builtin bundles
|
||||
*
|
||||
* !#zh
|
||||
* 内置 bundle
|
||||
*
|
||||
* @enum BuiltinBundleName
|
||||
*/
|
||||
var BuiltinBundleName = {
|
||||
/**
|
||||
* !#en
|
||||
* The builtin bundle corresponds to 'assets/resources'.
|
||||
*
|
||||
* !#zh
|
||||
* 内置 bundle, 对应 'assets/resources' 目录
|
||||
*
|
||||
* @property RESOURCES
|
||||
* @readonly
|
||||
* @type {String}
|
||||
*/
|
||||
RESOURCES: 'resources',
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The builtin bundle corresponds to 'internal/resources'.
|
||||
*
|
||||
* !#zh
|
||||
* 内置 bundle, 对应 'internal/resources' 目录
|
||||
*
|
||||
* @property INTERNAL
|
||||
* @readonly
|
||||
* @type {String}
|
||||
*/
|
||||
INTERNAL: 'internal',
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The builtin bundle
|
||||
*
|
||||
* !#zh
|
||||
* 内置 bundle
|
||||
*
|
||||
* @property MAIN
|
||||
* @readonly
|
||||
* @type {String}
|
||||
*/
|
||||
MAIN: 'main',
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The builtin bundle, exists when Start Scene asset bundle is checked on the project building panel
|
||||
*
|
||||
* !#zh
|
||||
* 内置 bundle, 如果构建面板开启了首场景分包,则会有 START_SCENE bundle
|
||||
*
|
||||
* @property START_SCENE
|
||||
* @readonly
|
||||
* @type {String}
|
||||
*/
|
||||
START_SCENE: 'start-scene',
|
||||
};
|
||||
|
||||
module.exports = { assets, files, parsed, pipeline, fetchPipeline, transformPipeline, RequestType, bundles, BuiltinBundleName };
|
328
engine/cocos2d/core/asset-manager/task.js
Normal file
328
engine/cocos2d/core/asset-manager/task.js
Normal file
@@ -0,0 +1,328 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @module cc.AssetManager
|
||||
*/
|
||||
|
||||
var _taskId = 0;
|
||||
var MAX_DEAD_NUM = 500;
|
||||
var _deadPool = [];
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Task is used to run in the pipeline for some effect
|
||||
*
|
||||
* !#zh
|
||||
* 任务用于在管线中运行以达成某种效果
|
||||
*
|
||||
* @class Task
|
||||
*/
|
||||
function Task (options) {
|
||||
/**
|
||||
* !#en
|
||||
* The id of task
|
||||
*
|
||||
* !#zh
|
||||
* 任务id
|
||||
*
|
||||
* @property id
|
||||
* @type {Number}
|
||||
*/
|
||||
this.id = _taskId++;
|
||||
|
||||
this._isFinish = true;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The callback when task is completed
|
||||
*
|
||||
* !#zh
|
||||
* 完成回调
|
||||
*
|
||||
* @property onComplete
|
||||
* @type {Function}
|
||||
*/
|
||||
this.onComplete = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The callback of progression
|
||||
*
|
||||
* !#zh
|
||||
* 进度回调
|
||||
*
|
||||
* @property onProgress
|
||||
* @type {Function}
|
||||
*/
|
||||
this.onProgress = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The callback when something goes wrong
|
||||
*
|
||||
* !#zh
|
||||
* 错误回调
|
||||
*
|
||||
* @property onError
|
||||
* @type {Function}
|
||||
*/
|
||||
this.onError = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The source of task
|
||||
*
|
||||
* !#zh
|
||||
* 任务的源
|
||||
*
|
||||
* @property source
|
||||
* @type {*}
|
||||
*/
|
||||
this.source = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The output of task
|
||||
*
|
||||
* !#zh
|
||||
* 任务的输出
|
||||
*
|
||||
* @property output
|
||||
* @type {*}
|
||||
*/
|
||||
this.output = null
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The input of task
|
||||
*
|
||||
* !#zh
|
||||
* 任务的输入
|
||||
*
|
||||
* @property input
|
||||
* @type {*}
|
||||
*/
|
||||
this.input = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The progression of task
|
||||
*
|
||||
* !#zh
|
||||
* 任务的进度
|
||||
*
|
||||
* @property progress
|
||||
* @type {*}
|
||||
*/
|
||||
this.progress = null;
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Custom options
|
||||
*
|
||||
* !#zh
|
||||
* 自定义参数
|
||||
*
|
||||
* @property options
|
||||
* @type {Object}
|
||||
*/
|
||||
this.options = null;
|
||||
this.set(options);
|
||||
};
|
||||
|
||||
Task.prototype = {
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Create a new Task
|
||||
*
|
||||
* !#zh
|
||||
* 创建一个任务
|
||||
*
|
||||
* @method constructor
|
||||
* @param {Object} [options] - Some optional paramters
|
||||
* @param {Function} [options.onComplete] - Callback when the task is completed, if the pipeline is synchronous, onComplete is unnecessary.
|
||||
* @param {Function} [options.onProgress] - Continuously callback when the task is runing, if the pipeline is synchronous, onProgress is unnecessary.
|
||||
* @param {Function} [options.onError] - Callback when something goes wrong, if the pipeline is synchronous, onError is unnecessary.
|
||||
* @param {*} options.input - Something will be handled with pipeline
|
||||
* @param {*} [options.progress] - Progress information, you may need to assign it manually when multiple pipeline share one progress
|
||||
* @param {Object} [options.options] - Custom parameters
|
||||
*
|
||||
* @typescript
|
||||
* constructor(options?: {onComplete?: (err: Error, result: any) => void, onError?: () => void, onProgress?: Function, input: any, progress?: any, options?: Record<string, any>})
|
||||
*/
|
||||
constructor: Task,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Set paramters of this task
|
||||
*
|
||||
* !#zh
|
||||
* 设置任务的参数
|
||||
*
|
||||
* @method set
|
||||
* @param {Object} [options] - Some optional paramters
|
||||
* @param {Function} [options.onComplete] - Callback when the task complete, if the pipeline is synchronous, onComplete is unnecessary.
|
||||
* @param {Function} [options.onProgress] - Continuously callback when the task is runing, if the pipeline is synchronous, onProgress is unnecessary.
|
||||
* @param {Function} [options.onError] - Callback when something goes wrong, if the pipeline is synchronous, onError is unnecessary.
|
||||
* @param {*} options.input - Something will be handled with pipeline
|
||||
* @param {*} [options.progress] - Progress information, you may need to assign it manually when multiple pipeline share one progress
|
||||
* @param {Object} [options.options] - Custom parameters
|
||||
*
|
||||
* @example
|
||||
* var task = new Task();
|
||||
* task.set({input: ['test'], onComplete: (err, result) => console.log(err), onProgress: (finish, total) => console.log(finish / total)});
|
||||
*
|
||||
* @typescript
|
||||
* set(options?: {onComplete?: (err: Error, result: any) => void, onError?: () => void, onProgress?: Function, input: any, progress?: any, options?: Record<string, any>}): void
|
||||
*/
|
||||
set (options) {
|
||||
options = options || Object.create(null);
|
||||
this.onComplete = options.onComplete;
|
||||
this.onProgress = options.onProgress;
|
||||
this.onError = options.onError;
|
||||
this.source = this.input = options.input;
|
||||
this.output = null;
|
||||
this.progress = options.progress;
|
||||
// custom data
|
||||
this.options = options.options || Object.create(null);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Dispatch event
|
||||
*
|
||||
* !#zh
|
||||
* 发布事件
|
||||
*
|
||||
* @method dispatch
|
||||
* @param {string} event - The event name
|
||||
* @param {*} param1 - Parameter 1
|
||||
* @param {*} param2 - Parameter 2
|
||||
* @param {*} param3 - Parameter 3
|
||||
* @param {*} param4 - Parameter 4
|
||||
*
|
||||
* @example
|
||||
* var task = Task.create();
|
||||
* Task.onComplete = (msg) => console.log(msg);
|
||||
* Task.dispatch('complete', 'hello world');
|
||||
*
|
||||
* @typescript
|
||||
* dispatch(event: string, param1?: any, param2?: any, param3?: any, param4?: any): void
|
||||
*/
|
||||
dispatch (event, param1, param2, param3, param4) {
|
||||
switch (event) {
|
||||
case 'complete' :
|
||||
this.onComplete && this.onComplete(param1, param2, param3, param4);
|
||||
break;
|
||||
case 'progress':
|
||||
this.onProgress && this.onProgress(param1, param2, param3, param4);
|
||||
break;
|
||||
case 'error':
|
||||
this.onError && this.onError(param1, param2, param3, param4);
|
||||
break;
|
||||
default:
|
||||
var str = 'on' + event[0].toUpperCase() + event.substr(1);
|
||||
if (typeof this[str] === 'function') {
|
||||
this[str](param1, param2, param3, param4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Recycle this for reuse
|
||||
*
|
||||
* !#zh
|
||||
* 回收 task 用于复用
|
||||
*
|
||||
* @method recycle
|
||||
*
|
||||
* @typescript
|
||||
* recycle(): void
|
||||
*/
|
||||
recycle () {
|
||||
if (_deadPool.length === MAX_DEAD_NUM) return;
|
||||
this.onComplete = null;
|
||||
this.onProgress = null;
|
||||
this.onError = null;
|
||||
this.source = this.output = this.input = null;
|
||||
this.progress = null;
|
||||
this.options = null;
|
||||
_deadPool.push(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Whether or not this task is completed
|
||||
*
|
||||
* !#zh
|
||||
* 此任务是否已经完成
|
||||
*
|
||||
* @property isFinish
|
||||
* @type {Boolean}
|
||||
*/
|
||||
get isFinish () {
|
||||
return this._isFinish;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Create a new task from pool
|
||||
*
|
||||
* !#zh
|
||||
* 从对象池中创建 task
|
||||
*
|
||||
* @static
|
||||
* @method create
|
||||
* @param {Object} [options] - Some optional paramters
|
||||
* @param {Function} [options.onComplete] - Callback when the task complete, if the pipeline is synchronous, onComplete is unnecessary.
|
||||
* @param {Function} [options.onProgress] - Continuously callback when the task is runing, if the pipeline is synchronous, onProgress is unnecessary.
|
||||
* @param {Function} [options.onError] - Callback when something goes wrong, if the pipeline is synchronous, onError is unnecessary.
|
||||
* @param {*} options.input - Something will be handled with pipeline
|
||||
* @param {*} [options.progress] - Progress information, you may need to assign it manually when multiple pipeline share one progress
|
||||
* @param {Object} [options.options] - Custom parameters
|
||||
* @returns {Task} task
|
||||
*
|
||||
* @typescript
|
||||
* create(options?: {onComplete?: (err: Error, result: any) => void, onError?: () => void, onProgress?: Function, input: any, progress?: any, options?: Record<string, any>}): Task
|
||||
*/
|
||||
Task.create = function (options) {
|
||||
var out = null;
|
||||
if (_deadPool.length !== 0) {
|
||||
out = _deadPool.pop();
|
||||
out.set(options);
|
||||
}
|
||||
else {
|
||||
out = new Task(options);
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
module.exports = Task;
|
183
engine/cocos2d/core/asset-manager/urlTransformer.js
Normal file
183
engine/cocos2d/core/asset-manager/urlTransformer.js
Normal file
@@ -0,0 +1,183 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const { decodeUuid } = require('./helper');
|
||||
const RequestItem = require('./request-item');
|
||||
const { RequestType, bundles } = require('./shared');
|
||||
|
||||
function parse (task) {
|
||||
|
||||
var input = task.input, options = task.options;
|
||||
input = Array.isArray(input) ? input : [ input ];
|
||||
|
||||
task.output = [];
|
||||
for (var i = 0; i < input.length; i ++ ) {
|
||||
var item = input[i];
|
||||
var out = RequestItem.create();
|
||||
if (typeof item === 'string') {
|
||||
item = Object.create(null);
|
||||
item[options.__requestType__ || RequestType.UUID] = input[i];
|
||||
}
|
||||
if (typeof item === 'object') {
|
||||
// local options will overlap glabal options
|
||||
cc.js.addon(item, options);
|
||||
if (item.preset) {
|
||||
cc.js.addon(item, cc.assetManager.presets[item.preset]);
|
||||
}
|
||||
for (var key in item) {
|
||||
switch (key) {
|
||||
case RequestType.UUID:
|
||||
var uuid = out.uuid = decodeUuid(item.uuid);
|
||||
if (bundles.has(item.bundle)) {
|
||||
var config = bundles.get(item.bundle)._config;
|
||||
var info = config.getAssetInfo(uuid);
|
||||
if (info && info.redirect) {
|
||||
if (!bundles.has(info.redirect)) throw new Error(`Please load bundle ${info.redirect} first`);
|
||||
config = bundles.get(info.redirect)._config;
|
||||
info = config.getAssetInfo(uuid);
|
||||
}
|
||||
out.config = config;
|
||||
out.info = info;
|
||||
}
|
||||
out.ext = item.ext || '.json';
|
||||
break;
|
||||
case '__requestType__':
|
||||
case 'ext':
|
||||
case 'bundle':
|
||||
case 'preset':
|
||||
case 'type': break;
|
||||
case RequestType.DIR:
|
||||
if (bundles.has(item.bundle)) {
|
||||
var infos = [];
|
||||
bundles.get(item.bundle)._config.getDirWithPath(item.dir, item.type, infos);
|
||||
for (let i = 0, l = infos.length; i < l; i++) {
|
||||
var info = infos[i];
|
||||
input.push({uuid: info.uuid, __isNative__: false, ext: '.json', bundle: item.bundle});
|
||||
}
|
||||
}
|
||||
out.recycle();
|
||||
out = null;
|
||||
break;
|
||||
case RequestType.PATH:
|
||||
if (bundles.has(item.bundle)) {
|
||||
var config = bundles.get(item.bundle)._config;
|
||||
var info = config.getInfoWithPath(item.path, item.type);
|
||||
|
||||
if (info && info.redirect) {
|
||||
if (!bundles.has(info.redirect)) throw new Error(`you need to load bundle ${info.redirect} first`);
|
||||
config = bundles.get(info.redirect)._config;
|
||||
info = config.getAssetInfo(info.uuid);
|
||||
}
|
||||
|
||||
if (!info) {
|
||||
out.recycle();
|
||||
throw new Error(`Bundle ${item.bundle} doesn't contain ${item.path}`);
|
||||
}
|
||||
out.config = config;
|
||||
out.uuid = info.uuid;
|
||||
out.info = info;
|
||||
}
|
||||
out.ext = item.ext || '.json';
|
||||
break;
|
||||
case RequestType.SCENE:
|
||||
if (bundles.has(item.bundle)) {
|
||||
var config = bundles.get(item.bundle)._config;
|
||||
var info = config.getSceneInfo(item.scene);
|
||||
|
||||
if (info && info.redirect) {
|
||||
if (!bundles.has(info.redirect)) throw new Error(`you need to load bundle ${info.redirect} first`);
|
||||
config = bundles.get(info.redirect)._config;
|
||||
info = config.getAssetInfo(info.uuid);
|
||||
}
|
||||
if (!info) {
|
||||
out.recycle();
|
||||
throw new Error(`Bundle ${config.name} doesn't contain scene ${item.scene}`);
|
||||
}
|
||||
out.config = config;
|
||||
out.uuid = info.uuid;
|
||||
out.info = info;
|
||||
}
|
||||
break;
|
||||
case '__isNative__':
|
||||
out.isNative = item.__isNative__;
|
||||
break;
|
||||
case RequestType.URL:
|
||||
out.url = item.url;
|
||||
out.uuid = item.uuid || item.url;
|
||||
out.ext = item.ext || cc.path.extname(item.url);
|
||||
out.isNative = item.__isNative__ !== undefined ? item.__isNative__ : true;
|
||||
break;
|
||||
default: out.options[key] = item[key];
|
||||
}
|
||||
if (!out) break;
|
||||
}
|
||||
}
|
||||
if (!out) continue;
|
||||
task.output.push(out);
|
||||
if (!out.uuid && !out.url) throw new Error('Can not parse this input:' + JSON.stringify(item));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function combine (task) {
|
||||
var input = task.output = task.input;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
var item = input[i];
|
||||
if (item.url) continue;
|
||||
|
||||
var url = '', base = '';
|
||||
var config = item.config;
|
||||
if (item.isNative) {
|
||||
base = (config && config.nativeBase) ? (config.base + config.nativeBase) : cc.assetManager.generalNativeBase;
|
||||
}
|
||||
else {
|
||||
base = (config && config.importBase) ? (config.base + config.importBase) : cc.assetManager.generalImportBase;
|
||||
}
|
||||
|
||||
let uuid = item.uuid;
|
||||
|
||||
var ver = '';
|
||||
if (item.info) {
|
||||
if (item.isNative) {
|
||||
ver = item.info.nativeVer ? ('.' + item.info.nativeVer) : '';
|
||||
}
|
||||
else {
|
||||
ver = item.info.ver ? ('.' + item.info.ver) : '';
|
||||
}
|
||||
}
|
||||
|
||||
// ugly hack, WeChat does not support loading font likes 'myfont.dw213.ttf'. So append hash to directory
|
||||
if (item.ext === '.ttf') {
|
||||
url = `${base}/${uuid.slice(0, 2)}/${uuid}${ver}/${item.options.__nativeName__}`;
|
||||
}
|
||||
else {
|
||||
url = `${base}/${uuid.slice(0, 2)}/${uuid}${ver}${item.ext}`;
|
||||
}
|
||||
|
||||
item.url = url;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = { parse, combine };
|
350
engine/cocos2d/core/asset-manager/utilities.js
Normal file
350
engine/cocos2d/core/asset-manager/utilities.js
Normal file
@@ -0,0 +1,350 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
const dependUtil = require('./depend-util');
|
||||
const { isScene, decodeUuid } = require('./helper');
|
||||
const { assets } = require('./shared');
|
||||
const { callInNextTick } = require('../platform/utils');
|
||||
const MissingObjectReporter = CC_EDITOR && Editor.require('app://editor/page/scene-utils/missing-object-reporter');
|
||||
require('../assets/CCAsset');
|
||||
|
||||
var utils = {
|
||||
|
||||
processOptions (options) {
|
||||
if (CC_EDITOR) return;
|
||||
var uuids = options.uuids;
|
||||
var paths = options.paths;
|
||||
var types = options.types;
|
||||
var bundles = options.deps;
|
||||
var realEntries = options.paths = Object.create(null);
|
||||
|
||||
if (options.debug === false) {
|
||||
for (let i = 0, l = uuids.length; i < l; i++) {
|
||||
uuids[i] = decodeUuid(uuids[i]);
|
||||
}
|
||||
|
||||
for (let id in paths) {
|
||||
let entry = paths[id];
|
||||
let type = entry[1];
|
||||
entry[1] = types[type];
|
||||
}
|
||||
}
|
||||
else {
|
||||
var out = Object.create(null);
|
||||
for (let i = 0, l = uuids.length; i < l; i++) {
|
||||
let uuid = uuids[i];
|
||||
uuids[i] = out[uuid] = decodeUuid(uuid);
|
||||
}
|
||||
uuids = out;
|
||||
}
|
||||
|
||||
for (let id in paths) {
|
||||
let entry = paths[id];
|
||||
realEntries[uuids[id]] = entry;
|
||||
}
|
||||
|
||||
var scenes = options.scenes;
|
||||
for (let name in scenes) {
|
||||
let uuid = scenes[name];
|
||||
scenes[name] = uuids[uuid];
|
||||
}
|
||||
|
||||
var packs = options.packs;
|
||||
for (let packId in packs) {
|
||||
let packedIds = packs[packId];
|
||||
for (let j = 0; j < packedIds.length; ++j) {
|
||||
packedIds[j] = uuids[packedIds[j]];
|
||||
}
|
||||
}
|
||||
|
||||
var versions = options.versions;
|
||||
if (versions) {
|
||||
for (let folder in versions) {
|
||||
var entries = versions[folder];
|
||||
for (let i = 0; i < entries.length; i += 2) {
|
||||
let uuid = entries[i];
|
||||
entries[i] = uuids[uuid] || uuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var redirect = options.redirect;
|
||||
if (redirect) {
|
||||
for (let i = 0; i < redirect.length; i += 2) {
|
||||
redirect[i] = uuids[redirect[i]];
|
||||
redirect[i + 1] = bundles[redirect[i + 1]];
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
clear (task, clearRef) {
|
||||
for (var i = 0, l = task.input.length; i < l; i++) {
|
||||
var item = task.input[i];
|
||||
if (clearRef) {
|
||||
!item.isNative && item.content && item.content.decRef && item.content.decRef(false);
|
||||
}
|
||||
item.recycle();
|
||||
}
|
||||
task.input = null;
|
||||
},
|
||||
|
||||
urlAppendTimestamp (url) {
|
||||
if (cc.assetManager.downloader.appendTimeStamp && typeof url === 'string') {
|
||||
if (/\?/.test(url))
|
||||
return url + '&_t=' + (new Date() - 0);
|
||||
else
|
||||
return url + '?_t=' + (new Date() - 0);
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
retry (process, times, wait, onComplete, index) {
|
||||
index = index || 0;
|
||||
process(index, function (err, result) {
|
||||
index++;
|
||||
if (!err || index > times) {
|
||||
onComplete && onComplete(err, result);
|
||||
}
|
||||
else {
|
||||
setTimeout(function () {
|
||||
utils.retry(process, times, wait, onComplete, index);
|
||||
}, wait);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getDepends (uuid, data, exclude, depends, preload, asyncLoadAssets, config) {
|
||||
try {
|
||||
var info = dependUtil.parse(uuid, data);
|
||||
var includeNative = true;
|
||||
if (data instanceof cc.Asset && (!data.__nativeDepend__ || data._nativeAsset)) includeNative = false;
|
||||
if (!preload) {
|
||||
asyncLoadAssets = !CC_EDITOR && (!!data.asyncLoadAssets || (asyncLoadAssets && !info.preventDeferredLoadDependents));
|
||||
for (let i = 0, l = info.deps.length; i < l; i++) {
|
||||
let dep = info.deps[i];
|
||||
if (!(dep in exclude)) {
|
||||
exclude[dep] = true;
|
||||
depends.push({uuid: dep, __asyncLoadAssets__: asyncLoadAssets, bundle: config && config.name});
|
||||
}
|
||||
}
|
||||
|
||||
if (includeNative && !asyncLoadAssets && !info.preventPreloadNativeObject && info.nativeDep) {
|
||||
config && (info.nativeDep.bundle = config.name);
|
||||
depends.push(Object.assign({}, info.nativeDep));
|
||||
}
|
||||
|
||||
} else {
|
||||
for (let i = 0, l = info.deps.length; i < l; i++) {
|
||||
let dep = info.deps[i];
|
||||
if (!(dep in exclude)) {
|
||||
exclude[dep] = true;
|
||||
depends.push({uuid: dep, bundle: config && config.name});
|
||||
}
|
||||
}
|
||||
if (includeNative && info.nativeDep) {
|
||||
config && (info.nativeDep.bundle = config.name);
|
||||
depends.push(Object.assign({}, info.nativeDep));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
cc.error(e.message, e.stack);
|
||||
}
|
||||
},
|
||||
|
||||
cache (id, asset, cacheAsset) {
|
||||
if (!asset) return;
|
||||
var _isScene = isScene(asset);
|
||||
if (!_isScene && cacheAsset) {
|
||||
assets.add(id, asset);
|
||||
}
|
||||
if (_isScene) {
|
||||
if (CC_EDITOR && !asset.scene) {
|
||||
Editor.error('Sorry, the scene data of "%s" is corrupted!', asset._uuid);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setProperties (uuid, asset, assetsMap) {
|
||||
|
||||
var missingAsset = false;
|
||||
let depends = asset.__depends__;
|
||||
if (depends) {
|
||||
var missingAssetReporter = null;
|
||||
for (var i = 0, l = depends.length; i < l; i++) {
|
||||
var depend = depends[i];
|
||||
var dependAsset = assetsMap[depend.uuid + '@import'];
|
||||
if (!dependAsset) {
|
||||
if (CC_EDITOR) {
|
||||
!missingAssetReporter && (missingAssetReporter = new MissingObjectReporter(asset));
|
||||
missingAssetReporter.stashByOwner(depend.owner, depend.prop, Editor.serialize.asAsset(depend.uuid));
|
||||
}
|
||||
else {
|
||||
cc.error('The asset ' + depend.uuid + ' is missing!');
|
||||
}
|
||||
missingAsset = true;
|
||||
}
|
||||
else {
|
||||
depend.owner[depend.prop] = dependAsset.addRef();
|
||||
}
|
||||
}
|
||||
|
||||
missingAssetReporter && missingAssetReporter.reportByOwner();
|
||||
asset.__depends__ = undefined;
|
||||
}
|
||||
|
||||
if (asset.__nativeDepend__) {
|
||||
if (!asset._nativeAsset) {
|
||||
if (assetsMap[uuid + '@native']) {
|
||||
asset._nativeAsset = assetsMap[uuid + '@native'];
|
||||
}
|
||||
else {
|
||||
missingAsset = true;
|
||||
if (CC_EDITOR) {
|
||||
console.error(`the native asset of ${uuid} is missing!`);
|
||||
}
|
||||
}
|
||||
}
|
||||
asset.__nativeDepend__ = undefined;
|
||||
}
|
||||
return missingAsset;
|
||||
},
|
||||
|
||||
gatherAsset (task) {
|
||||
let source = task.source;
|
||||
if (!task.options.__outputAsArray__ && source.length === 1) {
|
||||
task.output = source[0].content;
|
||||
}
|
||||
else {
|
||||
let output = task.output = [];
|
||||
for (var i = 0, l = source.length; i < l; i++) {
|
||||
output.push(source[i].content);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
forEach (array, process, onComplete) {
|
||||
var count = 0;
|
||||
var errs = [];
|
||||
if (array.length === 0) onComplete && onComplete(errs);
|
||||
for (var i = 0, l = array.length; i < l; i++) {
|
||||
process(array[i], function (err) {
|
||||
if (err) {
|
||||
errs.push(err);
|
||||
}
|
||||
count ++;
|
||||
if (count === l) {
|
||||
onComplete && onComplete(errs);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
parseParameters (options, onProgress, onComplete) {
|
||||
if (onComplete === undefined) {
|
||||
var isCallback = typeof options === 'function';
|
||||
if (onProgress) {
|
||||
onComplete = onProgress;
|
||||
if (!isCallback) {
|
||||
onProgress = null;
|
||||
}
|
||||
}
|
||||
else if (onProgress === undefined && isCallback) {
|
||||
onComplete = options;
|
||||
options = null;
|
||||
onProgress = null;
|
||||
}
|
||||
if (onProgress !== undefined && isCallback) {
|
||||
onProgress = options;
|
||||
options = null;
|
||||
}
|
||||
}
|
||||
options = options || Object.create(null);
|
||||
return { options, onProgress, onComplete };
|
||||
},
|
||||
|
||||
parseLoadResArgs (type, onProgress, onComplete) {
|
||||
if (onComplete === undefined) {
|
||||
var isValidType = cc.js.isChildClassOf(type, cc.Asset);
|
||||
if (onProgress) {
|
||||
onComplete = onProgress;
|
||||
if (isValidType) {
|
||||
onProgress = null;
|
||||
}
|
||||
}
|
||||
else if (onProgress === undefined && !isValidType) {
|
||||
onComplete = type;
|
||||
onProgress = null;
|
||||
type = null;
|
||||
}
|
||||
if (onProgress !== undefined && !isValidType) {
|
||||
onProgress = type;
|
||||
type = null;
|
||||
}
|
||||
}
|
||||
return { type, onProgress, onComplete };
|
||||
},
|
||||
|
||||
checkCircleReference (owner, uuid, map, checked) {
|
||||
if (!checked) {
|
||||
checked = Object.create(null);
|
||||
}
|
||||
let item = map[uuid];
|
||||
if (!item || checked[uuid]) {
|
||||
return false;
|
||||
}
|
||||
checked[uuid] = true;
|
||||
var result = false;
|
||||
var deps = dependUtil.getDeps(uuid);
|
||||
if (deps) {
|
||||
for (var i = 0, l = deps.length; i < l; i++) {
|
||||
var dep = deps[i];
|
||||
if (dep === owner || utils.checkCircleReference(owner, dep, map, checked)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
asyncify (cb) {
|
||||
return function (p1, p2) {
|
||||
if (!cb) return;
|
||||
let refs = [];
|
||||
if (Array.isArray(p2)) {
|
||||
p2.forEach(x => x instanceof cc.Asset && refs.push(x.addRef()));
|
||||
} else {
|
||||
p2 instanceof cc.Asset && refs.push(p2.addRef());
|
||||
}
|
||||
callInNextTick(() => {
|
||||
refs.forEach(x => x.decRef(false));
|
||||
cb(p1, p2);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = utils;
|
Reference in New Issue
Block a user