diff --git a/src/framework/app-base.js b/src/framework/app-base.js index 09e9c38431b..49d2bcbfa49 100644 --- a/src/framework/app-base.js +++ b/src/framework/app-base.js @@ -237,15 +237,6 @@ class AppBase extends EventHandler { */ this.renderNextFrame = false; - /** - * Enable if you want entity type script attributes to not be re-mapped when an entity is - * cloned. - * - * @type {boolean} - * @ignore - */ - this.useLegacyScriptAttributeCloning = script.legacy; - this._librariesLoaded = false; this._fillMode = FILLMODE_KEEP_ASPECT; this._resolutionMode = RESOLUTION_FIXED; @@ -767,43 +758,7 @@ class AppBase extends EventHandler { } _preloadScripts(sceneData, callback) { - if (!script.legacy) { - callback(); - return; - } - - this.systems.script.preloading = true; - - const scripts = this._getScriptReferences(sceneData); - - const l = scripts.length; - const progress = new Progress(l); - const regex = /^http(s)?:\/\//; - - if (l) { - const onLoad = (err, ScriptType) => { - if (err) - console.error(err); - - progress.inc(); - if (progress.done()) { - this.systems.script.preloading = false; - callback(); - } - }; - - for (let i = 0; i < l; i++) { - let scriptUrl = scripts[i]; - // support absolute URLs (for now) - if (!regex.test(scriptUrl.toLowerCase()) && this._scriptPrefix) - scriptUrl = path.join(this._scriptPrefix, scripts[i]); - - this.loader.load(scriptUrl, 'script', onLoad); - } - } else { - this.systems.script.preloading = false; - callback(); - } + callback(); } // set application properties from data file @@ -942,52 +897,32 @@ class AppBase extends EventHandler { const scriptsIndex = {}; const bundlesIndex = {}; - if (!script.legacy) { - // add scripts in order of loading first - for (let i = 0; i < this.scriptsOrder.length; i++) { - const id = this.scriptsOrder[i]; - if (!assets[id]) - continue; - - scriptsIndex[id] = true; - list.push(assets[id]); - } + // add scripts in order of loading first + for (let i = 0; i < this.scriptsOrder.length; i++) { + const id = this.scriptsOrder[i]; + if (!assets[id]) + continue; - // then add bundles - if (this.enableBundles) { - for (const id in assets) { - if (assets[id].type === 'bundle') { - bundlesIndex[id] = true; - list.push(assets[id]); - } - } - } + scriptsIndex[id] = true; + list.push(assets[id]); + } - // then add rest of assets + // then add bundles + if (this.enableBundles) { for (const id in assets) { - if (scriptsIndex[id] || bundlesIndex[id]) - continue; - - list.push(assets[id]); - } - } else { - if (this.enableBundles) { - // add bundles - for (const id in assets) { - if (assets[id].type === 'bundle') { - bundlesIndex[id] = true; - list.push(assets[id]); - } + if (assets[id].type === 'bundle') { + bundlesIndex[id] = true; + list.push(assets[id]); } } + } - // then add rest of assets - for (const id in assets) { - if (bundlesIndex[id]) - continue; + // then add rest of assets + for (const id in assets) { + if (scriptsIndex[id] || bundlesIndex[id]) + continue; - list.push(assets[id]); - } + list.push(assets[id]); } for (let i = 0; i < list.length; i++) { @@ -1132,10 +1067,6 @@ class AppBase extends EventHandler { this.stats.frame.updateStart = now(); // #endif - // Perform ComponentSystem update - if (script.legacy) - this.systems.fire('fixedUpdate', 1.0 / 60.0); - this.systems.fire(this._inTools ? 'toolsUpdate' : 'update', dt); this.systems.fire('animationUpdate', dt); this.systems.fire('postUpdate', dt); diff --git a/src/framework/application.js b/src/framework/application.js index 25003b2ac3b..9643d9f995a 100644 --- a/src/framework/application.js +++ b/src/framework/application.js @@ -9,7 +9,6 @@ import { BatchManager } from '../scene/batching/batch-manager.js'; import { AppBase } from './app-base.js'; import { AppOptions } from './app-options.js'; -import { script } from './script.js'; import { AnimationComponentSystem } from './components/animation/system.js'; import { AnimComponentSystem } from './components/anim/system.js'; import { AudioListenerComponentSystem } from './components/audio-listener/system.js'; @@ -24,7 +23,6 @@ import { ParticleSystemComponentSystem } from './components/particle-system/syst import { RenderComponentSystem } from './components/render/system.js'; import { RigidBodyComponentSystem } from './components/rigid-body/system.js'; import { ScreenComponentSystem } from './components/screen/system.js'; -import { ScriptLegacyComponentSystem } from './components/script-legacy/system.js'; import { ScrollViewComponentSystem } from './components/scroll-view/system.js'; import { ScrollbarComponentSystem } from './components/scrollbar/system.js'; import { SoundComponentSystem } from './components/sound/system.js'; @@ -169,7 +167,7 @@ class Application extends AppBase { RenderComponentSystem, CameraComponentSystem, LightComponentSystem, - script.legacy ? ScriptLegacyComponentSystem : ScriptComponentSystem, + ScriptComponentSystem, SoundComponentSystem, AudioListenerComponentSystem, ParticleSystemComponentSystem, diff --git a/src/framework/asset/asset-registry.js b/src/framework/asset/asset-registry.js index c85b3e4fd5a..11007871c58 100644 --- a/src/framework/asset/asset-registry.js +++ b/src/framework/asset/asset-registry.js @@ -5,8 +5,6 @@ import { TagsCache } from '../../core/tags-cache.js'; import { standardMaterialTextureParameters } from '../../scene/materials/standard-material-parameters.js'; -import { script } from '../script.js'; - import { Asset } from './asset.js'; /** @@ -438,7 +436,7 @@ class AssetRegistry extends EventHandler { this.fire('error:' + asset.id, err, asset); asset.fire('error', err, asset); } else { - if (!script.legacy && asset.type === 'script') { + if (asset.type === 'script') { const handler = this._loader.getHandler('script'); if (handler._cache[asset.id] && handler._cache[asset.id].parentNode === document.head) { // remove old element diff --git a/src/framework/components/script-legacy/component.js b/src/framework/components/script-legacy/component.js deleted file mode 100644 index 38fb66bcf22..00000000000 --- a/src/framework/components/script-legacy/component.js +++ /dev/null @@ -1,210 +0,0 @@ -import { Debug } from '../../../core/debug.js'; -import { path } from '../../../core/path.js'; - -import { Component } from '../component.js'; - -class ScriptLegacyComponent extends Component { - constructor(system, entity) { - super(system, entity); - this.on('set_scripts', this.onSetScripts, this); - } - - send(name, functionName) { - Debug.deprecated('ScriptLegacyComponent.send() is deprecated and will be removed soon. Please use: https://developer.playcanvas.com/user-manual/scripting/communication/'); - - const args = Array.prototype.slice.call(arguments, 2); - const instances = this.entity.script.instances; - let fn; - - if (instances && instances[name]) { - fn = instances[name].instance[functionName]; - if (fn) { - return fn.apply(instances[name].instance, args); - } - } - return undefined; - } - - onEnable() { - // if the scripts of the component have been loaded - // then call the appropriate methods on the component - if (this.data.areScriptsLoaded && !this.system.preloading) { - if (!this.data.initialized) { - this.system._initializeScriptComponent(this); - } else { - this.system._enableScriptComponent(this); - } - - if (!this.data.postInitialized) { - this.system._postInitializeScriptComponent(this); - } - } - } - - onDisable() { - this.system._disableScriptComponent(this); - } - - onSetScripts(name, oldValue, newValue) { - if (!this.system._inTools || this.runInTools) { - // if we only need to update script attributes then update them and return - if (this._updateScriptAttributes(oldValue, newValue)) { - return; - } - - // disable the script first - if (this.enabled) { - this.system._disableScriptComponent(this); - } - - this.system._destroyScriptComponent(this); - - this.data.areScriptsLoaded = false; - - // get the urls - const scripts = newValue; - const urls = scripts.map(function (s) { - return s.url; - }); - - // try to load the scripts synchronously first - if (this._loadFromCache(urls)) { - return; - } - - // not all scripts are in the cache so load them asynchronously - this._loadScripts(urls); - } - } - - // Check if only script attributes need updating in which - // case just update the attributes and return otherwise return false - _updateScriptAttributes(oldValue, newValue) { - let onlyUpdateAttributes = true; - - if (oldValue.length !== newValue.length) { - onlyUpdateAttributes = false; - } else { - for (let i = 0, len = newValue.length; i < len; i++) { - if (oldValue[i].url !== newValue[i].url) { - onlyUpdateAttributes = false; - break; - } - } - } - - if (onlyUpdateAttributes) { - for (const key in this.instances) { - if (this.instances.hasOwnProperty(key)) { - this.system._updateAccessors(this.entity, this.instances[key]); - } - } - } - - return onlyUpdateAttributes; - } - - // Load each url from the cache synchronously. If one of the urls is not in the cache - // then stop and return false. - _loadFromCache(urls) { - const cached = []; - - const prefix = this.system.app._scriptPrefix || ''; - const regex = /^http(s)?:\/\//i; - - for (let i = 0, len = urls.length; i < len; i++) { - let url = urls[i]; - if (!regex.test(url)) { - url = path.join(prefix, url); - } - - const type = this.system.app.loader.getFromCache(url, 'script'); - - // if we cannot find the script in the cache then return and load - // all scripts with the resource loader - if (!type) { - return false; - } - - cached.push(type); - } - - for (let i = 0, len = cached.length; i < len; i++) { - const ScriptType = cached[i]; - - // check if this is a regular JS file - if (ScriptType === true) { - continue; - } - - // ScriptType may be null if the script component is loading an ordinary JavaScript lib rather than a PlayCanvas script - // Make sure that script component hasn't been removed since we started loading - if (ScriptType && this.entity.script) { - // Make sure that we haven't already instantiated another identical script while loading - // e.g. if you do addComponent, removeComponent, addComponent, in quick succession - if (!this.entity.script.instances[ScriptType._pcScriptName]) { - const instance = new ScriptType(this.entity); - this.system._preRegisterInstance(this.entity, urls[i], ScriptType._pcScriptName, instance); - } - } - } - - if (this.data) { - this.data.areScriptsLoaded = true; - } - - // We only need to initialize after preloading is complete - // During preloading all scripts are initialized after everything is loaded - if (!this.system.preloading) { - this.system.onInitialize(this.entity); - this.system.onPostInitialize(this.entity); - } - - return true; - } - - _loadScripts(urls) { - let count = urls.length; - - const prefix = this.system.app._scriptPrefix || ''; - - urls.forEach((url) => { - let _url = null; - let _unprefixed = null; - // support absolute URLs (for now) - if (url.toLowerCase().startsWith('http://') || url.toLowerCase().startsWith('https://')) { - _unprefixed = url; - _url = url; - } else { - _unprefixed = url; - _url = path.join(prefix, url); - } - this.system.app.loader.load(_url, 'script', (err, ScriptType) => { - count--; - if (!err) { - // ScriptType is null if the script is not a PlayCanvas script - if (ScriptType && this.entity.script) { - if (!this.entity.script.instances[ScriptType._pcScriptName]) { - const instance = new ScriptType(this.entity); - this.system._preRegisterInstance(this.entity, _unprefixed, ScriptType._pcScriptName, instance); - } - } - } else { - console.error(err); - } - if (count === 0) { - this.data.areScriptsLoaded = true; - - // We only need to initialize after preloading is complete - // During preloading all scripts are initialized after everything is loaded - if (!this.system.preloading) { - this.system.onInitialize(this.entity); - this.system.onPostInitialize(this.entity); - } - } - }); - }); - } -} - -export { ScriptLegacyComponent }; diff --git a/src/framework/components/script-legacy/data.js b/src/framework/components/script-legacy/data.js deleted file mode 100644 index 72701a80365..00000000000 --- a/src/framework/components/script-legacy/data.js +++ /dev/null @@ -1,18 +0,0 @@ -class ScriptLegacyComponentData { - constructor() { - // serialized - this.scripts = []; - this.enabled = true; - - // not serialized - this.instances = {}; - this._instances = {}; - this.runInTools = false; - this.attributes = {}; - this.initialized = false; - this.postInitialized = false; - this.areScriptsLoaded = false; - } -} - -export { ScriptLegacyComponentData }; diff --git a/src/framework/components/script-legacy/system.js b/src/framework/components/script-legacy/system.js deleted file mode 100644 index 7c781c82aa8..00000000000 --- a/src/framework/components/script-legacy/system.js +++ /dev/null @@ -1,520 +0,0 @@ -import { extend } from '../../../core/core.js'; -import { events } from '../../../core/events.js'; -import { Debug } from '../../../core/debug.js'; - -import { Color } from '../../../core/math/color.js'; -import { Curve } from '../../../core/math/curve.js'; -import { CurveSet } from '../../../core/math/curve-set.js'; -import { Vec2 } from '../../../core/math/vec2.js'; -import { Vec3 } from '../../../core/math/vec3.js'; -import { Vec4 } from '../../../core/math/vec4.js'; - -import { Entity } from '../../entity.js'; - -import { Component } from '../component.js'; -import { ComponentSystem } from '../system.js'; - -import { ScriptLegacyComponent } from './component.js'; -import { ScriptLegacyComponentData } from './data.js'; - -const _schema = [ - 'enabled', - 'scripts', - 'instances', - 'runInTools' -]; - -const INITIALIZE = 'initialize'; -const POST_INITIALIZE = 'postInitialize'; -const UPDATE = 'update'; -const POST_UPDATE = 'postUpdate'; -const FIXED_UPDATE = 'fixedUpdate'; -const TOOLS_UPDATE = 'toolsUpdate'; -const ON_ENABLE = 'onEnable'; -const ON_DISABLE = 'onDisable'; - -class ScriptLegacyComponentSystem extends ComponentSystem { - constructor(app) { - super(app); - - this.id = 'script'; - - this.ComponentType = ScriptLegacyComponent; - this.DataType = ScriptLegacyComponentData; - this.schema = _schema; - - // used by application during preloading phase to ensure scripts aren't - // initialized until everything is loaded - this.preloading = false; - - // arrays to cache script instances for fast iteration - this.instancesWithUpdate = []; - this.instancesWithFixedUpdate = []; - this.instancesWithPostUpdate = []; - this.instancesWithToolsUpdate = []; - - this.on('beforeremove', this.onBeforeRemove, this); - this.app.systems.on(INITIALIZE, this.onInitialize, this); - this.app.systems.on(POST_INITIALIZE, this.onPostInitialize, this); - this.app.systems.on(UPDATE, this.onUpdate, this); - this.app.systems.on(FIXED_UPDATE, this.onFixedUpdate, this); - this.app.systems.on(POST_UPDATE, this.onPostUpdate, this); - this.app.systems.on(TOOLS_UPDATE, this.onToolsUpdate, this); - } - - initializeComponentData(component, data, properties) { - properties = ['runInTools', 'enabled', 'scripts']; - - // convert attributes array to dictionary - if (data.scripts && data.scripts.length) { - data.scripts.forEach(function (script) { - if (script.attributes && Array.isArray(script.attributes)) { - const dict = {}; - for (let i = 0; i < script.attributes.length; i++) { - dict[script.attributes[i].name] = script.attributes[i]; - } - - script.attributes = dict; - } - }); - } - - super.initializeComponentData(component, data, properties); - } - - cloneComponent(entity, clone) { - // overridden to make sure urls list is duplicated - const src = this.store[entity.getGuid()]; - const data = { - runInTools: src.data.runInTools, - scripts: [], - enabled: src.data.enabled - }; - - // manually clone scripts so that we don't clone attributes with pc.extend - // which will result in a stack overflow when extending 'entity' script attributes - const scripts = src.data.scripts; - for (let i = 0, len = scripts.length; i < len; i++) { - const attributes = scripts[i].attributes; - if (attributes) { - delete scripts[i].attributes; - } - - data.scripts.push(extend({}, scripts[i])); - - if (attributes) { - data.scripts[i].attributes = this._cloneAttributes(attributes); - scripts[i].attributes = attributes; - } - } - - return this.addComponent(clone, data); - } - - onBeforeRemove(entity, component) { - // if the script component is enabled - // call onDisable on all its instances first - if (component.enabled) { - this._disableScriptComponent(component); - } - - // then call destroy on all the script instances - this._destroyScriptComponent(component); - } - - onInitialize(root) { - this._registerInstances(root); - - if (root.enabled) { - if (root.script && root.script.enabled) { - this._initializeScriptComponent(root.script); - } - - const children = root._children; - for (let i = 0, len = children.length; i < len; i++) { - if (children[i] instanceof Entity) { - this.onInitialize(children[i]); - } - } - } - } - - onPostInitialize(root) { - if (root.enabled) { - if (root.script && root.script.enabled) { - this._postInitializeScriptComponent(root.script); - } - - const children = root._children; - for (let i = 0, len = children.length; i < len; i++) { - if (children[i] instanceof Entity) { - this.onPostInitialize(children[i]); - } - } - } - } - - _callInstancesMethod(script, method) { - const instances = script.data.instances; - for (const name in instances) { - if (instances.hasOwnProperty(name)) { - const instance = instances[name].instance; - if (instance[method]) { - instance[method](); - } - } - } - } - - _initializeScriptComponent(script) { - this._callInstancesMethod(script, INITIALIZE); - script.data.initialized = true; - - // check again if the script and the entity are enabled - // in case they got disabled during initialize - if (script.enabled && script.entity.enabled) { - this._enableScriptComponent(script); - } - } - - _enableScriptComponent(script) { - this._callInstancesMethod(script, ON_ENABLE); - } - - _disableScriptComponent(script) { - this._callInstancesMethod(script, ON_DISABLE); - } - - _destroyScriptComponent(script) { - const instances = script.data.instances; - for (const name in instances) { - if (instances.hasOwnProperty(name)) { - const instance = instances[name].instance; - if (instance.destroy) { - instance.destroy(); - } - - if (instance.update) { - const index = this.instancesWithUpdate.indexOf(instance); - if (index >= 0) { - this.instancesWithUpdate.splice(index, 1); - } - } - - if (instance.fixedUpdate) { - const index = this.instancesWithFixedUpdate.indexOf(instance); - if (index >= 0) { - this.instancesWithFixedUpdate.splice(index, 1); - } - } - - if (instance.postUpdate) { - const index = this.instancesWithPostUpdate.indexOf(instance); - if (index >= 0) { - this.instancesWithPostUpdate.splice(index, 1); - } - } - - if (instance.toolsUpdate) { - const index = this.instancesWithToolsUpdate.indexOf(instance); - if (index >= 0) { - this.instancesWithToolsUpdate.splice(index, 1); - } - } - - if (script.instances[name].instance === script[name]) { - delete script[name]; - } - delete script.instances[name]; - } - } - } - - _postInitializeScriptComponent(script) { - this._callInstancesMethod(script, POST_INITIALIZE); - script.data.postInitialized = true; - } - - _updateInstances(method, updateList, dt) { - for (let i = 0, len = updateList.length; i < len; i++) { - const item = updateList[i]; - if (item && item.entity && item.entity.enabled && item.entity.script.enabled) { - item[method](dt); - } - } - } - - onUpdate(dt) { - this._updateInstances(UPDATE, this.instancesWithUpdate, dt); - } - - onFixedUpdate(dt) { - this._updateInstances(FIXED_UPDATE, this.instancesWithFixedUpdate, dt); - } - - onPostUpdate(dt) { - this._updateInstances(POST_UPDATE, this.instancesWithPostUpdate, dt); - } - - onToolsUpdate(dt) { - this._updateInstances(TOOLS_UPDATE, this.instancesWithToolsUpdate, dt); - } - - broadcast(name, functionName) { - Debug.deprecated('ScriptLegacyComponentSystem.broadcast() is deprecated and will be removed soon. Please use: https://developer.playcanvas.com/user-manual/scripting/communication/'); - - const args = Array.prototype.slice.call(arguments, 2); - - const dataStore = this.store; - - for (const id in dataStore) { - if (dataStore.hasOwnProperty(id)) { - const data = dataStore[id].data; - if (data.instances[name]) { - const fn = data.instances[name].instance[functionName]; - if (fn) { - fn.apply(data.instances[name].instance, args); - } - } - } - } - } - - _preRegisterInstance(entity, url, name, instance) { - if (entity.script) { - entity.script.data._instances = entity.script.data._instances || {}; - if (entity.script.data._instances[name]) { - throw Error(`Script name collision '${name}'. Scripts from '${url}' and '${entity.script.data._instances[name].url}' {${entity.getGuid()}}`); - } - entity.script.data._instances[name] = { - url: url, - name: name, - instance: instance - }; - } - } - - _registerInstances(entity) { - if (entity.script) { - if (entity.script.data._instances) { - entity.script.instances = entity.script.data._instances; - - for (const instanceName in entity.script.instances) { - const preRegistered = entity.script.instances[instanceName]; - const instance = preRegistered.instance; - - events.attach(instance); - - if (instance.update) { - this.instancesWithUpdate.push(instance); - } - - if (instance.fixedUpdate) { - this.instancesWithFixedUpdate.push(instance); - } - - if (instance.postUpdate) { - this.instancesWithPostUpdate.push(instance); - } - - if (instance.toolsUpdate) { - this.instancesWithToolsUpdate.push(instance); - } - - if (entity.script.scripts) { - this._createAccessors(entity, preRegistered); - } - - // Make instance accessible from the script component of the Entity - if (entity.script[instanceName]) { - throw Error(`Script with name '${instanceName}' is already attached to Script Component`); - } else { - entity.script[instanceName] = instance; - } - } - - // Remove temp storage - delete entity.script.data._instances; - } - } - - const children = entity._children; - for (let i = 0, len = children.length; i < len; i++) { - if (children[i] instanceof Entity) { - this._registerInstances(children[i]); - } - } - } - - _cloneAttributes(attributes) { - const result = {}; - - for (const key in attributes) { - if (!attributes.hasOwnProperty(key)) - continue; - - if (attributes[key].type !== 'entity') { - result[key] = extend({}, attributes[key]); - } else { - // don't pc.extend an entity - const val = attributes[key].value; - delete attributes[key].value; - - result[key] = extend({}, attributes[key]); - result[key].value = val; - - attributes[key].value = val; - } - } - - return result; - } - - _createAccessors(entity, instance) { - const len = entity.script.scripts.length; - const url = instance.url; - - for (let i = 0; i < len; i++) { - const script = entity.script.scripts[i]; - if (script.url === url) { - const attributes = script.attributes; - if (script.name && attributes) { - for (const key in attributes) { - if (attributes.hasOwnProperty(key)) { - this._createAccessor(attributes[key], instance); - } - } - - entity.script.data.attributes[script.name] = this._cloneAttributes(attributes); - } - break; - } - } - } - - _createAccessor(attribute, instance) { - const self = this; - - // create copy of attribute data - // to avoid overwriting the same attribute values - // that are used by the Editor - attribute = { - name: attribute.name, - value: attribute.value, - type: attribute.type - }; - - this._convertAttributeValue(attribute); - - Object.defineProperty(instance.instance, attribute.name, { - get: function () { - return attribute.value; - }, - set: function (value) { - const oldValue = attribute.value; - attribute.value = value; - self._convertAttributeValue(attribute); - instance.instance.fire('set', attribute.name, oldValue, attribute.value); - }, - configurable: true - }); - } - - _updateAccessors(entity, instance) { - const len = entity.script.scripts.length; - const url = instance.url; - - for (let i = 0; i < len; i++) { - const scriptComponent = entity.script; - const script = scriptComponent.scripts[i]; - if (script.url === url) { - const name = script.name; - const attributes = script.attributes; - if (name) { - if (attributes) { - // create / update attribute accessors - for (const key in attributes) { - if (attributes.hasOwnProperty(key)) { - this._createAccessor(attributes[key], instance); - } - } - } - - // delete accessors for attributes that no longer exist - // and fire onAttributeChange when an attribute value changed - const previousAttributes = scriptComponent.data.attributes[name]; - if (previousAttributes) { - for (const key in previousAttributes) { - const oldAttribute = previousAttributes[key]; - if (!(key in attributes)) { - delete instance.instance[oldAttribute.name]; - } else { - if (attributes[key].value !== oldAttribute.value) { - if (instance.instance.onAttributeChanged) { - instance.instance.onAttributeChanged(oldAttribute.name, oldAttribute.value, attributes[key].value); - } - } - } - } - } - - if (attributes) { - scriptComponent.data.attributes[name] = this._cloneAttributes(attributes); - } else { - delete scriptComponent.data.attributes[name]; - } - } - - break; - } - } - } - - _convertAttributeValue(attribute) { - if (attribute.type === 'rgb' || attribute.type === 'rgba') { - if (Array.isArray(attribute.value)) { - attribute.value = attribute.value.length === 3 ? - new Color(attribute.value[0], attribute.value[1], attribute.value[2]) : - new Color(attribute.value[0], attribute.value[1], attribute.value[2], attribute.value[3]); - } - } else if (attribute.type === 'vec2') { - if (Array.isArray(attribute.value)) - attribute.value = new Vec2(attribute.value[0], attribute.value[1]); - - } else if (attribute.type === 'vec3' || attribute.type === 'vector') { - if (Array.isArray(attribute.value)) - attribute.value = new Vec3(attribute.value[0], attribute.value[1], attribute.value[2]); - - } else if (attribute.type === 'vec4') { - if (Array.isArray(attribute.value)) - attribute.value = new Vec4(attribute.value[0], attribute.value[1], attribute.value[2], attribute.value[3]); - - } else if (attribute.type === 'entity') { - if (attribute.value !== null && typeof attribute.value === 'string') - attribute.value = this.app.root.findByGuid(attribute.value); - - } else if (attribute.type === 'curve' || attribute.type === 'colorcurve') { - const curveType = attribute.value.keys[0] instanceof Array ? CurveSet : Curve; - attribute.value = new curveType(attribute.value.keys); - - /* eslint-disable no-self-assign */ - attribute.value.type = attribute.value.type; - /* eslint-enable no-self-assign */ - } - } - - destroy() { - super.destroy(); - - this.app.systems.off(INITIALIZE, this.onInitialize, this); - this.app.systems.off(POST_INITIALIZE, this.onPostInitialize, this); - this.app.systems.off(UPDATE, this.onUpdate, this); - this.app.systems.off(FIXED_UPDATE, this.onFixedUpdate, this); - this.app.systems.off(POST_UPDATE, this.onPostUpdate, this); - this.app.systems.off(TOOLS_UPDATE, this.onToolsUpdate, this); - } -} - -Component._buildAccessors(ScriptLegacyComponent.prototype, _schema); - -export { ScriptLegacyComponentSystem }; diff --git a/src/framework/entity.js b/src/framework/entity.js index 08b80812789..de2ad5d2e5b 100644 --- a/src/framework/entity.js +++ b/src/framework/entity.js @@ -667,7 +667,7 @@ function resolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, oldEntity, n } // Handle entity script attributes - if (components.script && !newEntity._app.useLegacyScriptAttributeCloning) { + if (components.script) { newEntity.script.resolveDuplicatedEntityReferenceProperties(components.script, duplicatedIdsMap); } diff --git a/src/framework/handlers/script.js b/src/framework/handlers/script.js index 27a60167dfd..bca774bf995 100644 --- a/src/framework/handlers/script.js +++ b/src/framework/handlers/script.js @@ -55,35 +55,17 @@ class ScriptHandler extends ResourceHandler { const onScriptLoad = (url.load, (err, url, extra) => { if (!err) { - if (script.legacy) { - let Type = null; - // pop the type from the loading stack - if (ScriptTypes._types.length) { - Type = ScriptTypes._types.pop(); - } - - if (Type) { - // store indexed by URL - this._scripts[url] = Type; - } else { - Type = null; - } + const obj = { }; - // return the resource - callback(null, Type, extra); - } else { - const obj = { }; + for (let i = 0; i < ScriptTypes._types.length; i++) + obj[ScriptTypes._types[i].name] = ScriptTypes._types[i]; - for (let i = 0; i < ScriptTypes._types.length; i++) - obj[ScriptTypes._types[i].name] = ScriptTypes._types[i]; + ScriptTypes._types.length = 0; - ScriptTypes._types.length = 0; + callback(null, obj, extra); - callback(null, obj, extra); - - // no cache for scripts - delete self._loader._cache[ResourceLoader.makeKey(url, 'script')]; - } + // no cache for scripts + delete self._loader._cache[ResourceLoader.makeKey(url, 'script')]; } else { callback(err); } diff --git a/src/framework/script.js b/src/framework/script.js index 55f4bf6b6b5..86f7bf6bd9d 100644 --- a/src/framework/script.js +++ b/src/framework/script.js @@ -1,7 +1,6 @@ import { events } from '../core/events.js'; import { getApplication } from './globals.js'; -import { ScriptTypes } from './script/script-types.js'; /** * Callback used by {@link script.createLoadingScreen}. @@ -19,8 +18,6 @@ import { ScriptTypes } from './script/script-types.js'; * @ignore */ -let _legacy = false; - // flag to avoid creating multiple loading screens e.g. when // loading screen scripts are reloaded let _createdLoadingScreen = false; @@ -36,106 +33,6 @@ const script = { // set during script load to be used for initializing script app: null, - /** - * Create a script resource object. A script file should contain a single call to - * {@link script.create} and the callback should return a script object which will be - * instantiated when attached to Entities. - * - * @param {string} name - The name of the script object. - * @param {CreateScriptCallback} callback - The callback function which is passed an - * {@link AppBase} object, which is used to access Entities and Components, and should - * return the Type of the script resource to be instanced for each Entity. - * @example - * pc.script.create(function (app) { - * var Scriptable = function (entity) { - * // store entity - * this.entity = entity; - * - * // use app - * app.components.model.addComponent(entity, { - * // component properties - * }); - * }; - * - * return Scriptable; - * }); - * @ignore - */ - create(name, callback) { - if (!_legacy) - return; - - // get the ScriptType from the callback - const ScriptType = callback(script.app); - - // store the script name - ScriptType._pcScriptName = name; - - // Push this onto loading stack - ScriptTypes.push(ScriptType, _legacy); - - this.fire("created", name, callback); - }, - - /** - * Creates a script attribute for the current script. The script attribute can be accessed - * inside the script instance like so 'this.attributeName' or outside a script instance like so - * 'entity.script.attributeName'. Script attributes can be edited from the Attribute Editor of - * the PlayCanvas Editor like normal Components. - * - * @param {string} name - The name of the attribute. - * @param {string} type - The type of the attribute. Can be: 'number', 'string', 'boolean', - * 'asset', 'entity', 'rgb', 'rgba', 'vector', 'enumeration', 'curve', 'colorcurve'. - * @param {object} defaultValue - The default value of the attribute. - * @param {object} options - Optional parameters for the attribute. - * @param {number} options.min - The minimum value of the attribute. - * @param {number} options.max - The maximum value of the attribute. - * @param {number} options.step - The step that will be used when changing the attribute value - * in the PlayCanvas Editor. - * @param {number} options.decimalPrecision - A number that specifies the number of decimal - * digits allowed for the value. - * @param {object[]} options.enumerations - An array of name, value pairs from which the user - * can select one if the attribute type is an enumeration. - * @param {string[]} options.curves - (For 'curve' attributes only) An array of strings that - * define the names of each curve in the curve editor. - * @param {boolean} options.color - (For 'curve' attributes only) If true then the curve - * attribute will be a color curve. - * @example - * pc.script.attribute('speed', 'number', 5); - * pc.script.attribute('message', 'string', "My message"); - * pc.script.attribute('enemyPosition', 'vector', [1, 0, 0]); - * pc.script.attribute('spellType', 'enumeration', 0, { - * enumerations: [{ - * name: "Fire", - * value: 0 - * }, { - * name: "Ice", - * value: 1 - * }] - * }); - * pc.script.attribute('enemy', 'entity'); - * pc.script.attribute('enemySpeed', 'curve'); - * pc.script.attribute('enemyPosition', 'curve', null, { - * curves: ['x', 'y', 'z'] - * }); - * pc.script.attribute('color', 'colorcurve', null, { - * type: 'rgba' - * }); - * - * pc.script.create('scriptable', function (app) { - * var Scriptable = function (entity) { - * // store entity - * this.entity = entity; - * }; - * - * return Scriptable; - * }); - * @ignore - */ - attribute(name, type, defaultValue, options) { - // only works when parsing the script... - }, - /** * Handles the creation of the loading screen of the application. A script can subscribe to the * events of a {@link AppBase} to show a loading screen, progress bar etc. In order for @@ -165,15 +62,6 @@ const script = { } }; -Object.defineProperty(script, 'legacy', { - get: function () { - return _legacy; - }, - set: function (value) { - _legacy = value; - } -}); - events.attach(script); export { script }; diff --git a/src/framework/script/script-types.js b/src/framework/script/script-types.js index 01ce741153e..322c641ce1c 100644 --- a/src/framework/script/script-types.js +++ b/src/framework/script/script-types.js @@ -1,12 +1,8 @@ class ScriptTypes { static _types = []; - static push(Type, isLegacy) { - if (isLegacy && ScriptTypes._types.length > 0) { - console.assert('Script Ordering Error. Contact support@playcanvas.com'); - } else { - ScriptTypes._types.push(Type); - } + static push(Type) { + ScriptTypes._types.push(Type); } } diff --git a/src/framework/script/script.js b/src/framework/script/script.js index b25939d386c..d6bede29603 100644 --- a/src/framework/script/script.js +++ b/src/framework/script/script.js @@ -1,7 +1,5 @@ -import { Debug } from '../../core/debug.js'; import { EventHandler } from '../../core/event-handler.js'; -import { script } from '../script.js'; import { AppBase } from '../app-base.js'; import { ScriptAttributes } from './script-attributes.js'; @@ -57,11 +55,6 @@ function getReservedScriptNames() { * @category Script */ function createScript(name, app) { - if (script.legacy) { - Debug.error('This project is using the legacy script system. You cannot call pc.createScript().'); - return null; - } - if (reservedScriptNames.has(name)) throw new Error(`Script name '${name}' is reserved, please rename the script`); @@ -127,11 +120,6 @@ createScript.reservedAttributes = reservedAttributes; * @category Script */ function registerScript(script, name, app) { - if (script.legacy) { - Debug.error('This project is using the legacy script system. You cannot call pc.registerScript().'); - return; - } - if (typeof script !== 'function') throw new Error(`script class: '${script}' must be a constructor function (i.e. class).`); @@ -149,7 +137,7 @@ function registerScript(script, name, app) { const registry = app ? app.scripts : AppBase.getApplication().scripts; registry.add(script); - ScriptTypes.push(script, script.legacy); + ScriptTypes.push(script); } /* eslint-enable jsdoc/check-examples */ diff --git a/src/index.js b/src/index.js index 85526e5298f..1932181b009 100644 --- a/src/index.js +++ b/src/index.js @@ -262,8 +262,6 @@ export { ScreenComponent } from './framework/components/screen/component.js'; export { ScreenComponentSystem } from './framework/components/screen/system.js'; export { ScriptComponent } from './framework/components/script/component.js'; export { ScriptComponentSystem } from './framework/components/script/system.js'; -export { ScriptLegacyComponent } from './framework/components/script-legacy/component.js'; -export { ScriptLegacyComponentSystem } from './framework/components/script-legacy/system.js'; export { ScrollbarComponent } from './framework/components/scrollbar/component.js'; export { ScrollbarComponentSystem } from './framework/components/scrollbar/system.js'; export * from './framework/components/scroll-view/constants.js'; diff --git a/test/framework/entity.test.mjs b/test/framework/entity.test.mjs index 24c3db445e1..51dd33c1ea3 100644 --- a/test/framework/entity.test.mjs +++ b/test/framework/entity.test.mjs @@ -443,55 +443,6 @@ describe('Entity', function () { expect(subtree2.a_a.script.test.entityArrayAttr[1].getGuid()).to.equal(app.root.getGuid()); }); - it('does not resolve entity script attributes that refer to entities within the duplicated subtree if app.useLegacyScriptAttributeCloning is true', function () { - const TestScript = createScript('test'); - TestScript.attributes.add('entityAttr', { type: 'entity' }); - TestScript.attributes.add('entityArrayAttr', { type: 'entity', array: true }); - - const subtree1 = createSubtree(); - app.root.addChild(subtree1.a); - subtree1.a.addComponent('script'); - subtree1.a.script.create('test', { - attributes: { - entityAttr: subtree1.a_a.getGuid(), - entityArrayAttr: [subtree1.a_a.getGuid()] - } - }); - expect(subtree1.a.script.test.entityAttr.getGuid()).to.equal(subtree1.a_a.getGuid()); - expect(subtree1.a.script.test.entityArrayAttr).to.be.an('array'); - expect(subtree1.a.script.test.entityArrayAttr.length).to.equal(1); - expect(subtree1.a.script.test.entityArrayAttr[0].getGuid()).to.equal(subtree1.a_a.getGuid()); - - subtree1.a_a.addComponent('script'); - subtree1.a_a.script.create('test', { - attributes: { - entityAttr: subtree1.a.getGuid(), - entityArrayAttr: [subtree1.a.getGuid(), subtree1.a_a_a.getGuid()] - } - }); - - expect(subtree1.a_a.script.test.entityAttr.getGuid()).to.equal(subtree1.a.getGuid()); - expect(subtree1.a_a.script.test.entityArrayAttr).to.be.an('array'); - expect(subtree1.a_a.script.test.entityArrayAttr.length).to.equal(2); - expect(subtree1.a_a.script.test.entityArrayAttr[0].getGuid()).to.equal(subtree1.a.getGuid()); - expect(subtree1.a_a.script.test.entityArrayAttr[1].getGuid()).to.equal(subtree1.a_a_a.getGuid()); - - app.useLegacyScriptAttributeCloning = true; - - const subtree2 = cloneSubtree(subtree1); - app.root.addChild(subtree2.a); - expect(subtree2.a.script.test.entityAttr.getGuid()).to.equal(subtree1.a_a.getGuid()); - expect(subtree2.a.script.test.entityArrayAttr).to.be.an('array'); - expect(subtree2.a.script.test.entityArrayAttr.length).to.equal(1); - expect(subtree2.a.script.test.entityArrayAttr[0].getGuid()).to.equal(subtree1.a_a.getGuid()); - - expect(subtree2.a_a.script.test.entityAttr.getGuid()).to.equal(subtree1.a.getGuid()); - expect(subtree2.a_a.script.test.entityArrayAttr).to.be.an('array'); - expect(subtree2.a_a.script.test.entityArrayAttr.length).to.equal(2); - expect(subtree2.a_a.script.test.entityArrayAttr[0].getGuid()).to.equal(subtree1.a.getGuid()); - expect(subtree2.a_a.script.test.entityArrayAttr[1].getGuid()).to.equal(subtree1.a_a_a.getGuid()); - }); - it('ensures that an instance of a subclass keeps its class prototype', function () { class UserEntity extends Entity {} const a = new UserEntity();