From c79379f57725b2dcaaab9edd17b6d899cf067bf6 Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 7 Aug 2018 11:45:11 +0800 Subject: [PATCH 0001/1631] fix angle computing (#3047) --- cocos2d/core/value-types/CCVec2.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/value-types/CCVec2.js b/cocos2d/core/value-types/CCVec2.js index 6498782991d..a23be20775a 100644 --- a/cocos2d/core/value-types/CCVec2.js +++ b/cocos2d/core/value-types/CCVec2.js @@ -485,12 +485,8 @@ proto.angle = function (vector) { * @return {number} from -MathPI to Math.PI */ proto.signAngle = function (vector) { - // NOTE: this algorithm will return 0.0 without signed if vectors are parallex - // var angle = this.angle(vector); - // var cross = this.cross(vector); - // return Math.sign(cross) * angle; - - return Math.atan2(this.y, this.x) - Math.atan2(vector.y, vector.x); + let angle = this.angle(vector); + return this.cross(vector) < 0 ? -angle : angle; }; /** From a808e31cf2d74698496b7a2fdc6dd3117a31372f Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 13 Aug 2018 15:10:30 +0800 Subject: [PATCH 0002/1631] fix editBox multiLine confirm (#3074) --- cocos2d/core/editbox/CCSGEditBox.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/editbox/CCSGEditBox.js b/cocos2d/core/editbox/CCSGEditBox.js index 902eaea376a..9a83c830d36 100644 --- a/cocos2d/core/editbox/CCSGEditBox.js +++ b/cocos2d/core/editbox/CCSGEditBox.js @@ -932,7 +932,7 @@ _ccsg.EditBox.KeyboardReturnType = KeyboardReturnType; defaultValue: editBox._text, maxLength: 140, multiple: multiline, - confirmHold: true, + confirmHold: false, // hide keyboard mannually by wx.onKeyboardConfirm confirmType: "done", success: function (res) { editBox._delegate && editBox._delegate.editBoxEditingDidBegan && editBox._delegate.editBoxEditingDidBegan(editBox); From 6935b80044d7be27a11c93283900053e09baea2d Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 13 Sep 2018 09:52:53 +0800 Subject: [PATCH 0003/1631] fix get layer properties is null (#3235) --- cocos2d/tilemap/CCTMXXMLParser.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/cocos2d/tilemap/CCTMXXMLParser.js b/cocos2d/tilemap/CCTMXXMLParser.js index 67afeb90e11..62560cc1cee 100644 --- a/cocos2d/tilemap/CCTMXXMLParser.js +++ b/cocos2d/tilemap/CCTMXXMLParser.js @@ -821,14 +821,8 @@ cc.TMXMapInfo.prototype = { } // The parent element is the last layer - let layerProps = getPropertyList(selLayer); - if (layerProps) { - let layerProp = {}; - for (let j = 0; j < layerProps.length; j++) { - layerProp[layerProps[j].getAttribute('name')] = layerProps[j].getAttribute('value'); - } - layer.properties = layerProp; - } + layer.properties = getPropertyList(selLayer); + return layer; }, From 95c3fe0b3c8dc8a652291a0ba1968079c0119a10 Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 13 Sep 2018 10:21:55 +0800 Subject: [PATCH 0004/1631] fix scrollView manually scroll (#3242) --- cocos2d/core/components/CCScrollView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index 8c32b746b0b..e36878ed77d 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -819,7 +819,7 @@ let ScrollView = cc.Class({ anchor = anchor.clampf(cc.v2(0, 0), cc.v2(1, 1)); - let scrollSize = this.node.getContentSize(); + let scrollSize = this.content.parent.getContentSize(); let contentSize = this.content.getContentSize(); let bottomDeta = this._getContentBottomBoundary() - this._bottomBoundary; bottomDeta = -bottomDeta; From a4f7c2c939c1cb8bf8ece4c9dc0b9ea1ac899bdf Mon Sep 17 00:00:00 2001 From: kenshin <420373550@qq.com> Date: Thu, 13 Sep 2018 10:29:28 +0800 Subject: [PATCH 0005/1631] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E8=B6=8A=E6=9D=A5=E8=B6=8A=E6=85=A2=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E7=94=B1=E4=BA=8EJS=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E7=9A=84=E7=B4=A2=E5=BC=95=E6=95=B0=E6=8D=AE=E8=B6=8A?= =?UTF-8?q?=E6=9D=A5=E8=B6=8A=E5=A4=9A=E5=AF=BC=E8=87=B4=E7=9A=84=E3=80=82?= =?UTF-8?q?=20(#3241)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed loader performance dropdown caused by large array access --- cocos2d/core/load-pipeline/loading-items.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/load-pipeline/loading-items.js b/cocos2d/core/load-pipeline/loading-items.js index d003cadde78..89d83dfe3c6 100644 --- a/cocos2d/core/load-pipeline/loading-items.js +++ b/cocos2d/core/load-pipeline/loading-items.js @@ -739,12 +739,14 @@ proto.destroy = function () { // Reinitialize CallbacksInvoker, generate three new objects, could be improved CallbacksInvoker.call(this); - - _queues[this._id] = null; + if (_queueDeps[this._id]) { _queueDeps[this._id].completed.length = 0; _queueDeps[this._id].deps.length = 0; } + delete _queues[this._id]; + delete _queueDeps[this._id]; + if (_pool.indexOf(this) === -1 && _pool.length < _POOL_MAX_LENGTH) { _pool.push(this); } From 3867bc977a282a503ccb32425b7a56b52ba68ba5 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 13 Sep 2018 15:40:57 +0800 Subject: [PATCH 0006/1631] fix ios videoplay bug for fireball/issues/8392 (#3245) --- cocos2d/videoplayer/video-player-impl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index e9da47228cd..1c8fa67519a 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -81,7 +81,7 @@ let VideoPlayerImpl = cc.Class({ //binding event let cbs = this.__eventListeners; cbs.loadedmetadata = function () { - this._loadedmeta = true; + self._loadedmeta = true; if (sys.os === sys.OS_IOS && sys.isBrowser) { triggerFullScene(video, self._fullScreenEnabled); } From 33ab9e3147f5d34de83cd9b8b502fa815f661b12 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 14 Sep 2018 19:16:24 +0800 Subject: [PATCH 0007/1631] remove cc.macro.ENABLE_3D usage (#3252) --- cocos2d/core/3d/CCSkinnedMeshRenderer.js | 4 +--- cocos2d/core/mesh/CCMeshRenderer.js | 4 +--- cocos2d/core/mesh/mesh-renderer.js | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/cocos2d/core/3d/CCSkinnedMeshRenderer.js b/cocos2d/core/3d/CCSkinnedMeshRenderer.js index 960eea630d4..46ad71a30f9 100644 --- a/cocos2d/core/3d/CCSkinnedMeshRenderer.js +++ b/cocos2d/core/3d/CCSkinnedMeshRenderer.js @@ -50,9 +50,7 @@ let SkinnedMeshRenderer = cc.Class({ _createMaterial() { let material = new renderEngine.MeshMaterial(); material.color = cc.Color.WHITE; - if (cc.macro.ENABLE_3D) { - material._mainTech._passes[0].setDepth(true, true); - } + material._mainTech._passes[0].setDepth(true, true); material.useModel = false; material.useSkinning = true; diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index be851063f72..c9cea14f247 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -76,9 +76,7 @@ let MeshRenderer = cc.Class({ _createMaterial (subMesh) { let material = new renderEngine.MeshMaterial(); material.color = cc.Color.WHITE; - if (cc.macro.ENABLE_3D) { - material._mainTech._passes[0].setDepth(true, true); - } + material._mainTech._passes[0].setDepth(true, true); material.useModel = true; if (subMesh._vertexBuffer._format._attr2el[gfx.ATTR_COLOR]) { diff --git a/cocos2d/core/mesh/mesh-renderer.js b/cocos2d/core/mesh/mesh-renderer.js index 508ce148de0..023b37a6bb2 100644 --- a/cocos2d/core/mesh/mesh-renderer.js +++ b/cocos2d/core/mesh/mesh-renderer.js @@ -52,9 +52,7 @@ let meshRendererAssembler = { let m = material.clone(); m.color = BLACK_COLOR; m.useTexture = false; - if (cc.macro.ENABLE_3D) { - m._mainTech._passes[0].setDepth(true, true); - } + m._mainTech._passes[0].setDepth(true, true); data.material = m; let indices = []; From 675128b0d9c42809ab3574421685d48d83548b6b Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 14 Sep 2018 23:55:53 +0800 Subject: [PATCH 0008/1631] expose js._registeredClassIds js._registeredClassNames to unload scripts dynamically (#3174) --- cocos2d/core/platform/js.js | 77 +++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/cocos2d/core/platform/js.js b/cocos2d/core/platform/js.js index fbdca5da420..547576f13b4 100644 --- a/cocos2d/core/platform/js.js +++ b/cocos2d/core/platform/js.js @@ -382,7 +382,16 @@ function isTempClassId (id) { var _idToClass = {}; var _nameToClass = {}; - function getRegister (key, table) { + function setup (key, publicName, table) { + js.getset(js, publicName, + function () { + return Object.assign({}, table); + }, + function (value) { + js.clear(table); + Object.assign(table, value); + } + ); return function (id, constructor) { // deregister old if (constructor.prototype.hasOwnProperty(key)) { @@ -418,9 +427,37 @@ cc.js.unregisterClass to remove the id of unused class'; * @param {Function} constructor * @private */ - js._setClassId = getRegister('__cid__', _idToClass); + /** + * !#en All classes registered in the engine, indexed by ID. + * !#zh 引擎中已注册的所有类型,通过 ID 进行索引。 + * @property _registeredClassIds + * @example + * // save all registered classes before loading scripts + * let builtinClassIds = cc.js._registeredClassIds; + * let builtinClassNames = cc.js._registeredClassNames; + * // load some scripts that contain CCClass + * ... + * // clear all loaded classes + * cc.js._registeredClassIds = builtinClassIds; + * cc.js._registeredClassNames = builtinClassNames; + */ + js._setClassId = setup('__cid__', '_registeredClassIds', _idToClass); - var doSetClassName = getRegister('__classname__', _nameToClass); + /** + * !#en All classes registered in the engine, indexed by name. + * !#zh 引擎中已注册的所有类型,通过名称进行索引。 + * @property _registeredClassNames + * @example + * // save all registered classes before loading scripts + * let builtinClassIds = cc.js._registeredClassIds; + * let builtinClassNames = cc.js._registeredClassNames; + * // load some scripts that contain CCClass + * ... + * // clear all loaded classes + * cc.js._registeredClassIds = builtinClassIds; + * cc.js._registeredClassNames = builtinClassNames; + */ + var doSetClassName = setup('__classname__', '_registeredClassNames', _nameToClass); /** * Register the class by specified name manually @@ -514,40 +551,6 @@ cc.js.unregisterClass to remove the id of unused class'; } return ''; }; - - if (CC_DEV) { - js.getset(js, '_registeredClassIds', - function () { - var dump = {}; - for (var id in _idToClass) { - dump[id] = _idToClass[id]; - } - return dump; - }, - function (value) { - js.clear(_idToClass); - for (var id in value) { - _idToClass[id] = value[id]; - } - } - ); - js.getset(js, '_registeredClassNames', - function () { - var dump = {}; - for (var id in _nameToClass) { - dump[id] = _nameToClass[id]; - } - return dump; - }, - function (value) { - js.clear(_nameToClass); - for (var id in value) { - _nameToClass[id] = value[id]; - } - } - ); - } - })(); /** From 4e9110bc27c74f892877b85b89e180634f717ef0 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Mon, 17 Sep 2018 11:10:36 +0800 Subject: [PATCH 0009/1631] fix building 2.5D (#3253) --- cocos2d/core/3d/CCSkeletonAnimationClip.js | 8 ++++++-- cocos2d/core/3d/index.js | 9 ++++++--- cocos2d/core/assets/CCSpriteFrame.js | 2 +- cocos2d/core/index.js | 6 +++--- cocos2d/core/mesh/CCMesh.js | 14 +++++++++++--- cocos2d/core/mesh/index.js | 6 ++++-- 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/cocos2d/core/3d/CCSkeletonAnimationClip.js b/cocos2d/core/3d/CCSkeletonAnimationClip.js index d9e59c1b3a6..ad1419bb5b0 100644 --- a/cocos2d/core/3d/CCSkeletonAnimationClip.js +++ b/cocos2d/core/3d/CCSkeletonAnimationClip.js @@ -67,9 +67,13 @@ var SkeletonAnimationClip = cc.Class({ this._model.initAnimationClip(this); }, - _serialize: CC_EDITOR && function () { + _serialize: CC_EDITOR && function (exporting) { + let modelUuid = this._modelUuid; + if (exporting) { + modelUuid = Editor.Utils.UuidUtils.compressUuid(modelUuid, true); + } return { - modelUuid: this._modelUuid, + modelUuid: modelUuid, animationID: this._animationID, name: this._name, } diff --git a/cocos2d/core/3d/index.js b/cocos2d/core/3d/index.js index 3d1a2c9df34..6b476c92be5 100644 --- a/cocos2d/core/3d/index.js +++ b/cocos2d/core/3d/index.js @@ -1,9 +1,12 @@ -if (!CC_TEST) { +if (!CC_TEST && (!CC_EDITOR || !Editor.isMainProcess)) { require('./polyfill-3d'); } require('./CCModel'); require('./CCSkeletonAnimationClip'); -require('./CCSkeletonAnimation'); -require('./CCSkinnedMeshRenderer'); + +if (!CC_EDITOR || !Editor.isMainProcess) { + require('./CCSkeletonAnimation'); + require('./CCSkinnedMeshRenderer'); +} diff --git a/cocos2d/core/assets/CCSpriteFrame.js b/cocos2d/core/assets/CCSpriteFrame.js index 908b0a6c13c..cddc410929d 100644 --- a/cocos2d/core/assets/CCSpriteFrame.js +++ b/cocos2d/core/assets/CCSpriteFrame.js @@ -70,7 +70,7 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ _textureSetter: { set: function (texture) { if (texture) { - if (CC_EDITOR && !(texture instanceof cc.Texture2D)) { + if (CC_EDITOR && Editor.isBuilder) { // just building this._texture = texture; return; diff --git a/cocos2d/core/index.js b/cocos2d/core/index.js index c52cb58def2..680f0dd1fb4 100644 --- a/cocos2d/core/index.js +++ b/cocos2d/core/index.js @@ -39,9 +39,9 @@ if (!CC_EDITOR || !Editor.isMainProcess) { require('./collider/CCIntersection'); require('./physics'); require('./camera/CCCamera'); - - require('./mesh'); - require('./3d'); } +require('./mesh'); +require('./3d'); + require('./base-ui/CCWidgetManager'); diff --git a/cocos2d/core/mesh/CCMesh.js b/cocos2d/core/mesh/CCMesh.js index e675d2806b6..335a6a49e11 100644 --- a/cocos2d/core/mesh/CCMesh.js +++ b/cocos2d/core/mesh/CCMesh.js @@ -59,6 +59,10 @@ var Mesh = cc.Class({ properties: { _modelSetter: { set: function (model) { + if (CC_EDITOR && Editor.isBuilder) { + // just building + return; + } this._initWithModel(model); } }, @@ -261,11 +265,15 @@ var Mesh = cc.Class({ this._model.initMesh(this); }, - _serialize: CC_EDITOR && function () { + _serialize: CC_EDITOR && function (exporting) { + let modelUuid = this._modelUuid; + if (exporting) { + modelUuid = Editor.Utils.UuidUtils.compressUuid(modelUuid, true); + } return { - modelUuid: this._modelUuid, + modelUuid: modelUuid, meshID: this._meshID, - } + }; }, _deserialize (data, handle) { diff --git a/cocos2d/core/mesh/index.js b/cocos2d/core/mesh/index.js index 55de77b9ed4..5ba5fb7ad84 100644 --- a/cocos2d/core/mesh/index.js +++ b/cocos2d/core/mesh/index.js @@ -1,3 +1,5 @@ require('./CCMesh'); -require('./CCMeshRenderer'); -require('./mesh-renderer'); +if (!CC_EDITOR || !Editor.isMainProcess) { + require('./CCMeshRenderer'); + require('./mesh-renderer'); +} From e750c0a4f75b55ba5250e7a2ed6b057f6e7e3df0 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 17 Sep 2018 15:55:51 +0800 Subject: [PATCH 0010/1631] add StudioWidget (#3255) * add StudioWidget * refine code --- cocos2d/core/base-ui/CCWidgetManager.js | 9 +-------- cocos2d/core/components/CCStudioComponent.js | 10 ++++++++++ cocos2d/core/components/CCWidget.js | 14 +++++++++++++- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/cocos2d/core/base-ui/CCWidgetManager.js b/cocos2d/core/base-ui/CCWidgetManager.js index 5bbf5785f83..21d700f2a6a 100644 --- a/cocos2d/core/base-ui/CCWidgetManager.js +++ b/cocos2d/core/base-ui/CCWidgetManager.js @@ -229,14 +229,7 @@ function visitNode (node) { var widget = node._widget; if (widget) { if (CC_DEV) { - var target = widget._target; - if (target) { - var isParent = node !== target && node.isChildOf(target); - if (!isParent) { - cc.errorID(6500); - widget._target = null; - } - } + widget._validateTargetInDEV(); } align(node, widget); if ((!CC_EDITOR || animationState.animatedSinceLastFrame) && widget.alignMode !== AlignMode.ALWAYS) { diff --git a/cocos2d/core/components/CCStudioComponent.js b/cocos2d/core/components/CCStudioComponent.js index 3b673f3cc2f..6aa445efef9 100644 --- a/cocos2d/core/components/CCStudioComponent.js +++ b/cocos2d/core/components/CCStudioComponent.js @@ -316,3 +316,13 @@ StudioComponent.PlaceHolder = cc.Class({ cc.StudioComponent = module.exports = StudioComponent; + +var StudioWidget = cc.Class({ + name: 'cc.StudioWidget', + extends: cc.Widget, + _validateTargetInDEV () {} +}); + +cc.StudioWidget = module.exports = StudioWidget; + + diff --git a/cocos2d/core/components/CCWidget.js b/cocos2d/core/components/CCWidget.js index be959046461..5dbd84eed3b 100644 --- a/cocos2d/core/components/CCWidget.js +++ b/cocos2d/core/components/CCWidget.js @@ -576,9 +576,21 @@ var Widget = cc.Class({ WidgetManager.remove(this); }, + _validateTargetInDEV: CC_DEV && function () { + var target = this._target; + if (target) { + var isParent = this.node !== target && this.node.isChildOf(target); + if (!isParent) { + cc.errorID(6500); + this._target = null; + } + } + + }, + _setAlign: function (flag, isAlign) { var current = (this._alignFlags & flag) > 0; - if (isAlign == current) { + if (isAlign === current) { return; } var isHorizontal = (flag & LEFT_RIGHT) > 0; From 8b8db697775dee3b4a5829a40ea2e552b5083071 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 17 Sep 2018 16:50:52 +0800 Subject: [PATCH 0011/1631] fix mask bug for fireball/issues/8431 (#3257) * fix mask bug for fireball/issues/8431 * refine code * refine code --- cocos2d/core/components/CCMask.js | 47 +++++++++++++++---- .../webgl/assemblers/mask-assembler.js | 35 +------------- 2 files changed, 39 insertions(+), 43 deletions(-) diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 35f58a94f5b..6aba58439bf 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -31,6 +31,7 @@ const StencilMaterial = renderEngine.StencilMaterial; const RenderComponent = require('./CCRenderComponent'); const RenderFlow = require('../renderer/render-flow'); const Graphics = require('../graphics/graphics'); +const Node = require('../CCNode'); let _vec2_temp = cc.v2(); let _mat4_temp = math.mat4.create(); @@ -80,6 +81,11 @@ let Mask = cc.Class({ inspector: 'packages://inspector/inspectors/comps/mask.js' }, + ctor () { + this._graphics = null; + this._clearGraphics = null; + }, + properties: { _spriteFrame: { default: null, @@ -236,18 +242,11 @@ let Mask = cc.Class({ }, onLoad () { - this._graphics = new Graphics(); - this._graphics.node = this.node; - this._graphics.lineWidth = 0; - this._graphics.strokeColor = cc.color(0, 0, 0, 0); + this._createGraphics(); }, onRestore () { - if (!this._graphics) { - this._graphics = new Graphics(); - this._graphics.node = this.node; - this._graphics.lineWidth = 0; - } + this._createGraphics(); if (this._type !== MaskType.IMAGE_STENCIL) { this._updateGraphics(); } @@ -293,7 +292,7 @@ let Mask = cc.Class({ onDestroy () { this._super(); - this._graphics.destroy(); + this._removeGraphics(); }, _resizeNodeToTargetNode: CC_EDITOR && function () { @@ -365,6 +364,24 @@ let Mask = cc.Class({ this.markForRender(true); }, + _createGraphics () { + if (!this._graphics) { + this._graphics = new Graphics(); + this._graphics.node = this.node; + this._graphics.lineWidth = 0; + this._graphics.strokeColor = cc.color(0, 0, 0, 0); + } + + if (!this._clearGraphics) { + this._clearGraphics = new Graphics(); + this._clearGraphics.node = new Node(); + this._clearGraphics._activateMaterial(); + this._clearGraphics.lineWidth = 0; + this._clearGraphics.rect(0, 0, cc.visibleRect.width, cc.visibleRect.height); + this._clearGraphics.fill(); + } + }, + _updateGraphics () { let node = this.node; let graphics = this._graphics; @@ -392,6 +409,16 @@ let Mask = cc.Class({ } }, + _removeGraphics () { + if (this._graphics) { + this._graphics.destroy(); + } + + if (this._clearGraphics) { + this._clearGraphics.destroy(); + } + }, + _hitTest (cameraPt) { let node = this.node; let size = node.getContentSize(), diff --git a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js index f73ebd73dc4..bd95ca1afd1 100644 --- a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js @@ -24,33 +24,13 @@ ****************************************************************************/ const StencilManager = require('../stencil-manager'); -const Node = require('../../../CCNode'); const Mask = require('../../../components/CCMask'); const Graphics = require('../../../graphics/graphics'); const RenderFlow = require('../../render-flow'); - const spriteAssembler = require('./sprite/simple'); const graphicsAssembler = require('./graphics'); let _stencilMgr = StencilManager.sharedManager; -// for nested mask, we might need multiple graphics component to avoid data conflict -let _graphicsPool = []; -let _graphicsUsing = []; - -function getGraphics () { - let graphics = _graphicsPool.pop(); - - if (!graphics) { - let graphicsNode = new Node(); - graphics = graphicsNode.addComponent(Graphics); - graphics._activateMaterial(); - graphics.lineWidth = 0; - graphics.rect(0, 0, cc.visibleRect.width, cc.visibleRect.height); - graphics.fill(); - graphicsAssembler.updateRenderData(graphics); - } - return graphics; -} let maskFrontAssembler = { updateRenderData (mask) { @@ -61,6 +41,7 @@ let maskFrontAssembler = { else { // for updateGraphics calculation mask._renderData = mask.requestRenderData(); + graphicsAssembler.updateRenderData(mask._clearGraphics); } } let renderData = mask._renderData; @@ -91,7 +72,6 @@ let maskFrontAssembler = { _stencilMgr.pushMask(mask); _stencilMgr.clear(); - mask._clearGraphics = getGraphics(); graphicsAssembler.fillBuffers(mask._clearGraphics, renderer); _stencilMgr.enterLevel(); @@ -118,17 +98,6 @@ let maskEndAssembler = { if (mask._type !== Mask.Type.IMAGE_STENCIL || mask.spriteFrame) { // HACK: Must pop mask after batch, so we can only put this logic in fillBuffers _stencilMgr.exitMask(); - - _graphicsUsing.push(mask._clearGraphics); - mask._clearGraphics = null; - - // Clear graphics can only be recycled after the mask stack exits entirely. - if (_stencilMgr.stage === StencilManager.Stage.DISABLED) { - for (let i = 0; i < _graphicsUsing.length; i++) { - _graphicsPool.push(_graphicsUsing[i]); - } - _graphicsUsing.length = 0; - } } mask.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; @@ -141,4 +110,4 @@ Mask._postAssembler = maskEndAssembler; module.exports = { front: maskFrontAssembler, end: maskEndAssembler -} \ No newline at end of file +}; From dd03abaea6d0e849aaa132dbce5d91098b52181a Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 17 Sep 2018 17:31:02 +0800 Subject: [PATCH 0012/1631] fix meshBuffer realloac vData (#3258) --- cocos2d/core/renderer/webgl/mesh-buffer.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/renderer/webgl/mesh-buffer.js b/cocos2d/core/renderer/webgl/mesh-buffer.js index 4449c711626..95f9f6627a7 100644 --- a/cocos2d/core/renderer/webgl/mesh-buffer.js +++ b/cocos2d/core/renderer/webgl/mesh-buffer.js @@ -101,15 +101,18 @@ let MeshBuffer = cc.Class({ }, _reallocVData (copyOldData) { - let oldVData = this._vData; + let oldVData; + if (this._vData) { + oldVData = new Uint8Array(oldVData.buffer); + } this._vData = new Float32Array(this._initVDataCount); this._uintVData = new Uint32Array(this._vData.buffer); + let newData = new Uint8Array(this._uintVData.buffer); if (oldVData && copyOldData) { - let vData = this._vData; for (let i = 0, l = oldVData.length; i < l; i++) { - vData[i] = oldVData[i]; + newData[i] = oldVData[i]; } } From 32bfb00d403ca96eb572e597ef530c64e57033a6 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Mon, 17 Sep 2018 18:06:23 +0800 Subject: [PATCH 0013/1631] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0f7b2159600..b1c968eaf70 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ -Re: cocos-creator/fireball# +Re: cocos-creator/2d-tasks# -Changelog: +Changes: * \ No newline at end of file +--> From 7fc6a0cc8d147b0a48d6094ccaa2e7fd83424f40 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 17 Sep 2018 18:16:14 +0800 Subject: [PATCH 0014/1631] fix wxSubContextView helpURL in engine (#3260) --- cocos2d/core/components/WXSubContextView.js | 2 +- editor/i18n/zh/localization.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/WXSubContextView.js b/cocos2d/core/components/WXSubContextView.js index 5b313410c9a..f1da1160b25 100644 --- a/cocos2d/core/components/WXSubContextView.js +++ b/cocos2d/core/components/WXSubContextView.js @@ -64,7 +64,7 @@ else { editor: CC_EDITOR && { menu: 'i18n:MAIN_MENU.component.others/WXSubContextView', - help: 'i18n:COMPONENT.help_url.wxSubContextView' + help: 'i18n:COMPONENT.help_url.wx_subcontext_view' }, ctor () { diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 6eedb330e3d..8c64375721a 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -25,7 +25,7 @@ module.exports = { "toggleContainer": "http://www.cocos.com/docs/creator/components/toggleContainer.html", "slider": "http://www.cocos.com/docs/creator/components/slider.html", "block_input_events": "http://www.cocos.com/docs/creator/components/block-input-events.html", - "wx_subcontext_view": "http://www.cocos.com/docs/creator/components/wx-subcontext-view.html" + "wx_subcontext_view": "http://docs.cocos.com/creator/manual/zh/publish/publish-wechatgame-sub-domain.html" }, 'animation': { 'default_clip': '在勾选自动播放或调用 play() 时默认播放的动画 clip。', From 42de39656fea48876f091cc8707ab46936f43ada Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 17 Sep 2018 22:06:21 +0800 Subject: [PATCH 0015/1631] add subContextVIew helpURL, en version (#3261) --- editor/i18n/en/localization.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 4048877775c..f936c2999c1 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -23,7 +23,7 @@ module.exports = { "pageviewIndicator": "http://www.cocos.com/docs/creator/components/pageviewIndicator.html", "slider": "http://www.cocos.com/docs/creator/components/slider.html", "block_input_events": "http://www.cocos.com/docs/creator/components/block-input-events.html", - "wx_subcontext_view": "http://www.cocos.com/docs/creator/components/wx-subcontext-view.html" + "wx_subcontext_view": "http://docs.cocos.com/creator/manual/en/publish/publish-wechatgame-sub-domain.html" }, "animation": { "default_clip": "When checking, the deault animation clip is automatically played.", From 9c113549ae856a9945a705b6394597a0cd19a1a5 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 18 Sep 2018 15:29:38 +0800 Subject: [PATCH 0016/1631] add inspector panel to StudioWidget (#3267) * add inspector panel to StudioWidget * refine code --- cocos2d/core/components/CCStudioComponent.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cocos2d/core/components/CCStudioComponent.js b/cocos2d/core/components/CCStudioComponent.js index 6aa445efef9..e2bc96b4a34 100644 --- a/cocos2d/core/components/CCStudioComponent.js +++ b/cocos2d/core/components/CCStudioComponent.js @@ -320,6 +320,9 @@ cc.StudioComponent = module.exports = StudioComponent; var StudioWidget = cc.Class({ name: 'cc.StudioWidget', extends: cc.Widget, + editor: CC_EDITOR && { + inspector: 'packages://inspector/inspectors/comps/ccwidget.js', + }, _validateTargetInDEV () {} }); From ff91265b16d2f2cf40cdd8847ae1f8418c0d42b6 Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 18 Sep 2018 17:02:07 +0800 Subject: [PATCH 0017/1631] fix meshbuff reallocVData (#3270) --- cocos2d/core/renderer/webgl/mesh-buffer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/webgl/mesh-buffer.js b/cocos2d/core/renderer/webgl/mesh-buffer.js index 95f9f6627a7..e8e7e3a530a 100644 --- a/cocos2d/core/renderer/webgl/mesh-buffer.js +++ b/cocos2d/core/renderer/webgl/mesh-buffer.js @@ -103,7 +103,7 @@ let MeshBuffer = cc.Class({ _reallocVData (copyOldData) { let oldVData; if (this._vData) { - oldVData = new Uint8Array(oldVData.buffer); + oldVData = new Uint8Array(this._vData.buffer); } this._vData = new Float32Array(this._initVDataCount); From ddda80fe9a9754908450be4dee0d9cc8d28939b5 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 18 Sep 2018 17:16:32 +0800 Subject: [PATCH 0018/1631] Support switch 2D/3D edit mode (#3266) --- cocos2d/core/CCNode.js | 5 +++ cocos2d/core/CCPrivateNode.js | 5 +++ cocos2d/core/renderer/index.js | 39 ------------------- .../renderer/webgl/render-component-walker.js | 4 +- 4 files changed, 12 insertions(+), 41 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 59c9f5976d1..29caa8acdbb 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1095,6 +1095,11 @@ var Node = cc.Class({ } } }, + + showInEditor: { + default: true, + editorOnly: true + } }, /** diff --git a/cocos2d/core/CCPrivateNode.js b/cocos2d/core/CCPrivateNode.js index f7384570aa4..613e4ce2cef 100644 --- a/cocos2d/core/CCPrivateNode.js +++ b/cocos2d/core/CCPrivateNode.js @@ -98,6 +98,11 @@ let PrivateNode = cc.Class({ }, override: true }, + showInEditor: { + default: false, + editorOnly: true, + override: true + } }, /** diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index f0007f21dc8..72b30b21ad4 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -26,8 +26,6 @@ const renderEngine = require('./render-engine'); const math = renderEngine.math; -let _pos = math.vec3.create(); - function _initBuiltins(device) { let defaultTexture = new renderEngine.Texture2D(device, { images: [], @@ -116,29 +114,6 @@ cc.renderer = module.exports = { this._walker = new RenderComponentWalker(this.device, this.scene); - if (CC_EDITOR) { - this._cameraNode = new cc.Node(); - - this._camera = new renderEngine.Camera(); - this._camera.setColor(0, 0, 0, 1); - this._camera.setFov(Math.PI * 60 / 180); - this._camera.setNear(0.1); - this._camera.setFar(1024); - this._camera.setNode(this._cameraNode); - - let view = new renderEngine.View(); - this._camera.view = view; - this._camera.dirty = true; - - if (CC_EDITOR) { - this._camera.setColor(0, 0, 0, 0); - } - this._camera.setStages([ - 'transparent' - ]); - this.scene.addCamera(this._camera); - } - let builtins = _initBuiltins(this.device); this._forward = new renderEngine.ForwardRenderer(this.device, builtins); }, @@ -178,20 +153,6 @@ cc.renderer = module.exports = { this._camera.tx = vp.x; this._camera.ty = vp.y + vp.height; } - else if (CC_EDITOR && this.canvas) { - let canvas = this.canvas; - let scaleX = cc.view.getScaleX(); - let scaleY = cc.view.getScaleY(); - - let node = this._cameraNode; - _pos.x = node.x = canvas.width / scaleX / 2; - _pos.y = node.y = canvas.height / scaleY / 2; - _pos.z = 0; - - node.z = canvas.height / scaleY / 1.1566; - node.lookAt(_pos); - this._camera.dirty = true; - } }, render (ecScene) { diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/render-component-walker.js index 539c2fe2dbe..d97ff9f6a7b 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/render-component-walker.js @@ -149,7 +149,7 @@ RenderComponentWalker.prototype = { let model = this._modelPool.add(); this._batchedModels.push(model); model.sortKey = this._sortKey++; - model._cullingMask = CC_EDITOR ? 1 : this.cullingMask; + model._cullingMask = this.cullingMask; model.setNode(this.node); model.addEffect(effect); model.addInputAssembler(ia); @@ -177,7 +177,7 @@ RenderComponentWalker.prototype = { let model = this._modelPool.add(); this._batchedModels.push(model); model.sortKey = this._sortKey++; - model._cullingMask = CC_EDITOR ? 1 : this.cullingMask; + model._cullingMask = this.cullingMask; model.setNode(this.node); model.addEffect(effect); model.addInputAssembler(iaRenderData.ia); From 74ea008b34ea5523fc471b01437546221f879bdb Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 18 Sep 2018 17:26:35 +0800 Subject: [PATCH 0019/1631] improve camera (#3263) * improve camera * add setPromitiveType for mesh * improve camera * update camera comment * refine code --- cocos2d/core/camera/CCCamera.js | 250 +++++++++++++++++++++++++------- cocos2d/core/mesh/CCMesh.js | 20 +++ 2 files changed, 214 insertions(+), 56 deletions(-) diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 9eb77b30cbe..b9fb7b39830 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -35,7 +35,6 @@ const vec3 = cc.vmath.vec3; let _mat4_temp_1 = mat4.create(); let _mat4_temp_2 = mat4.create(); -let _vec3_temp_1 = vec3.create(); let _cameras = []; @@ -45,12 +44,10 @@ function repositionDebugCamera () { if (!_debugCamera) return; let node = _debugCamera._node; - let visibleRect = cc.visibleRect; - node.z = visibleRect.height / 1.1566; - node.x = _vec3_temp_1.x = visibleRect.width / 2; - node.y = _vec3_temp_1.y = visibleRect.height / 2; - _vec3_temp_1.z = 0; - node.lookAt(_vec3_temp_1); + let canvas = cc.game.canvas; + node.z = canvas.height / 1.1566; + node.x = canvas.width / 2; + node.y = canvas.height / 2; } /** @@ -59,8 +56,17 @@ function repositionDebugCamera () { * @enum Camera.ClearFlags */ let ClearFlags = cc.Enum({ + /** + * @property COLOR + */ COLOR: 1, + /** + * @property DEPTH + */ DEPTH: 2, + /** + * @property STENCIL + */ STENCIL: 4, }); @@ -86,16 +92,10 @@ let Camera = cc.Class({ 'transparent' ]); - this._fov = Math.PI * 60 / 180; - camera.setFov(this._fov); - camera.setNear(0.1); - camera.setFar(4096); - let view = new renderEngine.View(); camera.view = view; camera.dirty = true; - this._matrixDirty = true; this._inited = false; this._camera = camera; } @@ -117,6 +117,12 @@ let Camera = cc.Class({ _depth: 0, _zoomRatio: 1, _targetTexture: null, + _fov: 60, + _orthoSize: 10, + _nearClip: 0.1, + _farClip: 4096, + _ortho: false, + _rect: cc.rect(0,0,1,1), /** * !#en @@ -131,7 +137,115 @@ let Camera = cc.Class({ }, set (value) { this._zoomRatio = value; - this._matrixDirty = true; + this._updateFov(); + } + }, + + /** + * !#en + * Field of view. The width of the Camera’s view angle, measured in degrees along the local Y axis. + * !#zh + * 决定摄像机视角的宽度,当摄像机处于透视投影模式下这个属性才会生效。 + * @property {Number} fov + * @default 60 + */ + fov: { + get () { + return this._fov; + }, + set (v) { + this._fov = v; + this._updateFov(); + } + }, + + /** + * !#en + * The viewport size of the Camera when set to orthographic projection. + * !#zh + * 摄像机在正交投影模式下的视窗大小。 + * @property {Number} orthoSize + * @default 10 + */ + orthoSize: { + get () { + return this._orthoSize; + }, + set (v) { + this._orthoSize = v; + this._updateOrthoSize(); + } + }, + + /** + * !#en + * The near clipping plane. + * !#zh + * 摄像机的近剪裁面。 + * @property {Number} nearClip + * @default 0.1 + */ + nearClip: { + get () { + return this._nearClip; + }, + set (v) { + this._nearClip = v; + this._updateClippingpPlanes(); + } + }, + + /** + * !#en + * The far clipping plane. + * !#zh + * 摄像机的远剪裁面。 + * @property {Number} farClip + * @default 4096 + */ + farClip: { + get () { + return this._farClip; + }, + set (v) { + this._farClip = v; + this._updateClippingpPlanes(); + } + }, + + /** + * !#en + * Is the camera orthographic (true) or perspective (false)? + * !#zh + * 设置摄像机的投影模式是正交还是透视模式。 + * @property {Boolean} ortho + * @default false + */ + ortho: { + get () { + return this._ortho; + }, + set (v) { + this._ortho = v; + this._updateProjection(); + } + }, + + /** + * !#en + * Four values (0-1) that indicate where on the screen this camera view will be drawn. + * !#zh + * 决定摄像机绘制在屏幕上哪个位置,值为 0-1。 + * @property {Rect} rect + * @default cc.rect(0,0,1,1) + */ + rect: { + get () { + return this._rect; + }, + set (v) { + this._rect = v; + this._updateRect(); } }, @@ -224,6 +338,12 @@ let Camera = cc.Class({ this._targetTexture = value; this._updateTargetTexture(); } + }, + + _is3D: { + get () { + return this.node._is3DNode; + } } }, @@ -313,40 +433,70 @@ let Camera = cc.Class({ }, _updateBackgroundColor () { - if (this._camera) { - let color = this._backgroundColor; - this._camera.setColor( - color.r / 255, - color.g / 255, - color.b / 255, - color.a / 255, - ); - } + if (!this._camera) return; + + let color = this._backgroundColor; + this._camera.setColor( + color.r / 255, + color.g / 255, + color.b / 255, + color.a / 255, + ); }, _updateTargetTexture () { + if (!this._camera) return; + let texture = this._targetTexture; - if (this._camera) { - this._camera._framebuffer = texture ? texture._framebuffer : null; - } + this._camera._framebuffer = texture ? texture._framebuffer : null; + }, + + _updateFov () { + if (!this._camera) return; + + let fov = this._fov * cc.macro.RAD; + fov = Math.atan(Math.tan(fov/2) / this.zoomRatio)*2; + this._camera.setFov(fov); + }, + + _updateOrthoSize () { + if (!this._camera) return; + this._camera.setOrthoHeight(this._orthoSize); + }, + + _updateClippingpPlanes () { + if (!this._camera) return; + this._camera.setNear(this._nearClip); + this._camera.setFar(this._farClip); }, - _onMatrixDirty () { - this._matrixDirty = true; + _updateProjection () { + if (!this._camera) return; + let type = this._ortho ? 1 : 0; + this._camera.setType(type); + }, + + _updateRect () { + if (!this._camera) return; + this._camera.setRect(this._rect); }, _init () { if (this._inited) return; this._inited = true; - if (this._camera) { - this._camera.setNode(this.node); - this._camera.setClearFlags(this._clearFlags); - this._camera._sortDepth = this._depth; - this._updateBackgroundColor(); - this._updateCameraMask(); - this._updateTargetTexture(); - } + let camera = this._camera; + if (!camera) return; + camera.setNode(this.node); + camera.setClearFlags(this._clearFlags); + camera._sortDepth = this._depth; + this._updateBackgroundColor(); + this._updateCameraMask(); + this._updateTargetTexture(); + this._updateFov(); + this._updateOrthoSize(); + this._updateClippingpPlanes(); + this._updateProjection(); }, onLoad () { @@ -354,7 +504,6 @@ let Camera = cc.Class({ }, onEnable () { - this._matrixDirty = true; if (game.renderType !== game.RENDER_TYPE_CANVAS) { cc.director.on(cc.Director.EVENT_BEFORE_DRAW, this.beforeDraw, this); renderer.scene.addCamera(this._camera); @@ -505,30 +654,19 @@ let Camera = cc.Class({ beforeDraw: function () { let node = this.node; - - if (!this._matrixDirty && !node._worldMatDirty) - return; - let camera = this._camera; - let fov = Math.atan(Math.tan(this._fov/2) / this.zoomRatio)*2; - camera.setFov(fov); + + if (!node._is3DNode) { + let height = cc.game.canvas.height / cc.view._scaleY; - let height = cc.game.canvas.height / cc.view._scaleY; + let targetTexture = this._targetTexture; + if (targetTexture) { + height = targetTexture.height; + } - let targetTexture = this._targetTexture; - if (targetTexture) { - height = targetTexture.height; + node.z = height / (Math.tan( this._camera._fov/2) * 2); } - node._updateWorldMatrix(); - _vec3_temp_1.x = node._worldMatrix.m12; - _vec3_temp_1.y = node._worldMatrix.m13; - _vec3_temp_1.z = 0; - - node.z = height / 1.1566; - node.lookAt(_vec3_temp_1); - - this._matrixDirty = false; camera.dirty = true; } }); diff --git a/cocos2d/core/mesh/CCMesh.js b/cocos2d/core/mesh/CCMesh.js index 335a6a49e11..6e02a9327d3 100644 --- a/cocos2d/core/mesh/CCMesh.js +++ b/cocos2d/core/mesh/CCMesh.js @@ -210,6 +210,25 @@ var Mesh = cc.Class({ } }, + /** + * !#en + * Set the sub mesh primitive type. + * !#zh + * 设置子网格绘制线条的方式。 + * @method setPrimitiveType + * @param {Number} type + * @param {Number} index + */ + setPrimitiveType (type, index) { + index = index || 0; + let subMesh = this._subMeshes[index]; + if (!subMesh) { + cc.warn(`Do not have sub mesh at index ${index}`); + return; + } + this._subMeshes[index]._primitiveType = type; + }, + /** * !#en * Clear the buffer data. @@ -286,4 +305,5 @@ var Mesh = cc.Class({ } }); + cc.Mesh = module.exports = Mesh; From 13bb676e7d7284fa978a2277bf3f151c5aba39fc Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 19 Sep 2018 10:33:51 +0800 Subject: [PATCH 0020/1631] fix getExtension expires on WeChat 6.6.5 and below (#3271) --- cocos2d/core/renderer/render-engine.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 8c0a3cbb116..4d26cb2b895 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -8418,7 +8418,7 @@ var Texture2D = (function (Texture$$1) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._wrapT); var ext = this._device.ext('EXT_texture_filter_anisotropic'); - if (ext) { + if (ext && ext.TEXTURE_MAX_ANISOTROPY_EXT) { gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy); } }; @@ -8748,7 +8748,7 @@ var TextureCube = (function (Texture$$1) { // gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, this._wrapR); var ext = this._device.ext('EXT_texture_filter_anisotropic'); - if (ext) { + if (ext && ext.TEXTURE_MAX_ANISOTROPY_EXT) { gl.texParameteri(gl.TEXTURE_CUBE_MAP, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy); } }; From ad99c5ef20a0be834e370691315a43d948e4d90c Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Thu, 20 Sep 2018 12:03:33 +0800 Subject: [PATCH 0021/1631] fix the cc not defined problem in subdomain (#3284) --- index.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index fbe8f2cb37c..754e97c4f1a 100644 --- a/index.js +++ b/index.js @@ -37,13 +37,10 @@ var _global = typeof window === 'undefined' ? global : window; * @module cc * @main cc */ -cc = _global.cc || {}; +_global.cc = _global.cc || {}; // For internal usage -_cc = _global._cc || {}; - -// For internal usage -_cc = {}; +_global._cc = _global._cc || {}; require('./predefine'); @@ -74,4 +71,4 @@ if (CC_EDITOR) { } } -module.exports = cc; \ No newline at end of file +module.exports = _global.cc; \ No newline at end of file From 53a9e9b3d6f08d16f9b03fddec78879c1957b239 Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 20 Sep 2018 12:03:55 +0800 Subject: [PATCH 0022/1631] fix paveViewIndicator, blockInputEvent helpURL in engine (#3285) --- cocos2d/core/components/CCBlockInputEvents.js | 2 +- editor/i18n/en/localization.js | 4 ++-- editor/i18n/zh/localization.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/CCBlockInputEvents.js b/cocos2d/core/components/CCBlockInputEvents.js index aa236a2dbf9..62eebdf646e 100644 --- a/cocos2d/core/components/CCBlockInputEvents.js +++ b/cocos2d/core/components/CCBlockInputEvents.js @@ -49,7 +49,7 @@ const BlockInputEvents = cc.Class({ editor: { menu: 'i18n:MAIN_MENU.component.ui/Block Input Events', inspector: 'packages://inspector/inspectors/comps/block-input-events.js', - help: 'i18n:COMPONENT.help_url.block-input-events', + help: 'i18n:COMPONENT.help_url.block_input_events', }, onEnable () { diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index f936c2999c1..c1bc1540c1b 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -20,9 +20,9 @@ module.exports = { "toggleGroup": "http://www.cocos.com/docs/creator/components/toggleGroup.html", "toggleContainer": "http://www.cocos.com/docs/creator/components/toggleContainer.html", "pageview": "http://www.cocos.com/docs/creator/components/pageview.html", - "pageviewIndicator": "http://www.cocos.com/docs/creator/components/pageviewIndicator.html", + "pageviewIndicator": "http://docs.cocos.com/creator/manual/en/components/pageviewindicator.html", "slider": "http://www.cocos.com/docs/creator/components/slider.html", - "block_input_events": "http://www.cocos.com/docs/creator/components/block-input-events.html", + "block_input_events": "http://docs.cocos.com/creator/manual/en/components/block-input-events.html", "wx_subcontext_view": "http://docs.cocos.com/creator/manual/en/publish/publish-wechatgame-sub-domain.html" }, "animation": { diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 8c64375721a..6d12e3f7135 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -19,12 +19,12 @@ module.exports = { "motionStreak": "http://www.cocos.com/docs/creator/components/motion-streak.html", "richtext": "http://www.cocos.com/docs/creator/components/richtext.html", "pageview": "http://www.cocos.com/docs/creator/components/pageview.html", - "pageviewIndicator": "http://www.cocos.com/docs/creator/components/pageviewIndicator.html", + "pageviewIndicator": "http://docs.cocos.com/creator/manual/zh/components/pageviewindicator.html", "toggle": "http://www.cocos.com/docs/creator/components/toggle.html", "toggleGroup": "http://www.cocos.com/docs/creator/components/toggleGroup.html", "toggleContainer": "http://www.cocos.com/docs/creator/components/toggleContainer.html", "slider": "http://www.cocos.com/docs/creator/components/slider.html", - "block_input_events": "http://www.cocos.com/docs/creator/components/block-input-events.html", + "block_input_events": "http://docs.cocos.com/creator/manual/zh/components/block-input-events.html", "wx_subcontext_view": "http://docs.cocos.com/creator/manual/zh/publish/publish-wechatgame-sub-domain.html" }, 'animation': { From f900f8246b8f6f3108b0b2e5e05ee2768c16d415 Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 20 Sep 2018 16:32:28 +0800 Subject: [PATCH 0023/1631] adjust localization in engine (#3287) --- editor/i18n/en/localization.js | 764 ++++++++++++++++---------------- editor/i18n/zh/localization.js | 774 +++++++++++++++++---------------- 2 files changed, 772 insertions(+), 766 deletions(-) diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index c1bc1540c1b..72a7aea2d50 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -1,386 +1,390 @@ module.exports = { - "help_url": { - "animation": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/animation/", - "sprite": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/sprite/", - "label": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/label/", - "canvas": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/canvas/", - "spine": "http://www.cocos.com/docs/creator/components/spine.html", - "widget": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/widget/", - "button": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/button/", - "progressbar": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/progress/", - "mask": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/mask/", - "scrollview": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/scrollview/", - "scrollbar": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/scrollbar/", - "layout": "http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/components/layout/", - "tiledmap": "http://www.cocos.com/docs/creator/components/tiledmap.html", - "editbox": "http://www.cocos.com/docs/creator/components/editbox.html", - "videoplayer": "http://www.cocos.com/docs/creator/components/videoplayer.html", - "richtext": "http://www.cocos.com/docs/creator/components/richtext.html", - "toggle": "http://www.cocos.com/docs/creator/components/toggle.html", - "toggleGroup": "http://www.cocos.com/docs/creator/components/toggleGroup.html", - "toggleContainer": "http://www.cocos.com/docs/creator/components/toggleContainer.html", - "pageview": "http://www.cocos.com/docs/creator/components/pageview.html", - "pageviewIndicator": "http://docs.cocos.com/creator/manual/en/components/pageviewindicator.html", - "slider": "http://www.cocos.com/docs/creator/components/slider.html", - "block_input_events": "http://docs.cocos.com/creator/manual/en/components/block-input-events.html", - "wx_subcontext_view": "http://docs.cocos.com/creator/manual/en/publish/publish-wechatgame-sub-domain.html" - }, - "animation": { - "default_clip": "When checking, the deault animation clip is automatically played.", - "clips": "You can access and play animation clips via a script", - "play_on_load": "Automatically play animation clip with the scene is loaded" - }, - "audio": { - "clip": "About to be played.", - "volume": "How loud to play an audio clip", - "mute": "Mute. Audio may continue to play, however ther will be no sound.", - "loop": "Loop audio clip? (repeat it over and over)", - "play_on_load": "Automatically play audio clip with the game is running?" - }, - "sprite": { - "sprite_frame": "SpriteFrame image to use", - "atlas": "Atlas that the image belongs to", - "type": "Rendering Mode: Simple, Sliced, Tiled or Filled", - "original_size": "Use the Images original size as the Node size?", - "edit_button": "Edit", - "select_button": "Select In Atlas", - "select_tooltip": "Choose Atlas", - "edit_tooltip": "Open Sprite Editor, set squares and other data", - 'fill_type': 'The direction of filling, choose from Horizontal, Vertical and Radial', - 'fill_center': 'For radial filling, set the center of the circle, value range is 0 to 1', - 'fill_start': 'The normalized value indicate where to start filling', - 'fill_range': 'The normalizad value indicate how much of the sprite we want to show', - 'src_blend_factor': 'The source image blend mode', - 'dst_blend_factor': 'The destination image blend mode', - 'size_mode': 'Set the size of the node which Sprite component is on. CUSTOM for setting width and height manually;TRIMMED to use image size with transparent pixels trimmed; RAW to use image size without trimming.', - 'trim': 'Whether to render transparent pixels around image in node\'s bounding box. If you check this option the boudning box will not include transparent pixels around the image.' - }, - "button": { - "click_event": { - "target": "Node receives a click event?", - "component": "Component receives a click event?", - "handler": "What method is called on the click event?", - "customEventData": "The extra event data passed to the event handler, it's passed in as the last argument in the event handler. " + 'COMPONENT': { + "help_url": { + "audiosource": "http://docs.cocos.com/creator/manual/en/components/audiosource.html", + "animation": "http://docs.cocos.com/creator/manual/en/components/animation.html", + "sprite": "http://docs.cocos.com/creator/manual/en/components/sprite.html", + "label": "http://docs.cocos.com/creator/manual/en/components/label.html", + "canvas": "http://docs.cocos.com/creator/manual/en/components/canvas.html", + "spine": "http://docs.cocos.com/creator/manual/en/components/spine.html", + "widget": "http://docs.cocos.com/creator/manual/en/components/widget.html", + "button": "http://docs.cocos.com/creator/manual/en/components/button.html", + "progressbar": "http://docs.cocos.com/creator/manual/en/components/progress.html", + "mask": "http://docs.cocos.com/creator/manual/en/components/mask.html", + "scrollview": "http://docs.cocos.com/creator/manual/en/components/scrollview.html", + "scrollbar": "http://docs.cocos.com/creator/manual/en/components/scrollbar.html", + "layout": "http://docs.cocos.com/creator/manual/en/components/layout.html", + "tiledmap": "http://docs.cocos.com/creator/manual/en/components/tiledmap.html", + "editbox": "http://docs.cocos.com/creator/manual/en/components/editbox.html", + "videoplayer": "http://docs.cocos.com/creator/manual/en/components/videoplayer.html", + "motionStreak": "http://docs.cocos.com/creator/manual/en/components/motion-streak.html", + "richtext": "http://docs.cocos.com/creator/manual/en/components/richtext.html", + "pageview": "http://docs.cocos.com/creator/manual/en/components/pageview.html", + "pageviewIndicator": "http://docs.cocos.com/creator/manual/en/components/pageviewindicator.html", + "toggle": "http://docs.cocos.com/creator/manual/en/components/toggle.html", + "toggleGroup": "http://docs.cocos.com/creator/manual/en/components/toggleGroup.html", + "toggleContainer": "http://docs.cocos.com/creator/manual/en/components/toggleContainer.html", + "slider": "http://docs.cocos.com/creator/manual/en/components/slider.html", + "block_input_events": "http://docs.cocos.com/creator/manual/en/components/block-input-events.html", + "wx_subcontext_view": "http://docs.cocos.com/creator/manual/en/publish/publish-wechatgame-sub-domain.html" }, - "interactable": "Interactive button? When this one is not selected, the button is in a disabled state", - "transition": "Transition Type: when the state changes", - "normal_color": "Button color", - "pressed_color": "Button color when pressed", - "hover_color": "Button color when the mouse hovers over it", - "disabled_color": "Button color when disabled", - "duration": "How long until the button color/scale transitions to a new color?", - "zoom_scale": "When user press the button, the button will zoom to a scale.The final scale of the button equals (button original scale * zoomScale), zoomScale could be negative value.", - "auto_gray_effect": "When this flag is true, Button target sprite will turn gray when interactable is false.", - "normal_sprite": "The Sprite that is used when the button is in a normal sate.", - "pressed_sprite": "The Sprite that is used when the button is in a pressed sate.", - "hover_sprite": "The Sprite that is used when the button is hovered over.", - "disabled_sprite": "The Sprite that is used when the button is in a disabled sate.", - "target": "reference to the Sprite as button's background. When the state of the button changes the sprite's color or spriteFrame will be updated.", - "click_events": "What method is called on the click event?" - }, - "canvas": { - "design_resolution": "The resolution of the assets used in the game, in pixels.", - "fit_height": "Canvas allows designers to automatically scale the resolution to the full height of devices screen", - "fit_width": "Canvas allows designers to automatically scale the resolution to the full width of devices screen" - }, - "label": { - "string": "Text of the Label", - "horizontal_align": "Horizontal alignment", - "vertical_align": "Vertical alignment", - "font_size": "Font size, in points", - "font_family": "Font family name", - "line_height": "Line height, in points", - "overflow": "Text layout modes: \n 1. CLAMP: text nodes outside the bounding box will be truncated \n 2. SHRINK: automatically shrink text box according to the constraint node \n 3. RESIZE: Automatically updates the Node based on heightof the text.", - "wrap": "Wrap text?", - "font": "What font to use", - "system_font": "Whether to use the system default font" - }, - "progress": { - "bar_sprite": "A progress bar is displayed with the Sprite node that can dynamically change the size", - "mode": "Horizontal or Vertical progress bar?", - "total_length": "Length of progress bar. The maximum length of 100", - "progress": "Current progress indicator, ranging from 0-1", - "reverse": "Can the progress bar update negatively (i.e go backwards)" - }, - "scrollbar": { - "handle": "reference to the interactive bar sprite", - "direction": "Scroll direction", - "auto_hide": "Hide scroll bar when it is not scrolling?", - "auto_hide_time": "How long to wait to hide the scroll bar when it is not scrolling?" - }, - "scrollview": { - "content": "A scrollable display of the Nodes content", - "horizontal": "Horizontal scroll", - "vertical": "Vertical scroll", - "inertia": "Use intertia when scrolling? (or just let your finger do all the work?)", - "brake": "When using interia scrolling what to do when the user stops touching? 0 never stop, 1 stop immediately", - "elastic": "Use elastic scrolling?", - "bounce_time": "When using elastic scrolling how long to rebound afterwards?", - "horizontal_bar": "Horizontal scrollbar", - "vertical_bar": "Vertical scrollbar", - "bounceDuration": 'The elapse time of bouncing back. A value of 0 will bounce back immediately', - "scrollEvents": 'Scrollview events callback', - "cancelInnerEvents": 'If cancelInnerEvents is set to true, the scroll behavior will cancel touch events on inner content nodes' - }, - 'pageview': { - "sizeMode": 'Specify the size type of each page in PageView', - "direction": 'The page view direction', - "scrollThreshold": 'The scroll threshold value, when drag exceeds this value, release the next page will automatically scroll, less than the restore', - "pageTurningEventTiming": 'Change the AutoScroll stop epsilon value of PageView, change this value could adjust the PageView\'s event triggering timing.', - "indicator": 'The Page View Indicator', - "pageTurningSpeed": 'The time required to turn over a page. unit: second', - "pageEvents": 'PageView events callback', - "autoPageTurningThreshold": 'Auto page turning velocity threshold. When users swipe the PageView quickly, it will calculate a velocity based on the scroll distance and time, if the calculated velocity is larger than the threshold, then it will trigger page turning' - }, - 'pageview_indicator': { - 'spriteFrame': 'The spriteFrame for each element', - 'direction': 'The location direction of PageViewIndicator', - 'cell_size': 'The cellSize for each element', - 'spacing': 'The distance between each element' - }, - 'toggle': { - "interactable": "Interactive Toggle? When this one is not selected, the Toggle is in a disabled state", - "transition": "Transition Type: when the state changes", - "normal_color": "Toggle color", - "pressed_color": "Toggle color when pressed", - "hover_color": "Toggle color when the mouse hovers over it", - "disabled_color": "Toggle color when disabled", - "duration": "How long until the Toggle color/scale transitions to a new color?", - "zoom_scale": "When user press the Toggle, the Toggle will zoom to a scale.The final scale of the Toggle equals (Toggle original scale * zoomScale), zoomScale could be negative value.", - "auto_gray_effect": "When this flag is true, Toggle target sprite will turn gray when interactable is false.", - "normal_sprite": "The Sprite that is used when the Toggle is in a normal sate.", - "pressed_sprite": "The Sprite that is used when the Toggle is in a pressed sate.", - "hover_sprite": "The Sprite that is used when the Toggle is hovered over.", - "disabled_sprite": "The Sprite that is used when the Toggle is in a disabled sate.", - "target": "reference to the Sprite as Toggle's background. When the state of the button changes the sprite's color or spriteFrame will be updated.", - 'isChecked': 'If this flag is true, the associated checkMark sprite component will be enabled, otherwise the checkMark will be disabled.', - 'checkMark': 'The Sprite component displayed when Toggle is checked.', - 'toggleGroup': 'The toggle group which the toggle belongs to. When it is null, the toggle is a CheckBox. Otherwise, the toggle is a RadioButton.' - }, - 'toggle_group': { - 'allowSwitchOff': "If this setting is true, a toggle could be switched off and on when pressed.If it is false, it will make sure there is always only one toggle could be switched on and the already switched on toggle can't be switched off." - }, - 'slider': { - 'handle': 'The "handle" part of the slider', - 'direction': 'The slider direction', - 'progress': 'The current progress of the slider. The valid value is between 0-1', - 'slideEvents': 'The slider events callback' - }, - "widget": { - "target": 'Specifies an alignment target that can only be one of the parent nodes of the current node. The default value is null, and when null, indicates the current parent', - "align_top": "Top edge alignment of the parent Node", - "align_bottom": "Bottom edge alignment of the parent Node", - "align_left": "Left edge alignment of the parent Node", - "align_right": "Right edge alignment of the parent Node", - "align_h_center": "Align to the horizontal midpoint of the parent Node", - "align_v_center": "Align to the vertical midpoint of the parent Node", - "align_mode": "Specifies the alignment mode of the Widget, which determines when the widget should refresh at runtime.", - "top": "Top edge postion in pixels. This can be a percentage and a positive or negative value", - "bottom": "Bottom edge postion in pixels. This can be a percentage and a positive or negative value", - "left": "Left edge postion in pixels. This can be a percentage and a positive or negative value", - "right": "Right edge postion in pixels. This can be a percentage and a positive or negative value", - 'horizontal_center': 'Horizontal midpoint offset in pixels, This can be a percentage and a positive or negative value', - 'vertical_center': 'Vertical midpoint offset in pixels, This can be a percentage and a positive or negative value' - }, - "layout": { - "layout_type": "Automatic layout mode: \n 1. NONE, no automatic arrangement of child Nodes \n 2. HORIZONTAL, automatic horizontal arrangement of child Nodes \n 3. VERTICAL, automatic vertical arrangement of child Nodes\n 4. GRID, automatic grid arrangement of child Nodes", - "resize_mode": "Automatic resize mode: \n 1. NONE, no resize of both child Nodes and container. \n 2. CHILDREN, resize child Nodes. \n 3. CONTAINER, resize container Node.", - 'padding_left': 'Use a padding between left sides of the Node', - 'padding_right': 'Use a padding between right sides of the Node', - 'padding_top': 'Use a padding between top sides of the Node', - 'padding_bottom': 'Use a padding between bottom sides of the Node', - "space_x": "The horizontal distance between adjacent child Nodes", - "space_y": "The vertical distance between adjacent child Nodes", - "vertical_direction": "Vertically align in the direction of the child Nodes: \n 1. TOP_TO_BOTTOM, \n 2. BOTTOM_TO_TOP", - "horizontal_direction": "Horizontally align in the direction of the child Nodes: \n 1. LEFT_TO_RIGHT \n 2. RIGHT_TO_LEFT", - "cell_size": "In Grid layout, the size of each child element.", - "start_axis": "In Grid layout, the arrangement direction of children elements." - }, - "particle": { - "export_title": "Export custom particle data to plist file.", - "export": "Export", - "export_error": "This resource does not support exports outside of the project", - "sync": "Sync", - 'sync_tips': "Synchronize the parameters in the File to Custom" - }, - "editbox": { - "string": "The initial input text of EditBox.", - "backgroundImage": "The background image of EditBox.", - "returnType": "The keyboard return type of EditBox. This is useful for keyboard of mobile device.", - "input_flag": "Specify the input flag: password or capitalize word. ", - "input_mode": "Specify the input mode: multiline or single line.", - "font_size": "The font size of input label.", - "line_height": "The line height of input label.", - "stay_on_top": "Set to true and the input is always visible and be on top of the game view", - "tab_index": "Set the tabIndex of the DOM input element, only useful on Web.", - "font_color": "The font color of input label.", - "placeholder": "The content string of placeholder.", - "placeholder_font_size": "The font size of placeholder label.", - "placeholder_font_color": "The font color of placeholder label.", - "max_length": "The maximize input characters." - }, - "videoplayer": { - "resourceType": "The resource type of VideoPlayer, currently support remote URL and local videos.", - "url": "The remote URL of video.", - "video": "The local video full path.", - "volume": "The volume of the video.(0.0 ~ 1.0)", - "mute": "Mutes the VideoPlayer. Mute sets the volume=0, Un-Mute restore the original volume.", - "currentTime": "The start time when video start to play.", - "keepAspectRatio": "Whether keep the original video's aspect ratio.", - "isFullscreen": "Whether keep the video fullscreen when it is playing.", - }, - "webview": { - "url": "A given URL to be loaded by the WebView, it should have a http or https prefix." - }, - "richtext": { - "string": "Text of the RichText, you could use BBcode in the string", - "horizontal_align": "Horizontal alignment", - "font_size": "Font size, in points", - "font": "Custom TTF font of RichText", - "line_height": "Line height, in points", - "max_width": "The maximize width of RichText, pass 0 means not limit the maximize width.", - "image_atlas": "The image atlas for the img tag. For each src value in the img tag, there should be a valid spriteFrame in the image atlas.", - "handleTouchEvent": "Once checked, the RichText will block all input events (mouse and touch) within the bounding box of the node, preventing the input from penetrating into the underlying node." - }, - "skeleton": { - "skeleton_data": "The skeleton data contains the skeleton information, drag the json file exported from Spine to get started.", - "default_skin": "Choose the default skin.", - "animation": "The name of current playing animation.", - "loop": "Whether loop current animation", - "time_scale": "The time scale of animations of this skeleton", - "debug_slots": "Indicates whether show debug slots.", - "debug_bones": "Indicates whether show debug bones.", - "premultipliedAlpha": "Indicates whether to enable premultiplied alpha.", - }, - "dragon_bones": { - "dragon_bones_asset": "The json data contains the DragonBones information, drag the json file exported from DragonBones to get started.", - "dragon_bones_atlas_asset": "The json data contains the Texture information, drag the json file exported from DragonBones to get started.", - "armature_name": "The name of current armature.", - "animation_name": "The name of current playing animation.", - "time_scale": "The time scale of this armature.", - "play_times": "The play times of the default animation.\n-1 means using the value of config file\n0 means repeat for ever\n>0 means repeat times", - "debug_bones": "Indicates whether open debug bones" - }, - 'motionStreak': { - 'fadeTime': "Trail fragment fade time, in seconds", - 'minSeg': "The minimum distance between of the trail", - 'stroke': "The width of the trail", - 'texture': "The texture of the trail", - 'color': "The color of the trail", - 'fastMode': "Whether to enable fast mode" - }, - "missing_scirpt": { - "error_compiled": "Error on executing script, or the script reference is missing. Please check error log carefully and correct/recover your script. The component will be restored once scripting error is gone. If you no long need the missing script, please remove this component manually.", - "error_not_compiled": "Error on compiling script. Please check error log carefully and correct your script. This component will be restored once compiling error is gone." - }, - 'collider': { - 'editing': 'Edit this collider component', - 'category': 'Collider component category', - 'mask': 'The collider mask can collide with this collider' - }, - 'particle_system': { - 'preview': 'Play particle in edit mode', - 'custom': 'If set custom to true, then use custom properties insteadof read particle file', - 'file': 'The plist file', - 'spriteFrame': 'SpriteFrame of Particle System', - 'texture': 'Texture of Particle System, readonly, please use spriteFrame to setup new texture', - 'particleCount': 'Current quantity of particles that are being simulated', - 'srcBlendFactor': 'Specify the source Blend Factor', - 'dstBlendFactor': 'Specify the destination Blend Factor', - 'playOnLoad': 'If set to true, the particle system will automatically start playing on onLoad', - 'autoRemoveOnFinish': 'Indicate whether the owner node will be auto-removed when it has no particles left', - 'duration': 'How many seconds the emitter wil run. -1 means forever', - 'emissionRate': 'Emission rate of the particles', - 'life': 'Life and variation of each particle setter', - 'totalParticles': 'Maximum particles of the system', - 'startColor': 'Start color of each particle', - 'startColorVar': 'Variation of the start color', - 'endColor': 'Ending color of each particle', - 'endColorVar': 'Variation of the end color', - 'angle': 'Angle and variation of each particle setter', - 'startSize': 'Start size and variation in pixels of each particle', - 'endSize': 'End size and variation in pixels of each particle', - 'startSpin': 'Start angle and variation of each particle', - 'endSpin': 'End angle and variation of each particle', - 'sourcePos': 'Source position of the emitter', - 'posVar': 'Variation of source position', - 'positionType': 'Particles movement type', - 'emitterMode': 'Particles emitter modes', - 'gravity': 'Gravity of the emitter', - 'speed': 'Speed and variation of the emitter', - 'tangentialAccel': 'Tangential acceleration and variation of each particle. Only available in Gravity mode ', - 'radialAccel': 'Acceleration and variation of each particle. Only available in Gravity mode', - 'rotationIsDir': 'Indicate whether the rotation of each particle equals to its direction. Only available in Gravity mode', - 'startRadius': 'Starting radius and variation of the particles. Only available in Radius mode', - 'endRadius': 'Ending radius and variation of the particles. Only available in Radius mode', - 'rotatePerS': 'Number of degress to rotate a particle around the source pos per second and variation. Only available in Radius mode', - }, - "mask": { - 'type': 'The mask type', - 'spriteFrame': 'The mask image', - 'inverted': 'The Reverse mask (Not supported Canvas Mode)', - 'alphaThreshold': 'The alpha threshold,The content is drawn only where the stencil have pixel with alpha greater than the alphaThreshold (Not supported Canvas Mode)', - 'segements': 'The segements for ellipse mask' - }, - 'physics': { - 'rigidbody': { - 'enabledContactListener': 'Should enabled contact listener. When a collision is trigger, the collision callback will only be called when enabled contact listener.', - 'bullet': 'Is this a fast moving body that should be prevented from tunneling through other moving bodies?', - 'type': 'Rigidbody type : Static, Kinematic, Dynamic or Animated.', - 'allowSleep': 'Set this flag to false if this body should never fall asleep. Note that this increases CPU usage.', - 'gravityScale': 'Scale the gravity applied to this body.', - 'linearDamping': 'Linear damping is use to reduce the linear velocity. The damping parameter can be larger than 1, but the damping effect becomes sensitive to the time step when the damping parameter is large.', - 'angularDamping': 'Angular damping is use to reduce the angular velocity. The damping parameter can be larger than 1 but the damping effect becomes sensitive to the time step when the damping parameter is large.', - 'linearVelocity': 'The linear velocity of the body\'s origin in world co-ordinates', - 'angularVelocity': 'The angular velocity of the body.', - 'fixedRotation': 'Should this body be prevented from rotating?', - 'awake': 'Is this body initially awake or sleeping?' + "animation": { + "default_clip": "When checking, the deault animation clip is automatically played.", + "clips": "You can access and play animation clips via a script", + "play_on_load": "Automatically play animation clip with the scene is loaded" }, - 'physics_collider': { - 'density': 'The density', - 'sensor': 'A sensor collider collects contact information but never generates a collision response', - 'friction': 'The friction coefficient, usually in the range [0,1].', - 'restitution': 'The restitution (elasticity) usually in the range [0,1].', - 'anchor': 'The anchor of the rigidbody.', - 'connectedAnchor': 'The anchor of the connected rigidbody.', - 'connectedBody': 'The rigidbody to which the other end of the joint is attached.', - 'collideConnected': 'Should the two rigid bodies connected with this joint collide with each other?', - 'distance': 'The distance separating the two ends of the joint.', - 'frequency': 'The spring frequency.', - 'dampingRatio': 'The damping ratio.', - 'linearOffset': 'The linear offset from connected rigidbody to rigidbody.', - 'angularOffset': 'The angular offset from connected rigidbody to rigidbody.', - 'maxForce': 'The maximum force can be applied to rigidbody.', - 'maxTorque': 'The maximum torque can be applied to rigidbody.', - 'correctionFactor': 'The position correction factor in the range [0,1].', - 'mouseRegion': 'The node used to register touch evnet. If this is null, it will be the joint\'s node.', - 'target': 'The target point. The mouse joint will move choosed rigidbody to target point.', - 'localAxisA': 'The local joint axis relative to rigidbody.', - 'enableLimit': 'Enable joint distance limit?', - 'enableMotor': 'Enable joint motor?', - 'lowerLimit': 'The lower joint limit.', - 'upperLimit': 'The upper joint limit.', - 'maxMotorForce': 'The maxium force can be applied to rigidbody to rearch the target motor speed.', - 'motorSpeed': 'The expected motor speed.', - 'referenceAngle': 'The reference angle. An angle between bodies considered to be zero for the joint angle.', - 'lowerAngle': 'The lower angle.', - 'upperAngle': 'The upper angle.', - 'maxMotorTorque': 'The maxium torque can be applied to rigidbody to rearch the target motor speed.', - 'maxLength': 'The max length.', - 'offset': 'Position offset', - 'size': 'Box size', - 'radius': 'Circle radius', - 'tag': 'Tag. If a node has several collider components, you can judge which type of collider is collided according to the tag.', - 'points': 'Polygon points' + "audio": { + "clip": "About to be played.", + "volume": "How loud to play an audio clip", + "mute": "Mute. Audio may continue to play, however ther will be no sound.", + "loop": "Loop audio clip? (repeat it over and over)", + "play_on_load": "Automatically play audio clip with the game is running?" + }, + "sprite": { + "sprite_frame": "SpriteFrame image to use", + "atlas": "Atlas that the image belongs to", + "type": "Rendering Mode: Simple, Sliced, Tiled or Filled", + "original_size": "Use the Images original size as the Node size?", + "edit_button": "Edit", + "select_button": "Select In Atlas", + "select_tooltip": "Choose Atlas", + "edit_tooltip": "Open Sprite Editor, set squares and other data", + 'fill_type': 'The direction of filling, choose from Horizontal, Vertical and Radial', + 'fill_center': 'For radial filling, set the center of the circle, value range is 0 to 1', + 'fill_start': 'The normalized value indicate where to start filling', + 'fill_range': 'The normalizad value indicate how much of the sprite we want to show', + 'src_blend_factor': 'The source image blend mode', + 'dst_blend_factor': 'The destination image blend mode', + 'size_mode': 'Set the size of the node which Sprite component is on. CUSTOM for setting width and height manually;TRIMMED to use image size with transparent pixels trimmed; RAW to use image size without trimming.', + 'trim': 'Whether to render transparent pixels around image in node\'s bounding box. If you check this option the boudning box will not include transparent pixels around the image.' + }, + "button": { + "click_event": { + "target": "Node receives a click event?", + "component": "Component receives a click event?", + "handler": "What method is called on the click event?", + "customEventData": "The extra event data passed to the event handler, it's passed in as the last argument in the event handler. " + }, + "interactable": "Interactive button? When this one is not selected, the button is in a disabled state", + "transition": "Transition Type: when the state changes", + "normal_color": "Button color", + "pressed_color": "Button color when pressed", + "hover_color": "Button color when the mouse hovers over it", + "disabled_color": "Button color when disabled", + "duration": "How long until the button color/scale transitions to a new color?", + "zoom_scale": "When user press the button, the button will zoom to a scale.The final scale of the button equals (button original scale * zoomScale), zoomScale could be negative value.", + "auto_gray_effect": "When this flag is true, Button target sprite will turn gray when interactable is false.", + "normal_sprite": "The Sprite that is used when the button is in a normal sate.", + "pressed_sprite": "The Sprite that is used when the button is in a pressed sate.", + "hover_sprite": "The Sprite that is used when the button is hovered over.", + "disabled_sprite": "The Sprite that is used when the button is in a disabled sate.", + "target": "reference to the Sprite as button's background. When the state of the button changes the sprite's color or spriteFrame will be updated.", + "click_events": "What method is called on the click event?" + }, + "canvas": { + "design_resolution": "The resolution of the assets used in the game, in pixels.", + "fit_height": "Canvas allows designers to automatically scale the resolution to the full height of devices screen", + "fit_width": "Canvas allows designers to automatically scale the resolution to the full width of devices screen" + }, + "label": { + "string": "Text of the Label", + "horizontal_align": "Horizontal alignment", + "vertical_align": "Vertical alignment", + "font_size": "Font size, in points", + "font_family": "Font family name", + "line_height": "Line height, in points", + "overflow": "Text layout modes: \n 1. CLAMP: text nodes outside the bounding box will be truncated \n 2. SHRINK: automatically shrink text box according to the constraint node \n 3. RESIZE: Automatically updates the Node based on heightof the text.", + "wrap": "Wrap text?", + "font": "What font to use", + "system_font": "Whether to use the system default font" + }, + "progress": { + "bar_sprite": "A progress bar is displayed with the Sprite node that can dynamically change the size", + "mode": "Horizontal or Vertical progress bar?", + "total_length": "Length of progress bar. The maximum length of 100", + "progress": "Current progress indicator, ranging from 0-1", + "reverse": "Can the progress bar update negatively (i.e go backwards)" + }, + "scrollbar": { + "handle": "reference to the interactive bar sprite", + "direction": "Scroll direction", + "auto_hide": "Hide scroll bar when it is not scrolling?", + "auto_hide_time": "How long to wait to hide the scroll bar when it is not scrolling?" + }, + "scrollview": { + "content": "A scrollable display of the Nodes content", + "horizontal": "Horizontal scroll", + "vertical": "Vertical scroll", + "inertia": "Use intertia when scrolling? (or just let your finger do all the work?)", + "brake": "When using interia scrolling what to do when the user stops touching? 0 never stop, 1 stop immediately", + "elastic": "Use elastic scrolling?", + "bounce_time": "When using elastic scrolling how long to rebound afterwards?", + "horizontal_bar": "Horizontal scrollbar", + "vertical_bar": "Vertical scrollbar", + "bounceDuration": 'The elapse time of bouncing back. A value of 0 will bounce back immediately', + "scrollEvents": 'Scrollview events callback', + "cancelInnerEvents": 'If cancelInnerEvents is set to true, the scroll behavior will cancel touch events on inner content nodes' + }, + 'pageview': { + "sizeMode": 'Specify the size type of each page in PageView', + "direction": 'The page view direction', + "scrollThreshold": 'The scroll threshold value, when drag exceeds this value, release the next page will automatically scroll, less than the restore', + "pageTurningEventTiming": 'Change the AutoScroll stop epsilon value of PageView, change this value could adjust the PageView\'s event triggering timing.', + "indicator": 'The Page View Indicator', + "pageTurningSpeed": 'The time required to turn over a page. unit: second', + "pageEvents": 'PageView events callback', + "autoPageTurningThreshold": 'Auto page turning velocity threshold. When users swipe the PageView quickly, it will calculate a velocity based on the scroll distance and time, if the calculated velocity is larger than the threshold, then it will trigger page turning' + }, + 'pageview_indicator': { + 'spriteFrame': 'The spriteFrame for each element', + 'direction': 'The location direction of PageViewIndicator', + 'cell_size': 'The cellSize for each element', + 'spacing': 'The distance between each element' + }, + 'toggle': { + "interactable": "Interactive Toggle? When this one is not selected, the Toggle is in a disabled state", + "transition": "Transition Type: when the state changes", + "normal_color": "Toggle color", + "pressed_color": "Toggle color when pressed", + "hover_color": "Toggle color when the mouse hovers over it", + "disabled_color": "Toggle color when disabled", + "duration": "How long until the Toggle color/scale transitions to a new color?", + "zoom_scale": "When user press the Toggle, the Toggle will zoom to a scale.The final scale of the Toggle equals (Toggle original scale * zoomScale), zoomScale could be negative value.", + "auto_gray_effect": "When this flag is true, Toggle target sprite will turn gray when interactable is false.", + "normal_sprite": "The Sprite that is used when the Toggle is in a normal sate.", + "pressed_sprite": "The Sprite that is used when the Toggle is in a pressed sate.", + "hover_sprite": "The Sprite that is used when the Toggle is hovered over.", + "disabled_sprite": "The Sprite that is used when the Toggle is in a disabled sate.", + "target": "reference to the Sprite as Toggle's background. When the state of the button changes the sprite's color or spriteFrame will be updated.", + 'isChecked': 'If this flag is true, the associated checkMark sprite component will be enabled, otherwise the checkMark will be disabled.', + 'checkMark': 'The Sprite component displayed when Toggle is checked.', + 'toggleGroup': 'The toggle group which the toggle belongs to. When it is null, the toggle is a CheckBox. Otherwise, the toggle is a RadioButton.' + }, + 'toggle_group': { + 'allowSwitchOff': "If this setting is true, a toggle could be switched off and on when pressed.If it is false, it will make sure there is always only one toggle could be switched on and the already switched on toggle can't be switched off." + }, + 'slider': { + 'handle': 'The "handle" part of the slider', + 'direction': 'The slider direction', + 'progress': 'The current progress of the slider. The valid value is between 0-1', + 'slideEvents': 'The slider events callback' + }, + "widget": { + "target": 'Specifies an alignment target that can only be one of the parent nodes of the current node. The default value is null, and when null, indicates the current parent', + "align_top": "Top edge alignment of the parent Node", + "align_bottom": "Bottom edge alignment of the parent Node", + "align_left": "Left edge alignment of the parent Node", + "align_right": "Right edge alignment of the parent Node", + "align_h_center": "Align to the horizontal midpoint of the parent Node", + "align_v_center": "Align to the vertical midpoint of the parent Node", + "align_mode": "Specifies the alignment mode of the Widget, which determines when the widget should refresh at runtime.", + "top": "Top edge postion in pixels. This can be a percentage and a positive or negative value", + "bottom": "Bottom edge postion in pixels. This can be a percentage and a positive or negative value", + "left": "Left edge postion in pixels. This can be a percentage and a positive or negative value", + "right": "Right edge postion in pixels. This can be a percentage and a positive or negative value", + 'horizontal_center': 'Horizontal midpoint offset in pixels, This can be a percentage and a positive or negative value', + 'vertical_center': 'Vertical midpoint offset in pixels, This can be a percentage and a positive or negative value' + }, + "layout": { + "layout_type": "Automatic layout mode: \n 1. NONE, no automatic arrangement of child Nodes \n 2. HORIZONTAL, automatic horizontal arrangement of child Nodes \n 3. VERTICAL, automatic vertical arrangement of child Nodes\n 4. GRID, automatic grid arrangement of child Nodes", + "resize_mode": "Automatic resize mode: \n 1. NONE, no resize of both child Nodes and container. \n 2. CHILDREN, resize child Nodes. \n 3. CONTAINER, resize container Node.", + 'padding_left': 'Use a padding between left sides of the Node', + 'padding_right': 'Use a padding between right sides of the Node', + 'padding_top': 'Use a padding between top sides of the Node', + 'padding_bottom': 'Use a padding between bottom sides of the Node', + "space_x": "The horizontal distance between adjacent child Nodes", + "space_y": "The vertical distance between adjacent child Nodes", + "vertical_direction": "Vertically align in the direction of the child Nodes: \n 1. TOP_TO_BOTTOM, \n 2. BOTTOM_TO_TOP", + "horizontal_direction": "Horizontally align in the direction of the child Nodes: \n 1. LEFT_TO_RIGHT \n 2. RIGHT_TO_LEFT", + "cell_size": "In Grid layout, the size of each child element.", + "start_axis": "In Grid layout, the arrangement direction of children elements." + }, + "particle": { + "export_title": "Export custom particle data to plist file.", + "export": "Export", + "export_error": "This resource does not support exports outside of the project", + "sync": "Sync", + 'sync_tips': "Synchronize the parameters in the File to Custom" + }, + "editbox": { + "string": "The initial input text of EditBox.", + "backgroundImage": "The background image of EditBox.", + "returnType": "The keyboard return type of EditBox. This is useful for keyboard of mobile device.", + "input_flag": "Specify the input flag: password or capitalize word. ", + "input_mode": "Specify the input mode: multiline or single line.", + "font_size": "The font size of input label.", + "line_height": "The line height of input label.", + "stay_on_top": "Set to true and the input is always visible and be on top of the game view", + "tab_index": "Set the tabIndex of the DOM input element, only useful on Web.", + "font_color": "The font color of input label.", + "placeholder": "The content string of placeholder.", + "placeholder_font_size": "The font size of placeholder label.", + "placeholder_font_color": "The font color of placeholder label.", + "max_length": "The maximize input characters." + }, + "videoplayer": { + "resourceType": "The resource type of VideoPlayer, currently support remote URL and local videos.", + "url": "The remote URL of video.", + "video": "The local video full path.", + "volume": "The volume of the video.(0.0 ~ 1.0)", + "mute": "Mutes the VideoPlayer. Mute sets the volume=0, Un-Mute restore the original volume.", + "currentTime": "The start time when video start to play.", + "keepAspectRatio": "Whether keep the original video's aspect ratio.", + "isFullscreen": "Whether keep the video fullscreen when it is playing.", + }, + "webview": { + "url": "A given URL to be loaded by the WebView, it should have a http or https prefix." + }, + "richtext": { + "string": "Text of the RichText, you could use BBcode in the string", + "horizontal_align": "Horizontal alignment", + "font_size": "Font size, in points", + "font": "Custom TTF font of RichText", + "line_height": "Line height, in points", + "max_width": "The maximize width of RichText, pass 0 means not limit the maximize width.", + "image_atlas": "The image atlas for the img tag. For each src value in the img tag, there should be a valid spriteFrame in the image atlas.", + "handleTouchEvent": "Once checked, the RichText will block all input events (mouse and touch) within the bounding box of the node, preventing the input from penetrating into the underlying node." + }, + "skeleton": { + "skeleton_data": "The skeleton data contains the skeleton information, drag the json file exported from Spine to get started.", + "default_skin": "Choose the default skin.", + "animation": "The name of current playing animation.", + "loop": "Whether loop current animation", + "time_scale": "The time scale of animations of this skeleton", + "debug_slots": "Indicates whether show debug slots.", + "debug_bones": "Indicates whether show debug bones.", + "premultipliedAlpha": "Indicates whether to enable premultiplied alpha.", + }, + "dragon_bones": { + "dragon_bones_asset": "The json data contains the DragonBones information, drag the json file exported from DragonBones to get started.", + "dragon_bones_atlas_asset": "The json data contains the Texture information, drag the json file exported from DragonBones to get started.", + "armature_name": "The name of current armature.", + "animation_name": "The name of current playing animation.", + "time_scale": "The time scale of this armature.", + "play_times": "The play times of the default animation.\n-1 means using the value of config file\n0 means repeat for ever\n>0 means repeat times", + "debug_bones": "Indicates whether open debug bones" + }, + 'motionStreak': { + 'fadeTime': "Trail fragment fade time, in seconds", + 'minSeg': "The minimum distance between of the trail", + 'stroke': "The width of the trail", + 'texture': "The texture of the trail", + 'color': "The color of the trail", + 'fastMode': "Whether to enable fast mode" + }, + "missing_scirpt": { + "error_compiled": "Error on executing script, or the script reference is missing. Please check error log carefully and correct/recover your script. The component will be restored once scripting error is gone. If you no long need the missing script, please remove this component manually.", + "error_not_compiled": "Error on compiling script. Please check error log carefully and correct your script. This component will be restored once compiling error is gone." + }, + 'collider': { + 'editing': 'Edit this collider component', + 'category': 'Collider component category', + 'mask': 'The collider mask can collide with this collider' + }, + 'particle_system': { + 'preview': 'Play particle in edit mode', + 'custom': 'If set custom to true, then use custom properties insteadof read particle file', + 'file': 'The plist file', + 'spriteFrame': 'SpriteFrame of Particle System', + 'texture': 'Texture of Particle System, readonly, please use spriteFrame to setup new texture', + 'particleCount': 'Current quantity of particles that are being simulated', + 'srcBlendFactor': 'Specify the source Blend Factor', + 'dstBlendFactor': 'Specify the destination Blend Factor', + 'playOnLoad': 'If set to true, the particle system will automatically start playing on onLoad', + 'autoRemoveOnFinish': 'Indicate whether the owner node will be auto-removed when it has no particles left', + 'duration': 'How many seconds the emitter wil run. -1 means forever', + 'emissionRate': 'Emission rate of the particles', + 'life': 'Life and variation of each particle setter', + 'totalParticles': 'Maximum particles of the system', + 'startColor': 'Start color of each particle', + 'startColorVar': 'Variation of the start color', + 'endColor': 'Ending color of each particle', + 'endColorVar': 'Variation of the end color', + 'angle': 'Angle and variation of each particle setter', + 'startSize': 'Start size and variation in pixels of each particle', + 'endSize': 'End size and variation in pixels of each particle', + 'startSpin': 'Start angle and variation of each particle', + 'endSpin': 'End angle and variation of each particle', + 'sourcePos': 'Source position of the emitter', + 'posVar': 'Variation of source position', + 'positionType': 'Particles movement type', + 'emitterMode': 'Particles emitter modes', + 'gravity': 'Gravity of the emitter', + 'speed': 'Speed and variation of the emitter', + 'tangentialAccel': 'Tangential acceleration and variation of each particle. Only available in Gravity mode ', + 'radialAccel': 'Acceleration and variation of each particle. Only available in Gravity mode', + 'rotationIsDir': 'Indicate whether the rotation of each particle equals to its direction. Only available in Gravity mode', + 'startRadius': 'Starting radius and variation of the particles. Only available in Radius mode', + 'endRadius': 'Ending radius and variation of the particles. Only available in Radius mode', + 'rotatePerS': 'Number of degress to rotate a particle around the source pos per second and variation. Only available in Radius mode', + }, + "mask": { + 'type': 'The mask type', + 'spriteFrame': 'The mask image', + 'inverted': 'The Reverse mask (Not supported Canvas Mode)', + 'alphaThreshold': 'The alpha threshold,The content is drawn only where the stencil have pixel with alpha greater than the alphaThreshold (Not supported Canvas Mode)', + 'segements': 'The segements for ellipse mask' + }, + 'physics': { + 'rigidbody': { + 'enabledContactListener': 'Should enabled contact listener. When a collision is trigger, the collision callback will only be called when enabled contact listener.', + 'bullet': 'Is this a fast moving body that should be prevented from tunneling through other moving bodies?', + 'type': 'Rigidbody type : Static, Kinematic, Dynamic or Animated.', + 'allowSleep': 'Set this flag to false if this body should never fall asleep. Note that this increases CPU usage.', + 'gravityScale': 'Scale the gravity applied to this body.', + 'linearDamping': 'Linear damping is use to reduce the linear velocity. The damping parameter can be larger than 1, but the damping effect becomes sensitive to the time step when the damping parameter is large.', + 'angularDamping': 'Angular damping is use to reduce the angular velocity. The damping parameter can be larger than 1 but the damping effect becomes sensitive to the time step when the damping parameter is large.', + 'linearVelocity': 'The linear velocity of the body\'s origin in world co-ordinates', + 'angularVelocity': 'The angular velocity of the body.', + 'fixedRotation': 'Should this body be prevented from rotating?', + 'awake': 'Is this body initially awake or sleeping?' + }, + 'physics_collider': { + 'density': 'The density', + 'sensor': 'A sensor collider collects contact information but never generates a collision response', + 'friction': 'The friction coefficient, usually in the range [0,1].', + 'restitution': 'The restitution (elasticity) usually in the range [0,1].', + 'anchor': 'The anchor of the rigidbody.', + 'connectedAnchor': 'The anchor of the connected rigidbody.', + 'connectedBody': 'The rigidbody to which the other end of the joint is attached.', + 'collideConnected': 'Should the two rigid bodies connected with this joint collide with each other?', + 'distance': 'The distance separating the two ends of the joint.', + 'frequency': 'The spring frequency.', + 'dampingRatio': 'The damping ratio.', + 'linearOffset': 'The linear offset from connected rigidbody to rigidbody.', + 'angularOffset': 'The angular offset from connected rigidbody to rigidbody.', + 'maxForce': 'The maximum force can be applied to rigidbody.', + 'maxTorque': 'The maximum torque can be applied to rigidbody.', + 'correctionFactor': 'The position correction factor in the range [0,1].', + 'mouseRegion': 'The node used to register touch evnet. If this is null, it will be the joint\'s node.', + 'target': 'The target point. The mouse joint will move choosed rigidbody to target point.', + 'localAxisA': 'The local joint axis relative to rigidbody.', + 'enableLimit': 'Enable joint distance limit?', + 'enableMotor': 'Enable joint motor?', + 'lowerLimit': 'The lower joint limit.', + 'upperLimit': 'The upper joint limit.', + 'maxMotorForce': 'The maxium force can be applied to rigidbody to rearch the target motor speed.', + 'motorSpeed': 'The expected motor speed.', + 'referenceAngle': 'The reference angle. An angle between bodies considered to be zero for the joint angle.', + 'lowerAngle': 'The lower angle.', + 'upperAngle': 'The upper angle.', + 'maxMotorTorque': 'The maxium torque can be applied to rigidbody to rearch the target motor speed.', + 'maxLength': 'The max length.', + 'offset': 'Position offset', + 'size': 'Box size', + 'radius': 'Circle radius', + 'tag': 'Tag. If a node has several collider components, you can judge which type of collider is collided according to the tag.', + 'points': 'Polygon points' + } + }, + 'block_input_events': { + 'brief_help': 'This component will block all input events, preventing the input from penetrating into the underlying node, typically for the background of the top UI.' + }, + 'tiledtile': { + 'row': 'Specify the TiledTile horizontal coordinate,use map tile as the unit.', + 'column': 'Specify the TiledTile vertical coordinate,use map tile as the unit.', + 'gid': 'Specify the TiledTile gid.', + 'layer': 'Specify which TiledLayer the TiledTile belong to.' } - }, - 'block_input_events': { - 'brief_help': 'This component will block all input events, preventing the input from penetrating into the underlying node, typically for the background of the top UI.' - }, - 'tiledtile': { - 'row': 'Specify the TiledTile horizontal coordinate,use map tile as the unit.', - 'column': 'Specify the TiledTile vertical coordinate,use map tile as the unit.', - 'gid': 'Specify the TiledTile gid.', - 'layer': 'Specify which TiledLayer the TiledTile belong to.' } }; \ No newline at end of file diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 6d12e3f7135..b14a127d202 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -1,392 +1,394 @@ module.exports = { - "help_url": { - "audiosource": "http://docs.cocos.com/creator/manual/zh/components/audiosource.html", - "animation": "http://www.cocos.com/docs/creator/components/animation.html", - "sprite": "http://www.cocos.com/docs/creator/components/sprite.html", - "label": "http://www.cocos.com/docs/creator/components/label.html", - "canvas": "http://www.cocos.com/docs/creator/components/canvas.html", - "spine": "http://www.cocos.com/docs/creator/components/spine.html", - "widget": "http://www.cocos.com/docs/creator/components/widget.html", - "button": "http://www.cocos.com/docs/creator/components/button.html", - "progressbar": "http://www.cocos.com/docs/creator/components/progress.html", - "mask": "http://www.cocos.com/docs/creator/components/mask.html", - "scrollview": "http://www.cocos.com/docs/creator/components/scrollview.html", - "scrollbar": "http://www.cocos.com/docs/creator/components/scrollbar.html", - "layout": "http://www.cocos.com/docs/creator/components/layout.html", - "tiledmap": "http://www.cocos.com/docs/creator/components/tiledmap.html", - "editbox": "http://www.cocos.com/docs/creator/components/editbox.html", - "videoplayer": "http://www.cocos.com/docs/creator/components/videoplayer.html", - "motionStreak": "http://www.cocos.com/docs/creator/components/motion-streak.html", - "richtext": "http://www.cocos.com/docs/creator/components/richtext.html", - "pageview": "http://www.cocos.com/docs/creator/components/pageview.html", - "pageviewIndicator": "http://docs.cocos.com/creator/manual/zh/components/pageviewindicator.html", - "toggle": "http://www.cocos.com/docs/creator/components/toggle.html", - "toggleGroup": "http://www.cocos.com/docs/creator/components/toggleGroup.html", - "toggleContainer": "http://www.cocos.com/docs/creator/components/toggleContainer.html", - "slider": "http://www.cocos.com/docs/creator/components/slider.html", - "block_input_events": "http://docs.cocos.com/creator/manual/zh/components/block-input-events.html", - "wx_subcontext_view": "http://docs.cocos.com/creator/manual/zh/publish/publish-wechatgame-sub-domain.html" - }, - 'animation': { - 'default_clip': '在勾选自动播放或调用 play() 时默认播放的动画 clip。', - 'clips': '通过脚本可以访问并播放的 AnimationClip 列表', - 'play_on_load': '是否在运行游戏后自动播放默认动画 clip。' - }, - 'audio': { - 'clip': '即将通过该组件播放的 AudioClip 引用', - 'volume': '通过该音源组件播放的声音的音量', - 'mute': '静音开关,静音的音源可以继续播放,但不会发出声音', - 'loop': '是否循环播放', - 'play_on_load': '是否在运行游戏后自动播放音源' - }, - 'sprite': { - 'sprite_frame': '渲染 Sprite 使用的 SpriteFrame 图片资源', - 'atlas': '图片资源所属的 Atlas 图集资源', - 'type': '渲染模式:\n - 普通(Simple):修改尺寸会整体拉伸图像,适用于序列帧动画和普通图像 \n' + - '- 九宫格(Sliced):修改尺寸时四个角的区域不会拉伸,适用于 UI 按钮和面板背景 \n' + - '- 平铺(Tiled):修改尺寸时会不断平铺原始大小的图片 \n' + - '- 填充(Filled):设置一定的填充起始位置和方向,能够以一定比率剪裁显示图片', - 'original_size': '是否使用图片资源的原始尺寸作为 Sprite 节点的 size', - 'edit_button': '编辑', - 'select_button': '选择', - 'select_tooltip': '选择 Atlas 中的其他 SpriteFrame', - 'edit_tooltip': '打开 Sprite 编辑器,设置九宫格等数据', - 'fill_type': '填充方向,可以选择横向(Horizontal),纵向(Vertical)和扇形(Radial)三种方向', - 'fill_center': '扇形填充时,指定扇形的中心点,取值范围 0 ~ 1', - 'fill_start': '填充起始位置,输入一个 0 ~ 1 之间的小数表示起始位置的百分比', - 'fill_range': '填充总量,取值范围 0 ~ 1 指定显示图像范围的百分比', - 'src_blend_factor': '混合显示两张图片时,源图片的取值模式', - 'dst_blend_factor': '混合显示两张图片时,目标图片的取值模式', - 'size_mode': '指定 Sprite 所在节点的尺寸,CUSTOM 表示自定义尺寸,TRIMMED 表示取原始图片剪裁透明像素后的尺寸,RAW 表示取原始图片未剪裁的尺寸', - 'trim': '节点约束框内是否包括透明像素区域,勾选此项会去除节点约束框内的透明区域' - }, - 'button': { - 'click_event': { - 'target': '接收点击事件的节点', - 'component': '接收点击事件的组件', - 'handler': '处理点击事件的方法', - "customEventData": "传给事件处理函数的额外参数,这个数据会当作最后一个参数传递给事件处理函数。" + 'COMPONENT': { + "help_url": { + "audiosource": "http://docs.cocos.com/creator/manual/zh/components/audiosource.html", + "animation": "http://docs.cocos.com/creator/manual/zh/components/animation.html", + "sprite": "http://docs.cocos.com/creator/manual/zh/components/sprite.html", + "label": "http://docs.cocos.com/creator/manual/zh/components/label.html", + "canvas": "http://docs.cocos.com/creator/manual/zh/components/canvas.html", + "spine": "http://docs.cocos.com/creator/manual/zh/components/spine.html", + "widget": "http://docs.cocos.com/creator/manual/zh/components/widget.html", + "button": "http://docs.cocos.com/creator/manual/zh/components/button.html", + "progressbar": "http://docs.cocos.com/creator/manual/zh/components/progress.html", + "mask": "http://docs.cocos.com/creator/manual/zh/components/mask.html", + "scrollview": "http://docs.cocos.com/creator/manual/zh/components/scrollview.html", + "scrollbar": "http://docs.cocos.com/creator/manual/zh/components/scrollbar.html", + "layout": "http://docs.cocos.com/creator/manual/zh/components/layout.html", + "tiledmap": "http://docs.cocos.com/creator/manual/zh/components/tiledmap.html", + "editbox": "http://docs.cocos.com/creator/manual/zh/components/editbox.html", + "videoplayer": "http://docs.cocos.com/creator/manual/zh/components/videoplayer.html", + "motionStreak": "http://docs.cocos.com/creator/manual/zh/components/motion-streak.html", + "richtext": "http://docs.cocos.com/creator/manual/zh/components/richtext.html", + "pageview": "http://docs.cocos.com/creator/manual/zh/components/pageview.html", + "pageviewIndicator": "http://docs.cocos.com/creator/manual/zh/components/pageviewindicator.html", + "toggle": "http://docs.cocos.com/creator/manual/zh/components/toggle.html", + "toggleGroup": "http://docs.cocos.com/creator/manual/zh/components/toggleGroup.html", + "toggleContainer": "http://docs.cocos.com/creator/manual/zh/components/toggleContainer.html", + "slider": "http://docs.cocos.com/creator/manual/zh/components/slider.html", + "block_input_events": "http://docs.cocos.com/creator/manual/zh/components/block-input-events.html", + "wx_subcontext_view": "http://docs.cocos.com/creator/manual/zh/publish/publish-wechatgame-sub-domain.html" }, - 'interactable': '按钮是否可交互,这一项未选中时,按钮处在禁用状态', - 'transition': '按钮状态变化时的过渡类型', - 'normal_color': '普通状态的按钮背景颜色', - 'pressed_color': '按下状态的按钮背景颜色', - 'hover_color': '悬停状态的按钮背景颜色', - 'disabled_color': '禁用状态的按钮背景颜色', - 'duration': '按钮颜色变化或者缩放变化的过渡时间', - 'zoom_scale': '当用户点击按钮后,按钮会缩放到一个值,这个值等于 Button 原始 scale * zoomScale, zoomScale 可以为负数', - 'auto_gray_effect': "如果这个标记为 true,当 button 的 interactable 属性为 false 的时候,会使用内置 shader 让 button 的 target 节点的 sprite 组件变灰", - 'normal_sprite': '普通状态的按钮背景图资源', - 'pressed_sprite': '按下状态的按钮背景图资源', - 'hover_sprite': '悬停状态的按钮背景图资源', - 'disabled_sprite': '禁用状态的按钮背景图资源', - 'target': '指定 Button 背景节点,Button 状态改变时会修改此节点的 Color 或 Sprite 属性', - 'click_events': '按钮点击事件的列表。先将数量改为1或更多,就可以为每个点击事件设置接受者和处理方法' - }, - 'canvas': { - 'design_resolution': '设计分辨率是游戏在设计时使用的分辨率参考,以像素为单位,通过下面的适配策略,可以在不同分辨率的设备上按照一定的方式对 Canvas 进行整体缩放来适配。', - 'fit_height': '自动缩放 Canvas 使设计分辨率的高度充满设备屏幕的高度', - 'fit_width': '自动缩放 Canvas 使设计分辨率的宽度充满设备屏幕的宽度' - }, - 'label': { - 'string': 'Label 显示的文本内容字符串', - 'horizontal_align': '文字水平对齐模式', - 'vertical_align': '文字垂直对齐模式', - 'font_size': '文字尺寸,以 point 为单位', - 'font_family': '文字字体名字', - 'line_height': '文字行高,以 point 为单位', - 'overflow': '文字排版模式,包括以下三种:\n 1. CLAMP: 节点约束框之外的文字会被截断 \n 2. SHRINK: 自动根据节点约束框缩小文字\n 3. RESIZE: 根据文本内容自动更新节点的 height 属性.', - 'wrap': '是否允许自动换行', - 'font': 'Label 使用的字体资源', - 'system_font': '是否使用系统默认字体,选中此项会将 file 属性置空', - }, - 'progress': { - 'bar_sprite': '进度条显示用的 Sprite 节点,可以动态改变尺寸', - 'mode': '进度条显示模式,目前支持水平和垂直两种', - 'total_length': '进度条在 progress 为 1 时的最大长度', - 'progress': '当前进度指示,范围从0到1', - 'reverse': '是否反向驱动进度条' - }, - 'scrollbar': { - 'handle': '作为当前滚动区域位置显示的滑块 Sprite', - 'direction': 'ScrollBar的滚动方向', - 'auto_hide': '是否在没有滚动动作时自动隐藏 ScrollBar', - 'auto_hide_time': '没有滚动动作后经过多久会自动隐藏', - }, - 'scrollview': { - 'content': '包含可滚动展示内容的节点引用', - 'horizontal': '是否开启水平滚动', - 'vertical': '是否开启垂直滚动', - 'inertia': '是否开启滚动惯性', - 'brake': '开启惯性后,在用户停止触摸后滚动多快停止,0表示永不停止,1表示立刻停止', - 'elastic': '是否允许滚动内容超过边界,并在停止触摸后回弹', - 'bounce_time': '回弹持续的时间', - 'horizontal_bar': '水平滚动的 ScrollBar', - 'vertical_bar': '垂直滚动的 ScrollBar', - "bounceDuration": '回弹持续的时间,0 表示将立即反弹', - "scrollEvents": '滚动视图的事件回调函数', - "cancelInnerEvents": '滚动行为是否会取消子节点上注册的触摸事件' - }, - 'pageview': { - "sizeMode": "页面视图中每个页面大小类型", - "direction": '页面视图滚动方向', - "scrollThreshold": '滚动临界值,默认单位百分比,当拖拽超出该数值时,松开会自动滚动下一页,小于时则还原', - "pageTurningEventTiming": '设置 PageView 页面自动滚动动画结束的阈值,修改此值可以调整 PageView 事件的发送时机。', - "indicator": '页面视图指示器组件', - "pageTurningSpeed": '每个页面翻页时所需时间。单位:秒', - 'pageEvents': '页面视图的事件回调函数', - "autoPageTurningThreshold": "快速滑动翻页临界值。 当用户快速滑动时,会根据滑动开始和结束的距离与时间计算出一个速度值,该值与此临界值相比较,如果大于临界值,则进行自动翻页", - }, - 'pageview_indicator': { - 'spriteFrame': '每个页面标记显示的图片', - 'direction': '页面标记摆放方向', - 'cell_size': '页面标记的大小', - 'spacing': '页面标记之间的边距' - }, - 'toggle': { - 'interactable': 'Toggle 是否可交互,这一项未选中时,Toggle 处在禁用状态', - 'transition': 'Toggle 状态变化时的过渡类型', - 'normal_color': '普通状态的 Toggle 背景颜色', - 'resize_node': '把 Toggle 的 node 的大小重置成 Target 的 node 的大小', - 'pressed_color': '按下状态的 Toggle 背景颜色', - 'hover_color': '悬停状态的 Toggle 背景颜色', - 'disabled_color': '禁用状态的 Toggle 背景颜色', - 'duration': 'Toggle 颜色变化或者缩放变化的过渡时间', - 'zoom_scale': '当用户点击 Toggle 后,Toggle 会缩放到一个值,这个值等于 Toggle 原始 scale * zoomScale, zoomScale 可以为负数', - 'auto_gray_effect': "如果这个标记为 true,当 toggle 的 interactable 属性为 false 的时候,会使用内置 shader 让 toggle 的 target 节点的 sprite 组件变灰", - 'normal_sprite': '普通状态的 Toggle 背景图资源', - 'pressed_sprite': '按下状态的 Toggle 背景图资源', - 'hover_sprite': '悬停状态的 Toggle 背景图资源', - 'disabled_sprite': '禁用状态的 Toggle 背景图资源', - 'target': '指定 Toggle 背景节点,Toggle 状态改变时会修改此节点的 Color 或 Sprite 属性', - 'isChecked': '如果这个设置为 true,则 check mark 组件会处于 enabled 状态,否则处于 disabled 状态。', - 'checkMark': 'Toggle 处于选中状态时显示的精灵图片', - 'toggleGroup': 'Toggle 所属的 ToggleGroup,这个属性是可选的。如果这个属性为 null,则 Toggle 是一个 CheckBox,否则,Toggle 是一个 RadioButton。' - }, - 'toggle_group': { - 'allowSwitchOff': "如果这个设置为 true, 那么 toggle 按钮在被点击的时候可以反复地被选中和未选中。" - }, - 'slider': { - 'handle': '滑块按钮部件', - 'direction': '滑动方向', - 'progress': '当前进度值,该数值的区间是 0-1 之间。', - 'slideEvents': '滑动器组件事件回调函数' - }, - 'widget': { - 'target': '指定一个对齐目标,只能是当前节点的其中一个父节点,默认为空,为空时表示当前父节点', - 'align_top': '是否对齐父节点顶边', - 'align_bottom': '是否对齐父节点底边', - 'align_left': '是否对齐父节点左边', - 'align_right': '是否对齐父节点右边', - 'align_h_center': '是否对齐父节点水平中点,开启这一选项将取消水平轴上的其他对齐选项', - 'align_v_center': '是否对齐父节点垂直中点,开启这一选项将取消垂直轴上的其他对齐选项', - "align_mode": "指定 Widget 的对齐模式,用于决定运行时 Widget 应该何时刷新。", - 'top': '本节点顶边和父节点顶边的距离,可输入负值,默认单位为像素(px),也可以输入百分比,根据父节点 height 和百分比数值计算出距离', - 'bottom': '本节点底边和父节点底边的距离,可输入负值,默认单位为像素(px),也可以输入百分比,根据父节点 height 和百分比数值计算出距离', - 'left': '本节点左边和父节点左边的距离,可输入负值,默认单位为像素(px),也可以输入百分比,根据父节点 width 和百分比数值计算出距离', - 'right': '本节点右边和父节点右边的距离,可输入负值,默认单位为像素(px),也可以输入百分比,根据父节点 width 和百分比数值计算出距离', - 'horizontal_center': '水平居中的偏移值,可输入负值,默认单位为像素(px),也可以是百分比', - 'vertical_center': '垂直居中的偏移值,可输入负值,默认单位为像素(px),也可以是百分比' - }, - 'layout': { - 'layout_type': '自动布局模式,包括:\n 1. NONE,不会对子节点进行自动布局 \n 2. HORIZONTAL,横向自动排布子物体 \n 3. VERTICAL,垂直自动排布子物体\n 4. GRID, 采用网格方式对子物体自动进行布局', - 'resize_mode': '缩放模式,包括:\n 1. NONE,不会对子节点和容器进行大小缩放 \n 2. CHILD, 对子节点的大小进行缩放 \n 3. CONTAINER, 对容器的大小进行缩放', - 'padding_left': 'Layout 节点左边界和子节点的内边距', - 'padding_right': 'Layout 节点右边界和子节点的内边距', - 'padding_top': 'Layout 节点上边界和子节点的内边距', - 'padding_bottom': 'Layout 节点下边界和子节点的内边距', - 'space_x': '相邻子节点之间的水平距离', - 'space_y': '相邻子节点之间的垂直距离', - 'vertical_direction': '垂直排列子节点的方向,包括:\n 1. TOP_TO_BOTTOM, 从上到下排列 \n 2. BOTTOM_TO_TOP, 从下到上排列', - 'horizontal_direction': '水平排列子节点的方向,包括:\n 1. LEFT_TO_RIGHT, 从左到右排列 \n 2. RIGHT_TO_LEFT, 从右到左排列', - 'cell_size': '网格布局中,规定每一个网格的大小', - 'start_axis': '网格布局中,子物体排版时的起始方向轴,支持水平和垂直两个方向。', - }, - 'particle': { - 'export_title': "将自定义的粒子数据导出成 plist 文件", - 'export': "导出", - 'export_error': "该资源不支持导出到项目外", - 'sync': "同步", - 'sync_tips': "同步 File 中的参数到 Custom" - }, - 'editbox': { - "string": "输入框的初始输入内容,如果为空则会显示占位符的文本", - "backgroundImage": "输入框的背景图片", - "input_flag": "指定输入标识:可以指定输入方式为密码或者单词首字母大写", - "returnType": "指定移动设备上面回车按钮的样式", - "input_mode": "指定输入模式: ANY表示多行输入,其它都是单行输入,移动平台上还可以指定键盘样式。", - "font_size": "输入框文本的字体大小", - "line_height": "输入框文本的行高", - "font_color": "输入框文本的颜色", - "stay_on_top": "设置为 True 则输入框总是可见,并且永远在游戏视图的上面", - "tab_index": "修改 DOM 输入元素的 tabIndex,这个属性只有在 Web 上面修改有意义。", - "placeholder": "输入框占位符的文本内容", - "placeholder_font_size": "输入框占位符的字体大小", - "placeholder_font_color": "输入框占位符的字体颜色", - "max_length": "输入框最大允许输入的字符个数", - }, - "videoplayer": { - "resourceType": "视频来源,支持本地视频 URL 和远程视频 URL", - "url": "远程视频的 URL", - "video": "本地视频的 URL", - "volume": "视频的音量(0.0 ~ 1.0)", - "mute": "是否静音视频。静音时设置音量为 0,取消静音是恢复原来的音量", - "currentTime": "从哪个时间点开始播放视频", - "keepAspectRatio": "是否保持视频原有的宽高比", - "isFullscreen": "是否全屏播放视频", - }, - "webview": { - "url": "指定一个 URL 地址,这个地址以 http 或者 https 开头,请填写一个有效的 URL 地址。" - }, - "richtext": { - "string": "富文本的内容字符串, 你可以在里面使用 BBCode 来指定特定文本的样式", - "horizontal_align": "水平对齐方式", - "font_size": "字体大小, 单位是 point", - "font": "富文本定制字体", - "line_height": "字体行高, 单位是 point", - "max_width": "富文本的最大宽度, 传 0 的话意味着必须手动换行.", - "image_atlas": "对于 img 标签里面的 src 属性名称,都需要在 imageAtlas 里面找到一个有效的 spriteFrame,否则 img tag 会判定为无效。", - "handleTouchEvent": "选中此选项后,RichText 将阻止节点边界框中的所有输入事件(鼠标和触摸),从而防止输入事件穿透到底层节点。" - }, - 'skeleton': { - "skeleton_data": "骨骼信息数据,拖拽 Spine 导出的骨骼动画信息 json 资源到这里来开始使用", - "default_skin": "选择默认的皮肤", - "animation": "正在播放的动画名称", - "loop": "是否循环播放当前动画", - "time_scale": "当前骨骼中所有动画的时间缩放率", - "debug_slots": "是否显示 slot 的 debug 信息", - "debug_bones": "是否显示 bone 的 debug 信息", - "premultipliedAlpha": "是否启用贴图预乘", - }, - "dragon_bones": { - "dragon_bones_asset": "骨骼信息数据,拖拽 DragonBones 导出的骨骼动画信息 json 资源到这里来开始使用", - "dragon_bones_atlas_asset": "Texture 信息数据,拖拽 DragonBones 导出的 Texture 信息 json 资源到这里来开始使用", - "armature_name": "当前的 Armature 名称", - "animation_name": "当前播放的动画名称", - "time_scale": "当前骨骼中所有动画的时间缩放率", - "play_times": "播放默认动画的循环次数\n-1 表示使用配置文件中的默认值\n0 表示无限循环\n>0 表示循环次数", - "debug_bones": "是否显示 bone 的 debug 信息" - }, - 'motionStreak': { - 'fadeTime': "拖尾的渐隐时间,以秒为单位", - 'minSeg': "拖尾之间最小距离", - 'stroke': "拖尾的宽度", - 'texture': "拖尾的贴图", - 'color': "拖尾的颜色", - 'fastMode': "是否启用了快速模式" - }, - "missing_scirpt": { - "error_compiled": '载入脚本时报错或脚本已丢失,请检查报错信息并进行修正,该组件将在修正后自动还原。如果脚本已删除,请手动删除该组件。', - "error_not_compiled": '脚本编译失败,请检查报错信息并进行修正,该组件将在修正后自动还原。' - }, - 'collider': { - 'editing': '是否需要编辑此碰撞组件', - 'category': '碰撞组件所属类别', - 'mask': '可以与碰撞组件相碰撞的组件掩码' - }, - 'particle_system': { - 'preview': '在编辑器模式下预览粒子,启用后选中粒子时,粒子将自动播放', - 'custom': '是否自定义粒子属性', - 'file': 'plist 格式的粒子配置文件', - 'spriteFrame': '粒子贴图定义', - 'texture': '粒子贴图,只读属性,请使用 spriteFrame 属性来替换贴图', - 'particleCount': '当前播放的粒子数量', - 'srcBlendFactor': '指定原图混合模式', - 'dstBlendFactor': '指定目标的混合模式', - 'playOnLoad': '如果设置为 true 运行时会自动发射粒子', - 'autoRemoveOnFinish': '粒子播放完毕后自动销毁所在的节点', - 'duration': '发射器生存时间,单位秒,-1表示持续发射', - 'emissionRate': '每秒发射的粒子数目', - 'life': '粒子的运行时间及变化范围', - 'totalParticles': '粒子最大数量', - 'startColor': '粒子初始颜色', - 'startColorVar': '粒子初始颜色变化范围', - 'endColor': '粒子结束颜色', - 'endColorVar': '粒子结束颜色变化范围', - 'angle': '粒子角度及变化范围', - 'startSize': '粒子的初始大小及变化范围', - 'endSize': '粒子结束时的大小及变化范围', - 'startSpin': '粒子开始自旋角度及变化范围', - 'endSpin': '粒子结束自旋角度及变化范围', - 'sourcePos': '发射器位置', - 'posVar': '发射器位置的变化范围。(横向和纵向)', - 'positionType': '粒子位置类型', - 'emitterMode': '发射器类型', - 'gravity': '重力', - 'speed': '速度及变化范围', - 'tangentialAccel': '每个粒子的切向加速度及变化范围,即垂直于重力方向的加速度,只有在重力模式下可用', - 'radialAccel': '粒子径向加速度及变化范围,即平行于重力方向的加速度,只有在重力模式下可用', - 'rotationIsDir': '每个粒子的旋转是否等于其方向,只有在重力模式下可用', - 'startRadius': '初始半径及变化范围,表示粒子出生时相对发射器的距离,只有在半径模式下可用', - 'endRadius': '结束半径及变化范围,只有在半径模式下可用', - 'rotatePerS': '粒子每秒围绕起始点的旋转角度及变化范围,只有在半径模式下可用', - }, - "mask": { - 'type': '遮罩类型', - 'spriteFrame': '遮罩所需要的贴图', - 'inverted': '反向遮罩(不支持 Canvas 模式)', - 'alphaThreshold': 'Alpha阈值,只有当模板的像素的 alpha 大于 alphaThreshold 时,才会绘制内容(不支持 Canvas 模式)', - 'segements': '椭圆遮罩的曲线细分数' - }, - 'physics': { - 'rigidbody': { - 'enabledContactListener': '是否启用接触接听器。当 collider 产生碰撞时,只有开启了接触接听器才会调用相应的回调函数', - 'bullet': '这个刚体是否是一个快速移动的刚体,并且需要禁止穿过其他快速移动的刚体', - 'type': '刚体类型: Static(静态), Kinematic(不受外力), Dynamic(动态)和 Animated(通过设置线性速度和角速度驱动)', - 'allowSleep': '如果此刚体永远都不应该进入睡眠,那么设置这个属性为 false。需要注意这将使 CPU 占用率提高', - 'gravityScale': '缩放应用在此刚体上的重力值', - 'linearDamping': 'Linear damping 用于衰减刚体的线性速度。衰减系数可以大于 1,但是当衰减系数比较大的时候,衰减的效果会变得比较敏感。', - 'angularDamping': 'Angular damping 用于衰减刚体的角速度。衰减系数可以大于 1,但是当衰减系数比较大的时候,衰减的效果会变得比较敏感。', - 'linearVelocity': '刚体在世界坐标下的线性速度', - 'angularVelocity': '刚体的角速度', - 'fixedRotation': '是否禁止此刚体进行旋转', - 'awake': '是否立刻唤醒此刚体' + 'animation': { + 'default_clip': '在勾选自动播放或调用 play() 时默认播放的动画 clip。', + 'clips': '通过脚本可以访问并播放的 AnimationClip 列表', + 'play_on_load': '是否在运行游戏后自动播放默认动画 clip。' }, - 'physics_collider': { - 'density': '密度', - 'sensor': '一个传感器类型的碰撞体会产生碰撞回调,但是不会发生物理碰撞效果。', - 'friction': '摩擦系数,取值一般在 [0, 1] 之间', - 'restitution': '弹性系数,取值一般在 [0, 1]之间', - 'anchor': '刚体的锚点。', - 'connectedAnchor': '关节另一端刚体的锚点。', - 'connectedBody': '关节另一端链接的刚体', - 'collideConnected': '链接到关节上的两个刚体是否应该相互碰撞?', - 'distance': '关节两端的距离', - 'frequency': '弹性系数。', - 'dampingRatio': '阻尼,表示关节变形后,恢复到初始状态受到的阻力。', - 'linearOffset': '关节另一端的刚体相对于起始端刚体的位置偏移量', - 'angularOffset': '关节另一端的刚体相对于起始端刚体的角度偏移量', - 'maxForce': '可以应用于刚体的最大的力值', - 'maxTorque': '可以应用于刚体的最大扭矩值', - 'correctionFactor': '位置矫正系数,范围为 [0, 1]', - 'mouseRegion': '用于注册触摸事件的节点。如果没有设置这个值,那么将会使用关节的节点来注册事件。', - 'target': '目标点,鼠标关节将会移动选中的刚体到指定的目标点', - 'localAxisA': '指定刚体可以移动的方向。', - 'enableLimit': '是否开启关节的距离限制?', - 'enableMotor': '是否开启关节马达?', - 'lowerLimit': '刚体能够移动的最小值', - 'upperLimit': '刚体能够移动的最大值', - 'maxMotorForce': '可以施加到刚体的最大力。', - 'motorSpeed': '期望的马达速度。', - 'referenceAngle': '相对角度。两个物体之间角度为零时可以看作相等于关节角度', - 'lowerAngle': '角度的最低限制。', - 'upperAngle': '角度的最高限制。', - 'maxMotorTorque': '可以施加到刚体的最大扭矩。', - 'maxLength': '最大长度。', - 'offset': '位置偏移量', - 'size': '包围盒大小', - 'radius': '圆形半径', - 'tag': '标签。当一个节点上有多个碰撞组件时,在发生碰撞后,可以使用此标签来判断是节点上的哪个碰撞组件被碰撞了。', - 'points': '多边形顶点数组' + 'audio': { + 'clip': '即将通过该组件播放的 AudioClip 引用', + 'volume': '通过该音源组件播放的声音的音量', + 'mute': '静音开关,静音的音源可以继续播放,但不会发出声音', + 'loop': '是否循环播放', + 'play_on_load': '是否在运行游戏后自动播放音源' + }, + 'sprite': { + 'sprite_frame': '渲染 Sprite 使用的 SpriteFrame 图片资源', + 'atlas': '图片资源所属的 Atlas 图集资源', + 'type': '渲染模式:\n - 普通(Simple):修改尺寸会整体拉伸图像,适用于序列帧动画和普通图像 \n' + + '- 九宫格(Sliced):修改尺寸时四个角的区域不会拉伸,适用于 UI 按钮和面板背景 \n' + + '- 平铺(Tiled):修改尺寸时会不断平铺原始大小的图片 \n' + + '- 填充(Filled):设置一定的填充起始位置和方向,能够以一定比率剪裁显示图片', + 'original_size': '是否使用图片资源的原始尺寸作为 Sprite 节点的 size', + 'edit_button': '编辑', + 'select_button': '选择', + 'select_tooltip': '选择 Atlas 中的其他 SpriteFrame', + 'edit_tooltip': '打开 Sprite 编辑器,设置九宫格等数据', + 'fill_type': '填充方向,可以选择横向(Horizontal),纵向(Vertical)和扇形(Radial)三种方向', + 'fill_center': '扇形填充时,指定扇形的中心点,取值范围 0 ~ 1', + 'fill_start': '填充起始位置,输入一个 0 ~ 1 之间的小数表示起始位置的百分比', + 'fill_range': '填充总量,取值范围 0 ~ 1 指定显示图像范围的百分比', + 'src_blend_factor': '混合显示两张图片时,源图片的取值模式', + 'dst_blend_factor': '混合显示两张图片时,目标图片的取值模式', + 'size_mode': '指定 Sprite 所在节点的尺寸,CUSTOM 表示自定义尺寸,TRIMMED 表示取原始图片剪裁透明像素后的尺寸,RAW 表示取原始图片未剪裁的尺寸', + 'trim': '节点约束框内是否包括透明像素区域,勾选此项会去除节点约束框内的透明区域' + }, + 'button': { + 'click_event': { + 'target': '接收点击事件的节点', + 'component': '接收点击事件的组件', + 'handler': '处理点击事件的方法', + "customEventData": "传给事件处理函数的额外参数,这个数据会当作最后一个参数传递给事件处理函数。" + }, + 'interactable': '按钮是否可交互,这一项未选中时,按钮处在禁用状态', + 'transition': '按钮状态变化时的过渡类型', + 'normal_color': '普通状态的按钮背景颜色', + 'pressed_color': '按下状态的按钮背景颜色', + 'hover_color': '悬停状态的按钮背景颜色', + 'disabled_color': '禁用状态的按钮背景颜色', + 'duration': '按钮颜色变化或者缩放变化的过渡时间', + 'zoom_scale': '当用户点击按钮后,按钮会缩放到一个值,这个值等于 Button 原始 scale * zoomScale, zoomScale 可以为负数', + 'auto_gray_effect': "如果这个标记为 true,当 button 的 interactable 属性为 false 的时候,会使用内置 shader 让 button 的 target 节点的 sprite 组件变灰", + 'normal_sprite': '普通状态的按钮背景图资源', + 'pressed_sprite': '按下状态的按钮背景图资源', + 'hover_sprite': '悬停状态的按钮背景图资源', + 'disabled_sprite': '禁用状态的按钮背景图资源', + 'target': '指定 Button 背景节点,Button 状态改变时会修改此节点的 Color 或 Sprite 属性', + 'click_events': '按钮点击事件的列表。先将数量改为1或更多,就可以为每个点击事件设置接受者和处理方法' + }, + 'canvas': { + 'design_resolution': '设计分辨率是游戏在设计时使用的分辨率参考,以像素为单位,通过下面的适配策略,可以在不同分辨率的设备上按照一定的方式对 Canvas 进行整体缩放来适配。', + 'fit_height': '自动缩放 Canvas 使设计分辨率的高度充满设备屏幕的高度', + 'fit_width': '自动缩放 Canvas 使设计分辨率的宽度充满设备屏幕的宽度' + }, + 'label': { + 'string': 'Label 显示的文本内容字符串', + 'horizontal_align': '文字水平对齐模式', + 'vertical_align': '文字垂直对齐模式', + 'font_size': '文字尺寸,以 point 为单位', + 'font_family': '文字字体名字', + 'line_height': '文字行高,以 point 为单位', + 'overflow': '文字排版模式,包括以下三种:\n 1. CLAMP: 节点约束框之外的文字会被截断 \n 2. SHRINK: 自动根据节点约束框缩小文字\n 3. RESIZE: 根据文本内容自动更新节点的 height 属性.', + 'wrap': '是否允许自动换行', + 'font': 'Label 使用的字体资源', + 'system_font': '是否使用系统默认字体,选中此项会将 file 属性置空', + }, + 'progress': { + 'bar_sprite': '进度条显示用的 Sprite 节点,可以动态改变尺寸', + 'mode': '进度条显示模式,目前支持水平和垂直两种', + 'total_length': '进度条在 progress 为 1 时的最大长度', + 'progress': '当前进度指示,范围从0到1', + 'reverse': '是否反向驱动进度条' + }, + 'scrollbar': { + 'handle': '作为当前滚动区域位置显示的滑块 Sprite', + 'direction': 'ScrollBar的滚动方向', + 'auto_hide': '是否在没有滚动动作时自动隐藏 ScrollBar', + 'auto_hide_time': '没有滚动动作后经过多久会自动隐藏', + }, + 'scrollview': { + 'content': '包含可滚动展示内容的节点引用', + 'horizontal': '是否开启水平滚动', + 'vertical': '是否开启垂直滚动', + 'inertia': '是否开启滚动惯性', + 'brake': '开启惯性后,在用户停止触摸后滚动多快停止,0表示永不停止,1表示立刻停止', + 'elastic': '是否允许滚动内容超过边界,并在停止触摸后回弹', + 'bounce_time': '回弹持续的时间', + 'horizontal_bar': '水平滚动的 ScrollBar', + 'vertical_bar': '垂直滚动的 ScrollBar', + "bounceDuration": '回弹持续的时间,0 表示将立即反弹', + "scrollEvents": '滚动视图的事件回调函数', + "cancelInnerEvents": '滚动行为是否会取消子节点上注册的触摸事件' + }, + 'pageview': { + "sizeMode": "页面视图中每个页面大小类型", + "direction": '页面视图滚动方向', + "scrollThreshold": '滚动临界值,默认单位百分比,当拖拽超出该数值时,松开会自动滚动下一页,小于时则还原', + "pageTurningEventTiming": '设置 PageView 页面自动滚动动画结束的阈值,修改此值可以调整 PageView 事件的发送时机。', + "indicator": '页面视图指示器组件', + "pageTurningSpeed": '每个页面翻页时所需时间。单位:秒', + 'pageEvents': '页面视图的事件回调函数', + "autoPageTurningThreshold": "快速滑动翻页临界值。 当用户快速滑动时,会根据滑动开始和结束的距离与时间计算出一个速度值,该值与此临界值相比较,如果大于临界值,则进行自动翻页", + }, + 'pageview_indicator': { + 'spriteFrame': '每个页面标记显示的图片', + 'direction': '页面标记摆放方向', + 'cell_size': '页面标记的大小', + 'spacing': '页面标记之间的边距' + }, + 'toggle': { + 'interactable': 'Toggle 是否可交互,这一项未选中时,Toggle 处在禁用状态', + 'transition': 'Toggle 状态变化时的过渡类型', + 'normal_color': '普通状态的 Toggle 背景颜色', + 'resize_node': '把 Toggle 的 node 的大小重置成 Target 的 node 的大小', + 'pressed_color': '按下状态的 Toggle 背景颜色', + 'hover_color': '悬停状态的 Toggle 背景颜色', + 'disabled_color': '禁用状态的 Toggle 背景颜色', + 'duration': 'Toggle 颜色变化或者缩放变化的过渡时间', + 'zoom_scale': '当用户点击 Toggle 后,Toggle 会缩放到一个值,这个值等于 Toggle 原始 scale * zoomScale, zoomScale 可以为负数', + 'auto_gray_effect': "如果这个标记为 true,当 toggle 的 interactable 属性为 false 的时候,会使用内置 shader 让 toggle 的 target 节点的 sprite 组件变灰", + 'normal_sprite': '普通状态的 Toggle 背景图资源', + 'pressed_sprite': '按下状态的 Toggle 背景图资源', + 'hover_sprite': '悬停状态的 Toggle 背景图资源', + 'disabled_sprite': '禁用状态的 Toggle 背景图资源', + 'target': '指定 Toggle 背景节点,Toggle 状态改变时会修改此节点的 Color 或 Sprite 属性', + 'isChecked': '如果这个设置为 true,则 check mark 组件会处于 enabled 状态,否则处于 disabled 状态。', + 'checkMark': 'Toggle 处于选中状态时显示的精灵图片', + 'toggleGroup': 'Toggle 所属的 ToggleGroup,这个属性是可选的。如果这个属性为 null,则 Toggle 是一个 CheckBox,否则,Toggle 是一个 RadioButton。' + }, + 'toggle_group': { + 'allowSwitchOff': "如果这个设置为 true, 那么 toggle 按钮在被点击的时候可以反复地被选中和未选中。" + }, + 'slider': { + 'handle': '滑块按钮部件', + 'direction': '滑动方向', + 'progress': '当前进度值,该数值的区间是 0-1 之间。', + 'slideEvents': '滑动器组件事件回调函数' + }, + 'widget': { + 'target': '指定一个对齐目标,只能是当前节点的其中一个父节点,默认为空,为空时表示当前父节点', + 'align_top': '是否对齐父节点顶边', + 'align_bottom': '是否对齐父节点底边', + 'align_left': '是否对齐父节点左边', + 'align_right': '是否对齐父节点右边', + 'align_h_center': '是否对齐父节点水平中点,开启这一选项将取消水平轴上的其他对齐选项', + 'align_v_center': '是否对齐父节点垂直中点,开启这一选项将取消垂直轴上的其他对齐选项', + "align_mode": "指定 Widget 的对齐模式,用于决定运行时 Widget 应该何时刷新。", + 'top': '本节点顶边和父节点顶边的距离,可输入负值,默认单位为像素(px),也可以输入百分比,根据父节点 height 和百分比数值计算出距离', + 'bottom': '本节点底边和父节点底边的距离,可输入负值,默认单位为像素(px),也可以输入百分比,根据父节点 height 和百分比数值计算出距离', + 'left': '本节点左边和父节点左边的距离,可输入负值,默认单位为像素(px),也可以输入百分比,根据父节点 width 和百分比数值计算出距离', + 'right': '本节点右边和父节点右边的距离,可输入负值,默认单位为像素(px),也可以输入百分比,根据父节点 width 和百分比数值计算出距离', + 'horizontal_center': '水平居中的偏移值,可输入负值,默认单位为像素(px),也可以是百分比', + 'vertical_center': '垂直居中的偏移值,可输入负值,默认单位为像素(px),也可以是百分比' + }, + 'layout': { + 'layout_type': '自动布局模式,包括:\n 1. NONE,不会对子节点进行自动布局 \n 2. HORIZONTAL,横向自动排布子物体 \n 3. VERTICAL,垂直自动排布子物体\n 4. GRID, 采用网格方式对子物体自动进行布局', + 'resize_mode': '缩放模式,包括:\n 1. NONE,不会对子节点和容器进行大小缩放 \n 2. CHILD, 对子节点的大小进行缩放 \n 3. CONTAINER, 对容器的大小进行缩放', + 'padding_left': 'Layout 节点左边界和子节点的内边距', + 'padding_right': 'Layout 节点右边界和子节点的内边距', + 'padding_top': 'Layout 节点上边界和子节点的内边距', + 'padding_bottom': 'Layout 节点下边界和子节点的内边距', + 'space_x': '相邻子节点之间的水平距离', + 'space_y': '相邻子节点之间的垂直距离', + 'vertical_direction': '垂直排列子节点的方向,包括:\n 1. TOP_TO_BOTTOM, 从上到下排列 \n 2. BOTTOM_TO_TOP, 从下到上排列', + 'horizontal_direction': '水平排列子节点的方向,包括:\n 1. LEFT_TO_RIGHT, 从左到右排列 \n 2. RIGHT_TO_LEFT, 从右到左排列', + 'cell_size': '网格布局中,规定每一个网格的大小', + 'start_axis': '网格布局中,子物体排版时的起始方向轴,支持水平和垂直两个方向。', + }, + 'particle': { + 'export_title': "将自定义的粒子数据导出成 plist 文件", + 'export': "导出", + 'export_error': "该资源不支持导出到项目外", + 'sync': "同步", + 'sync_tips': "同步 File 中的参数到 Custom" + }, + 'editbox': { + "string": "输入框的初始输入内容,如果为空则会显示占位符的文本", + "backgroundImage": "输入框的背景图片", + "input_flag": "指定输入标识:可以指定输入方式为密码或者单词首字母大写", + "returnType": "指定移动设备上面回车按钮的样式", + "input_mode": "指定输入模式: ANY表示多行输入,其它都是单行输入,移动平台上还可以指定键盘样式。", + "font_size": "输入框文本的字体大小", + "line_height": "输入框文本的行高", + "font_color": "输入框文本的颜色", + "stay_on_top": "设置为 True 则输入框总是可见,并且永远在游戏视图的上面", + "tab_index": "修改 DOM 输入元素的 tabIndex,这个属性只有在 Web 上面修改有意义。", + "placeholder": "输入框占位符的文本内容", + "placeholder_font_size": "输入框占位符的字体大小", + "placeholder_font_color": "输入框占位符的字体颜色", + "max_length": "输入框最大允许输入的字符个数", + }, + "videoplayer": { + "resourceType": "视频来源,支持本地视频 URL 和远程视频 URL", + "url": "远程视频的 URL", + "video": "本地视频的 URL", + "volume": "视频的音量(0.0 ~ 1.0)", + "mute": "是否静音视频。静音时设置音量为 0,取消静音是恢复原来的音量", + "currentTime": "从哪个时间点开始播放视频", + "keepAspectRatio": "是否保持视频原有的宽高比", + "isFullscreen": "是否全屏播放视频", + }, + "webview": { + "url": "指定一个 URL 地址,这个地址以 http 或者 https 开头,请填写一个有效的 URL 地址。" + }, + "richtext": { + "string": "富文本的内容字符串, 你可以在里面使用 BBCode 来指定特定文本的样式", + "horizontal_align": "水平对齐方式", + "font_size": "字体大小, 单位是 point", + "font": "富文本定制字体", + "line_height": "字体行高, 单位是 point", + "max_width": "富文本的最大宽度, 传 0 的话意味着必须手动换行.", + "image_atlas": "对于 img 标签里面的 src 属性名称,都需要在 imageAtlas 里面找到一个有效的 spriteFrame,否则 img tag 会判定为无效。", + "handleTouchEvent": "选中此选项后,RichText 将阻止节点边界框中的所有输入事件(鼠标和触摸),从而防止输入事件穿透到底层节点。" + }, + 'skeleton': { + "skeleton_data": "骨骼信息数据,拖拽 Spine 导出的骨骼动画信息 json 资源到这里来开始使用", + "default_skin": "选择默认的皮肤", + "animation": "正在播放的动画名称", + "loop": "是否循环播放当前动画", + "time_scale": "当前骨骼中所有动画的时间缩放率", + "debug_slots": "是否显示 slot 的 debug 信息", + "debug_bones": "是否显示 bone 的 debug 信息", + "premultipliedAlpha": "是否启用贴图预乘", + }, + "dragon_bones": { + "dragon_bones_asset": "骨骼信息数据,拖拽 DragonBones 导出的骨骼动画信息 json 资源到这里来开始使用", + "dragon_bones_atlas_asset": "Texture 信息数据,拖拽 DragonBones 导出的 Texture 信息 json 资源到这里来开始使用", + "armature_name": "当前的 Armature 名称", + "animation_name": "当前播放的动画名称", + "time_scale": "当前骨骼中所有动画的时间缩放率", + "play_times": "播放默认动画的循环次数\n-1 表示使用配置文件中的默认值\n0 表示无限循环\n>0 表示循环次数", + "debug_bones": "是否显示 bone 的 debug 信息" + }, + 'motionStreak': { + 'fadeTime': "拖尾的渐隐时间,以秒为单位", + 'minSeg': "拖尾之间最小距离", + 'stroke': "拖尾的宽度", + 'texture': "拖尾的贴图", + 'color': "拖尾的颜色", + 'fastMode': "是否启用了快速模式" + }, + "missing_scirpt": { + "error_compiled": '载入脚本时报错或脚本已丢失,请检查报错信息并进行修正,该组件将在修正后自动还原。如果脚本已删除,请手动删除该组件。', + "error_not_compiled": '脚本编译失败,请检查报错信息并进行修正,该组件将在修正后自动还原。' + }, + 'collider': { + 'editing': '是否需要编辑此碰撞组件', + 'category': '碰撞组件所属类别', + 'mask': '可以与碰撞组件相碰撞的组件掩码' + }, + 'particle_system': { + 'preview': '在编辑器模式下预览粒子,启用后选中粒子时,粒子将自动播放', + 'custom': '是否自定义粒子属性', + 'file': 'plist 格式的粒子配置文件', + 'spriteFrame': '粒子贴图定义', + 'texture': '粒子贴图,只读属性,请使用 spriteFrame 属性来替换贴图', + 'particleCount': '当前播放的粒子数量', + 'srcBlendFactor': '指定原图混合模式', + 'dstBlendFactor': '指定目标的混合模式', + 'playOnLoad': '如果设置为 true 运行时会自动发射粒子', + 'autoRemoveOnFinish': '粒子播放完毕后自动销毁所在的节点', + 'duration': '发射器生存时间,单位秒,-1表示持续发射', + 'emissionRate': '每秒发射的粒子数目', + 'life': '粒子的运行时间及变化范围', + 'totalParticles': '粒子最大数量', + 'startColor': '粒子初始颜色', + 'startColorVar': '粒子初始颜色变化范围', + 'endColor': '粒子结束颜色', + 'endColorVar': '粒子结束颜色变化范围', + 'angle': '粒子角度及变化范围', + 'startSize': '粒子的初始大小及变化范围', + 'endSize': '粒子结束时的大小及变化范围', + 'startSpin': '粒子开始自旋角度及变化范围', + 'endSpin': '粒子结束自旋角度及变化范围', + 'sourcePos': '发射器位置', + 'posVar': '发射器位置的变化范围。(横向和纵向)', + 'positionType': '粒子位置类型', + 'emitterMode': '发射器类型', + 'gravity': '重力', + 'speed': '速度及变化范围', + 'tangentialAccel': '每个粒子的切向加速度及变化范围,即垂直于重力方向的加速度,只有在重力模式下可用', + 'radialAccel': '粒子径向加速度及变化范围,即平行于重力方向的加速度,只有在重力模式下可用', + 'rotationIsDir': '每个粒子的旋转是否等于其方向,只有在重力模式下可用', + 'startRadius': '初始半径及变化范围,表示粒子出生时相对发射器的距离,只有在半径模式下可用', + 'endRadius': '结束半径及变化范围,只有在半径模式下可用', + 'rotatePerS': '粒子每秒围绕起始点的旋转角度及变化范围,只有在半径模式下可用', + }, + "mask": { + 'type': '遮罩类型', + 'spriteFrame': '遮罩所需要的贴图', + 'inverted': '反向遮罩(不支持 Canvas 模式)', + 'alphaThreshold': 'Alpha阈值,只有当模板的像素的 alpha 大于 alphaThreshold 时,才会绘制内容(不支持 Canvas 模式)', + 'segements': '椭圆遮罩的曲线细分数' + }, + 'physics': { + 'rigidbody': { + 'enabledContactListener': '是否启用接触接听器。当 collider 产生碰撞时,只有开启了接触接听器才会调用相应的回调函数', + 'bullet': '这个刚体是否是一个快速移动的刚体,并且需要禁止穿过其他快速移动的刚体', + 'type': '刚体类型: Static(静态), Kinematic(不受外力), Dynamic(动态)和 Animated(通过设置线性速度和角速度驱动)', + 'allowSleep': '如果此刚体永远都不应该进入睡眠,那么设置这个属性为 false。需要注意这将使 CPU 占用率提高', + 'gravityScale': '缩放应用在此刚体上的重力值', + 'linearDamping': 'Linear damping 用于衰减刚体的线性速度。衰减系数可以大于 1,但是当衰减系数比较大的时候,衰减的效果会变得比较敏感。', + 'angularDamping': 'Angular damping 用于衰减刚体的角速度。衰减系数可以大于 1,但是当衰减系数比较大的时候,衰减的效果会变得比较敏感。', + 'linearVelocity': '刚体在世界坐标下的线性速度', + 'angularVelocity': '刚体的角速度', + 'fixedRotation': '是否禁止此刚体进行旋转', + 'awake': '是否立刻唤醒此刚体' + }, + 'physics_collider': { + 'density': '密度', + 'sensor': '一个传感器类型的碰撞体会产生碰撞回调,但是不会发生物理碰撞效果。', + 'friction': '摩擦系数,取值一般在 [0, 1] 之间', + 'restitution': '弹性系数,取值一般在 [0, 1]之间', + 'anchor': '刚体的锚点。', + 'connectedAnchor': '关节另一端刚体的锚点。', + 'connectedBody': '关节另一端链接的刚体', + 'collideConnected': '链接到关节上的两个刚体是否应该相互碰撞?', + 'distance': '关节两端的距离', + 'frequency': '弹性系数。', + 'dampingRatio': '阻尼,表示关节变形后,恢复到初始状态受到的阻力。', + 'linearOffset': '关节另一端的刚体相对于起始端刚体的位置偏移量', + 'angularOffset': '关节另一端的刚体相对于起始端刚体的角度偏移量', + 'maxForce': '可以应用于刚体的最大的力值', + 'maxTorque': '可以应用于刚体的最大扭矩值', + 'correctionFactor': '位置矫正系数,范围为 [0, 1]', + 'mouseRegion': '用于注册触摸事件的节点。如果没有设置这个值,那么将会使用关节的节点来注册事件。', + 'target': '目标点,鼠标关节将会移动选中的刚体到指定的目标点', + 'localAxisA': '指定刚体可以移动的方向。', + 'enableLimit': '是否开启关节的距离限制?', + 'enableMotor': '是否开启关节马达?', + 'lowerLimit': '刚体能够移动的最小值', + 'upperLimit': '刚体能够移动的最大值', + 'maxMotorForce': '可以施加到刚体的最大力。', + 'motorSpeed': '期望的马达速度。', + 'referenceAngle': '相对角度。两个物体之间角度为零时可以看作相等于关节角度', + 'lowerAngle': '角度的最低限制。', + 'upperAngle': '角度的最高限制。', + 'maxMotorTorque': '可以施加到刚体的最大扭矩。', + 'maxLength': '最大长度。', + 'offset': '位置偏移量', + 'size': '包围盒大小', + 'radius': '圆形半径', + 'tag': '标签。当一个节点上有多个碰撞组件时,在发生碰撞后,可以使用此标签来判断是节点上的哪个碰撞组件被碰撞了。', + 'points': '多边形顶点数组' + } + }, + 'block_input_events': { + 'brief_help': '该组件将拦截所有输入事件,防止输入穿透到下层节点,一般用于上层 UI 的背景。' + }, + 'tiledtile': { + 'row': '指定 TiledTile 的横向坐标,以地图块为单位', + 'column': '指定 TiledTile 的纵向坐标,以地图块为单位', + 'gid': '指定 TiledTile 的 gid 值', + 'layer': '指定 TiledTile 属于哪一个 TiledLayer' } - }, - 'block_input_events': { - 'brief_help': '该组件将拦截所有输入事件,防止输入穿透到下层节点,一般用于上层 UI 的背景。' - }, - 'tiledtile': { - 'row': '指定 TiledTile 的横向坐标,以地图块为单位', - 'column': '指定 TiledTile 的纵向坐标,以地图块为单位', - 'gid': '指定 TiledTile 的 gid 值', - 'layer': '指定 TiledTile 属于哪一个 TiledLayer' } }; \ No newline at end of file From 6014dc36d6229f82246169fe7aa9ff6a79f7f162 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 20 Sep 2018 17:46:49 +0800 Subject: [PATCH 0024/1631] fix mask invalid bug (#3292) --- cocos2d/core/renderer/webgl/assemblers/mask-assembler.js | 1 + cocos2d/core/renderer/webgl/stencil-manager.js | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js index bd95ca1afd1..8ca28a3ba67 100644 --- a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js @@ -86,6 +86,7 @@ let maskFrontAssembler = { else { graphicsAssembler.fillBuffers(mask._graphics, renderer); } + _stencilMgr.enableMask(); } mask.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; diff --git a/cocos2d/core/renderer/webgl/stencil-manager.js b/cocos2d/core/renderer/webgl/stencil-manager.js index 20df8a7c95a..030fe68eedd 100644 --- a/cocos2d/core/renderer/webgl/stencil-manager.js +++ b/cocos2d/core/renderer/webgl/stencil-manager.js @@ -101,8 +101,6 @@ StencilManager.prototype = { ref = this.getWriteMask(); stencilMask = ref; writeMask = ref; - - this.stage = Stage.ENABLED; } } @@ -129,6 +127,10 @@ StencilManager.prototype = { this.stage = Stage.ENTER_LEVEL; }, + enableMask () { + this.stage = Stage.ENABLED; + }, + exitMask () { if (this._maskStack.length === 0) { cc.errorID(9001); From a9f9513a2a73a6dd5ec65318ff930973cf244f6a Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 20 Sep 2018 18:20:23 +0800 Subject: [PATCH 0025/1631] fix when the tilemap has no image, it will always report an error. (#3294) --- cocos2d/tilemap/CCTiledLayer.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/tilemap/CCTiledLayer.js b/cocos2d/tilemap/CCTiledLayer.js index 5c830b20ae7..eade0be1b7b 100644 --- a/cocos2d/tilemap/CCTiledLayer.js +++ b/cocos2d/tilemap/CCTiledLayer.js @@ -571,6 +571,10 @@ let TiledLayer = cc.Class({ _fillTextureGrids (tileset, texId) { let tex = this._textures[texId]; + if (!tex) { + return; + } + if (!tex.loaded) { tex.once('load', function () { this._fillTextureGrids(tileset, texId); From 664770d4a62caab85685ac0fbee305b5ccac78bc Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 21 Sep 2018 16:35:14 +0800 Subject: [PATCH 0026/1631] fixed switch 2d/3d node (#3297) --- cocos2d/core/3d/polyfill-3d.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index ef3ea6d32ca..9aee418f5fd 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -254,6 +254,7 @@ function _update3DFunction () { this._mulMat = _mulMat2d; this._syncEulerAngles = _syncEulerAngles2d; } + this._renderFlag |= RenderFlow.FLAG_TRANSFORM; } function _upgrade_1x_to_2x () { From be81afde507d80ea606ed419c310ae53a92a91b6 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 21 Sep 2018 18:00:25 +0800 Subject: [PATCH 0027/1631] fix stop all audio invalid for engine/issues/3199 (#3299) --- cocos2d/audio/CCAudioEngine.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cocos2d/audio/CCAudioEngine.js b/cocos2d/audio/CCAudioEngine.js index f59bf0ee656..8a44b64c0ae 100644 --- a/cocos2d/audio/CCAudioEngine.js +++ b/cocos2d/audio/CCAudioEngine.js @@ -693,7 +693,8 @@ var audioEngine = { var musicId = this._music.id; this._effect.volume = volume; for (var id in _id2audio) { - if (id === musicId) continue; + var audio = _id2audio[id]; + if (!audio || audio.id === musicId) continue; audioEngine.setVolume(id, volume); } }, @@ -735,8 +736,8 @@ var audioEngine = { effect.pauseCache.length = 0; for (var id in _id2audio) { - if (id === musicId) continue; var audio = _id2audio[id]; + if (!audio || audio.id === musicId) continue; var state = audio.getState(); if (state === this.AudioState.PLAYING) { effect.pauseCache.push(id); @@ -796,8 +797,8 @@ var audioEngine = { stopAllEffects: function () { var musicId = this._music.id; for (var id in _id2audio) { - if (id === musicId) continue; var audio = _id2audio[id]; + if (!audio || audio.id === musicId) continue; var state = audio.getState(); if (state === audioEngine.AudioState.PLAYING) { audio.stop(); From 1ed797b903aa5904b6d0fcf63697857a47471f50 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 21 Sep 2018 18:00:59 +0800 Subject: [PATCH 0028/1631] fix position event handling (#3289) --- cocos2d/core/CCNode.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index b2b30a87bbd..be4faadd447 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -623,7 +623,7 @@ var Node = cc.Class({ if (this._eventMask & POSITION_ON) { // send event if (CC_EDITOR) { - this.emit(EventType.POSITION_CHANGED, new cc.Vec2(oldValue, localPosition.y)); + this.emit(EventType.POSITION_CHANGED, new cc.Vec3(oldValue, localPosition.y, localPosition.z)); } else { this.emit(EventType.POSITION_CHANGED); @@ -666,7 +666,7 @@ var Node = cc.Class({ if (this._eventMask & POSITION_ON) { // send event if (CC_EDITOR) { - this.emit(EventType.POSITION_CHANGED, new cc.Vec2(localPosition.x, oldValue)); + this.emit(EventType.POSITION_CHANGED, new cc.Vec3(localPosition.x, oldValue, localPosition.z)); } else { this.emit(EventType.POSITION_CHANGED); @@ -2031,7 +2031,7 @@ var Node = cc.Class({ } if (CC_EDITOR) { - var oldPosition = new cc.Vec2(locPosition); + var oldPosition = new cc.Vec3(locPosition); } if (!CC_EDITOR || isFinite(x)) { locPosition.x = x; @@ -2299,6 +2299,9 @@ var Node = cc.Class({ * @param {Vec3} pos */ setWorldPos (pos) { + if (CC_EDITOR) { + var oldPosition = new cc.Vec3(this._position); + } // NOTE: this is faster than invert world matrix and transform the point if (this._parent) { this._parent._invTransformPoint(this._position, pos); From aaf8ac51a8f30a4cc9520d2c33a2fcedbc961289 Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 21 Sep 2018 18:20:31 +0800 Subject: [PATCH 0029/1631] fix once and on touchEventDispatching difference (#3295) --- cocos2d/core/event-manager/CCEventManager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/event-manager/CCEventManager.js b/cocos2d/core/event-manager/CCEventManager.js index f7ee2fc2f79..bfd1703a1e1 100644 --- a/cocos2d/core/event-manager/CCEventManager.js +++ b/cocos2d/core/event-manager/CCEventManager.js @@ -484,7 +484,7 @@ var eventManager = { _onTouchEventCallback: function (listener, argsObj) { // Skip if the listener was removed. - if (!listener._isRegistered) + if (!listener._isRegistered()) return false; var event = argsObj.event, selTouch = event.currentTouch; @@ -522,7 +522,7 @@ var eventManager = { return true; } - if (isClaimed && listener._registered && listener.swallowTouches) { + if (isClaimed && listener.swallowTouches) { if (argsObj.needsMutableSet) argsObj.touches.splice(selTouch, 1); return true; From 702186955281cd137f0837f7e31eeaa68f4a08f6 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 25 Sep 2018 10:58:37 +0800 Subject: [PATCH 0030/1631] modeify the note (#3302) --- cocos2d/actions/CCActionInterval.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index 14eb155191c..a5aabc7d5d7 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -2429,7 +2429,7 @@ cc.DelayTime = cc.Class({ /** * !#en Delays the action a certain amount of seconds. - * !#en 延迟指定的时间量。 + * !#zh 延迟指定的时间量。 * @method delayTime * @param {Number} d duration in seconds * @return {ActionInterval} From b6dffeb29dd33dac7460493983d4fd0cc42a7f6d Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 29 Aug 2018 16:17:44 +0800 Subject: [PATCH 0031/1631] fix actionManager can't remove all actions (#3159) --- cocos2d/actions/CCActionManager.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cocos2d/actions/CCActionManager.js b/cocos2d/actions/CCActionManager.js index 1ca5cce5feb..40f64b372bf 100644 --- a/cocos2d/actions/CCActionManager.js +++ b/cocos2d/actions/CCActionManager.js @@ -142,11 +142,16 @@ cc.ActionManager = cc._Class.extend(/** @lends cc.ActionManager# */{ */ removeAllActions:function () { var locTargets = this._arrayTargets; - for (var i = 0; i < locTargets.length; i++) { - var element = locTargets[i]; + + // RemoveAllActionsFromTarget changes the length of array _arrayTargets. + // So we iterate on the locTargets_clone instead of locTargets. + var locTargets_clone = cc.js.array.copy(locTargets); + for (var i = 0; i < locTargets_clone.length; i++) { + var element = locTargets_clone[i]; if (element) this.removeAllActionsFromTarget(element.target, true); } + locTargets_clone.length = 0; }, /** * !#en From 8069c455ad48ecd4896fd57358850626fb62768f Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 29 Aug 2018 17:35:30 +0800 Subject: [PATCH 0032/1631] fix actionManager can't remove all actions again (#3160) --- cocos2d/actions/CCActionManager.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/cocos2d/actions/CCActionManager.js b/cocos2d/actions/CCActionManager.js index 40f64b372bf..cb3f4b5c715 100644 --- a/cocos2d/actions/CCActionManager.js +++ b/cocos2d/actions/CCActionManager.js @@ -142,16 +142,13 @@ cc.ActionManager = cc._Class.extend(/** @lends cc.ActionManager# */{ */ removeAllActions:function () { var locTargets = this._arrayTargets; - - // RemoveAllActionsFromTarget changes the length of array _arrayTargets. - // So we iterate on the locTargets_clone instead of locTargets. - var locTargets_clone = cc.js.array.copy(locTargets); - for (var i = 0; i < locTargets_clone.length; i++) { - var element = locTargets_clone[i]; + for (var i = 0; i < locTargets.length; i++) { + var element = locTargets[i]; if (element) - this.removeAllActionsFromTarget(element.target, true); + this._putElement(element); } - locTargets_clone.length = 0; + this._arrayTargets.length = 0; + this._hashTargets = js.createMap(true); }, /** * !#en From 2ea3dd21e7cb56e9a49b74318a4a42f4010561ad Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Thu, 30 Aug 2018 13:37:23 +0800 Subject: [PATCH 0033/1631] modify touch event listener clear touches preTouchPool (#3162) --- cocos2d/core/platform/CCInputManager.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/platform/CCInputManager.js b/cocos2d/core/platform/CCInputManager.js index 4e5cbe70755..0c9f47c88b3 100644 --- a/cocos2d/core/platform/CCInputManager.js +++ b/cocos2d/core/platform/CCInputManager.js @@ -98,10 +98,10 @@ var inputManager = { * @param {Array} touches */ handleTouchesBegin: function (touches) { - var selTouch, index, curTouch, touchID, + var selTouch, index, curTouch, touchID, handleTouches = [], locTouchIntDict = this._touchesIntegerDict, now = sys.now(); - for(var i = 0, len = touches.length; i< len; i ++){ + for (let i = 0, len = touches.length; i < len; i ++) { selTouch = touches[i]; touchID = selTouch.getID(); index = locTouchIntDict[touchID]; @@ -133,7 +133,7 @@ var inputManager = { * @param {Array} touches */ handleTouchesMove: function(touches){ - var selTouch, index, touchID, + var selTouch, index, touchID, handleTouches = [], locTouches = this._touches, now = sys.now(); for(var i = 0, len = touches.length; i < len; i++){ @@ -172,6 +172,7 @@ var inputManager = { touchEvent._eventCode = cc.Event.EventTouch.ENDED; eventManager.dispatchEvent(touchEvent); } + this._preTouchPool.length = 0; }, /** @@ -186,6 +187,7 @@ var inputManager = { touchEvent._eventCode = cc.Event.EventTouch.CANCELLED; eventManager.dispatchEvent(touchEvent); } + this._preTouchPool.length = 0; }, /** From 67936ee0203dcd09e8f63b48e42251b4d797c8c3 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 30 Aug 2018 16:30:01 +0800 Subject: [PATCH 0034/1631] fix convertToLocationInView calculation bug for fireball/issues/8300 (#3166) --- cocos2d/core/platform/CCView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index a9e6efc24e0..9fab7274ed7 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -997,7 +997,7 @@ var View = cc._Class.extend({ convertToLocationInView: function (tx, ty, relatedPos) { var x = this._devicePixelRatio * (tx - relatedPos.left); var y = this._devicePixelRatio * (relatedPos.top + relatedPos.height - ty); - return this._isRotated ? {x: this._viewPortRect.width - y, y: x} : {x: x, y: y}; + return this._isRotated ? {x: cc.game.canvas.width - y, y: x} : {x: x, y: y}; }, _convertMouseToLocationInView: function (in_out_point, relatedPos) { From a908ffa681c87812676430b0a611962937395c86 Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 30 Aug 2018 18:00:29 +0800 Subject: [PATCH 0035/1631] fix infinite length in editbox (#3168) --- cocos2d/core/editbox/CCSGEditBox.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/editbox/CCSGEditBox.js b/cocos2d/core/editbox/CCSGEditBox.js index 467057ef3f7..dec4cda51ef 100644 --- a/cocos2d/core/editbox/CCSGEditBox.js +++ b/cocos2d/core/editbox/CCSGEditBox.js @@ -389,7 +389,7 @@ _ccsg.EditBox = _ccsg.Node.extend({ }, setString: function (text) { - if (text.length >= this._maxLength) { + if (this._maxLength >= 0 && text.length >= this._maxLength) { text = text.slice(0, this._maxLength); } this._text = text; From 92474901b18dfccd392a645c431ebf0f8d2278ae Mon Sep 17 00:00:00 2001 From: SijieWang Date: Tue, 4 Sep 2018 18:56:54 +0800 Subject: [PATCH 0036/1631] Problem that color type cannot be recognized (#3191) --- cocos2d/motion-streak/CCMotionStreak.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/motion-streak/CCMotionStreak.js b/cocos2d/motion-streak/CCMotionStreak.js index 46c98617329..8db0a503cdc 100644 --- a/cocos2d/motion-streak/CCMotionStreak.js +++ b/cocos2d/motion-streak/CCMotionStreak.js @@ -200,6 +200,7 @@ var MotionStreak = cc.Class({ this._motionStreak.tintWithColor(value); } }, + type: cc.Color, tooltip: CC_DEV && 'i18n:COMPONENT.motionStreak.color' }, From b5425e0edd6816d36d57aa1022bbdf58ce2d97f6 Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 11 Sep 2018 16:00:30 +0800 Subject: [PATCH 0037/1631] fix editbox domInput hidden when view rotated (#3228) --- cocos2d/core/platform/CCView.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 9fab7274ed7..eb616f38be7 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -355,6 +355,15 @@ var View = cc._Class.extend({ cc.container.style['-webkit-transform-origin'] = '0px 0px 0px'; cc.container.style.transformOrigin = '0px 0px 0px'; this._isRotated = true; + + // Fix for issue: https://github.com/cocos-creator/fireball/issues/8365 + // Reference: https://www.douban.com/note/343402554/ + // For Chrome, z-index not working after container transform rotate 90deg. + // Because 'transform' style adds canvas (the top-element of container) to a new stack context. + // That causes the DOM Input was hidden under canvas. + // This should be done after container rotated, instead of in style-mobile.css. + cc.game.canvas.style['-webkit-transform'] = 'translateZ(0px)'; + cc.game.canvas.style.transform = 'translateZ(0px)'; } if (this._orientationChanging) { setTimeout(function () { From e83c4f31e7892991c6c338323a6a4e4ee3049b32 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 13 Sep 2018 09:52:53 +0800 Subject: [PATCH 0038/1631] fix get layer properties is null (#3235) --- cocos2d/tilemap/CCTMXXMLParser.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/cocos2d/tilemap/CCTMXXMLParser.js b/cocos2d/tilemap/CCTMXXMLParser.js index 9929ba7a1d4..dc2e846fa5e 100644 --- a/cocos2d/tilemap/CCTMXXMLParser.js +++ b/cocos2d/tilemap/CCTMXXMLParser.js @@ -818,14 +818,8 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{ } // The parent element is the last layer - var layerProps = getPropertyList(selLayer); - if (layerProps) { - var layerProp = {}; - for (let j = 0; j < layerProps.length; j++) { - layerProp[layerProps[j].getAttribute('name')] = layerProps[j].getAttribute('value'); - } - layer.properties = layerProp; - } + layer.properties = getPropertyList(selLayer); + return layer; }, From 80b4c116299d87ee7defa699f91b202ebeda6918 Mon Sep 17 00:00:00 2001 From: kenshin <420373550@qq.com> Date: Thu, 13 Sep 2018 10:29:28 +0800 Subject: [PATCH 0039/1631] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E8=B6=8A=E6=9D=A5=E8=B6=8A=E6=85=A2=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E7=94=B1=E4=BA=8EJS=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E7=9A=84=E7=B4=A2=E5=BC=95=E6=95=B0=E6=8D=AE=E8=B6=8A?= =?UTF-8?q?=E6=9D=A5=E8=B6=8A=E5=A4=9A=E5=AF=BC=E8=87=B4=E7=9A=84=E3=80=82?= =?UTF-8?q?=20(#3241)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed loader performance dropdown caused by large array access --- cocos2d/core/load-pipeline/loading-items.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/load-pipeline/loading-items.js b/cocos2d/core/load-pipeline/loading-items.js index 0380a620bff..606c1dafe56 100644 --- a/cocos2d/core/load-pipeline/loading-items.js +++ b/cocos2d/core/load-pipeline/loading-items.js @@ -739,12 +739,14 @@ proto.destroy = function () { // Reinitialize CallbacksInvoker, generate three new objects, could be improved CallbacksInvoker.call(this); - - _queues[this._id] = null; + if (_queueDeps[this._id]) { _queueDeps[this._id].completed.length = 0; _queueDeps[this._id].deps.length = 0; } + delete _queues[this._id]; + delete _queueDeps[this._id]; + if (_pool.indexOf(this) === -1 && _pool.length < _POOL_MAX_LENGTH) { _pool.push(this); } From 47bb7f05284dc6e5ef1899ac13e032fdd97b87e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=BA=E6=98=8E?= Date: Thu, 13 Sep 2018 14:08:19 +0800 Subject: [PATCH 0040/1631] fix loadScene bug when scene is at plugin (#3243) --- cocos2d/core/CCDirector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/CCDirector.js b/cocos2d/core/CCDirector.js index 51946f3bba8..65dfce2950a 100644 --- a/cocos2d/core/CCDirector.js +++ b/cocos2d/core/CCDirector.js @@ -674,7 +674,7 @@ cc.Director = Class.extend(/** @lends cc.Director# */{ if (!key.endsWith('.fire')) { key += '.fire'; } - if (key[0] !== '/' && !key.startsWith('db://assets/')) { + if (key[0] !== '/' && !key.startsWith('db://')) { key = '/' + key; // 使用全名匹配 } // search scene From d4a34edd1658f52c9057f049262c265da000ab38 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 20 Sep 2018 18:20:23 +0800 Subject: [PATCH 0041/1631] fix when the tilemap has no image, it will always report an error. (#3294) --- cocos2d/tilemap/CCSGTMXLayer.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/tilemap/CCSGTMXLayer.js b/cocos2d/tilemap/CCSGTMXLayer.js index 1922080d460..325d35015b2 100644 --- a/cocos2d/tilemap/CCSGTMXLayer.js +++ b/cocos2d/tilemap/CCSGTMXLayer.js @@ -119,6 +119,10 @@ _ccsg.TMXLayer = _ccsg.Node.extend(/** @lends _ccsg.TMXLayer# */{ _fillTextureGrids: function (tileset, texId) { var tex = this._textures[texId]; + if (!tex) { + return; + } + if (!tex.loaded) { tex.once('load', function () { this._fillTextureGrids(tileset, texId); From 42c26a9073af74dae6b5a7af5e0b70fddbdfe65c Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 21 Sep 2018 18:00:25 +0800 Subject: [PATCH 0042/1631] fix stop all audio invalid for engine/issues/3199 (#3299) --- cocos2d/audio/CCAudioEngine.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cocos2d/audio/CCAudioEngine.js b/cocos2d/audio/CCAudioEngine.js index ded7eae87d2..4bf80ca72d4 100644 --- a/cocos2d/audio/CCAudioEngine.js +++ b/cocos2d/audio/CCAudioEngine.js @@ -667,7 +667,8 @@ var audioEngine = { var musicId = this._music.id; this._effect.volume = volume; for (var id in id2audio) { - if (id === musicId) continue; + var audio = id2audio[id]; + if (!audio || audio.id === musicId) continue; audioEngine.setVolume(id, volume); } }, @@ -709,8 +710,8 @@ var audioEngine = { effect.pauseCache.length = 0; for (var id in id2audio) { - if (id === musicId) continue; var audio = id2audio[id]; + if (!audio || audio.id === musicId) continue; var state = audio.getState(); if (state === this.AudioState.PLAYING) { effect.pauseCache.push(id); @@ -770,8 +771,8 @@ var audioEngine = { stopAllEffects: function () { var musicId = this._music.id; for (var id in id2audio) { - if (id === musicId) continue; var audio = id2audio[id]; + if (!audio || audio.id === musicId) continue; var state = audio.getState(); if (state === audioEngine.AudioState.PLAYING) { audio.stop(); From d6ec4c03aa86f40af14d21ef9f059fed5e540c58 Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 21 Sep 2018 18:20:31 +0800 Subject: [PATCH 0043/1631] fix once and on touchEventDispatching difference (#3295) --- cocos2d/core/event-manager/CCEventManager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/event-manager/CCEventManager.js b/cocos2d/core/event-manager/CCEventManager.js index ae52fb4cfdc..7d98305628b 100644 --- a/cocos2d/core/event-manager/CCEventManager.js +++ b/cocos2d/core/event-manager/CCEventManager.js @@ -483,7 +483,7 @@ var eventManager = { _onTouchEventCallback: function (listener, argsObj) { // Skip if the listener was removed. - if (!listener._isRegistered) + if (!listener._isRegistered()) return false; var event = argsObj.event, selTouch = event.currentTouch; @@ -521,7 +521,7 @@ var eventManager = { return true; } - if (isClaimed && listener._registered && listener.swallowTouches) { + if (isClaimed && listener.swallowTouches) { if (argsObj.needsMutableSet) argsObj.touches.splice(selTouch, 1); return true; From 96bda88193f046d4669a2fb38a5ad968c5d6a9df Mon Sep 17 00:00:00 2001 From: Coco Date: Tue, 25 Sep 2018 17:06:37 +0800 Subject: [PATCH 0044/1631] modify the game note to fix the tsd --- cocos2d/core/CCGame.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 3198b034780..5c1b5c7848f 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -38,7 +38,7 @@ const dynamicAtlasManager = require('../core/renderer/utils/dynamic-atlas/manage /** * !#en An object to boot the game. * !#zh 包含游戏主体信息并负责驱动游戏的游戏对象。 - * @class game + * @class Game * @static * @extends EventTarget */ @@ -879,6 +879,12 @@ EventTarget.call(game); cc.js.addon(game, EventTarget.prototype); /** + * @module cc + */ + +/** + * !#en This is a Game instance. + * !#zh 这是一个 Game 类的实例,包含游戏主体信息并负责驱动游戏的游戏对象。。 * @property game * @type Game */ From a6bbc1e52a22525657c384b1c5ab4edb9e0a584e Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Wed, 26 Sep 2018 17:04:06 +0800 Subject: [PATCH 0045/1631] add the note above Sprite.State (#3314) --- cocos2d/core/components/CCSprite.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index cd2de5ab180..fb943ad5bf7 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -121,7 +121,11 @@ var SizeMode = cc.Enum({ */ RAW: 2 }); - +/** + * !#en Sprite state can choice the normal or grayscale. + * !#zh 精灵颜色通道模式。 + * @enum Sprite.State + */ var State = cc.Enum({ /** * !#en The normal state From 8e1db324902a2ce957a1151c23c3a828a9232b3f Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 26 Sep 2018 21:00:59 +0800 Subject: [PATCH 0046/1631] fix scrollView bug --- cocos2d/core/components/CCScrollView.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index 2fe85cc83d3..c0b7de480cc 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -815,7 +815,7 @@ var ScrollView = cc.Class({ anchor = cc.pClamp(anchor, cc.p(0, 0), cc.p(1, 1)); - var scrollSize = this.node.getContentSize(); + var scrollSize = this.content.parent.getContentSize(); var contentSize = this.content.getContentSize(); var bottomDeta = this._getContentBottomBoundary() - this._bottomBoundary; bottomDeta = -bottomDeta; @@ -1329,11 +1329,6 @@ var ScrollView = cc.Class({ var currentOutOfBoundary = this._getHowMuchOutOfBoundary(); if (!cc.pFuzzyEqual(currentOutOfBoundary, cc.p(0, 0), EPSILON)) { this._autoScrollCurrentlyOutOfBoundary = true; - var afterOutOfBoundary = this._getHowMuchOutOfBoundary(adjustedDeltaMove); - if (currentOutOfBoundary.x * afterOutOfBoundary.x > 0 || - currentOutOfBoundary.y * afterOutOfBoundary.y > 0) { - this._autoScrollBraking = true; - } } }, From 0f1446b91c949e900ad46067efc07c968dd16582 Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 27 Sep 2018 13:53:18 +0800 Subject: [PATCH 0047/1631] fix editBox multiLine confirm for 1.10-release (#3321) --- cocos2d/core/editbox/CCSGEditBox.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/editbox/CCSGEditBox.js b/cocos2d/core/editbox/CCSGEditBox.js index dec4cda51ef..49c112a2524 100644 --- a/cocos2d/core/editbox/CCSGEditBox.js +++ b/cocos2d/core/editbox/CCSGEditBox.js @@ -934,7 +934,7 @@ _ccsg.EditBox.KeyboardReturnType = KeyboardReturnType; defaultValue: editBox._text, maxLength: 140, multiple: multiline, - confirmHold: true, + confirmHold: false, // hide keyboard mannually by wx.onKeyboardConfirm confirmType: "done", success: function (res) { editBox._delegate && editBox._delegate.editBoxEditingDidBegan && editBox._delegate.editBoxEditingDidBegan(editBox); From e7b02acd2243067e0c4811ffa9df4c77205efc7a Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Thu, 27 Sep 2018 14:24:57 +0800 Subject: [PATCH 0048/1631] sort the layout tool prop tips (#3328) --- editor/i18n/en/localization.js | 2 +- editor/i18n/zh/localization.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 72a7aea2d50..1255f501d67 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -187,7 +187,7 @@ module.exports = { }, "layout": { "layout_type": "Automatic layout mode: \n 1. NONE, no automatic arrangement of child Nodes \n 2. HORIZONTAL, automatic horizontal arrangement of child Nodes \n 3. VERTICAL, automatic vertical arrangement of child Nodes\n 4. GRID, automatic grid arrangement of child Nodes", - "resize_mode": "Automatic resize mode: \n 1. NONE, no resize of both child Nodes and container. \n 2. CHILDREN, resize child Nodes. \n 3. CONTAINER, resize container Node.", + "resize_mode": "Automatic resize mode: \n 1. NONE, no resize of both child Nodes and container. \n 2. CONTAINER, resize container Node. \n 3. CHILDREN, resize child Nodes.", 'padding_left': 'Use a padding between left sides of the Node', 'padding_right': 'Use a padding between right sides of the Node', 'padding_top': 'Use a padding between top sides of the Node', diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index b14a127d202..9c13333c3d5 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -191,7 +191,7 @@ module.exports = { }, 'layout': { 'layout_type': '自动布局模式,包括:\n 1. NONE,不会对子节点进行自动布局 \n 2. HORIZONTAL,横向自动排布子物体 \n 3. VERTICAL,垂直自动排布子物体\n 4. GRID, 采用网格方式对子物体自动进行布局', - 'resize_mode': '缩放模式,包括:\n 1. NONE,不会对子节点和容器进行大小缩放 \n 2. CHILD, 对子节点的大小进行缩放 \n 3. CONTAINER, 对容器的大小进行缩放', + 'resize_mode': '缩放模式,包括:\n 1. NONE,不会对子节点和容器进行大小缩放 \n 2. CONTAINER, 对容器的大小进行缩放 \n 3. CHILD, 对子节点的大小进行缩放', 'padding_left': 'Layout 节点左边界和子节点的内边距', 'padding_right': 'Layout 节点右边界和子节点的内边距', 'padding_top': 'Layout 节点上边界和子节点的内边距', From 96273700cc31bc1fcaa5aff7638b5f01f90abdde Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 27 Sep 2018 16:01:12 +0800 Subject: [PATCH 0049/1631] fix tmxLayer getProperty (#3327) --- cocos2d/tilemap/CCTMXXMLParser.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cocos2d/tilemap/CCTMXXMLParser.js b/cocos2d/tilemap/CCTMXXMLParser.js index dc2e846fa5e..59da89570fc 100644 --- a/cocos2d/tilemap/CCTMXXMLParser.js +++ b/cocos2d/tilemap/CCTMXXMLParser.js @@ -818,7 +818,14 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{ } // The parent element is the last layer - layer.properties = getPropertyList(selLayer); + let layerProps = getPropertyList(selLayer); + if (layerProps) { + let layerProp = {}; + for (let j = 0; j < layerProps.length; j++) { + layerProp[layerProps[j].getAttribute('name')] = layerProps[j].getAttribute('value'); + } + layer.properties = layerProp; + } return layer; }, From 761678a0dad474d6dac72cbc61992bf7986dac51 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 28 Sep 2018 10:42:57 +0800 Subject: [PATCH 0050/1631] fix 3d scale polyfill (#3290) * fix position event handling * fix 3d scale polyfill --- cocos2d/core/3d/polyfill-3d.js | 23 ++++++++--------------- cocos2d/core/CCNode.js | 2 -- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index 9aee418f5fd..92ac3c65591 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -125,7 +125,7 @@ function setPosition (newPosOrX, y, z) { } if (CC_EDITOR) { - let oldPosition = new cc.Vec3(pos); + var oldPosition = new cc.Vec3(pos); } pos.x = x; @@ -136,7 +136,12 @@ function setPosition (newPosOrX, y, z) { // fast check event if (this._eventMask & POSITION_ON) { - this.emit(EventType.POSITION_CHANGED); + if (CC_EDITOR) { + this.emit(EventType.POSITION_CHANGED, oldPosition); + } + else { + this.emit(EventType.POSITION_CHANGED); + } } } @@ -187,17 +192,6 @@ function setQuat (quat, y, z, w) { } } -/** - * !#en - * Returns the scale of the node. - * !#zh 获取节点的缩放。 - * @method getScale - * @return {cc.Vec3} The scale factor - */ -function getScale () { - return cc.v3(this._scale); -} - /** * !#en Sets the scale of three axis in local coordinates of the node. * !#zh 设置节点在本地坐标系中三个坐标轴上的缩放比例。 @@ -283,14 +277,13 @@ proto.setQuat = setQuat; proto.getPosition = getPosition; proto.setPosition = setPosition; -proto.getScale = getScale; proto.setScale = setScale; proto._upgrade_1x_to_2x = _upgrade_1x_to_2x; proto._update3DFunction = _update3DFunction; cc.js.getset(proto, 'position', getPosition, setPosition, false, true); -cc.js.getset(proto, 'scale', getScale, setScale, false, true); +cc.js.getset(proto, 'scale', proto.getScale, setScale, false, true); cc.js.getset(proto, 'is3DNode', function () { return this._is3DNode; diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index d2ce6553681..89c1be1cc1b 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -2085,8 +2085,6 @@ var Node = cc.Class({ * cc.log("Node Scale: " + node.getScale()); */ getScale () { - if (this._scale.x !== this._scale.y) - cc.logID(1603); return this._scale.x; }, From 4e380bf5653f070c87c96612d13dfc529e0c425b Mon Sep 17 00:00:00 2001 From: leda Date: Thu, 27 Sep 2018 19:45:46 -0700 Subject: [PATCH 0051/1631] call jsb.device.setMotion when set setAccelerometer on native (#3332) * modify the game note to fix the tsd * add the note above Sprite.State (#3314) * call jsb.device.setMotion when set setAccelerometer on native * move jsb.setMotion call into inputManager --- cocos2d/core/CCGame.js | 8 +++++++- cocos2d/core/components/CCSprite.js | 6 +++++- cocos2d/core/platform/CCInputExtension.js | 8 ++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 3198b034780..5c1b5c7848f 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -38,7 +38,7 @@ const dynamicAtlasManager = require('../core/renderer/utils/dynamic-atlas/manage /** * !#en An object to boot the game. * !#zh 包含游戏主体信息并负责驱动游戏的游戏对象。 - * @class game + * @class Game * @static * @extends EventTarget */ @@ -879,6 +879,12 @@ EventTarget.call(game); cc.js.addon(game, EventTarget.prototype); /** + * @module cc + */ + +/** + * !#en This is a Game instance. + * !#zh 这是一个 Game 类的实例,包含游戏主体信息并负责驱动游戏的游戏对象。。 * @property game * @type Game */ diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index cd2de5ab180..fb943ad5bf7 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -121,7 +121,11 @@ var SizeMode = cc.Enum({ */ RAW: 2 }); - +/** + * !#en Sprite state can choice the normal or grayscale. + * !#zh 精灵颜色通道模式。 + * @enum Sprite.State + */ var State = cc.Enum({ /** * !#en The normal state diff --git a/cocos2d/core/platform/CCInputExtension.js b/cocos2d/core/platform/CCInputExtension.js index 3bee4aaa707..1c71067ca77 100644 --- a/cocos2d/core/platform/CCInputExtension.js +++ b/cocos2d/core/platform/CCInputExtension.js @@ -73,6 +73,10 @@ inputManager.setAccelerometerEnabled = function (isEnable) { _t._accelCurTime = 0; scheduler.unscheduleUpdate(_t); } + + if (CC_JSB) { + jsb.device.setMotionEnabled(isEnable); + } }; /** @@ -83,6 +87,10 @@ inputManager.setAccelerometerEnabled = function (isEnable) { inputManager.setAccelerometerInterval = function (interval) { if (this._accelInterval !== interval) { this._accelInterval = interval; + + if (CC_JSB) { + jsb.device.setMotionInterval(interval); + } } }; From a61453da84095e98eccc452ed7aaef0e7d219889 Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 28 Sep 2018 11:00:40 +0800 Subject: [PATCH 0052/1631] fix deviceMotionEvent when view rotated (#3330) --- cocos2d/core/platform/CCInputExtension.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cocos2d/core/platform/CCInputExtension.js b/cocos2d/core/platform/CCInputExtension.js index d560ef30d0c..b25e87914a7 100644 --- a/cocos2d/core/platform/CCInputExtension.js +++ b/cocos2d/core/platform/CCInputExtension.js @@ -128,6 +128,12 @@ inputManager.didAccelerate = function (eventData) { y = -(eventData["beta"] / 90) * 0.981; z = (eventData["alpha"] / 90) * 0.981; } + + if (cc.view._isRotated) { + let tmp = x; + x = -y; + y = tmp; + } mAcceleration.x = x; mAcceleration.y = y; From e447af6bcf072723e3d6651b9bf20a1892db04e4 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 28 Sep 2018 14:20:29 +0800 Subject: [PATCH 0053/1631] fix merge --- editor/i18n/en/localization.js | 5 ++++- editor/i18n/zh/localization.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 1255f501d67..0b227c52acc 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -385,6 +385,9 @@ module.exports = { 'column': 'Specify the TiledTile vertical coordinate,use map tile as the unit.', 'gid': 'Specify the TiledTile gid.', 'layer': 'Specify which TiledLayer the TiledTile belong to.' - } + }, + 'skeleton_animation': { + 'search_animation_clips': 'Search Animation Clips' + }, } }; \ No newline at end of file diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 9c13333c3d5..af79d047237 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -389,6 +389,9 @@ module.exports = { 'column': '指定 TiledTile 的纵向坐标,以地图块为单位', 'gid': '指定 TiledTile 的 gid 值', 'layer': '指定 TiledTile 属于哪一个 TiledLayer' - } + }, + 'skeleton_animation': { + 'search_animation_clips': '搜索骨骼动画' + }, } }; \ No newline at end of file From 5f5991d2b282b2041705796dbbc3e30d56341eac Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Fri, 28 Sep 2018 17:08:47 +0800 Subject: [PATCH 0054/1631] move the parent prop from Node to base-node (#3334) --- cocos2d/core/CCNode.js | 2 +- cocos2d/core/utils/base-node.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index be4faadd447..edfa56a9239 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -3139,7 +3139,7 @@ var Node = cc.Class({ * @return {Boolean} */ -var SameNameGetSets = ['parent', 'position', 'scale', 'rotation']; +var SameNameGetSets = ['position', 'scale', 'rotation']; misc.propertyDefine(Node, SameNameGetSets); cc.Node = module.exports = Node; diff --git a/cocos2d/core/utils/base-node.js b/cocos2d/core/utils/base-node.js index 17139e3403e..3be6d38db15 100644 --- a/cocos2d/core/utils/base-node.js +++ b/cocos2d/core/utils/base-node.js @@ -1326,7 +1326,7 @@ if(CC_EDITOR) { } // Define public getter and setter methods to ensure api compatibility. -var SameNameGetSets = ['name', 'children', 'childrenCount',]; +var SameNameGetSets = ['parent', 'name', 'children', 'childrenCount',]; misc.propertyDefine(BaseNode, SameNameGetSets, {}); if (CC_DEV) { From 50c7efc750e880366dd82f081ceacd2df78b2af4 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 28 Sep 2018 17:13:15 +0800 Subject: [PATCH 0055/1631] should raise an exception if failed to initialize shaders (#3329) --- cocos2d/shaders/CCGLProgram.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/shaders/CCGLProgram.js b/cocos2d/shaders/CCGLProgram.js index 533462e6f82..cf646dfb263 100644 --- a/cocos2d/shaders/CCGLProgram.js +++ b/cocos2d/shaders/CCGLProgram.js @@ -94,7 +94,7 @@ cc.GLProgram = cc._Class.extend(/** @lends cc.GLProgram# */{ var status = this._glContext.getShaderParameter(shader, this._glContext.COMPILE_STATUS); if (!status) { - cc.logID(8100, this._glContext.getShaderSource(shader)); + cc.warnID(8100, this._glContext.getShaderSource(shader)); if (type === this._glContext.VERTEX_SHADER) cc.log("cocos2d: \n" + this.vertexShaderLog()); else @@ -150,7 +150,7 @@ cc.GLProgram = cc._Class.extend(/** @lends cc.GLProgram# */{ if (vertShaderStr) { this._vertShader = locGL.createShader(locGL.VERTEX_SHADER); if (!this._compileShader(this._vertShader, locGL.VERTEX_SHADER, vertShaderStr)) { - cc.logID(8101); + cc.warnID(8101); } } @@ -158,7 +158,7 @@ cc.GLProgram = cc._Class.extend(/** @lends cc.GLProgram# */{ if (fragShaderStr) { this._fragShader = locGL.createShader(locGL.FRAGMENT_SHADER); if (!this._compileShader(this._fragShader, locGL.FRAGMENT_SHADER, fragShaderStr)) { - cc.logID(8102); + cc.warnID(8102); } } From ab4a0ce7606578df09b7a7c6cff1ed5c17397369 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Fri, 28 Sep 2018 17:18:26 +0800 Subject: [PATCH 0056/1631] fix the parent prop not defined problem (#3322) --- cocos2d/core/utils/base-node.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cocos2d/core/utils/base-node.js b/cocos2d/core/utils/base-node.js index 3be6d38db15..6cf92d337fb 100644 --- a/cocos2d/core/utils/base-node.js +++ b/cocos2d/core/utils/base-node.js @@ -336,6 +336,13 @@ var BaseNode = cc.Class({ this._renderFlag = RenderFlow.FLAG_TRANSFORM; }, + /** + * !#en The parent of the node. + * !#zh 该节点的父节点。 + * @property {Node} parent + * @example + * cc.log("Node Parent: " + node.parent); + */ /** * !#en Get parent of the node. From 51787386d7e222b43a1701d146171c4796a063b7 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Fri, 28 Sep 2018 17:42:13 +0800 Subject: [PATCH 0057/1631] modify the systemEvent note (#3303) --- cocos2d/core/event/system-event.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/event/system-event.js b/cocos2d/core/event/system-event.js index 1ef25b27e70..7f72f5f58a9 100644 --- a/cocos2d/core/event/system-event.js +++ b/cocos2d/core/event/system-event.js @@ -64,8 +64,22 @@ var EventType = cc.Enum({ }); /** - * !#en The System event, it currently supports the key events and accelerometer events - * !#zh 系统事件,它目前支持按键事件和重力感应事件 + * !#en + * The System event, it currently supports keyboard events and accelerometer events.
+ * You can get the SystemEvent instance with cc.systemEvent.
+ * example: + * ``` + * cc.systemEvent.on(cc.SystemEvent.EventType.DEVICEMOTION, this.onDeviceMotionEvent, this); + * cc.systemEvent.off(cc.SystemEvent.EventType.DEVICEMOTION, this.onDeviceMotionEvent, this); + * ``` + * !#zh + * 系统事件,它目前支持按键事件和重力感应事件。
+ * 你可以通过 cc.systemEvent 获取到 SystemEvent 的实例。
+ * 参考示例: + * ``` + * cc.systemEvent.on(cc.SystemEvent.EventType.DEVICEMOTION, this.onDeviceMotionEvent, this); + * cc.systemEvent.off(cc.SystemEvent.EventType.DEVICEMOTION, this.onDeviceMotionEvent, this); + * ``` * @class SystemEvent * @extends EventTarget */ From 074244ec643034b294d0cc8f758ca598c1e027e4 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Sat, 29 Sep 2018 14:28:45 +0800 Subject: [PATCH 0058/1631] change the content.parent to _view prop (#3331) --- cocos2d/core/components/CCScrollView.js | 39 ++++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index e36878ed77d..2c69c083deb 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -193,6 +193,9 @@ let ScrollView = cc.Class({ this._scrollEventEmitMask = 0; this._isBouncing = false; this._scrolling = false; + + // content parent object + this._view = undefined; }, properties: { @@ -207,6 +210,7 @@ let ScrollView = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.scrollview.content', formerlySerializedAs: 'content', notify (oldValue) { + this._initView(); this._calculateBoundary(); } }, @@ -600,10 +604,10 @@ let ScrollView = cc.Class({ * @return {Vec2} - A Vec2 value indicate the maximize scroll offset in x and y axis. */ getMaxScrollOffset () { - let scrollSize = this.node.getContentSize(); + let viewSize = this._view.getContentSize(); let contentSize = this.content.getContentSize(); - let horizontalMaximizeOffset = contentSize.width - scrollSize.width; - let verticalMaximizeOffset = contentSize.height - scrollSize.height; + let horizontalMaximizeOffset = contentSize.width - viewSize.width; + let verticalMaximizeOffset = contentSize.height - viewSize.height; horizontalMaximizeOffset = horizontalMaximizeOffset >= 0 ? horizontalMaximizeOffset : 0; verticalMaximizeOffset = verticalMaximizeOffset >=0 ? verticalMaximizeOffset : 0; @@ -819,7 +823,7 @@ let ScrollView = cc.Class({ anchor = anchor.clampf(cc.v2(0, 0), cc.v2(1, 1)); - let scrollSize = this.content.parent.getContentSize(); + let scrollSize = this._view.getContentSize(); let contentSize = this.content.getContentSize(); let bottomDeta = this._getContentBottomBoundary() - this._bottomBoundary; bottomDeta = -bottomDeta; @@ -891,7 +895,7 @@ let ScrollView = cc.Class({ if(layout && layout.enabledInHierarchy) { layout.updateLayout(); } - let viewSize = this.content.parent.getContentSize(); + let viewSize = this._view.getContentSize(); let leftBottomPosition = this._convertToContentParentSpace(cc.v2(0, 0)); this._leftBoundary = leftBottomPosition.x; @@ -906,7 +910,7 @@ let ScrollView = cc.Class({ }, _convertToContentParentSpace (position) { - let contentParent = this.content.parent; + let contentParent = this._view; let viewPositionInWorldSpace = contentParent.convertToWorldSpace(position); return contentParent.convertToNodeSpaceAR(viewPositionInWorldSpace); }, @@ -1519,10 +1523,10 @@ let ScrollView = cc.Class({ if (this.content) { this.content.off(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); this.content.off(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); - if (this.content.parent) { - this.content.parent.off(NodeEvent.POSITION_CHANGED, this._calculateBoundary, this); - this.content.parent.off(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); - this.content.parent.off(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); + if (this._view) { + this._view.off(NodeEvent.POSITION_CHANGED, this._calculateBoundary, this); + this._view.off(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); + this._view.off(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); } } } @@ -1532,16 +1536,17 @@ let ScrollView = cc.Class({ onEnable () { if (!CC_EDITOR) { + this._initView(); this._registerEvent(); this.node.on(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); this.node.on(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); if (this.content) { this.content.on(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); this.content.on(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); - if (this.content.parent) { - this.content.parent.on(NodeEvent.POSITION_CHANGED, this._calculateBoundary, this); - this.content.parent.on(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); - this.content.parent.on(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); + if (this._view) { + this._view.on(NodeEvent.POSITION_CHANGED, this._calculateBoundary, this); + this._view.on(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); + this._view.on(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); } } } @@ -1552,6 +1557,12 @@ let ScrollView = cc.Class({ if (this._autoScrolling) { this._processAutoScrolling(dt); } + }, + + _initView () { + if (this.content) { + this._view = this.content.parent; + } } }); From bbcecd16b26350712508a29de74df0496c35edbf Mon Sep 17 00:00:00 2001 From: kenshin <420373550@qq.com> Date: Sat, 29 Sep 2018 14:30:34 +0800 Subject: [PATCH 0059/1631] fix motion streak index count error. (#3336) * fix motion streak index count error. * change --- cocos2d/core/renderer/webgl/assemblers/motion-streak.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index f3bade69cd3..666c9159a02 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -187,7 +187,7 @@ var motionStreakAssembler = { } renderData.vertexCount = renderData.dataLength; - renderData.indiceCount = (renderData.vertexCount - 2)*3; + renderData.indiceCount = renderData.vertexCount === 0 ? 0 : (renderData.vertexCount - 2)*3; }, fillBuffers (comp, renderer) { From 0a12999a7d29c2024ec55bef04c092037363c429 Mon Sep 17 00:00:00 2001 From: kenshin <420373550@qq.com> Date: Sat, 29 Sep 2018 21:35:16 +0800 Subject: [PATCH 0060/1631] add video player source for JSB adapter. (#3341) --- cocos2d/videoplayer/CCVideoPlayer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos2d/videoplayer/CCVideoPlayer.js b/cocos2d/videoplayer/CCVideoPlayer.js index 65cf28bd854..fef547a5ad5 100644 --- a/cocos2d/videoplayer/CCVideoPlayer.js +++ b/cocos2d/videoplayer/CCVideoPlayer.js @@ -270,7 +270,8 @@ let VideoPlayer = cc.Class({ statics: { EventType: EventType, - ResourceType: ResourceType + ResourceType: ResourceType, + Impl: VideoPlayerImpl }, ctor () { From ab4796582ea36fdeb68ea8a007f095fcdc49a034 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Sun, 30 Sep 2018 14:44:51 +0800 Subject: [PATCH 0061/1631] support 3d raycast (#3326) * support 3d raycast * fixed test * use DataView to read vertex * refine mesh setVertexes * refine raycast * refine rayMesh * fixed test * support specify the raycast root node * refine geom utils api * refine api * refine code --- cocos2d/core/3d/CCModel.js | 145 ++++---------- cocos2d/core/3d/geom-utils/aabb.js | 131 ++++++++++++ cocos2d/core/3d/geom-utils/index.js | 7 + cocos2d/core/3d/geom-utils/intersect.js | 253 ++++++++++++++++++++++++ cocos2d/core/3d/geom-utils/ray.js | 101 ++++++++++ cocos2d/core/3d/geom-utils/triangle.js | 116 +++++++++++ cocos2d/core/3d/index.js | 1 + cocos2d/core/camera/CCCamera.js | 20 ++ cocos2d/core/mesh/CCMesh.js | 87 +++++--- cocos2d/core/mesh/CCMeshRenderer.js | 6 + 10 files changed, 728 insertions(+), 139 deletions(-) create mode 100644 cocos2d/core/3d/geom-utils/aabb.js create mode 100644 cocos2d/core/3d/geom-utils/index.js create mode 100644 cocos2d/core/3d/geom-utils/intersect.js create mode 100644 cocos2d/core/3d/geom-utils/ray.js create mode 100644 cocos2d/core/3d/geom-utils/triangle.js diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index da6150d89d0..c8c8697169a 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -50,6 +50,19 @@ const _compType2Array = { 5126: Float32Array, }; +const _gltfAttribMap = { + POSITION: gfx.ATTR_POSITION, + NORMAL: gfx.ATTR_NORMAL, + TANGENT: gfx.ATTR_TANGENT, + COLOR_0: gfx.ATTR_COLOR0, + TEXCOORD_0: gfx.ATTR_UV0, + TEXCOORD_1: gfx.ATTR_UV1, + TEXCOORD_2: gfx.ATTR_UV2, + TEXCOORD_3: gfx.ATTR_UV3, + JOINTS_0: gfx.ATTR_JOINTS, + WEIGHTS_0: gfx.ATTR_WEIGHTS +}; + function createArray(gltf, bin, accessorID) { let acc = gltf.accessors[accessorID]; let bufView = gltf.bufferViews[acc.bufferView]; @@ -110,122 +123,18 @@ var Model = cc.Class({ let byteOffset = 10e7, maxByteOffset = 0; - if (attributes.POSITION !== undefined) { - let acc = accessors[attributes.POSITION]; + for (let gltfAttribName in attributes) { + const gfxAttribName = _gltfAttribMap[gltfAttribName]; + if (gfxAttribName === undefined) { + console.error(`Found unacceptable GlTf attribute ${gltfAttribName}.`); + return; + } + let acc = accessors[attributes[gltfAttribName]]; let vbView = gltf.bufferViews[acc.bufferView]; vcount = acc.count; vfmt.push({ - name: gfx.ATTR_POSITION, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - if (attributes.NORMAL !== undefined) { - let acc = accessors[attributes.NORMAL]; - let vbView = gltf.bufferViews[acc.bufferView]; - - vfmt.push({ - name: gfx.ATTR_NORMAL, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - if (attributes.TANGENT !== undefined) { - let acc = accessors[attributes.TANGENT]; - let vbView = gltf.bufferViews[acc.bufferView]; - vfmt.push({ - name: gfx.ATTR_TANGENT, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - if (attributes.COLOR_0 !== undefined) { - let acc = accessors[attributes.COLOR_0]; - let vbView = gltf.bufferViews[acc.bufferView]; - vfmt.push({ - name: gfx.ATTR_COLOR0, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - if (attributes.TEXCOORD_0 !== undefined) { - let acc = accessors[attributes.TEXCOORD_0]; - let vbView = gltf.bufferViews[acc.bufferView]; - vfmt.push({ - name: gfx.ATTR_UV0, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - if (attributes.TEXCOORD_1 !== undefined) { - let acc = accessors[attributes.TEXCOORD_1]; - let vbView = gltf.bufferViews[acc.bufferView]; - vfmt.push({ - name: gfx.ATTR_UV1, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - if (attributes.TEXCOORD_2 !== undefined) { - let acc = accessors[attributes.TEXCOORD_2]; - let vbView = gltf.bufferViews[acc.bufferView]; - vfmt.push({ - name: gfx.ATTR_UV2, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - if (attributes.TEXCOORD_3 !== undefined) { - let acc = accessors[attributes.TEXCOORD_3]; - let vbView = gltf.bufferViews[acc.bufferView]; - vfmt.push({ - name: gfx.ATTR_UV3, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - if (attributes.JOINTS_0 !== undefined) { - let acc = accessors[attributes.JOINTS_0]; - let vbView = gltf.bufferViews[acc.bufferView]; - vfmt.push({ - name: gfx.ATTR_JOINTS, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - if (attributes.WEIGHTS_0 !== undefined) { - let acc = accessors[attributes.WEIGHTS_0]; - let vbView = gltf.bufferViews[acc.bufferView]; - vfmt.push({ - name: gfx.ATTR_WEIGHTS, type: acc.componentType, num: _type2size[acc.type], + name: gfxAttribName, type: acc.componentType, num: _type2size[acc.type], byteLength: vbView.byteLength, byteOffset: vbView.byteOffset }); @@ -323,6 +232,18 @@ var Model = cc.Class({ data: ibData } + if (primitive.attributes.POSITION) { + let gltfAccessor = accessors[primitive.attributes.POSITION]; + let minPos = meshAsset._minPos, maxPos = meshAsset._maxPos + min = gltfAccessor.min, max = gltfAccessor.max; + minPos.x = Math.min(minPos.x, min[0]); + minPos.y = Math.min(minPos.y, min[1]); + minPos.z = Math.min(minPos.z, min[2]); + maxPos.x = Math.max(maxPos.x, max[0]); + maxPos.y = Math.max(maxPos.y, max[1]); + maxPos.z = Math.max(maxPos.z, max[2]); + } + meshAsset._subMeshes[i] = new renderEngine.InputAssembler(vb.buffer, ibBuffer); meshAsset._vbs[i] = vb; meshAsset._ibs[i] = ib; diff --git a/cocos2d/core/3d/geom-utils/aabb.js b/cocos2d/core/3d/geom-utils/aabb.js new file mode 100644 index 00000000000..68ae79abf8c --- /dev/null +++ b/cocos2d/core/3d/geom-utils/aabb.js @@ -0,0 +1,131 @@ +let vec3 = cc.vmath.vec3; +let mat3 = cc.vmath.mat3; + +let _v3_tmp = vec3.create(); +let _v3_tmp2 = vec3.create(); +let _m3_tmp = mat3.create(); + +// https://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/ +let transform_extent_m4 = function (out, extent, m4) { + _m3_tmp.m00 = Math.abs(m4.m00); _m3_tmp.m01 = Math.abs(m4.m01); _m3_tmp.m02 = Math.abs(m4.m02); + _m3_tmp.m03 = Math.abs(m4.m04); _m3_tmp.m04 = Math.abs(m4.m05); _m3_tmp.m05 = Math.abs(m4.m06); + _m3_tmp.m06 = Math.abs(m4.m08); _m3_tmp.m07 = Math.abs(m4.m09); _m3_tmp.m08 = Math.abs(m4.m10); + vec3.transformMat3(out, extent, _m3_tmp); +}; + +/** + * @class geomUtils.Aabb + * @param {Number} px + * @param {Number} py + * @param {Number} pz + * @param {Number} w + * @param {Number} h + * @param {Number} l + */ +function aabb(px, py, pz, w, h, l) { + this.center = vec3.create(px, py, pz); + this.halfExtents = vec3.create(w, h, l); +} + +let proto = aabb.prototype; + +/** + * Get the bounding points of this shape + * @method getBoundary + * @param {vec3} minPos + * @param {vec3} maxPos + */ +proto.getBoundary = function (minPos, maxPos) { + vec3.sub(minPos, this.center, this.halfExtents); + vec3.add(maxPos, this.center, this.halfExtents); +} + +/** + * Transform this shape + * @method transform + * @param {mat4} m the transform matrix + * @param {vec3} pos the position part of the transform + * @param {quat} rot the rotation part of the transform + * @param {vec3} scale the scale part of the transform + * @param {geomUtils.Aabb} [out] the target shape + */ +proto.transform = function (m, pos, rot, scale, out) { + if (!out) out = this; + vec3.transformMat4(out.center, this.center, m); + transform_extent_m4(out.halfExtents, this.halfExtents, m); +} + + +/** + * create a new aabb + * @method create + * @param {number} px X coordinates for aabb's original point + * @param {number} py Y coordinates for aabb's original point + * @param {number} pz Z coordinates for aabb's original point + * @param {number} w the half of aabb width + * @param {number} h the half of aabb height + * @param {number} l the half of aabb length + * @return {geomUtils.Aabb} + */ +aabb.create = function (px, py, pz, w, h, l) { + return new aabb(px, py, pz, w, h, l); +} + +/** + * clone a new aabb + * @method clone + * @param {geomUtils.Aabb} a the source aabb + * @return {geomUtils.Aabb} + */ +aabb.clone = function (a) { + return new Aabb(a.center.x, a.center.y, a.center.z, + a.halfExtents.x, a.halfExtents.y, a.halfExtents.z); +} + +/** + * copy the values from one aabb to another + * @method copy + * @param {geomUtils.Aabb} out the receiving aabb + * @param {geomUtils.Aabb} a the source aabb + * @return {geomUtils.Aabb} + */ +aabb.copy = function (out, a) { + vec3.copy(out.center, a.center); + vec3.copy(out.halfExtents, a.halfExtents); + + return out; +} + +/** + * create a new aabb from two corner points + * @method fromPoints + * @param {geomUtils.Aabb} out the receiving aabb + * @param {vec3} minPos lower corner position of the aabb + * @param {vec3} maxPos upper corner position of the aabb + * @return {geomUtils.Aabb} + */ +aabb.fromPoints = function (out, minPos, maxPos) { + vec3.scale(out.center, vec3.add(_v3_tmp, minPos, maxPos), 0.5); + vec3.scale(out.halfExtents, vec3.sub(_v3_tmp2, maxPos, minPos), 0.5); + return out; +} + +/** + * Set the components of a aabb to the given values + * @method set + * @param {geomUtils.Aabb} out the receiving aabb + * @param {number} px X coordinates for aabb's original point + * @param {number} py Y coordinates for aabb's original point + * @param {number} pz Z coordinates for aabb's original point + * @param {number} w the half of aabb width + * @param {number} h the half of aabb height + * @param {number} l the half of aabb length + * @return {geomUtils.Aabb} out + */ +aabb.set = function (out, px, py, pz, w, h, l) { + vec3.set(out.center, px, py, pz); + vec3.set(out.halfExtents, w, h, l); + return out; +} + +module.exports = aabb; diff --git a/cocos2d/core/3d/geom-utils/index.js b/cocos2d/core/3d/geom-utils/index.js new file mode 100644 index 00000000000..4241ce98557 --- /dev/null +++ b/cocos2d/core/3d/geom-utils/index.js @@ -0,0 +1,7 @@ + +cc.geomUtils = { + Triangle: require('./triangle'), + Aabb: require('./aabb'), + Ray: require('./ray'), + intersect: require('./intersect') +}; diff --git a/cocos2d/core/3d/geom-utils/intersect.js b/cocos2d/core/3d/geom-utils/intersect.js new file mode 100644 index 00000000000..3ef6d8bf8e6 --- /dev/null +++ b/cocos2d/core/3d/geom-utils/intersect.js @@ -0,0 +1,253 @@ + +const renderEngine = require('../../renderer/render-engine'); +const RecyclePool = renderEngine.RecyclePool; +const aabb = require('./aabb'); +const ray = require('./ray'); +const triangle = require('./triangle'); + +const mat4 = cc.vmath.mat4; +const vec3 = cc.vmath.vec3; + +/** + * !#en 3D intersection helper class + * !#zh 辅助类,用于测试 3D 物体是否相交 + * @class geomUtils.intersect + * @static + */ +let intersect = {}; + +/** + * !#en + * Check whether ray intersect with a 3d aabb + * !#zh + * 检测射线是否与 3D 包围盒相交 + * @method rayAabb + * @param {geomUtils.Ray} ray + * @param {geomUtils.Aabb} aabb + * @return Number +*/ +intersect.rayAabb = (function () { + let min = vec3.create(); + let max = vec3.create(); + return function (ray, aabb) { + let o = ray.o, d = ray.d; + let ix = 1 / d.x, iy = 1 / d.y, iz = 1 / d.z; + vec3.sub(min, aabb.center, aabb.halfExtents); + vec3.add(max, aabb.center, aabb.halfExtents); + let t1 = (min.x - o.x) * ix; + let t2 = (max.x - o.x) * ix; + let t3 = (min.y - o.y) * iy; + let t4 = (max.y - o.y) * iy; + let t5 = (min.z - o.z) * iz; + let t6 = (max.z - o.z) * iz; + let tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6)); + let tmax = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)), Math.max(t5, t6)); + if (tmax < 0 || tmin > tmax) return 0; + return tmin; + }; +})(); + +/** + * !#en + * Check whether ray intersect with a 3D triangle + * !#zh + * 检测射线是否与 3D 三角形相交 + * @method rayTriangle + * @param {geomUtils.Ray} ray + * @param {geomUtils.Triangle} triangle +*/ +intersect.rayTriangle = (function () { + let ab = vec3.create(0, 0, 0); + let ac = vec3.create(0, 0, 0); + let pvec = vec3.create(0, 0, 0); + let tvec = vec3.create(0, 0, 0); + let qvec = vec3.create(0, 0, 0); + + return function (ray, triangle) { + vec3.sub(ab, triangle.b, triangle.a); + vec3.sub(ac, triangle.c, triangle.a); + + vec3.cross(pvec, ray.d, ac); + let det = vec3.dot(ab, pvec); + + if (det <= 0) { + return 0; + } + + vec3.sub(tvec, ray.o, triangle.a); + let u = vec3.dot(tvec, pvec); + if (u < 0 || u > det) { + return 0; + } + + vec3.cross(qvec, tvec, ab); + let v = vec3.dot(ray.d, qvec); + if (v < 0 || u + v > det) { + return 0; + } + + let t = vec3.dot(ac, qvec) / det; + if (t < 0) return 0; + return t; + }; +})(); + + +intersect.rayMesh = (function () { + const gfx = renderEngine.gfx; + + let tri = triangle.create(); + let minDist = Infinity; + + const _compType2fn = { + 5120: 'getInt8', + 5121: 'getUint8', + 5122: 'getInt16', + 5123: 'getUint16', + 5124: 'getInt32', + 5125: 'getUint32', + 5126: 'getFloat32', + }; + + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness + const littleEndian = (function () { + let buffer = new ArrayBuffer(2); + new DataView(buffer).setInt16(0, 256, true); + // Int16Array uses the platform's endianness. + return new Int16Array(buffer)[0] === 256; + })(); + + return function (ray, mesh) { + minDist = Infinity; + let subMeshes = mesh._subMeshes; + for (let i = 0; i < subMeshes.length; i++) { + if (subMeshes[i]._primitiveType !== gfx.PT_TRIANGLES) continue; + + let vb = (mesh._vbs[i] || mesh._vbs[0]); + let vbData = vb.data; + let dv = new DataView(vbData.buffer, vbData.byteOffset, vbData.byteLength); + let ib = mesh._ibs[i].data; + + let format = vb.buffer._format; + let fmt = format.element(gfx.ATTR_POSITION); + let offset = fmt.offset, stride = fmt.stride; + let fn = _compType2fn[fmt.type]; + for (let i = 0; i < ib.length; i += 3) { + let idx = ib[i] * stride + offset; + vec3.set(tri.a, dv[fn]([idx], littleEndian), dv[fn]([idx + 4], littleEndian), dv[fn]([idx + 8], littleEndian)); + idx = ib[i + 1] * stride + offset; + vec3.set(tri.b, dv[fn]([idx], littleEndian), dv[fn]([idx + 4], littleEndian), dv[fn]([idx + 8], littleEndian)); + idx = ib[i + 2] * stride + offset; + vec3.set(tri.c, dv[fn]([idx], littleEndian), dv[fn]([idx + 4], littleEndian), dv[fn]([idx + 8], littleEndian)); + + let dist = intersect.rayTriangle(ray, tri); + if (dist > 0 && dist < minDist) { + minDist = dist; + } + } + } + return minDist; + }; +})(); + + +/** + * !#en + * Check whether ray intersect with nodes + * !#zh + * 检测射线是否与物体有交集 + * @method raycast + * @param {Node} root - If root is null, then traversal nodes from scene node + * @param {geomUtils.Ray} worldRay + * @param {Function} handler + * @param {Function} filter +*/ +intersect.raycast = (function () { + function traversal (node, cb) { + var children = node.children; + + for (var i = children.length - 1; i >= 0; i--) { + var child = children[i]; + traversal(child, cb); + } + + cb(node); + } + + function cmp (a, b) { + return a.distance - b.distance; + } + + function transformMat4Normal (out, a, m) { + let x = a.x, y = a.y, z = a.z, + rhw = m.m03 * x + m.m07 * y + m.m11 * z; + rhw = rhw ? 1 / rhw : 1; + out.x = (m.m00 * x + m.m04 * y + m.m08 * z) * rhw; + out.y = (m.m01 * x + m.m05 * y + m.m09 * z) * rhw; + out.z = (m.m02 * x + m.m06 * y + m.m10 * z) * rhw; + return out; + } + + let results = new RecyclePool(function () { + return { + distance: 0, + node: null + } + }, 1); + + // temp variable + let nodeAabb = aabb.create(); + let minPos = vec3.create(); + let maxPos = vec3.create(); + + let modelRay = ray.create(); + let m4 = mat4.create(); + + function distanceValid (distance) { + return distance > 0 && distance < Infinity; + } + + return function (root, worldRay, handler, filter) { + results.reset(); + + root = root || cc.director.getScene(); + traversal(root, function (node) { + if (filter && !filter(node)) return; + + // transform world ray to model ray + mat4.invert(m4, node.getWorldMatrix(m4)); + vec3.transformMat4(modelRay.o, worldRay.o, m4); + vec3.normalize(modelRay.d, transformMat4Normal(modelRay.d, worldRay.d, m4)); + + // raycast with bounding box + let distance = Infinity; + let component = node._renderComponent; + if (component && component._boundingBox) { + distance = intersect.rayAabb(modelRay, component._boundingBox); + } + else if (node.width && node.height) { + vec3.set(minPos, -node.width * node.anchorX, -node.height * node.anchorY, node.z); + vec3.set(maxPos, node.width * (1 - node.anchorX), node.height * (1 - node.anchorY), node.z); + aabb.fromPoints(nodeAabb, minPos, maxPos); + distance = intersect.rayAabb(modelRay, nodeAabb); + } + + if (!distanceValid(distance)) return; + + if (handler) { + distance = handler(modelRay, node, distance); + } + + if (distanceValid(distance)) { + let res = results.add(); + res.node = node; + res.distance = distance; + } + }); + + results.sort(cmp); + return results; + } +})(); + +module.exports = intersect; diff --git a/cocos2d/core/3d/geom-utils/ray.js b/cocos2d/core/3d/geom-utils/ray.js new file mode 100644 index 00000000000..d007d094122 --- /dev/null +++ b/cocos2d/core/3d/geom-utils/ray.js @@ -0,0 +1,101 @@ +const vec3 = cc.vmath.vec3; + +/** + * @class geomUtils.Ray + * @param {Number} ox + * @param {Number} oy + * @param {Number} oz + * @param {Number} dx + * @param {Number} dy + * @param {Number} dz + */ +function ray(ox, oy, oz, dx, dy, dz) { + this.o = vec3.new(ox, oy, oz); + this.d = vec3.new(dx, dy, dz); +} + +/** + * create a new ray + * @method create + * @param {Number} ox origin X component + * @param {Number} oy origin Y component + * @param {Number} oz origin Z component + * @param {Number} dx dir X component + * @param {Number} dy dir Y component + * @param {Number} dz dir Z component + * @return {geomUtils.Ray} + */ +ray.create = function (ox, oy, oz, dx, dy, dz) { + return new ray(ox, oy, oz, dx, dy, dz); +} + +/** + * Creates a new ray initialized with values from an existing ray + * @method clone + * @param {geomUtils.Ray} a ray to clone + * @returns {geomUtils.Ray} a new ray + */ +ray.clone = function (a) { + return new ray( + a.o.x, a.o.y, a.o.z, + a.d.x, a.d.y, a.d.z + ); +} + +/** + * Copy the values from one ray to another + * @method copy + * @param {geomUtils.Ray} out the receiving ray + * @param {geomUtils.Ray} a the source ray + * @returns {geomUtils.Ray} out + */ +ray.copy = function (out, a) { + out.o.x = a.o.x; + out.o.y = a.o.y; + out.o.z = a.o.z; + out.d.x = a.d.x; + out.d.y = a.d.y; + out.d.z = a.d.z; + + return out; +} + +/** + * Set the components of a vec3 to the given values + * @method set + * @param {vec3} out the receiving vector + * @param {Number} ox origin X component + * @param {Number} oy origin Y component + * @param {Number} oz origin Z component + * @param {Number} dx dir X component + * @param {Number} dy dir Y component + * @param {Number} dz dir Z component + * @returns {vec3} out + */ +ray.set = function (out, ox, oy, oz, dx, dy, dz) { + out.o.x = ox; + out.o.y = oy; + out.o.z = oz; + out.d.x = dx; + out.d.y = dy; + out.d.z = dz; + + return out; +} + +/** + * create ray from 2 points + * @method fromPoints + * @param {geomUtils.Ray} out the receiving plane + * @param {vec3} origin + * @param {vec3} lookAt + * @returns {geomUtils.Ray} out + */ +ray.fromPoints = function (out, origin, lookAt) { + vec3.copy(out.o, origin); + vec3.normalize(out.d, vec3.sub(out.d, lookAt, origin)); + + return out; +} + +module.exports = ray; diff --git a/cocos2d/core/3d/geom-utils/triangle.js b/cocos2d/core/3d/geom-utils/triangle.js new file mode 100644 index 00000000000..7b7f32b33d7 --- /dev/null +++ b/cocos2d/core/3d/geom-utils/triangle.js @@ -0,0 +1,116 @@ +const vec3 = cc.vmath.vec3; + +/** + * @class geomUtils.Triangle + * @param {Number} ax + * @param {Number} ay + * @param {Number} az + * @param {Number} bx + * @param {Number} by + * @param {Number} bz + * @param {Number} cx + * @param {Number} cy + * @param {Number} cz + */ +function triangle(ax, ay, az, bx, by, bz, cx, cy, cz) { + this.a = vec3.create(ax, ay, az); + this.b = vec3.create(bx, by, bz); + this.c = vec3.create(cx, cy, cz); +} + +/** + * create a new triangle + * @method create + * @param {number} ax + * @param {number} ay + * @param {number} az + * @param {number} bx + * @param {number} by + * @param {number} bz + * @param {number} cx + * @param {number} cy + * @param {number} cz + * @return {geomUtils.Triangle} + */ +triangle.create = function (ax, ay, az, bx, by, bz, cx, cy, cz) { + return new triangle(ax, ay, az, bx, by, bz, cx, cy, cz); +} + +/** + * clone a new triangle + * @method clone + * @param {geomUtils.Triangle} t the source plane + * @return {geomUtils.Triangle} + */ +triangle.clone = function (t) { + return new triangle( + t.a.x, t.a.y, t.a.z, + t.b.x, t.b.y, t.b.z, + t.c.x, t.c.y, t.c.z + ); +} + +/** + * copy the values from one triangle to another + * @method copy + * @param {geomUtils.Triangle} out the receiving triangle + * @param {geomUtils.Triangle} t the source triangle + * @return {geomUtils.Triangle} + */ +triangle.copy = function (out, t) { + vec3.copy(out.a, t.a); + vec3.copy(out.b, t.b); + vec3.copy(out.c, t.c); + + return out; +} + +/** + * Create a triangle from three points + * @method fromPoints + * @param {geomUtils.Triangle} out the receiving triangle + * @param {vec3} a + * @param {vec3} b + * @param {vec3} c + * @return {geomUtils.Triangle} + */ +triangle.fromPoints = function (out, a, b, c) { + vec3.copy(out.a, a); + vec3.copy(out.b, b); + vec3.copy(out.c, c); + return out; +} + +/** + * Set the components of a triangle to the given values + * + * @method set + * @param {geomUtils.Triangle} out the receiving plane + * @param {number} ax X component of a + * @param {number} ay Y component of a + * @param {number} az Z component of a + * @param {number} bx X component of b + * @param {number} by Y component of b + * @param {number} bz Z component of b + * @param {number} cx X component of c + * @param {number} cy Y component of c + * @param {number} cz Z component of c + * @return {plane} + */ +triangle.set = function (out, ax, ay, az, bx, by, bz, cx, cy, cz) { + out.a.x = ax; + out.a.y = ay; + out.a.z = az; + + out.b.x = bx; + out.b.y = by; + out.b.z = bz; + + out.c.x = cx; + out.c.y = cy; + out.c.z = cz; + + return out; +} + +module.exports = triangle; diff --git a/cocos2d/core/3d/index.js b/cocos2d/core/3d/index.js index 6b476c92be5..b15a29b8fe2 100644 --- a/cocos2d/core/3d/index.js +++ b/cocos2d/core/3d/index.js @@ -1,6 +1,7 @@ if (!CC_TEST && (!CC_EDITOR || !Editor.isMainProcess)) { require('./polyfill-3d'); + require('./geom-utils'); } require('./CCModel'); diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index b9fb7b39830..0f21f25e44a 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -28,6 +28,7 @@ const AffineTrans = require('../utils/affine-transform'); const renderEngine = require('../renderer/render-engine'); const renderer = require('../renderer/index'); const game = require('../CCGame'); +const ray = require('../3d/geom-utils/ray'); const mat4 = cc.vmath.mat4; const vec2 = cc.vmath.vec2; @@ -36,6 +37,9 @@ const vec3 = cc.vmath.vec3; let _mat4_temp_1 = mat4.create(); let _mat4_temp_2 = mat4.create(); +let _v3_temp_1 = vec3.create(); +let _v3_temp_2 = vec3.create(); + let _cameras = []; let _debugCamera = null; @@ -620,6 +624,22 @@ let Camera = cc.Class({ return out; }, + /** + * !#en + * Get a ray from screen position + * !#zh + * 从屏幕坐标获取一条射线 + * @method getRay + * @param {Vec3} screenPos + * @return {Ray} + */ + getRay (screenPos) { + this.node.getWorldPos(_v3_temp_1); + this._camera.screenToWorld(_v3_temp_2, screenPos, cc.visibleRect.width, cc.visibleRect.height); + vec3.sub(_v3_temp_2, _v3_temp_2, _v3_temp_1); + return ray.create(_v3_temp_1.x, _v3_temp_1.y, _v3_temp_1.z, _v3_temp_2.x, _v3_temp_2.y, _v3_temp_2.z); + }, + /** * !#en * Check whether the node is in the camera. diff --git a/cocos2d/core/mesh/CCMesh.js b/cocos2d/core/mesh/CCMesh.js index 6e02a9327d3..aea94a3a29a 100644 --- a/cocos2d/core/mesh/CCMesh.js +++ b/cocos2d/core/mesh/CCMesh.js @@ -33,19 +33,19 @@ function applyColor (data, offset, value) { function applyVec2 (data, offset, value) { data[offset] = value.x; - data[offset+1] = value.y; + data[offset + 1] = value.y; } function applyVec3 (data, offset, value) { data[offset] = value.x; - data[offset+1] = value.y; - data[offset+2] = value.z; + data[offset + 1] = value.y; + data[offset + 2] = value.z; } - /** - * @module cc - */ +/** +* @module cc +*/ /** * !#en Mesh Asset. * !#zh 网格资源。 @@ -91,6 +91,9 @@ var Mesh = cc.Class({ this._ibs = []; this._vbs = []; + + this._minPos = cc.v3(); + this._maxPos = cc.v3(); }, /** @@ -105,8 +108,8 @@ var Mesh = cc.Class({ */ init (vertexFormat, vertexCount, dynamic) { this.clear(); - - let data = new Uint8Array(vertexFormat._bytes*vertexCount); + + let data = new Uint8Array(vertexFormat._bytes * vertexCount); let vb = new gfx.VertexBuffer( renderer.device, vertexFormat, @@ -118,12 +121,10 @@ var Mesh = cc.Class({ this._vbs[0] = { buffer: vb, data: data, - float32Data: new Float32Array(data.buffer), - uint32Data: new Uint32Array(data.buffer), dirty: true }; }, - + /** * !#en * Set the vertex values. @@ -131,7 +132,7 @@ var Mesh = cc.Class({ * 设置顶点数据 * @method setVertexes * @param {String} name - the attribute name, e.g. gfx.ATTR_POSITION - * @param {[Vec2|Vec3|Color]} values - the vertex values + * @param {[Vec2|Vec3|Color|Number]} values - the vertex values * @param {Number} [index] */ setVertexes (name, values, index) { @@ -144,29 +145,61 @@ var Mesh = cc.Class({ return cc.warn(`Cannot find ${name} attribute in vertex defines.`); } - let stride = el.stride/4; - let offset = el.offset/4; - let data; - let applyFunc; + // whether the values is expanded + let isFlatMode = typeof values[0] === 'number'; + let elNum = el.num; + + let reader = Float32Array; + let bytes = 4; if (name === gfx.ATTR_COLOR) { - data = vb.uint32Data; - applyFunc = applyColor; + if (isFlatMode) { + reader = Float32Array; + bytes = 1; + } + else { + reader = Uint32Array; + } + } + + let data = vb[reader.name]; + if (!data) { + let vbData = vb.data; + data = vb[reader.name] = new reader(vbData.buffer, vbData.byteOffset, vbData.byteLength / bytes); + } + + let stride = el.stride / bytes; + let offset = el.offset / bytes; + + if (isFlatMode) { + for (let i = 0, l = (values.length / elNum); i < l; i++) { + let sOffset = i * elNum; + let dOffset = i * stride + offset; + for (let j = 0; j < elNum; j++) { + data[dOffset + j] = values[sOffset + j]; + } + } } else { - data = vb.float32Data; - if (el.num === 2) { - applyFunc = applyVec2; + let applyFunc; + if (name === gfx.ATTR_COLOR) { + applyFunc = applyColor; } else { - applyFunc = applyVec3; + + if (elNum === 2) { + applyFunc = applyVec2; + } + else { + applyFunc = applyVec3; + } } - } - for (let i = 0, l = values.length; i < l; i++) { - let v = values[i]; - let vOffset = i * stride + offset; - applyFunc(data, vOffset, v); + for (let i = 0, l = values.length; i < l; i++) { + let v = values[i]; + let vOffset = i * stride + offset; + applyFunc(data, vOffset, v); + } } vb.dirty = true; }, diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index c9cea14f247..c0b0f847ca6 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -28,6 +28,7 @@ const Mesh = require('./CCMesh'); const renderEngine = require('../renderer/render-engine'); const gfx = renderEngine.gfx; const RenderFlow = require('../renderer/render-flow'); +const aabb = require('../3d/geom-utils/aabb'); let MeshRenderer = cc.Class({ name: 'cc.MeshRenderer', @@ -66,6 +67,7 @@ let MeshRenderer = cc.Class({ ctor () { this._renderDatas = []; this._materials = []; + this._boundingBox = null; }, onEnable () { @@ -100,6 +102,10 @@ let MeshRenderer = cc.Class({ if (this._material && !force) { return; } + + if (aabb) { + this._boundingBox = aabb.fromPoints(aabb.create(), this._mesh._minPos, this._mesh._maxPos); + } this._reset(); From 31c536dfaf35bf63d8bf44b718aa69e4d517a7c2 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Sun, 30 Sep 2018 15:02:04 +0800 Subject: [PATCH 0062/1631] refine node api (#3340) * refine Node api * refine node api * refine node api * refine node api * refine node api * refine node api * refine node api * refine node api --- cocos2d/core/3d/polyfill-3d.js | 163 ++++------- cocos2d/core/CCNode.js | 334 ++++++++++++++--------- cocos2d/core/CCScene.js | 4 + cocos2d/core/physics/CCPhysicsManager.js | 2 +- cocos2d/core/physics/utils.js | 10 +- cocos2d/core/value-types/quat.js | 7 + cocos2d/deprecated.js | 26 ++ test/qunit/unit-es5/test-animation.js | 9 +- 8 files changed, 308 insertions(+), 247 deletions(-) diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index 92ac3c65591..40c0f41b694 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -30,6 +30,7 @@ const DirtyFlag = Node._LocalDirtyFlag; const math = require('../renderer/render-engine').math; const RenderFlow = require('../renderer/render-flow'); const misc = require('../utils/misc'); +const vec3 = cc.vmath.vec3; // ====== Node transform polyfills ====== const ONE_DEGREE = Math.PI / 180; @@ -81,32 +82,6 @@ function _calculWorldMatrix3d () { } - -/** - * !#en Returns a copy of the position (x, y, z) of the node in its parent's coordinates. - * !#zh 获取节点在父节点坐标系中的位置(x, y, z)。 - * @method getPosition - * @return {Vec3} The position (x, y, z) of the node in its parent's coordinates - */ -function getPosition () { - return new cc.Vec3(this._position); -} - -/** - * !#en - * Sets the position (x, y, z) of the node in its parent's coordinates.
- * Usually we use cc.v3(x, y, z) to compose cc.Vec3 object.
- * and Passing two numbers (x, y, z) is more efficient than passing cc.Vec3 object. - * !#zh - * 设置节点在父节点坐标系中的位置。
- * 可以通过两种方式设置坐标点:
- * 1. 传入 3 个数值 x, y, z。
- * 2. 传入 cc.v3(x, y, z) 类型为 cc.Vec3 的对象。 - * @method setPosition - * @param {Vec3|Number} newPosOrX - X coordinate for position or the position (x, y, z) of the node in coordinates - * @param {Number} [y] - Y coordinate for position - * @param {Number} [z] - Z coordinate for position - */ function setPosition (newPosOrX, y, z) { let x; if (y === undefined) { @@ -145,64 +120,6 @@ function setPosition (newPosOrX, y, z) { } } -/** - * !#en Get rotation of node (in quaternion). - * !#zh 获取该节点的 quaternion 旋转角度。 - * @method getQuat - * @return {cc.Quat} Quaternion object represents the rotation - */ -function getQuat () { - return math.quat.clone(this._quat); -} - -/** - * !#en Set rotation of node (in quaternion). - * !#zh 设置该节点的 quaternion 旋转角度。 - * @method setQuat - * @param {cc.Quat|Number} quat Quaternion object represents the rotation or the x value of quaternion - * @param {Number} y y value of quternion - * @param {Number} z z value of quternion - * @param {Number} w w value of quternion - */ -function setQuat (quat, y, z, w) { - let x = quat; - if (y === undefined) { - x = quat.x; - y = quat.y; - z = quat.z; - w = quat.w; - } - - let old = this._quat; - if (old.x !== x || old.y !== y || old.z !== z || old.w !== w) { - old.x = x; - old.y = y; - old.z = z; - old.w = w; - this.setLocalDirty(DirtyFlag.ROTATION); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; - - if (this._eventMask & ROTATION_ON) { - this.emit(EventType.ROTATION_CHANGED); - } - } - - if (CC_EDITOR) { - this._syncEulerAngles(); - } -} - -/** - * !#en Sets the scale of three axis in local coordinates of the node. - * !#zh 设置节点在本地坐标系中三个坐标轴上的缩放比例。 - * @method setScale - * @param {Number|Vec3} x - scaleX or scale object - * @param {Number} [y] - * @param {Number} [z] - * @example - * node.setScale(cc.v2(2, 2, 2)); - * node.setScale(2); - */ function setScale (x, y, z) { if (x && typeof x !== 'number') { y = x.y; @@ -229,33 +146,21 @@ function setScale (x, y, z) { } } -function _syncEulerAngles () { - this._rotationX = this._quat.getRoll(); - this._rotationY = this._quat.getPitch(); - this._rotationZ = this._quat.getYaw(); -} - function _update3DFunction () { if (this._is3DNode) { this._updateLocalMatrix = _updateLocalMatrix3d; this._calculWorldMatrix = _calculWorldMatrix3d; this._mulMat = cc.vmath.mat4.mul; - this._syncEulerAngles = _syncEulerAngles; } else { this._updateLocalMatrix = _updateLocalMatrix2d; this._calculWorldMatrix = _calculWorldMatrix2d; this._mulMat = _mulMat2d; - this._syncEulerAngles = _syncEulerAngles2d; } this._renderFlag |= RenderFlow.FLAG_TRANSFORM; } function _upgrade_1x_to_2x () { - if (CC_EDITOR && this instanceof cc.Scene) { - this._is3DNode = true; - } - if (this._is3DNode) { this._update3DFunction(); } @@ -268,22 +173,16 @@ let proto = cc.Node.prototype; const _updateLocalMatrix2d = proto._updateLocalMatrix; const _calculWorldMatrix2d = proto._calculWorldMatrix; const _upgrade_1x_to_2x_2d = proto._upgrade_1x_to_2x; -const _syncEulerAngles2d = proto._syncEulerAngles; const _mulMat2d = proto._mulMat; const _onBatchCreated2d = proto._onBatchCreated; -proto.getQuat = getQuat; -proto.setQuat = setQuat; - -proto.getPosition = getPosition; proto.setPosition = setPosition; proto.setScale = setScale; proto._upgrade_1x_to_2x = _upgrade_1x_to_2x; proto._update3DFunction = _update3DFunction; -cc.js.getset(proto, 'position', getPosition, setPosition, false, true); -cc.js.getset(proto, 'scale', proto.getScale, setScale, false, true); +cc.js.getset(proto, 'position', proto.getPosition, setPosition, false, true); cc.js.getset(proto, 'is3DNode', function () { return this._is3DNode; @@ -291,7 +190,61 @@ cc.js.getset(proto, 'is3DNode', function () { if (this._is3DNode === v) return; this._is3DNode = v; this._update3DFunction(); - this._syncEulerAngles(); }); -cc.js.getset(proto, 'quat', getQuat, setQuat); +cc.js.getset(proto, 'scaleZ', function () { + return this._scale.z; +}, function (v) { + if (this._scale.z !== value) { + this._scale.z = value; + this.setLocalDirty(DirtyFlag.SCALE); + this._renderFlag |= RenderFlow.FLAG_TRANSFORM; + + if (this._eventMask & SCALE_ON) { + this.emit(EventType.SCALE_CHANGED); + } + } +}); + +cc.js.getset(proto, 'z', function () { + return this._position.z; +}, function (value) { + let localPosition = this._position; + if (value !== localPosition.z) { + if (!CC_EDITOR || isFinite(value)) { + localPosition.z = value; + this.setLocalDirty(DirtyFlag.POSITION); + this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; + // fast check event + if (this._eventMask & POSITION_ON) { + this.emit(EventType.POSITION_CHANGED); + } + } + else { + cc.error(ERR_INVALID_NUMBER, 'new z'); + } + } +}); + +cc.js.getset(proto, 'eulerAngles', function () { + if (CC_EDITOR) { + return this._eulerAngles; + } + else { + return this._quat.getEulerAngles(cc.v3()); + } +}, function (v) { + if (CC_EDITOR) { + this._eulerAngles.set(v); + } + + math.quat.fromEuler(this._quat, v.x, v.y, v.z); + this.setLocalDirty(DirtyFlag.ROTATION); + this._renderFlag |= RenderFlow.FLAG_TRANSFORM; +}); + +// This property is used for Mesh Skeleton Animation +// Should be rememoved when node.rotation upgrade to quaternion value +cc.js.getset(proto, 'quat', function () { + return this._quat; +}, proto.setRotation); diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 1f9ca297df7..39a3bf17376 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -513,7 +513,7 @@ function _doDispatchEvent (owner, event) { * @class Node * @extends _BaseNode */ -var Node = cc.Class({ +let NodeDefines = { name: 'cc.Node', extends: BaseNode, @@ -524,17 +524,7 @@ var Node = cc.Class({ _contentSize: cc.Size, _anchorPoint: cc.v2(0.5, 0.5), _position: cc.Vec3, - _scaleX: { - default: undefined, - type: cc.Float - }, - _scaleY: { - default: undefined, - type: cc.Float - }, _scale: cc.Vec3, - _rotationX: 0.0, - _rotationY: 0.0, _quat: cc.Quat, _skewX: 0.0, _skewY: 0.0, @@ -680,82 +670,87 @@ var Node = cc.Class({ } }, }, - - z: { - get () { - return this._position.z; - }, - set (value) { - var localPosition = this._position; - if (value !== localPosition.z) { - if (!CC_EDITOR || isFinite(value)) { - localPosition.z = value; - this.setLocalDirty(LocalDirtyFlag.POSITION); - this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; - // fast check event - if (this._eventMask & POSITION_ON) { - this.emit(EventType.POSITION_CHANGED); - } - } - else { - cc.error(ERR_INVALID_NUMBER, 'new z'); - } - } - }, - }, + + /** + * !#en z axis position of node. + * !#zh 节点 Z 轴坐标。 + * @property z + * @type {Number} + */ /** * !#en Rotation of node. * !#zh 该节点旋转角度。 * @property rotation * @type {Number} + * @deprecated since v2.1 * @example * node.rotation = 90; * cc.log("Node Rotation: " + node.rotation); */ + rotation: { + get () { + return -this.angle; + }, + set (value) { + this.angle = -value; + } + }, /** - * !#en The rotation as Euler angles in degrees, used in 2.5D project. - * !#zh 该节点的欧拉角度,用于 2.5D 项目。 - * @property eulerAngles - * @type {Vec3} + * !#en + * Angle of node, the positive value is anti-clockwise direction. + * !#zh + * 该节点的旋转角度,正值为逆时针方向。 + * @property angle + * @type {Number} */ - eulerAngles: { + angle: { get () { - return cc.v3(this._rotationX, this._rotationY, this._rotationZ); + return this._eulerAngles.z; }, - set (v) { - this._rotationX = v.x; - this._rotationY = v.y; - this._rotationZ = v.z; - math.quat.fromEuler(this._quat, v.x, v.y, v.z); + set (value) { + this._eulerAngles.z = value; + math.quat.fromEuler(this._quat, 0, 0, value); this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; + + if (this._eventMask & ROTATION_ON) { + this.emit(EventType.ROTATION_CHANGED); + } } }, + /** + * !#en The rotation as Euler angles in degrees, used in 2.5D project. + * !#zh 该节点的欧拉角度,用于 2.5D 项目。 + * @property eulerAngles + * @type {Vec3} + */ + /** * !#en Rotation on x axis. * !#zh 该节点 X 轴旋转角度。 * @property rotationX * @type {Number} * @example + * @deprecated since v2.1 * node.rotationX = 45; * cc.log("Node Rotation X: " + node.rotationX); */ rotationX: { get () { - return this._rotationX; + return this._eulerAngles.x; }, set (value) { - if (this._rotationX !== value) { - this._rotationX = value; + if (this._eulerAngles.x !== value) { + this._eulerAngles.x = value; // Update quaternion from rotation - if (this._rotationX === this._rotationY) { + if (this._eulerAngles.x === this._eulerAngles.y) { math.quat.fromEuler(this._quat, 0, 0, -value); } else { - math.quat.fromEuler(this._quat, value, this._rotationY, 0); + math.quat.fromEuler(this._quat, value, this._eulerAngles.y, 0); } this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -773,22 +768,23 @@ var Node = cc.Class({ * @property rotationY * @type {Number} * @example + * @deprecated since v2.1 * node.rotationY = 45; * cc.log("Node Rotation Y: " + node.rotationY); */ rotationY: { get () { - return this._rotationY; + return this._eulerAngles.y; }, set (value) { - if (this._rotationY !== value) { - this._rotationY = value; + if (this._eulerAngles.y !== value) { + this._eulerAngles.y = value; // Update quaternion from rotation - if (this._rotationX === this._rotationY) { + if (this._eulerAngles.x === this._eulerAngles.y) { math.quat.fromEuler(this._quat, 0, 0, -value); } else { - math.quat.fromEuler(this._quat, this._rotationX, value, 0); + math.quat.fromEuler(this._quat, this._eulerAngles.x, value, 0); } this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -808,6 +804,14 @@ var Node = cc.Class({ * @example * node.scale = 1; */ + scale: { + get () { + return this._scale.x; + }, + set (v) { + this.setScale(v); + } + }, /** * !#en Scale on x axis. @@ -861,6 +865,13 @@ var Node = cc.Class({ }, }, + /** + * !#en Scale on z axis. + * !#zh 节点 Z 轴缩放。 + * @property scaleZ + * @type {Number} + */ + /** * !#en Skew x * !#zh 该节点 X 轴倾斜角度。 @@ -1129,7 +1140,7 @@ var Node = cc.Class({ this._eventMask = 0; this._cullingMask = 1 << this.groupIndex; - this._rotationZ = 0; + this._eulerAngles = cc.v3(); }, statics: { @@ -1243,19 +1254,6 @@ var Node = cc.Class({ // INTERNAL - _syncEulerAngles () { - let quat = this._quat; - let rotx = quat.getRoll(); - let roty = quat.getPitch(); - if (rotx === 0 && roty === 0) { - this._rotationX = this._rotationY = -quat.getYaw(); - } - else { - this._rotationX = rotx; - this._rotationY = roty; - } - }, - _upgrade_1x_to_2x () { // Upgrade scaleX, scaleY from v1.x // TODO: remove in future version, 3.0 ? @@ -1276,7 +1274,7 @@ var Node = cc.Class({ // Update quaternion from rotation, when upgrade from 1.x to 2.0 // If rotation x & y is 0 in old version, then update rotation from default quaternion is ok too let quat = this._quat; - if ((this._rotationX !== 0 || this._rotationY !== 0) && + if ((this._rotationX || this._rotationY) && (quat.x === 0 && quat.y === 0 && quat.z === 0 && quat.w === 1)) { if (this._rotationX === this._rotationY) { math.quat.fromEuler(quat, 0, 0, -this._rotationX); @@ -1287,7 +1285,7 @@ var Node = cc.Class({ } // Update rotation from quaternion else { - this._syncEulerAngles(); + this._quat.getEulerAngles(this._eulerAngles); } // Upgrade from 2.0.0 preview 4 & earlier versions @@ -2003,31 +2001,41 @@ var Node = cc.Class({ // TRANSFORM RELATED /** - * !#en Returns a copy of the position (x, y) of the node in its parent's coordinates. - * !#zh 获取节点在父节点坐标系中的位置(x, y)。 + * !#en + * Returns a copy of the position (x, y, z) of the node in its parent's coordinates. + * You can pass a cc.Vec2 or cc.Vec3 as the argument to receive the return values. + * !#zh + * 获取节点在父节点坐标系中的位置(x, y, z)。 + * 你可以传一个 cc.Vec2 或者 cc.Vec3 作为参数来接收返回值。 * @method getPosition - * @return {Vec2} The position (x, y) of the node in its parent's coordinates + * @param {Vec2|Vec3} [out] - The return value to receive position + * @return {Vec2|Vec3} The position (x, y, z) of the node in its parent's coordinates * @example * cc.log("Node Position: " + node.getPosition()); */ - getPosition () { - return new cc.Vec2(this._position); + getPosition (out) { + out = out || cc.v3(); + return out.set(this._position); }, /** * !#en - * Sets the position (x, y) of the node in its parent's coordinates.
- * Usually we use cc.v2(x, y) to compose cc.Vec2 object.
- * and Passing two numbers (x, y) is more efficient than passing cc.Vec2 object. + * Sets the position (x, y, z) of the node in its parent's coordinates.
+ * Usually we use cc.v2(x, y) to compose cc.Vec2 object,
+ * and passing two numbers (x, y) is more efficient than passing cc.Vec2 object. + * For 3D node we can use cc.v3(x, y, z) to compose cc.Vec3 object,
+ * and passing three numbers (x, y, z) is more efficient than passing cc.Vec3 object. * !#zh * 设置节点在父节点坐标系中的位置。
- * 可以通过两种方式设置坐标点:
- * 1. 传入 2 个数值 x 和 y。
+ * 可以通过下面的方式设置坐标点:
+ * 1. 传入 2 个数值 x, y。
* 2. 传入 cc.v2(x, y) 类型为 cc.Vec2 的对象。 + * 3. 对于 3D 节点可以传入 3 个数值 x, y, z。
+ * 4. 对于 3D 节点可以传入 cc.v3(x, y, z) 类型为 cc.Vec3 的对象。 * @method setPosition - * @param {Vec2|Number} newPosOrX - X coordinate for position or the position (x, y) of the node in coordinates + * @param {Vec2|Vec3|Number} newPosOrX - X coordinate for position or the position (x, y, z) of the node in coordinates * @param {Number} [y] - Y coordinate for position - * @example {@link cocos2d/core/utils/base-node/setPosition.js} + * @param {Number} [z] - Z coordinate for position */ setPosition (newPosOrX, y) { var x; @@ -2077,26 +2085,39 @@ var Node = cc.Class({ /** * !#en * Returns the scale factor of the node. - * Assertion will fail when scale x != scale y. - * !#zh 获取节点的缩放。当 X 轴和 Y 轴有相同的缩放数值时。 + * Need pass a cc.Vec2 or cc.Vec3 as the argument to receive the return values. + * !#zh 获取节点的缩放,需要传一个 cc.Vec2 或者 cc.Vec3 作为参数来接收返回值。 * @method getScale - * @return {Number} The scale factor + * @param {Vec2|Vec3} out + * @return {Vec2|Vec3} The scale factor * @example - * cc.log("Node Scale: " + node.getScale()); + * cc.log("Node Scale: " + node.getScale(cc.v3())); */ - getScale () { - return this._scale.x; + getScale (out) { + if (out !== undefined) { + return out.set(this._scale); + } + else { + cc.warnID(1400, 'cc.Node.getScale', 'cc.Node.scale or cc.Node.getScale(cc.Vec3)'); + return this._scale.x; + } }, /** - * !#en Sets the scale factor of the node. 1.0 is the default scale factor. This function can modify the X and Y scale at the same time. - * !#zh 设置节点的缩放比例,默认值为 1.0。这个函数可以在同一时间修改 X 和 Y 缩放。 + * !#en + * Sets the scale of axis in local coordinates of the node. + * You can operate 2 axis in 2D node, and 3 axis in 3D node. + * !#zh + * 设置节点在本地坐标系中坐标轴上的缩放比例。 + * 2D 节点可以操作两个坐标轴,而 3D 节点可以操作三个坐标轴。 * @method setScale - * @param {Number|Vec2} scaleX - scaleX or scale - * @param {Number} [scaleY] + * @param {Number|Vec2|Vec3} x - scaleX or scale object + * @param {Number} [y] + * @param {Number} [z] * @example - * node.setScale(cc.v2(1, 1)); - * node.setScale(1); + * node.setScale(cc.v2(2, 2)); + * node.setScale(cc.v3(2, 2, 2)); // for 3D node + * node.setScale(2); */ setScale (x, y) { if (x && typeof x !== 'number') { @@ -2119,32 +2140,60 @@ var Node = cc.Class({ }, /** - * !#en Get rotation of node (along z axi). - * !#zh 获取该节点以局部坐标系 Z 轴为轴进行旋转的角度。 + * !#en + * Get rotation of node (in quaternion). + * Need pass a cc.Quat as the argument to receive the return values. + * !#zh + * 获取该节点的 quaternion 旋转角度,需要传一个 cc.Quat 作为参数来接收返回值。 * @method getRotation - * @param {Number} rotation Degree rotation value + * @param {Quat} out + * @return {Quat} Quaternion object represents the rotation */ - getRotation () { - return this._rotationX; + getRotation (out) { + if (out instanceof cc.Quat) { + return out.set(this._quat); + } + else { + cc.warnID(1400, 'cc.Node.getRotation', 'cc.Node.angle or cc.Node.getRotation(cc.Quat)'); + return -this.angle; + } }, - /** - * !#en Set rotation of node (along z axi). - * !#zh 设置该节点以局部坐标系 Z 轴为轴进行旋转的角度。 + * !#en Set rotation of node (in quaternion). + * !#zh 设置该节点的 quaternion 旋转角度。 * @method setRotation - * @param {Number} rotation Degree rotation value - */ - setRotation (value) { - if (this._rotationX !== value || this._rotationY !== value) { - this._rotationX = this._rotationY = value; - // Update quaternion from rotation - math.quat.fromEuler(this._quat, 0, 0, -value); - this.setLocalDirty(LocalDirtyFlag.ROTATION); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; + * @param {cc.Quat|Number} quat Quaternion object represents the rotation or the x value of quaternion + * @param {Number} y y value of quternion + * @param {Number} z z value of quternion + * @param {Number} w w value of quternion + */ + setRotation (quat, y, z, w) { + if (typeof quat === 'number' && y === undefined) { + cc.warnID(1400, 'cc.Node.setRotation(Number)', 'cc.Node.angle or cc.Node.setRotation(quat)') + this.angle = -quat; + } + else { + let x = quat; + if (y === undefined) { + x = quat.x; + y = quat.y; + z = quat.z; + w = quat.w; + } - if (this._eventMask & ROTATION_ON) { - this.emit(EventType.ROTATION_CHANGED); + let old = this._quat; + if (old.x !== x || old.y !== y || old.z !== z || old.w !== w) { + old.x = x; + old.y = y; + old.z = z; + old.w = w; + this.setLocalDirty(DirtyFlag.ROTATION); + this._renderFlag |= RenderFlow.FLAG_TRANSFORM; + + if (this._eventMask & ROTATION_ON) { + this.emit(EventType.ROTATION_CHANGED); + } } } }, @@ -2434,26 +2483,19 @@ var Node = cc.Class({ //math.mat4.fromRTS(t, this._quat, this._position, this._scale); if (dirtyFlag & (LocalDirtyFlag.RT | LocalDirtyFlag.SKEW)) { - let hasRotation = this._rotationX || this._rotationY; + let rotation = -this._eulerAngles.z; let hasSkew = this._skewX || this._skewY; let sx = this._scale.x, sy = this._scale.y; - if (hasRotation || hasSkew) { + if (rotation || hasSkew) { let a = 1, b = 0, c = 0, d = 1; // rotation - if (hasRotation) { - let rotationRadiansX = this._rotationX * ONE_DEGREE; - c = Math.sin(rotationRadiansX); - d = Math.cos(rotationRadiansX); - if (this._rotationY === this._rotationX) { - a = d; - b = -c; - } - else { - let rotationRadiansY = this._rotationY * ONE_DEGREE; - a = Math.cos(rotationRadiansY); - b = -Math.sin(rotationRadiansY); - } + if (rotation) { + let rotationRadians = rotation * ONE_DEGREE; + c = Math.sin(rotationRadians); + d = Math.cos(rotationRadians); + a = d; + b = -c; } // scale t.m00 = a *= sx; @@ -3027,6 +3069,8 @@ var Node = cc.Class({ this._localMatDirty = LocalDirtyFlag.ALL; this._worldMatDirty = true; + this._quat.getEulerAngles(this._eulerAngles); + this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._renderComponent) { if (this._renderComponent.enabled) { @@ -3058,7 +3102,35 @@ var Node = cc.Class({ eventManager.pauseTarget(this); } }, -}); +}; + +if (CC_EDITOR) { + // deprecated, only used to import old data in editor + js.mixin(NodeDefines.properties, { + _scaleX: { + default: undefined, + type: cc.Float, + editorOnly: true + }, + _scaleY: { + default: undefined, + type: cc.Float, + editorOnly: true + }, + _rotationX: { + default: undefined, + type: cc.Float, + editorOnly: true + }, + _rotationY: { + default: undefined, + type: cc.Float, + editorOnly: true + }, + }); +} + +let Node = cc.Class(NodeDefines); // 3D Node Property @@ -3184,8 +3256,6 @@ var Node = cc.Class({ let _p = Node.prototype; -js.getset(_p, 'rotation', _p.getRotation, _p.setRotation); js.getset(_p, 'position', _p.getPosition, _p.setPosition, false, true); -js.getset(_p, 'scale', _p.getScale, _p.setScale, false, true); cc.Node = module.exports = Node; diff --git a/cocos2d/core/CCScene.js b/cocos2d/core/CCScene.js index da03a5c525e..f5c4cbe2dff 100644 --- a/cocos2d/core/CCScene.js +++ b/cocos2d/core/CCScene.js @@ -40,6 +40,10 @@ cc.Scene = cc.Class({ extends: require('./CCNode'), properties: { + _is3DNode: { + default: true, + override: true + }, /** * !#en Indicates whether all (directly or indirectly) static referenced assets of this scene are releasable by default after scene unloading. diff --git a/cocos2d/core/physics/CCPhysicsManager.js b/cocos2d/core/physics/CCPhysicsManager.js index e13ff732ffa..2217724f1db 100644 --- a/cocos2d/core/physics/CCPhysicsManager.js +++ b/cocos2d/core/physics/CCPhysicsManager.js @@ -484,7 +484,7 @@ var PhysicsManager = cc.Class({ node.position = vec2_tmp; // sync rotation - node.rotation = angle; + node.angle = -angle; node._eventMask = tempMask; diff --git a/cocos2d/core/physics/utils.js b/cocos2d/core/physics/utils.js index 70316c1ef96..c9ab47468f4 100644 --- a/cocos2d/core/physics/utils.js +++ b/cocos2d/core/physics/utils.js @@ -24,13 +24,13 @@ ****************************************************************************/ function getWorldRotation (node) { - var rot = node.rotationX; + var rot = node.angle; var parent = node.parent; while(parent.parent){ - rot += parent.rotationX; + rot += parent.angle; parent = parent.parent; } - return rot; + return -rot; } function getWorldScale (node) { @@ -49,10 +49,10 @@ function getWorldScale (node) { } function convertToNodeRotation (node, rotation) { - rotation -= node.rotationX; + rotation -= -node.angle; var parent = node.parent; while(parent.parent){ - rotation -= parent.rotationX; + rotation -= -parent.angle; parent = parent.parent; } return rotation; diff --git a/cocos2d/core/value-types/quat.js b/cocos2d/core/value-types/quat.js index 1e3c4ea04f0..2b161de83c9 100644 --- a/cocos2d/core/value-types/quat.js +++ b/cocos2d/core/value-types/quat.js @@ -135,6 +135,13 @@ proto.getYaw = function () { return 180 * Math.atan2(siny, cosy) / Math.PI; }; +proto.getEulerAngles = function (out) { + out = out || cc.v3(); + out.x = this.getRoll(); + out.y = this.getPitch(); + out.z = this.getYaw(); +} + proto.lerp = function (to, ratio, out) { out = out || new cc.Quat(); cc.vmath.quat.slerp(out, this, to, ratio); diff --git a/cocos2d/deprecated.js b/cocos2d/deprecated.js index 60680344dc5..76c0b398acf 100644 --- a/cocos2d/deprecated.js +++ b/cocos2d/deprecated.js @@ -67,6 +67,26 @@ if (CC_DEBUG) { }); } + function markAsDeprecated (ownerCtor, deprecatedProps, ownerName) { + if (!ownerCtor) { + return; + } + ownerName = ownerName || js.getClassName(ownerCtor); + let descriptors = Object.getOwnPropertyDescriptors(ownerCtor.prototype); + deprecatedProps.forEach(function (prop) { + let deprecatedProp = prop[0]; + let newProp = prop[1]; + let descriptor = descriptors[deprecatedProp]; + js.getset(ownerCtor.prototype, deprecatedProp, function () { + cc.warnID(1400, `${ownerName}.${deprecatedProp}`, `${ownerName}.${newProp}`); + return descriptor.get.call(this); + }, function (v) { + cc.warnID(1400, `${ownerName}.${deprecatedProp}`, `${ownerName}.${newProp}`); + descriptor.set.call(this, v); + }) + }) + } + function markAsRemovedInObject (ownerObj, removedProps, ownerName) { if (!ownerObj) { // 可能被裁剪了 @@ -330,6 +350,12 @@ if (CC_DEBUG) { '_sgNode', ]); + markAsDeprecated(cc.Node, [ + ['rotationX', 'eulerAngles'], + ['rotationY', 'eulerAngles'], + ['rotation', 'angle'], + ]) + markFunctionWarning(cc.Node.prototype, { getNodeToParentTransform: 'getLocalMatrix', getNodeToParentTransformAR: 'getLocalMatrix', diff --git a/test/qunit/unit-es5/test-animation.js b/test/qunit/unit-es5/test-animation.js index e23b7939ebb..b14e098c9eb 100644 --- a/test/qunit/unit-es5/test-animation.js +++ b/test/qunit/unit-es5/test-animation.js @@ -3,6 +3,7 @@ largeModule('Animation', SetupEngine); var color = cc.color; var Color = cc.Color; var v2 = cc.v2; +var v3 = cc.v3; test('curve types', function () { var initClipData = cc._Test.initClipData; @@ -63,7 +64,7 @@ test('DynamicAnimCurve', function () { anim.ratios = [0.0, 1.0]; anim.sample(null, 0.1, null); - deepEqual(target.position, v2(55, 456), 'The composed position should animated'); + deepEqual(target.position, v2(55, 456, 0), 'The composed position should animated'); anim.target = target; anim.prop = 'foo'; @@ -406,17 +407,17 @@ test('SampledAnimCurve', function () { state.time = 0.2; state.sample(); - deepEqual(entity.position, v2(0, 0), 'entity position should be (0,0)'); + deepEqual(entity.position, v3(0, 0, 0), 'entity position should be (0, 0, 0)'); state.time = 0.7; state.sample(); - deepEqual(entity.position, v2(100, 100), 'entity position should be (100, 100)'); + deepEqual(entity.position, v3(100, 100, 0), 'entity position should be (100, 100, 0)'); state.time = 0.9; state.sample(); - deepEqual(entity.position, v2(100, 100), 'entity position should be (100, 100)'); + deepEqual(entity.position, v3(100, 100, 0), 'entity position should be (100, 100, 0)'); }); From f06d8ee7d6b19d32e7c0f2933685b9d152f0a18d Mon Sep 17 00:00:00 2001 From: PP Date: Sun, 30 Sep 2018 15:59:34 +0800 Subject: [PATCH 0063/1631] fix button bug for 2.1-release create button state enum fix setNormalSprite when change button interactable in editor fix button can't set opacity in color transition reset button to normal data when change transition reset pr #808 add node COLOR_CHANGED event --- cocos2d/core/CCNode.js | 25 +++++ cocos2d/core/components/CCButton.js | 141 +++++++++++++++++++++++----- 2 files changed, 143 insertions(+), 23 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 89c1be1cc1b..45048750234 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -60,6 +60,7 @@ const SCALE_ON = 1 << 1; const ROTATION_ON = 1 << 2; const SIZE_ON = 1 << 3; const ANCHOR_ON = 1 << 4; +const COLOR_ON = 1 << 5; let BuiltinGroupIndex = cc.Enum({ @@ -249,6 +250,16 @@ var EventType = cc.Enum({ * @static */ ANCHOR_CHANGED: 'anchor-changed', + /** + * !#en The event type for color change events. + * Performance note, this event will be triggered every time corresponding properties being changed, + * if the event callback have heavy logic it may have great performance impact, try to avoid such scenario. + * !#zh 当节点颜色改变时触发的事件。 + * 性能警告:这个事件会在每次对应的属性被修改时触发,如果事件回调损耗较高,有可能对性能有很大的负面影响,请尽量避免这种情况。 + * @property {String} COLOR_CHANGED + * @static + */ + COLOR_CHANGED: 'color-changed', /** * !#en The event type for new child added events. * !#zh 当新的子节点被添加时触发的事件。 @@ -944,6 +955,10 @@ var Node = cc.Class({ if (this._renderComponent) { this._renderFlag |= RenderFlow.FLAG_COLOR; } + + if (this._eventMask & COLOR_ON) { + this.emit(EventType.COLOR_CHANGED, value); + } } }, }, @@ -1450,6 +1465,7 @@ var Node = cc.Class({ * node.on(cc.Node.EventType.TOUCH_END, callback, this); * node.on(cc.Node.EventType.TOUCH_CANCEL, callback, this); * node.on(cc.Node.EventType.ANCHOR_CHANGED, callback); + * node.on(cc.Node.EventType.COLOR_CHANGED, callback); */ on (type, callback, target, useCapture) { let forDispatch = this._checknSetupSysEvent(type); @@ -1473,6 +1489,9 @@ var Node = cc.Class({ case EventType.ANCHOR_CHANGED: this._eventMask |= ANCHOR_ON; break; + case EventType.COLOR_CHANGED: + this._eventMask |= COLOR_ON; + break; } if (!this._bubblingListeners) { this._bubblingListeners = new EventTarget(); @@ -1614,6 +1633,9 @@ var Node = cc.Class({ case EventType.ANCHOR_CHANGED: this._eventMask &= ~ANCHOR_ON; break; + case EventType.COLOR_CHANGED: + this._eventMask &= ~COLOR_ON; + break; } } } @@ -1672,6 +1694,9 @@ var Node = cc.Class({ if ((this._eventMask & ANCHOR_ON) && !listeners.hasEventListener(EventType.ANCHOR_CHANGED)) { this._eventMask &= ~ANCHOR_ON; } + if ((this._eventMask & COLOR_ON) && !listeners.hasEventListener(EventType.COLOR_CHANGED)) { + this._eventMask &= ~COLOR_ON; + } } if (this._capturingListeners) { this._capturingListeners.targetOff(target); diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 0c3163fc45c..bf04582ffc6 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -61,6 +61,13 @@ let Transition = cc.Enum({ SCALE: 3 }); +const State = cc.Enum({ + NORMAL: 0, + HOVER: 1, + PRESSED: 2, + DISABLED: 3, +}); + /** * !#en * Button has 4 Transition types
@@ -132,10 +139,6 @@ let Button = cc.Class({ this._originalScale = 1.0; this._sprite = null; - - if (CC_EDITOR) { - this._previousNormalSprite = null; - } }, editor: CC_EDITOR && { @@ -158,14 +161,7 @@ let Button = cc.Class({ interactable: { default: true, tooltip: CC_DEV && 'i18n:COMPONENT.button.interactable', - notify (oldValue) { - if (CC_EDITOR) { - if (oldValue) { - this._previousNormalSprite = this.normalSprite; - } else { - this.normalSprite = this._previousNormalSprite; - } - } + notify () { this._updateState(); if (!this.interactable) { @@ -207,7 +203,10 @@ let Button = cc.Class({ default: Transition.NONE, tooltip: CC_DEV && 'i18n:COMPONENT.button.transition', type: Transition, - animatable: false + animatable: false, + notify (oldValue) { + this._updateTransition(oldValue); + }, }, // color transition @@ -222,6 +221,9 @@ let Button = cc.Class({ displayName: 'Normal', tooltip: CC_DEV && 'i18n:COMPONENT.button.normal_color', notify () { + if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL) { + this.target.opacity = this.normalColor.a; + } this._updateState(); } }, @@ -235,6 +237,12 @@ let Button = cc.Class({ default: cc.color(211, 211, 211), displayName: 'Pressed', tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color', + notify () { + if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED) { + this.target.opacity = this.pressedColor.a; + } + this._updateState(); + } }, /** @@ -246,6 +254,12 @@ let Button = cc.Class({ default: cc.Color.WHITE, displayName: 'Hover', tooltip: CC_DEV && 'i18n:COMPONENT.button.hover_color', + notify () { + if (this.transition === Transition.Color && this._getButtonState() === State.HOVER) { + this.target.opacity = this.hoverColor.a; + } + this._updateState(); + } }, /** @@ -258,6 +272,9 @@ let Button = cc.Class({ displayName: 'Disabled', tooltip: CC_DEV && 'i18n:COMPONENT.button.disabled_color', notify () { + if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED) { + this.target.opacity = this.disabledColor.a; + } this._updateState(); } }, @@ -429,12 +446,77 @@ let Button = cc.Class({ } else { this.node.on('spriteframe-changed', function (comp) { if (this.transition === Transition.SPRITE) { - this.normalSprite = comp.spriteFrame; + this._setCurrentStateSprite(comp.spriteFrame); + } + }.bind(this)); + this.node.on('color-changed', function (color) { + if (this.transition === Transition.COLOR) { + this._setCurrentStateColor(color); } }.bind(this)); } }, + _getStateColor (state) { + switch (state) { + case State.NORMAL: + return this.normalColor; + case State.HOVER: + return this.hoverColor; + case State.PRESSED: + return this.pressedColor; + case State.DISABLED: + return this.disabledColor; + } + }, + + _getStateSprite (state) { + switch (state) { + case State.NORMAL: + return this.normalSprite; + case State.HOVER: + return this.hoverSprite; + case State.PRESSED: + return this.pressedSprite; + case State.DISABLED: + return this.disabledSprite; + } + }, + + _setCurrentStateColor (color) { + switch ( this._getButtonState() ) { + case State.NORMAL: + this.normalColor = color; + break; + case State.HOVER: + this.hoverColor = color; + break; + case State.PRESSED: + this.pressedColor = color; + break; + case State.DISABLED: + this.disabledColor = color; + break; + } + }, + + _setCurrentStateSprite (spriteFrame) { + switch ( this._getButtonState() ) { + case State.NORMAL: + this.normalSprite = spriteFrame; + break; + case State.HOVER: + this.hoverSprite = spriteFrame; + break; + case State.PRESSED: + this.pressedSprite = spriteFrame; + break; + case State.DISABLED: + this.disabledSprite = spriteFrame; + break; + } + }, + onDisable () { this._resetState(); @@ -469,6 +551,7 @@ let Button = cc.Class({ if (this.transition === Transition.COLOR) { target.color = this._fromColor.lerp(this._toColor, ratio); + target.opacity = target.color.a; } else if (this.transition === Transition.SCALE) { target.scale = misc.lerp(this._fromScale, this._toScale, ratio); } @@ -529,9 +612,9 @@ let Button = cc.Class({ } else { let state; if (hit) { - state = 'pressed'; + state = State.PRESSED; } else { - state = 'normal'; + state = State.NORMAL; } this._applyTransition(state); } @@ -584,26 +667,27 @@ let Button = cc.Class({ _getButtonState () { let state; if (!this.interactable) { - state = 'disabled'; + state = State.DISABLED; } else if (this._pressed) { - state = 'pressed'; + state = State.PRESSED; } else if (this._hovered) { - state = 'hover'; + state = State.HOVER; } else { - state = 'normal'; + state = State.NORMAL; } return state; }, _updateColorTransition (state) { - let color = this[state + 'Color']; + let color = this._getStateColor(state); let target = this.target; if (CC_EDITOR) { target.color = color; + target.opacity = color.a; } else { this._fromColor = target.color.clone(); @@ -614,14 +698,14 @@ let Button = cc.Class({ }, _updateSpriteTransition (state) { - let sprite = this[state + 'Sprite']; + let sprite = this._getStateSprite(state); if (this._sprite && sprite) { this._sprite.spriteFrame = sprite; } }, _updateScaleTransition (state) { - if (state === 'pressed') { + if (state === State.PRESSED) { this._zoomUp(); } else { this._zoomBack(); @@ -642,6 +726,17 @@ let Button = cc.Class({ this._transitionFinished = false; }, + _updateTransition (oldTransition) { + // Reset to normal data when change transition. + if (oldTransition === Transition.COLOR) { + this._updateColorTransition(State.NORMAL); + } + else if (oldTransition === Transition.SPRITE) { + this._updateSpriteTransition(State.NORMAL); + } + this._updateState(); + }, + _applyTransition (state) { let transition = this.transition; if (transition === Transition.COLOR) { From 94d74162861eb6958ac45e2ecfb1c4772afa0778 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Sat, 6 Oct 2018 10:45:36 +0800 Subject: [PATCH 0064/1631] Fix mask cannot clear stencil buffer when stencil is sprite (#3349) --- cocos2d/core/renderer/webgl/assemblers/mask-assembler.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js index 8ca28a3ba67..b54e1fbe972 100644 --- a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js @@ -25,7 +25,6 @@ const StencilManager = require('../stencil-manager'); const Mask = require('../../../components/CCMask'); -const Graphics = require('../../../graphics/graphics'); const RenderFlow = require('../../render-flow'); const spriteAssembler = require('./sprite/simple'); const graphicsAssembler = require('./graphics'); @@ -35,13 +34,15 @@ let _stencilMgr = StencilManager.sharedManager; let maskFrontAssembler = { updateRenderData (mask) { if (!mask._renderData) { + // Update clear graphics material + graphicsAssembler.updateRenderData(mask._clearGraphics); + if (mask._type === Mask.Type.IMAGE_STENCIL) { mask._renderData = spriteAssembler.createData(mask); } else { // for updateGraphics calculation mask._renderData = mask.requestRenderData(); - graphicsAssembler.updateRenderData(mask._clearGraphics); } } let renderData = mask._renderData; From beb3bac221f2ee1293295774b5bcd2716355d3af Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 8 Oct 2018 11:53:53 +0800 Subject: [PATCH 0065/1631] fixed the DistanceJoint api name (#3351) --- cocos2d/core/physics/joint/CCDistanceJoint.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cocos2d/core/physics/joint/CCDistanceJoint.js b/cocos2d/core/physics/joint/CCDistanceJoint.js index ad35605226d..5c2cc0a2b97 100644 --- a/cocos2d/core/physics/joint/CCDistanceJoint.js +++ b/cocos2d/core/physics/joint/CCDistanceJoint.js @@ -98,7 +98,6 @@ var DistanceJoint = cc.Class({ * !#zh * 阻尼,表示关节变形后,恢复到初始状态受到的阻力。 * @property {Number} dampingRatio - * @property 0 */ dampingRatio: { tooltip: CC_DEV && 'i18n:COMPONENT.physics.physics_collider.dampingRatio', From 1f866929f36c045eb6f340307663560890bddc03 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 8 Oct 2018 15:00:33 +0800 Subject: [PATCH 0066/1631] fix mask bug in spine for 2d-tasks/issues/643 (#3350) * fix mask bug in spine for 2d-tasks/issues/643 * add copy pass * refine code --- cocos2d/core/renderer/render-engine.js | 65 +++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 4d26cb2b895..5cde5e1ff02 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -10300,7 +10300,8 @@ var Pass = function Pass(name) { // depth this._depthTest = false; this._depthWrite = false; - this._depthFunc = gfx.DS_FUNC_LESS, this._stencilTest = false; + this._depthFunc = gfx.DS_FUNC_LESS; + this._stencilTest = false; // front this._stencilFuncFront = gfx.DS_FUNC_ALWAYS; this._stencilRefFront = 0; @@ -10319,6 +10320,42 @@ var Pass = function Pass(name) { this._stencilWriteMaskBack = 0xff; }; +Pass.prototype.copy = function (pass) { + this._programName = pass._programName; + // cullmode + this._cullMode = pass._cullMode; + // blending + this._blend = pass._blend; + this._blendEq = pass._blendEq; + this._blendAlphaEq = pass._blendAlphaEq; + this._blendSrc = pass._blendSrc; + this._blendDst = pass._blendDst; + this._blendSrcAlpha = pass._blendSrcAlpha; + this._blendDstAlpha = pass._blendDstAlpha; + this._blendColor = pass._blendColor; + // depth + this._depthTest = pass._depthTest; + this._depthWrite = pass._depthWrite; + this._depthFunc = pass._depthFunc; + this._stencilTest = pass._stencilTest; + // front + this._stencilFuncFront = pass._stencilFuncFront; + this._stencilRefFront = pass._stencilRefFront; + this._stencilMaskFront = pass._stencilMaskFront; + this._stencilFailOpFront = pass._stencilFailOpFront; + this._stencilZFailOpFront = pass._stencilZFailOpFront; + this._stencilZPassOpFront = pass._stencilZPassOpFront; + this._stencilWriteMaskFront = pass._stencilWriteMaskFront; + // back + this._stencilFuncBack = pass._stencilFuncBack; + this._stencilRefBack = pass._stencilRefBack; + this._stencilMaskBack = pass._stencilMaskBack; + this._stencilFailOpBack = pass._stencilFailOpBack; + this._stencilZFailOpBack = pass._stencilZFailOpBack; + this._stencilZPassOpBack = pass._stencilZPassOpBack; + this._stencilWriteMaskBack = pass._stencilWriteMaskBack; +}; + Pass.prototype.setCullMode = function setCullMode (cullMode) { this._cullMode = cullMode; }; @@ -10477,6 +10514,29 @@ var Technique = function Technique(stages, parameters, passes, layer) { var prototypeAccessors$3 = { passes: { configurable: true },stageIDs: { configurable: true } }; +Technique.prototype.copy = function (technique) { + this._id = technique._id; + this._stageIDs = technique._stageIDs; + + this._parameters = []; + for (let i = 0; i < technique._parameters.length; ++i) { + let parameter = technique._parameters[i]; + this._parameters.push({name: parameter.name, type: parameter.type}); + } + + for (let i = 0; i < technique._passes.length; ++i) { + let pass = this._passes[i]; + if (!pass) { + pass = new renderer.Pass(); + this._passes.push(pass); + } + pass.copy(technique._passes[i]); + } + this._passes.length = technique._passes.length; + + this._layer = technique._layer; +}; + Technique.prototype.setStages = function setStages (stages) { this._stageIDs = config.stageIDs(stages); }; @@ -14184,6 +14244,7 @@ var SpriteMaterial = (function (Material$$1) { SpriteMaterial.prototype.clone = function clone () { var copy = new SpriteMaterial(); + copy._mainTech.copy(this._mainTech); copy.texture = this.texture; copy.useTexture = this.useTexture; copy.useModel = this.useModel; @@ -14275,6 +14336,7 @@ var GraySpriteMaterial = (function (Material$$1) { GraySpriteMaterial.prototype.clone = function clone () { var copy = new GraySpriteMaterial(); + copy._mainTech.copy(this._mainTech); copy.texture = this.texture; copy.color = this.color; copy.updateHash(); @@ -14387,6 +14449,7 @@ var StencilMaterial = (function (Material$$1) { StencilMaterial.prototype.clone = function clone () { var copy = new StencilMaterial(); + copy._mainTech.copy(this._mainTech); copy.useTexture = this.useTexture; copy.useModel = this.useModel; copy.useColor = this.useColor; From 1626685336babf9100b334b0d5f26cd7325e1422 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 8 Oct 2018 19:12:04 +0800 Subject: [PATCH 0067/1631] fix button bug in engine for 2.1-release (#3354) --- cocos2d/core/components/CCButton.js | 30 ++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index bf04582ffc6..f0f3b462ef0 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -419,7 +419,7 @@ let Button = cc.Class({ let target = this.target; let transition = this.transition; if (transition === Transition.COLOR && this.interactable) { - target.color = this.normalColor; + this._setTargetColor(this.normalColor); } else if (transition === Transition.SCALE) { target.scale = this._originalScale; } @@ -457,6 +457,15 @@ let Button = cc.Class({ } }, + _setTargetColor(color) { + let target = this.target; + if (!target) { + return; + } + target.color = color; + target.opacity = color.a; + }, + _getStateColor (state) { switch (state) { case State.NORMAL: @@ -550,8 +559,8 @@ let Button = cc.Class({ } if (this.transition === Transition.COLOR) { - target.color = this._fromColor.lerp(this._toColor, ratio); - target.opacity = target.color.a; + let color = this._fromColor.lerp(this._toColor, ratio); + this._setTargetColor(color); } else if (this.transition === Transition.SCALE) { target.scale = misc.lerp(this._fromScale, this._toScale, ratio); } @@ -681,15 +690,18 @@ let Button = cc.Class({ return state; }, - _updateColorTransition (state) { + _updateColorTransitionImmediately (state) { let color = this._getStateColor(state); - let target = this.target; + this._setTargetColor(color); + }, - if (CC_EDITOR) { - target.color = color; - target.opacity = color.a; + _updateColorTransition (state) { + if (CC_EDITOR || state === State.DISABLED) { + this._updateColorTransitionImmediately(state); } else { + let color = this._getStateColor(state); + let target = this.target; this._fromColor = target.color.clone(); this._toColor = color; this.time = 0; @@ -729,7 +741,7 @@ let Button = cc.Class({ _updateTransition (oldTransition) { // Reset to normal data when change transition. if (oldTransition === Transition.COLOR) { - this._updateColorTransition(State.NORMAL); + this._updateColorTransitionImmediately(State.NORMAL); } else if (oldTransition === Transition.SPRITE) { this._updateSpriteTransition(State.NORMAL); From f7ddedb84a90fca33af4cc83416558855dfcd8ae Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 8 Oct 2018 19:12:39 +0800 Subject: [PATCH 0068/1631] fixed node.setRotation (#3353) --- cocos2d/core/CCNode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index f22cfdcb4d7..f83951e460d 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -2213,7 +2213,7 @@ let NodeDefines = { old.y = y; old.z = z; old.w = w; - this.setLocalDirty(DirtyFlag.ROTATION); + this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._eventMask & ROTATION_ON) { From 5240e5c77c40ac4412d60bcf74d07663ed7f28b3 Mon Sep 17 00:00:00 2001 From: kenshin <420373550@qq.com> Date: Tue, 9 Oct 2018 11:39:52 +0800 Subject: [PATCH 0069/1631] add cross origin flag for script download. (#3356) --- cocos2d/core/load-pipeline/downloader.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index b58cfe862e8..1c1d2854f33 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -49,6 +49,11 @@ function downloadScript (item, callback, isAsync) { var url = item.url, d = document, s = document.createElement('script'); + + if (window.location.protocol !== 'file:') { + s.crossOrigin = 'anonymous'; + } + s.async = isAsync; s.src = urlAppendTimestamp(url); function loadHandler () { From 81a00a440df1a31b9bbf595536e4b38021f81e45 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Tue, 9 Oct 2018 14:03:58 +0800 Subject: [PATCH 0070/1631] Fix rendering residue for transparent images on Chrome69. (#3357) * Fix rendering residue for transparent images on Chrome69. * Disable dynamicAtlasManager to fix rendering residue for transparent images on Chrome69. --- cocos2d/core/CCGame.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 5c1b5c7848f..0e75bb3854f 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -778,6 +778,10 @@ var game = { if (!cc.macro.CLEANUP_IMAGE_CACHE && dynamicAtlasManager) { dynamicAtlasManager.enabled = true; } + // Disable dynamicAtlasManager to fix rendering residue for transparent images on Chrome69. + if (cc.sys.browserType == cc.sys.BROWSER_TYPE_CHROME && parseFloat(cc.sys.browserVersion) >= 69.0) { + dynamicAtlasManager.enabled = false; + } } if (!this._renderContext) { this.renderType = this.RENDER_TYPE_CANVAS; From 225d4a71c8c02e43b41709bf430836c8a7e7b193 Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 10 Oct 2018 11:57:17 +0800 Subject: [PATCH 0071/1631] fix segments invalid in mask (#3361) * fix segments invalid in mask * refine code --- cocos2d/core/components/CCMask.js | 35 ++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 6aba58439bf..9b710e92a64 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -36,6 +36,18 @@ const Node = require('../CCNode'); let _vec2_temp = cc.v2(); let _mat4_temp = math.mat4.create(); +let _circlepoints =[]; +function _calculateCircle (center, radius, segements) { + _circlepoints.length = 0; + let anglePerStep = Math.PI * 2 / segements; + for (let step = 0; step < segements; ++step) { + _circlepoints.push(cc.v2(radius.x * Math.cos(anglePerStep * step) + center.x, + radius.y * Math.sin(anglePerStep * step) + center.y)); + } + + return _circlepoints; +} + /** * !#en the type for mask. * !#zh 遮罩组件类型 @@ -223,7 +235,9 @@ let Mask = cc.Class({ }, set: function (value) { this._segments = misc.clampf(value, SEGEMENTS_MIN, SEGEMENTS_MAX); + this._updateGraphics(); }, + type: cc.Integer, tooltip: CC_DEV && 'i18n:COMPONENT.mask.segements', }, @@ -395,11 +409,22 @@ let Mask = cc.Class({ graphics.rect(x, y, width, height); } else if (this._type === MaskType.ELLIPSE) { - let cx = x + width / 2, - cy = y + height / 2, - rx = width / 2, - ry = height / 2; - graphics.ellipse(cx, cy, rx, ry); + let center = cc.v2(x + width / 2, y + height / 2); + let radius = { + x: width / 2, + y: height / 2 + }; + let points = _calculateCircle(center, radius, this._segments); + for (let i = 0; i < points.length; ++i) { + let point = points[i]; + if (i === 0) { + graphics.moveTo(point.x, point.y); + } + else { + graphics.lineTo(point.x, point.y); + } + } + graphics.close(); } if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { graphics.stroke(); From f5126cf3b380383ab145a0c9d6b52bccfb294a13 Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 10 Oct 2018 14:09:44 +0800 Subject: [PATCH 0072/1631] fix play particlesystem error bug (#3363) --- cocos2d/particle/CCParticleSystem.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index a99580deafc..5e47be82a38 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -873,12 +873,7 @@ var ParticleSystem = cc.Class({ resetSystem: function () { this._stopped = false; this._simulator.reset(); - if (!this._material) { - this._activateMaterial(); - } - else { - this.markForCustomIARender(true); - } + this._activateMaterial(); }, /** From e2f492517119fe17f10fe36854567ad7a4054bef Mon Sep 17 00:00:00 2001 From: leda Date: Wed, 10 Oct 2018 16:05:41 +0800 Subject: [PATCH 0073/1631] add Impl var for WebView (#3359) --- cocos2d/webview/CCWebView.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/webview/CCWebView.js b/cocos2d/webview/CCWebView.js index eea424921df..71abc42b140 100644 --- a/cocos2d/webview/CCWebView.js +++ b/cocos2d/webview/CCWebView.js @@ -107,6 +107,7 @@ let WebView = cc.Class({ statics: { EventType: EventType, + Impl: WebViewImpl }, From ad35dba6491af8d853bcc6226100633337ffbf54 Mon Sep 17 00:00:00 2001 From: caochao Date: Thu, 11 Oct 2018 09:56:30 +0800 Subject: [PATCH 0074/1631] cc.loader.loadResArray type supports Array (#3312) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * cc.loader.loadResArray类型参数支持数组 * cc.loader.loadResArray type supports Array --- cocos2d/core/load-pipeline/CCLoader.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/load-pipeline/CCLoader.js b/cocos2d/core/load-pipeline/CCLoader.js index 50dfaca8c87..c2698d110ef 100644 --- a/cocos2d/core/load-pipeline/CCLoader.js +++ b/cocos2d/core/load-pipeline/CCLoader.js @@ -388,7 +388,7 @@ proto._urlNotFound = function (url, type, completeCallback) { */ proto._parseLoadResArgs = function (type, onProgress, onComplete) { if (onComplete === undefined) { - var isValidType = js.isChildClassOf(type, cc.RawAsset); + var isValidType = (type instanceof Array) || js.isChildClassOf(type, cc.RawAsset); if (onProgress) { onComplete = onProgress; if (isValidType) { @@ -571,6 +571,7 @@ proto._loadResUuids = function (uuids, progressCallback, completeCallback, urls) * 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 */ proto.loadResArray = function (urls, type, progressCallback, completeCallback) { var args = this._parseLoadResArgs(type, progressCallback, completeCallback); @@ -579,14 +580,16 @@ proto.loadResArray = function (urls, type, progressCallback, completeCallback) { completeCallback = args.onComplete; var uuids = []; + var isTypesArray = type instanceof Array; for (var i = 0; i < urls.length; i++) { var url = urls[i]; - var uuid = this._getResUuid(url, type); + var assetType = isTypesArray ? type[i] : type; + var uuid = this._getResUuid(url, assetType); if (uuid) { uuids.push(uuid); } else { - this._urlNotFound(url, type, completeCallback); + this._urlNotFound(url, assetType, completeCallback); return; } } From 00057cd9feaf2294adb674ca6e8d9f1fb05a048a Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Thu, 11 Oct 2018 10:15:17 +0800 Subject: [PATCH 0075/1631] open DragonBones API CCFactory.getInstance() (#3358) --- extensions/dragonbones/CCFactory.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index b02da97d985..fd35c13c473 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -24,11 +24,21 @@ ****************************************************************************/ let BaseObject = dragonBones.BaseObject; - +/** + * @class CCFactory + * @extends BaseFactory + * @namespace dragonBones +*/ var CCFactory = dragonBones.CCFactory = cc.Class({ name: 'dragonBones.CCFactory', extends: dragonBones.BaseFactory, - + /** + * @method getInstance + * @return {CCFactory} + * @static + * @example + * let factory = dragonBones.CCFactory.getInstance(); + */ statics: { _factory: null, getInstance () { From 3328591f8d2e3dac63d7f8110c128ef59c128897 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Thu, 11 Oct 2018 10:18:30 +0800 Subject: [PATCH 0076/1631] fixed model deserialize on wechat platform (#3365) --- cocos2d/core/3d/CCModel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index c8c8697169a..4b4a7f718b2 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -88,7 +88,7 @@ var Model = cc.Class({ return this._bin; }, set(bin) { - this._bin = bin.buffer; + this._bin = bin.buffer || bin; this._initNodes(); }, override: true From c5a67c8f9bca44e57d2300b8893831a712c1b744 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Thu, 11 Oct 2018 10:57:03 +0800 Subject: [PATCH 0077/1631] open DragonBones API CCFactory.getInstance() (#3366) --- extensions/dragonbones/CCFactory.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index fd35c13c473..d5aee21c2f8 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -24,10 +24,14 @@ ****************************************************************************/ let BaseObject = dragonBones.BaseObject; + +/** + * @module dragonBones +*/ + /** * @class CCFactory * @extends BaseFactory - * @namespace dragonBones */ var CCFactory = dragonBones.CCFactory = cc.Class({ name: 'dragonBones.CCFactory', From 4e07eaa2e0fbf407df1ccd964c1b3b70a54932bc Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Thu, 11 Oct 2018 11:07:16 +0800 Subject: [PATCH 0078/1631] modify the initView API (#3364) --- cocos2d/core/components/CCScrollView.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index 2c69c083deb..f83c4d0f0c7 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -193,9 +193,6 @@ let ScrollView = cc.Class({ this._scrollEventEmitMask = 0; this._isBouncing = false; this._scrolling = false; - - // content parent object - this._view = undefined; }, properties: { @@ -342,6 +339,15 @@ let ScrollView = cc.Class({ default: true, animatable: false, tooltip: CC_DEV && 'i18n:COMPONENT.scrollview.cancelInnerEvents' + }, + + // private object + _view: { + get: function () { + if (this.content) { + return this.content.parent; + } + } } }, @@ -1536,7 +1542,6 @@ let ScrollView = cc.Class({ onEnable () { if (!CC_EDITOR) { - this._initView(); this._registerEvent(); this.node.on(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); this.node.on(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); @@ -1557,12 +1562,6 @@ let ScrollView = cc.Class({ if (this._autoScrolling) { this._processAutoScrolling(dt); } - }, - - _initView () { - if (this.content) { - this._view = this.content.parent; - } } }); From cd79f3d95a828287f1422a83fa98e799873a4e8c Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 11 Oct 2018 19:35:22 +0800 Subject: [PATCH 0079/1631] Use RenderFlow to drive scene visit process (#3370) * Use RenderFlow to drive scene visit process * Fix tests * Remove useless code --- cocos2d/core/3d/polyfill-3d.js | 2 - cocos2d/core/camera/CCCamera.js | 3 +- cocos2d/core/renderer/canvas/index.js | 2 +- ...r-walker.js => render-component-handle.js} | 39 +++++------ cocos2d/core/renderer/index.js | 18 ++--- cocos2d/core/renderer/render-flow.js | 65 ++++++++++--------- .../webgl/assemblers/graphics/impl.js | 2 +- cocos2d/core/renderer/webgl/mesh-buffer.js | 14 ++-- ...r-component-walker.js => model-batcher.js} | 36 +++------- cocos2d/deprecated.js | 4 +- cocos2d/particle/particle-system-assembler.js | 2 +- modules.json | 2 +- test/qunit/lib/polyfill-for-phantom.js | 17 +++++ test/qunit/unit-es5/test-spriteRenderer.js | 13 ++-- 14 files changed, 108 insertions(+), 111 deletions(-) rename cocos2d/core/renderer/canvas/{canvas-render-walker.js => render-component-handle.js} (84%) rename cocos2d/core/renderer/webgl/{render-component-walker.js => model-batcher.js} (88%) diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index 40c0f41b694..b8b6fc8b4ba 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -29,8 +29,6 @@ const EventType = Node.EventType; const DirtyFlag = Node._LocalDirtyFlag; const math = require('../renderer/render-engine').math; const RenderFlow = require('../renderer/render-flow'); -const misc = require('../utils/misc'); -const vec3 = cc.vmath.vec3; // ====== Node transform polyfills ====== const ONE_DEGREE = Math.PI / 180; diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 0f21f25e44a..0c4069259de 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -27,6 +27,7 @@ const AffineTrans = require('../utils/affine-transform'); const renderEngine = require('../renderer/render-engine'); const renderer = require('../renderer/index'); +const RenderFlow = require('../renderer/render-flow'); const game = require('../CCGame'); const ray = require('../3d/geom-utils/ray'); @@ -668,7 +669,7 @@ let Camera = cc.Class({ // force update node world matrix this.node.getWorldMatrix(_mat4_temp_1); this.beforeDraw(); - renderer._walker.visit(root); + RenderFlow.visit(root); renderer._forward.renderCamera(this._camera, renderer.scene); }, diff --git a/cocos2d/core/renderer/canvas/index.js b/cocos2d/core/renderer/canvas/index.js index a89c2fcbb00..9defc1eb39e 100644 --- a/cocos2d/core/renderer/canvas/index.js +++ b/cocos2d/core/renderer/canvas/index.js @@ -25,6 +25,6 @@ module.exports = { ForwardRenderer: require('./forward-renderer'), - RenderComponentWalker: require('./canvas-render-walker'), + RenderComponentHandle: require('./render-component-handle'), _renderers: require('./renderers') }; \ No newline at end of file diff --git a/cocos2d/core/renderer/canvas/canvas-render-walker.js b/cocos2d/core/renderer/canvas/render-component-handle.js similarity index 84% rename from cocos2d/core/renderer/canvas/canvas-render-walker.js rename to cocos2d/core/renderer/canvas/render-component-handle.js index 42f7b7b9550..fc8522c9688 100644 --- a/cocos2d/core/renderer/canvas/canvas-render-walker.js +++ b/cocos2d/core/renderer/canvas/render-component-handle.js @@ -23,11 +23,9 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('../../platform/js'); -const RenderFlow = require('../render-flow'); require('./renderers'); -let RenderComponentWalker = function (device, defaultCamera) { +let RenderComponentHandle = function (device, defaultCamera) { this._device = device; // let vx = this._device._vx; // let vy = this._device._vy; @@ -37,36 +35,35 @@ let RenderComponentWalker = function (device, defaultCamera) { this.parentOpacity = 1; this.parentOpacityDirty = 0; this.worldMatDirty = 0; - - RenderFlow.init(this); + this.walking = false; }; -RenderComponentWalker.prototype = { - constructor: RenderComponentWalker, +RenderComponentHandle.prototype = { + constructor: RenderComponentHandle, - reset() {}, - - _commitComp (comp, assembler) { - let ctx = this._device._ctx; - let cam = this._camera; - ctx.setTransform(cam.a, cam.b, cam.c, cam.d, cam.tx, cam.ty); - ctx.scale(1, -1); - assembler.draw(ctx, comp); - }, - - visit (scene) { + reset() { let ctx = this._device._ctx; let canvas = this._device._canvas; - let color = cc.Camera.main.backgroundColor; + var color = cc.Camera.main ? cc.Camera.main.backgroundColor : cc.color(); let rgba = `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a/255})`; ctx.fillStyle = rgba; ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height); this._device._stats.drawcalls = 0; + }, + + terminate () { - RenderFlow.render(scene); + }, + + _commitComp (comp, assembler) { + let ctx = this._device._ctx; + let cam = this._camera; + ctx.setTransform(cam.a, cam.b, cam.c, cam.d, cam.tx, cam.ty); + ctx.scale(1, -1); + assembler.draw(ctx, comp); } }; -module.exports = RenderComponentWalker; \ No newline at end of file +module.exports = RenderComponentHandle; \ No newline at end of file diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 72b30b21ad4..25c92bc315e 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -24,7 +24,7 @@ ****************************************************************************/ const renderEngine = require('./render-engine'); -const math = renderEngine.math; +const RenderFlow = require('./render-flow'); function _initBuiltins(device) { let defaultTexture = new renderEngine.Texture2D(device, { @@ -90,14 +90,15 @@ cc.renderer = module.exports = { * @type {Number} */ drawCalls: 0, - _walker: null, + // Render component handler + _handle: null, _cameraNode: null, _camera: null, _forward: null, initWebGL (canvas, opts) { require('./webgl/assemblers'); - const RenderComponentWalker = require('./webgl/render-component-walker'); + const ModelBatcher = require('./webgl/model-batcher'); this.Texture2D = renderEngine.Texture2D; @@ -112,8 +113,8 @@ cc.renderer = module.exports = { this.scene = new renderEngine.Scene(); - this._walker = new RenderComponentWalker(this.device, this.scene); - + this._handle = new ModelBatcher(this.device, this.scene); + RenderFlow.init(this._handle); let builtins = _initBuiltins(this.device); this._forward = new renderEngine.ForwardRenderer(this.device, builtins); }, @@ -134,7 +135,8 @@ cc.renderer = module.exports = { this._camera = { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }; - this._walker = new canvasRenderer.RenderComponentWalker(this.device, this._camera); + this._handle = new canvasRenderer.RenderComponentHandle(this.device, this._camera); + RenderFlow.init(this._handle); this._forward = new canvasRenderer.ForwardRenderer(); }, @@ -159,7 +161,7 @@ cc.renderer = module.exports = { this.device._stats.drawcalls = 0; if (ecScene) { // walk entity component scene to generate models - this._walker.visit(ecScene); + RenderFlow.visit(ecScene); // Render models in renderer scene this._forward.render(this.scene); this.drawCalls = this.device._stats.drawcalls; @@ -167,7 +169,7 @@ cc.renderer = module.exports = { }, clear () { - this._walker.reset(); + this._handle.reset(); this._forward._reset(); } }; \ No newline at end of file diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 14e020a7b6a..ecb82fb8484 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -12,7 +12,7 @@ const POST_UPDATE_RENDER_DATA = 1 << 8; const POST_RENDER = 1 << 9; const FINAL = 1 << 10; -let _walker = null; +let _batcher; let _cullingMask = 0; // @@ -32,7 +32,7 @@ _proto._localTransform = function (node) { }; _proto._worldTransform = function (node) { - _walker.worldMatDirty ++; + _batcher.worldMatDirty ++; let t = node._matrix; let position = node._position; @@ -43,7 +43,7 @@ _proto._worldTransform = function (node) { node._renderFlag &= ~WORLD_TRANSFORM; this._next._func(node); - _walker.worldMatDirty --; + _batcher.worldMatDirty --; }; _proto._color = function (node) { @@ -58,12 +58,12 @@ _proto._color = function (node) { }; _proto._opacity = function (node) { - _walker.parentOpacityDirty++; + _batcher.parentOpacityDirty++; node._renderFlag &= ~OPACITY; this._next._func(node); - _walker.parentOpacityDirty--; + _batcher.parentOpacityDirty--; }; _proto._updateRenderData = function (node) { @@ -75,24 +75,25 @@ _proto._updateRenderData = function (node) { _proto._render = function (node) { let comp = node._renderComponent; - _walker._commitComp(comp, comp._assembler, node._cullingMask); + _batcher._commitComp(comp, comp._assembler, node._cullingMask); this._next._func(node); }; _proto._customIARender = function (node) { let comp = node._renderComponent; - _walker._commitIA(comp, comp._assembler, node._cullingMask); + _batcher._commitIA(comp, comp._assembler, node._cullingMask); this._next._func(node); }; _proto._children = function (node) { let cullingMask = _cullingMask; + let batcher = _batcher; - let parentOpacity = _walker.parentOpacity; - _walker.parentOpacity *= (node._opacity / 255); + let parentOpacity = batcher.parentOpacity; + batcher.parentOpacity *= (node._opacity / 255); - let worldTransformFlag = _walker.worldMatDirty ? WORLD_TRANSFORM : 0; - let worldOpacityFlag = _walker.parentOpacityDirty ? COLOR : 0; + let worldTransformFlag = batcher.worldMatDirty ? WORLD_TRANSFORM : 0; + let worldOpacityFlag = batcher.parentOpacityDirty ? COLOR : 0; let children = node._children; for (let i = 0, l = children.length; i < l; i++) { @@ -102,12 +103,12 @@ _proto._children = function (node) { c._renderFlag |= worldTransformFlag | worldOpacityFlag; // TODO: Maybe has better way to implement cascade opacity - c._color.a = c._opacity * _walker.parentOpacity; + c._color.a = c._opacity * batcher.parentOpacity; flows[c._renderFlag]._func(c); c._color.a = 255; } - _walker.parentOpacity = parentOpacity; + batcher.parentOpacity = parentOpacity; this._next._func(node); @@ -123,7 +124,7 @@ _proto._postUpdateRenderData = function (node) { _proto._postRender = function (node) { let comp = node._renderComponent; - _walker._commitComp(comp, comp._postAssembler, node._cullingMask); + _batcher._commitComp(comp, comp._postAssembler, node._cullingMask); this._next._func(node); }; @@ -187,40 +188,42 @@ function getFlow (flag) { return flow; } +// +function init (node) { + let flag = node._renderFlag; + let r = flows[flag] = getFlow(flag); + r._func(node); +} + +RenderFlow.flows = flows; +RenderFlow.createFlow = createFlow; +RenderFlow.visit = function (scene) { + _batcher.reset(); + _batcher.walking = true; -function render (scene) { _cullingMask = 1 << scene.groupIndex; if (scene._renderFlag & WORLD_TRANSFORM) { - _walker.worldMatDirty ++; + _batcher.worldMatDirty ++; scene._calculWorldMatrix(); scene._renderFlag &= ~WORLD_TRANSFORM; flows[scene._renderFlag]._func(scene); - _walker.worldMatDirty --; + _batcher.worldMatDirty --; } else { flows[scene._renderFlag]._func(scene); } -} -// -function init (node) { - let flag = node._renderFlag; - let r = flows[flag] = getFlow(flag); - r._func(node); -} - -RenderFlow.flows = flows; -RenderFlow.createFlow = createFlow; -RenderFlow.render = render; + _batcher.terminate(); + _batcher.walking = false; +}; -RenderFlow.init = function (walker) { - _walker = walker; +RenderFlow.init = function (batcher) { + _batcher = batcher; flows[0] = EMPTY_FLOW; - for (let i = 1; i < FINAL; i++) { flows[i] = new RenderFlow(); } diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js index f66d48931bb..76946c8a764 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js @@ -217,7 +217,7 @@ cc.js.mixin(Impl.prototype, { requestRenderData () { let renderData = new IARenderData(); - let meshbuffer = new MeshBuffer(renderer._walker, vfmtPosColor); + let meshbuffer = new MeshBuffer(renderer._handle, vfmtPosColor); renderData.meshbuffer = meshbuffer; this._renderDatas.push(renderData); diff --git a/cocos2d/core/renderer/webgl/mesh-buffer.js b/cocos2d/core/renderer/webgl/mesh-buffer.js index e8e7e3a530a..0d49d4bc915 100644 --- a/cocos2d/core/renderer/webgl/mesh-buffer.js +++ b/cocos2d/core/renderer/webgl/mesh-buffer.js @@ -3,7 +3,7 @@ const gfx = renderEngine.gfx; let MeshBuffer = cc.Class({ name: 'cc.MeshBuffer', - ctor (renderer, vertexFormat) { + ctor (batcher, vertexFormat) { this.byteStart = 0; this.byteOffset = 0; this.indiceStart = 0; @@ -15,7 +15,7 @@ let MeshBuffer = cc.Class({ this._vertexBytes = this._vertexFormat._bytes; this._vb = new gfx.VertexBuffer( - renderer._device, + batcher._device, vertexFormat, gfx.USAGE_DYNAMIC, new ArrayBuffer(), @@ -23,7 +23,7 @@ let MeshBuffer = cc.Class({ ); this._ib = new gfx.IndexBuffer( - renderer._device, + batcher._device, gfx.INDEX_FMT_UINT16, gfx.USAGE_STATIC, new ArrayBuffer(), @@ -34,7 +34,7 @@ let MeshBuffer = cc.Class({ this._iData = null; this._uintVData = null; - this._renderer = renderer; + this._batcher = batcher; this._initVDataCount = 256 * vertexFormat._bytes; // actually 256 * 4 * (vertexFormat._bytes / 4) this._initIDataCount = 256 * 6; @@ -87,9 +87,9 @@ let MeshBuffer = cc.Class({ }, request (vertexCount, indiceCount) { - if (this._renderer._buffer !== this) { - this._renderer._flush(); - this._renderer._buffer = this; + if (this._batcher._buffer !== this) { + this._batcher._flush(); + this._batcher._buffer = this; } this.requestStatic(vertexCount, indiceCount); diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/model-batcher.js similarity index 88% rename from cocos2d/core/renderer/webgl/render-component-walker.js rename to cocos2d/core/renderer/webgl/model-batcher.js index d97ff9f6a7b..8464177bfe3 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/model-batcher.js @@ -23,34 +23,23 @@ THE SOFTWARE. ****************************************************************************/ -const macro = require('../../platform/CCMacro'); const renderEngine = require('../render-engine'); const defaultVertexFormat = require('./vertex-format').vfmtPosUv; const StencilManager = require('./stencil-manager'); -const dynamicAtlasManager = require('../utils/dynamic-atlas/manager'); -const RenderFlow = require('../render-flow'); const QuadBuffer = require('./quad-buffer'); const MeshBuffer = require('./mesh-buffer'); let idGenerater = new (require('../../platform/id-generater'))('VertextFormat'); -const gfx = renderEngine.gfx; const RecyclePool = renderEngine.RecyclePool; const InputAssembler = renderEngine.InputAssembler; -const FLOATS_PER_VERT = defaultVertexFormat._bytes / 4; -const BYTE_PER_INDEX = 2; -const MAX_VERTEX = macro.BATCH_VERTEX_COUNT; -const MAX_VERTEX_BYTES = MAX_VERTEX * defaultVertexFormat._bytes; -const MAX_INDICE = MAX_VERTEX * BYTE_PER_INDEX; -const MAX_INDICE_BYTES = MAX_INDICE * 2; - let _buffers = {}; const empty_material = new renderEngine.Material(); empty_material.updateHash(); -var RenderComponentWalker = function (device, renderScene) { +var ModelBatcher = function (device, renderScene) { this._renderScene = renderScene; this._device = device; this._stencilMgr = StencilManager.sharedManager; @@ -81,12 +70,10 @@ var RenderComponentWalker = function (device, renderScene) { this.parentOpacity = 1; this.parentOpacityDirty = 0; this.worldMatDirty = 0; - - RenderFlow.init(this); }; -RenderComponentWalker.prototype = { - constructor: RenderComponentWalker, +ModelBatcher.prototype = { + constructor: ModelBatcher, reset() { // Reset pools @@ -207,22 +194,17 @@ RenderComponentWalker.prototype = { assembler.renderIA(comp, this); }, - visit (scene) { - this.reset(); - this.walking = true; - - RenderFlow.render(scene); - - if (dynamicAtlasManager) { - dynamicAtlasManager.update(); + terminate () { + if (cc.dynamicAtlasManager && cc.dynamicAtlasManager.enabled) { + cc.dynamicAtlasManager.update(); } - + + // flush current rest Model this._flush(); for (let key in _buffers) { _buffers[key].uploadData(); } - this.walking = false; }, getBuffer (type, vertextFormat) { @@ -251,4 +233,4 @@ RenderComponentWalker.prototype = { } } -module.exports = RenderComponentWalker; \ No newline at end of file +module.exports = ModelBatcher; \ No newline at end of file diff --git a/cocos2d/deprecated.js b/cocos2d/deprecated.js index 76c0b398acf..7e22953302f 100644 --- a/cocos2d/deprecated.js +++ b/cocos2d/deprecated.js @@ -83,7 +83,7 @@ if (CC_DEBUG) { }, function (v) { cc.warnID(1400, `${ownerName}.${deprecatedProp}`, `${ownerName}.${newProp}`); descriptor.set.call(this, v); - }) + }); }) } @@ -354,7 +354,7 @@ if (CC_DEBUG) { ['rotationX', 'eulerAngles'], ['rotationY', 'eulerAngles'], ['rotation', 'angle'], - ]) + ]); markFunctionWarning(cc.Node.prototype, { getNodeToParentTransform: 'getLocalMatrix', diff --git a/cocos2d/particle/particle-system-assembler.js b/cocos2d/particle/particle-system-assembler.js index 37ab738fe45..445abd6772d 100644 --- a/cocos2d/particle/particle-system-assembler.js +++ b/cocos2d/particle/particle-system-assembler.js @@ -38,7 +38,7 @@ var particleSystemAssembler = { comp._vertexFormat = vfmtPosUvColor; // Create quad buffer for vertex and index - comp._buffer = new QuadBuffer(renderer._walker, vfmtPosUvColor); + comp._buffer = new QuadBuffer(renderer._handle, vfmtPosUvColor); comp._ia = new renderEngine.InputAssembler(); comp._ia._vertexBuffer = comp._buffer._vb; diff --git a/modules.json b/modules.json index b475bfb33b8..4b3669fbb00 100644 --- a/modules.json +++ b/modules.json @@ -35,7 +35,7 @@ { "name": "WebGL Renderer", "entries": [ - "./cocos2d/core/renderer/webgl/render-component-walker.js", + "./cocos2d/core/renderer/webgl/model-batcher.js", "./cocos2d/core/renderer/webgl/assemblers/index.js", "./extensions/dragonbones/webgl-assembler.js" ] diff --git a/test/qunit/lib/polyfill-for-phantom.js b/test/qunit/lib/polyfill-for-phantom.js index 227c70e68cc..a783c5b0327 100644 --- a/test/qunit/lib/polyfill-for-phantom.js +++ b/test/qunit/lib/polyfill-for-phantom.js @@ -151,4 +151,21 @@ if (!Object.assign) { return to; } }); + } + + if (!Object.getOwnPropertyDescriptors) { + Object.defineProperty(Object, 'getOwnPropertyDescriptors', { + enumerable: false, + configurable: true, + writable: true, + value: function (target) { + var res = {}; + var props = Object.getOwnPropertyNames(target); + for (var i = 0; i < props.length; i++) { + var name = props[i]; + res[name] = Object.getOwnPropertyDescriptor(target, name); + } + return res; + } + }); } \ No newline at end of file diff --git a/test/qunit/unit-es5/test-spriteRenderer.js b/test/qunit/unit-es5/test-spriteRenderer.js index b39de423b70..effca1ff55f 100644 --- a/test/qunit/unit-es5/test-spriteRenderer.js +++ b/test/qunit/unit-es5/test-spriteRenderer.js @@ -190,6 +190,7 @@ if (!isPhantomJS) { sprite._assembler.updateRenderData(sprite); var vertices = sprite._renderData._data; + var uvs = sprite._spriteFrame.uv; strictEqual(vertices.length == 8, true, 'have 8 vertices'); strictEqual(vertices[0].x, 0, 'x0 test success'); @@ -200,14 +201,10 @@ if (!isPhantomJS) { strictEqual(vertices[1].y, 60, 'y1 test success'); strictEqual(vertices[2].y, 100, 'y2 test success'); // - deepClose(vertices[0].u, 10 / 100, 0.01, 'full quad u0 test success'); - deepClose(vertices[0].v, 70 / 100, 0.01, 'full quad v0 test success'); - deepClose(vertices[3].u, 50 / 100, 0.01, 'full quad u1 test success'); - deepClose(vertices[3].v, 10 / 100, 0.01, 'full quad v1 test success'); - deepClose(vertices[4].u, 10 / 100, 0.01, 'part quad u0 test success'); - deepClose(vertices[4].v, 70 / 100, 0.01, 'part quad v0 test success'); - deepClose(vertices[7].u, 30 / 100, 0.01, 'part quad u1 test success'); - deepClose(vertices[7].v, 30 / 100, 0.01, 'part quad v1 test success'); + deepClose(uvs[0], 10 / 100, 0.01, 'full quad u0 test success'); + deepClose(uvs[1], 70 / 100, 0.01, 'full quad v0 test success'); + deepClose(uvs[6], 50 / 100, 0.01, 'full quad u1 test success'); + deepClose(uvs[7], 10 / 100, 0.01, 'full quad v1 test success'); }; if (spriteFrame.textureLoaded()) { testCallBack(); From 72ea8b180c281eed43bc88d1f4d5f6270b4675f0 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Fri, 12 Oct 2018 09:56:30 +0800 Subject: [PATCH 0080/1631] Optimize batch rendering of Sprites in case of color changes (#3368) * Fix rendering residue for transparent images on Chrome69. * Disable dynamicAtlasManager to fix rendering residue for transparent images on Chrome69. * For batch rendering of sprite, update the color only when useColor is set to true. * Optimize batch rendering of Sprites in case of color changes * Change defaultVertexFormat to vfmtPosUvColor in render-component-walker. * Change defaultVertexFormat to vfmtPosUvColor in render-component-walker. * Optimize batch rendering of BMFont in case of color changes --- cocos2d/core/components/CCLabel.js | 2 + cocos2d/core/components/CCRenderComponent.js | 7 ++- cocos2d/core/components/CCSprite.js | 2 + .../renderer/webgl/assemblers/label/bmfont.js | 6 ++- .../renderer/webgl/assemblers/label/ttf.js | 5 ++- .../webgl/assemblers/motion-streak.js | 3 +- .../webgl/assemblers/sprite/bar-filled.js | 5 ++- .../renderer/webgl/assemblers/sprite/mesh.js | 5 ++- .../webgl/assemblers/sprite/radial-filled.js | 7 ++- .../webgl/assemblers/sprite/simple.js | 33 ++++++++------ .../webgl/assemblers/sprite/sliced.js | 4 ++ .../renderer/webgl/assemblers/sprite/tiled.js | 45 +++++++++++-------- .../renderer/webgl/render-component-walker.js | 2 +- cocos2d/tilemap/tmx-layer-assembler.js | 3 +- extensions/dragonbones/webgl-assembler.js | 3 +- extensions/spine/spine-assembler.js | 3 +- 16 files changed, 85 insertions(+), 50 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 2fe08e88a3c..a952526f85e 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -570,6 +570,8 @@ let Label = cc.Class({ this._srcBlendFactor = cc.macro.BlendFactor.SRC_ALPHA; } material.texture = this._texture; + // For batch rendering, do not use uniform color. + material.useColor = false; this._updateMaterial(material); } diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 4ff2a9f050a..3e4830c3baa 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -181,8 +181,11 @@ let RenderComponent = cc.Class({ _updateColor () { let material = this._material; if (material) { - material.color = this.node.color; - material.updateHash(); + // For batch rendering, update the color only when useColor is set to true. + if (material.useColor) { + material.color = this.node.color; + material.updateHash(); + } // reset flag when set color to material successfully this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index fb943ad5bf7..4465f21e94f 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -500,6 +500,8 @@ var Sprite = cc.Class({ } material = this._spriteMaterial; } + // For batch rendering, do not use uniform color. + material.useColor = false; // Set texture if (spriteFrame && spriteFrame.textureLoaded()) { let texture = spriteFrame.getTexture(); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js index c4b985ee3ca..cf3445faea2 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js @@ -35,7 +35,7 @@ module.exports = js.addon({ let node = comp.node, renderData = comp._renderData, data = renderData._data, - color = node.color._val; + color = node._color._val; let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, @@ -48,7 +48,8 @@ module.exports = js.addon({ buffer.request(vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData; + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; for (let i = 0; i < vertexCount; i++) { let vert = data[i]; @@ -56,6 +57,7 @@ module.exports = js.addon({ vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset++] = vert.u; vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index 0d980acdc10..d6503d7f7dc 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -49,6 +49,7 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let data = comp._renderData._data, node = comp.node, + color = node._color._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; @@ -59,7 +60,8 @@ module.exports = js.addon({ buffer.request(4, 6); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData; + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; // vertex for (let i = 0; i < 4; i++) { @@ -68,6 +70,7 @@ module.exports = js.addon({ vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset++] = vert.u; vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index f3bade69cd3..04c3c515da6 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -25,7 +25,6 @@ const MotionStreak = require('../../../components/CCMotionStreak'); const RenderFlow = require('../../render-flow'); -const vfmtPosUvColor = require('../vertex-format').vfmtPosUvColor; function Point (point, dir) { this.point = point || cc.v2(); @@ -195,7 +194,7 @@ var motionStreakAssembler = { renderData = comp._renderData, data = renderData._data; - let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), + let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, vertexCount = renderData.vertexCount; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index 474fe243802..0d45402644d 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -224,6 +224,7 @@ module.exports = { let data = sprite._renderData._data, node = sprite.node, + color = node._color._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; @@ -234,7 +235,8 @@ module.exports = { buffer.request(4, 6); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData; + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; // vertex for (let i = 0; i < 4; i++) { @@ -243,6 +245,7 @@ module.exports = { vbuf[vertexOffset++] = vert.y; vbuf[vertexOffset++] = vert.u; vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; } } }; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js index e8f024b84bf..344cd93f1f6 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js @@ -25,7 +25,7 @@ const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - module.exports = { +module.exports = { useModel: false, createData (sprite) { @@ -155,6 +155,7 @@ const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); fillBuffers (sprite, renderer) { let node = sprite.node, + color = node._color._val, renderData = sprite._renderData, data = renderData._data; @@ -179,6 +180,7 @@ const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, + uintbuf = buffer._uintVData, ibuf = buffer._iData; for (let i = 0, l = renderData.vertexCount; i < l; i++) { @@ -187,6 +189,7 @@ const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); vbuf[vertexOffset++] = vertice.y; vbuf[vertexOffset++] = vertice.u; vbuf[vertexOffset++] = vertice.v; + uintbuf[vertexOffset++] = color; } let triangles = vertices.triangles; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js index 3dca7ed1efa..fe153d9a88b 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js @@ -331,7 +331,8 @@ module.exports = { fillBuffers (sprite, renderer) { let renderData = sprite._renderData, data = renderData._data, - node = sprite.node; + node = sprite.node, + color = node._color._val; let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, @@ -340,7 +341,8 @@ module.exports = { // buffer let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, - vbuf = buffer._vData; + vbuf = buffer._vData, + uintbuf = buffer._uintVData; let ibuf = buffer._iData, indiceOffset = buffer.indiceOffset, @@ -355,6 +357,7 @@ module.exports = { vbuf[vertexOffset ++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset ++] = vert.u; vbuf[vertexOffset ++] = vert.v; + uintbuf[vertexOffset ++] = color; } for (let i = 0; i < count; i++) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js index d684b2c0218..930fa9ddf1f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js @@ -53,6 +53,7 @@ module.exports = { fillBuffers (sprite, renderer) { let data = sprite._renderData._data, node = sprite.node, + color = node._color._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; @@ -63,18 +64,19 @@ module.exports = { buffer.request(4, 6); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData; + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; // get uv from sprite frame directly let uv = sprite._spriteFrame.uv; vbuf[vertexOffset+2] = uv[0]; vbuf[vertexOffset+3] = uv[1]; - vbuf[vertexOffset+6] = uv[2]; - vbuf[vertexOffset+7] = uv[3]; - vbuf[vertexOffset+10] = uv[4]; - vbuf[vertexOffset+11] = uv[5]; - vbuf[vertexOffset+14] = uv[6]; - vbuf[vertexOffset+15] = uv[7]; + vbuf[vertexOffset+7] = uv[2]; + vbuf[vertexOffset+8] = uv[3]; + vbuf[vertexOffset+12] = uv[4]; + vbuf[vertexOffset+13] = uv[5]; + vbuf[vertexOffset+17] = uv[6]; + vbuf[vertexOffset+18] = uv[7]; let data0 = data[0], data3 = data[3], vl = data0.x, vr = data3.x, @@ -89,14 +91,19 @@ module.exports = { vbuf[vertexOffset] = al + cb + tx; vbuf[vertexOffset+1] = bl + db + ty; // right bottom - vbuf[vertexOffset+4] = ar + cb + tx; - vbuf[vertexOffset+5] = br + db + ty; + vbuf[vertexOffset+5] = ar + cb + tx; + vbuf[vertexOffset+6] = br + db + ty; // left top - vbuf[vertexOffset+8] = al + ct + tx; - vbuf[vertexOffset+9] = bl + dt + ty; + vbuf[vertexOffset+10] = al + ct + tx; + vbuf[vertexOffset+11] = bl + dt + ty; // right top - vbuf[vertexOffset+12] = ar + ct + tx; - vbuf[vertexOffset+13] = br + dt + ty; + vbuf[vertexOffset+15] = ar + ct + tx; + vbuf[vertexOffset+16] = br + dt + ty; + // color + uintbuf[vertexOffset+4] = color; + uintbuf[vertexOffset+9] = color; + uintbuf[vertexOffset+14] = color; + uintbuf[vertexOffset+19] = color; }, createData (sprite) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js index 3279497dabd..8ccb7940d5e 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js @@ -103,6 +103,8 @@ module.exports = { } let renderData = sprite._renderData, + node = sprite.node, + color = node._color._val, data = renderData._data; let buffer = renderer._meshBuffer, @@ -118,6 +120,7 @@ module.exports = { // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, + uintbuf = buffer._uintVData, ibuf = buffer._iData; for (let i = 4; i < 20; ++i) { @@ -128,6 +131,7 @@ module.exports = { vbuf[vertexOffset++] = vert.y; vbuf[vertexOffset++] = uvs.u; vbuf[vertexOffset++] = uvs.v; + uintbuf[vertexOffset++] = color; } for (let r = 0; r < 3; ++r) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js index 9e60ca17d47..40685213fdb 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js @@ -88,6 +88,7 @@ module.exports = { fillBuffers (sprite, renderer) { let node = sprite.node, + color = node._color._val, renderData = sprite._renderData, data = renderData._data; @@ -102,6 +103,7 @@ module.exports = { // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, + uintbuf = buffer._uintVData, ibuf = buffer._iData; let rotated = sprite.spriteFrame._rotated; @@ -133,14 +135,14 @@ module.exports = { vbuf[vertexOffset] = x * a + y * c + tx; vbuf[vertexOffset+1] = x * b + y * d + ty; // rb - vbuf[vertexOffset+4] = x1 * a + y * c + tx; - vbuf[vertexOffset+5] = x1 * b + y * d + ty; + vbuf[vertexOffset+5] = x1 * a + y * c + tx; + vbuf[vertexOffset+6] = x1 * b + y * d + ty; // lt - vbuf[vertexOffset+8] = x * a + y1 * c + tx; - vbuf[vertexOffset+9] = x * b + y1 * d + ty; + vbuf[vertexOffset+10] = x * a + y1 * c + tx; + vbuf[vertexOffset+11] = x * b + y1 * d + ty; // rt - vbuf[vertexOffset+12] = x1 * a + y1 * c + tx; - vbuf[vertexOffset+13] = x1 * b + y1 * d + ty; + vbuf[vertexOffset+15] = x1 * a + y1 * c + tx; + vbuf[vertexOffset+16] = x1 * b + y1 * d + ty; // UV if (rotated) { @@ -148,30 +150,35 @@ module.exports = { vbuf[vertexOffset+2] = uv[0]; vbuf[vertexOffset+3] = uv[1]; // rb - vbuf[vertexOffset+6] = uv[0]; - vbuf[vertexOffset+7] = uv[1] + (uv[7] - uv[1]) * coefu; + vbuf[vertexOffset+7] = uv[0]; + vbuf[vertexOffset+8] = uv[1] + (uv[7] - uv[1]) * coefu; // lt - vbuf[vertexOffset+10] = uv[0] + (uv[6] - uv[0]) * coefv; - vbuf[vertexOffset+11] = uv[1]; + vbuf[vertexOffset+12] = uv[0] + (uv[6] - uv[0]) * coefv; + vbuf[vertexOffset+13] = uv[1]; // rt - vbuf[vertexOffset+14] = vbuf[vertexOffset+10]; - vbuf[vertexOffset+15] = vbuf[vertexOffset+7]; + vbuf[vertexOffset+17] = vbuf[vertexOffset+12]; + vbuf[vertexOffset+18] = vbuf[vertexOffset+8]; } else { // lb vbuf[vertexOffset+2] = uv[0]; vbuf[vertexOffset+3] = uv[1]; // rb - vbuf[vertexOffset+6] = uv[0] + (uv[6] - uv[0]) * coefu; - vbuf[vertexOffset+7] = uv[1]; + vbuf[vertexOffset+7] = uv[0] + (uv[6] - uv[0]) * coefu; + vbuf[vertexOffset+8] = uv[1]; // lt - vbuf[vertexOffset+10] = uv[0]; - vbuf[vertexOffset+11] = uv[1] + (uv[7] - uv[1]) * coefv; + vbuf[vertexOffset+12] = uv[0]; + vbuf[vertexOffset+13] = uv[1] + (uv[7] - uv[1]) * coefv; // rt - vbuf[vertexOffset+14] = vbuf[vertexOffset+6]; - vbuf[vertexOffset+15] = vbuf[vertexOffset+11]; + vbuf[vertexOffset+17] = vbuf[vertexOffset+7]; + vbuf[vertexOffset+18] = vbuf[vertexOffset+13]; } - vertexOffset += 16; + // color + uintbuf[vertexOffset+4] = color; + uintbuf[vertexOffset+9] = color; + uintbuf[vertexOffset+14] = color; + uintbuf[vertexOffset+19] = color; + vertexOffset += 20; } } diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/render-component-walker.js index 539c2fe2dbe..d97e59387a8 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/render-component-walker.js @@ -25,7 +25,7 @@ const macro = require('../../platform/CCMacro'); const renderEngine = require('../render-engine'); -const defaultVertexFormat = require('./vertex-format').vfmtPosUv; +const defaultVertexFormat = require('./vertex-format').vfmtPosUvColor; const StencilManager = require('./stencil-manager'); const dynamicAtlasManager = require('../utils/dynamic-atlas/manager'); const RenderFlow = require('../render-flow'); diff --git a/cocos2d/tilemap/tmx-layer-assembler.js b/cocos2d/tilemap/tmx-layer-assembler.js index dde3eb961af..517ad692eaf 100644 --- a/cocos2d/tilemap/tmx-layer-assembler.js +++ b/cocos2d/tilemap/tmx-layer-assembler.js @@ -28,7 +28,6 @@ const TiledMap = require('./CCTiledMap'); const renderEngine = require('../core/renderer/render-engine'); const RenderFlow = require('../core/renderer/render-flow'); -const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; const Orientation = TiledMap.Orientation; const TileFlag = TiledMap.TileFlag; @@ -63,7 +62,7 @@ let tmxAssembler = { let renderData = comp._renderData; let data = renderData._data; - let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), + let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, vertexCount = renderData.vertexCount; diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 9bbdc6d36b3..28c6bfc9c43 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -31,7 +31,6 @@ const math = renderEngine.math; const js = require('../../cocos2d/core/platform/js'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); -const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; let _matrix = math.mat4.create(); let _v3 = cc.v3(); @@ -86,7 +85,7 @@ let armatureAssembler = { let armature = comp._armature; if (!armature || comp._isChildArmature) return; - let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), + let buffer = renderer._meshBuffer, renderData = comp._renderData; _vertexOffset = buffer.byteOffset >> 2; diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index fb0de3b931e..8d9aed1b5c0 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -28,7 +28,6 @@ const Skeleton = require('./Skeleton'); const spine = require('./lib/spine'); const renderer = require('../../cocos2d/core/renderer'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); -const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; const renderEngine = renderer.renderEngine; const gfx = renderEngine.gfx; const SpriteMaterial = renderEngine.SpriteMaterial; @@ -325,7 +324,7 @@ var spineAssembler = { let vertexs = data._data; let indices = data._indices; - let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), + let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, vertexCount = data.vertexCount; From 296daef539218cd62b220bfcf51ec38b4e678296 Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 12 Oct 2018 10:45:58 +0800 Subject: [PATCH 0081/1631] fix audio setCurrentTime unbindEnded (#3373) --- cocos2d/audio/CCAudio.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/audio/CCAudio.js b/cocos2d/audio/CCAudio.js index 568120454c9..43d794fcd5a 100644 --- a/cocos2d/audio/CCAudio.js +++ b/cocos2d/audio/CCAudio.js @@ -235,8 +235,8 @@ Audio.State = { return; } - this._unbindEnded(); if (!(CC_QQPLAY || CC_WECHATGAME)) { + this._unbindEnded(); this._bindEnded(function () { this._bindEnded(); }.bind(this)); From 2a1a17f75fbfcba39a582469af165adc6577eebe Mon Sep 17 00:00:00 2001 From: Coco Date: Fri, 12 Oct 2018 15:12:32 +0800 Subject: [PATCH 0082/1631] make webview add listenerEvent berfor load --- cocos2d/webview/CCWebView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/webview/CCWebView.js b/cocos2d/webview/CCWebView.js index eea424921df..b475ed6e51b 100644 --- a/cocos2d/webview/CCWebView.js +++ b/cocos2d/webview/CCWebView.js @@ -123,13 +123,13 @@ let WebView = cc.Class({ onEnable () { let impl = this._impl; impl.createDomElementIfNeeded(this.node.width, this.node.height); - impl.loadURL(this._url); - impl.setVisible(true); if (!CC_EDITOR) { impl.setEventListener(EventType.LOADED, this._onWebViewLoaded.bind(this)); impl.setEventListener(EventType.LOADING, this._onWebViewLoading.bind(this)); impl.setEventListener(EventType.ERROR, this._onWebViewLoadError.bind(this)); } + impl.loadURL(this._url); + impl.setVisible(true); }, onDisable () { From 7ca9ff74eb0870d3d99daa635e341bb16d110981 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 12 Oct 2018 18:23:38 +0800 Subject: [PATCH 0083/1631] Upgrade render engine for native renderer (#3378) * Upgrade render engine * Fix Camera._node usage for JSB --- cocos2d/core/camera/CCCamera.js | 2 +- cocos2d/core/renderer/render-engine.js | 15 +- cocos2d/core/renderer/render-engine.jsb.js | 378 ++++++++++++++++----- 3 files changed, 297 insertions(+), 98 deletions(-) diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 0c4069259de..843f978038b 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -48,7 +48,7 @@ let _debugCamera = null; function repositionDebugCamera () { if (!_debugCamera) return; - let node = _debugCamera._node; + let node = _debugCamera.getNode(); let canvas = cc.game.canvas; node.z = canvas.height / 1.1566; node.x = canvas.width / 2; diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 179a37ed896..bc960a1c3b8 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -14148,7 +14148,7 @@ var SpriteMaterial = (function (Material$$1) { prototypeAccessors.useTexture.set = function (val) { this._effect.define('useTexture', val); }; - + prototypeAccessors.useModel.get = function () { return this._effect.getDefine('useModel'); }; @@ -14200,6 +14200,7 @@ var SpriteMaterial = (function (Material$$1) { SpriteMaterial.prototype.clone = function clone () { var copy = new SpriteMaterial(); + copy._mainTech.copy(this._mainTech); copy.texture = this.texture; copy.useTexture = this.useTexture; copy.useModel = this.useModel; @@ -14291,6 +14292,7 @@ var GraySpriteMaterial = (function (Material$$1) { GraySpriteMaterial.prototype.clone = function clone () { var copy = new GraySpriteMaterial(); + copy._mainTech.copy(this._mainTech); copy.texture = this.texture; copy.color = this.color; copy.updateHash(); @@ -14358,7 +14360,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useTexture.get = function () { - this._effect.getDefine('useTexture'); + return this._effect.getDefine('useTexture'); }; prototypeAccessors.useTexture.set = function (val) { @@ -14366,7 +14368,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useModel.get = function () { - this._effect.getDefine('useModel'); + return this._effect.getDefine('useModel'); }; prototypeAccessors.useModel.set = function (val) { @@ -14374,7 +14376,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useColor.get = function () { - this._effect.getDefine('useColor'); + return this._effect.getDefine('useColor'); }; prototypeAccessors.useColor.set = function (val) { @@ -14403,6 +14405,7 @@ var StencilMaterial = (function (Material$$1) { StencilMaterial.prototype.clone = function clone () { var copy = new StencilMaterial(); + copy._mainTech.copy(this._mainTech); copy.useTexture = this.useTexture; copy.useModel = this.useModel; copy.useColor = this.useColor; @@ -14596,8 +14599,8 @@ var MeshMaterial = (function (Material$$1) { return MeshMaterial; }(Material)); -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + var Device$2 = function Device(canvasEL) { var ctx; diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 5fc7a5a1970..2b65f788a9f 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -372,6 +372,13 @@ VertexFormat.prototype.element = function element (attrName) { var gl$1 = window.__gl; var gfx$1 = window.gfx; +var _tmpGetSetDesc = { + get: undefined, + set: undefined, + enumerable: true, + configurable: true +}; + window.device = gfx$1.Device.getInstance(); window.device._gl = window.__gl; @@ -398,14 +405,18 @@ _p._ctor = function(device, format, usage, data, numVertices) { this.init(device, format._nativeObj, usage, data, numVertices); this._nativePtr = this.self(); }; -cc.defineGetterSetter(_p, "count", _p.getCount); +_tmpGetSetDesc.get = _p.getCount; +_tmpGetSetDesc.set = undefined; +Object.defineProperty(_p, "count", _tmpGetSetDesc); _p = gfx$1.IndexBuffer.prototype; _p._ctor = function(device, format, usage, data, numIndices) { this.init(device, format, usage, data, numIndices); this._nativePtr = this.self(); }; -cc.defineGetterSetter(_p, "count", _p.getCount); +_tmpGetSetDesc.get = _p.getCount; +_tmpGetSetDesc.set = undefined; +Object.defineProperty(_p, "count", _tmpGetSetDesc); gfx$1.VertexFormat = VertexFormat; Object.assign(gfx$1, enums); @@ -491,8 +502,11 @@ _p.updateSubImage = function(option) { this.updateSubImageNative(data); }; -cc.defineGetterSetter(_p, "_width", _p.getWidth); -cc.defineGetterSetter(_p, "_height", _p.getHeight); +_tmpGetSetDesc.get = _p.getWidth; +_tmpGetSetDesc.set = undefined; +Object.defineProperty(_p, "_width", _tmpGetSetDesc); +_tmpGetSetDesc.get = _p.getHeight; +Object.defineProperty(_p, "_height", _tmpGetSetDesc); _p = gfx$1.FrameBuffer.prototype; _p._ctor = function(device, width, height, options) { @@ -572,8 +586,106 @@ var config = { }; // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - + var renderer$1 = window.renderer; + +var Effect = function Effect(techniques, properties, defines) { + if ( properties === void 0 ) properties = {}; + if ( defines === void 0 ) defines = []; + + this._techniques = techniques; + this._properties = properties; + this._defines = defines; + + var techniqueObjs = []; + var techniqueObj; + for (var i = 0, len = techniques.length; i < len; ++i) { + techniqueObj = techniques[i]._nativeObj; + techniqueObjs.push(techniqueObj); + } + + this._nativeObj = new renderer$1.EffectNative(); + this._nativeObj.init(techniqueObjs, properties, defines); + this._nativePtr = this._nativeObj.self(); + + // TODO: check if params is valid for current technique??? +}; + +Effect.prototype.clear = function clear () { + this._techniques.length = 0; + this._properties = null; + this._defines.length = 0; +}; + +Effect.prototype.getTechnique = function getTechnique (stage) { + var this$1 = this; + + var stageID = config.stageID(stage); + for (var i = 0; i < this._techniques.length; ++i) { + var tech = this$1._techniques[i]; + if (tech.stageIDs & stageID) { + return tech; + } + } + + return null; +}; + +Effect.prototype.getProperty = function getProperty (name) { + return this._properties[name]; +}; + +Effect.prototype.setProperty = function setProperty (name, value) { + // TODO: check if params is valid for current technique??? + this._properties[name] = value; + this._nativeObj.setProperty(name, value); +}; + +Effect.prototype.getDefine = function getDefine (name) { + var this$1 = this; + + for (var i = 0; i < this._defines.length; ++i) { + var def = this$1._defines[i]; + if ( def.name === name ) { + return def.value; + } + } + + console.warn(("Failed to get define " + name + ", define not found.")); + return null; +}; + +Effect.prototype.define = function define (name, value) { + var this$1 = this; + + for (var i = 0; i < this._defines.length; ++i) { + var def = this$1._defines[i]; + if ( def.name === name ) { + def.value = value; + return; + } + } + + this._nativeObj.setDefine(name, value); + + console.warn(("Failed to set define " + name + ", define not found.")); +}; + +Effect.prototype.extractDefines = function extractDefines (out) { + var this$1 = this; + if ( out === void 0 ) out = {}; + + for (var i = 0; i < this._defines.length; ++i) { + var def = this$1._defines[i]; + out[def.name] = def.value; + } + + return out; +}; + +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +var renderer$2 = window.renderer; var _genID = 0; var Technique = function Technique(stages, parameters, passes, layer) { @@ -593,10 +705,34 @@ var Technique = function Technique(stages, parameters, passes, layer) { for (var i = 0, len = passes.length; i < len; ++i) { passesNative.push(passes[i]._native); } - this._nativeObj = new renderer$1.TechniqueNative(stages, parameters, passesNative, layer); + this._nativeObj = new renderer$2.TechniqueNative(stages, parameters, passesNative, layer); }; +Technique.prototype.copy = function copy (technique) { + var this$1 = this; + + this._id = technique._id; + this._stageIDs = technique._stageIDs; + + this._parameters = []; + for (var i = 0; i < technique._parameters.length; ++i) { + var parameter = technique._parameters[i]; + this$1._parameters.push({name: parameter.name, type: parameter.type}); + } + + for (var i$1 = 0; i$1 < technique._passes.length; ++i$1) { + var pass = this$1._passes[i$1]; + if (!pass) { + pass = new renderer$2.Pass(); + this$1._passes.push(pass); + } + pass.copy(technique._passes[i$1]); + } + this._passes.length = technique._passes.length; + this._layer = technique._layer; +}; + Technique.prototype.setStages = function setStages (stages) { this._stageIDs = config.stageIDs(stages); this._stages = stages; @@ -607,7 +743,7 @@ Technique.prototype.setStages = function setStages (stages) { // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. var gfx$4 = window.gfx; -var renderer$2 = window.renderer; +var renderer$3 = window.renderer; var Pass = function Pass(name) { this._programName = name; @@ -628,7 +764,10 @@ var Pass = function Pass(name) { // depth this._depthTest = false; this._depthWrite = false; - this._depthFunc = gfx$4.DS_FUNC_LESS, this._stencilTest = false; + this._depthFunc = gfx$4.DS_FUNC_LESS; + + // stencil + this._stencilTest = false; // front this._stencilFuncFront = gfx$4.DS_FUNC_ALWAYS; this._stencilRefFront = 0; @@ -672,10 +811,46 @@ var Pass = function Pass(name) { binary[22] = this._stencilZFailOpBack; binary[23] = this._stencilZPassOpBack; binary[24] = this._stencilWriteMaskBack; - this._native = new renderer$2.PassNative(); + this._native = new renderer$3.PassNative(); this._native.init(this._programName, binary); }; +Pass.prototype.copy = function copy (pass) { + this._programName = pass._programName; + // cullmode + this._cullMode = pass._cullMode; + // blending + this._blend = pass._blend; + this._blendEq = pass._blendEq; + this._blendAlphaEq = pass._blendAlphaEq; + this._blendSrc = pass._blendSrc; + this._blendDst = pass._blendDst; + this._blendSrcAlpha = pass._blendSrcAlpha; + this._blendDstAlpha = pass._blendDstAlpha; + this._blendColor = pass._blendColor; + // depth + this._depthTest = pass._depthTest; + this._depthWrite = pass._depthWrite; + this._depthFunc = pass._depthFunc; + this._stencilTest = pass._stencilTest; + // front + this._stencilFuncFront = pass._stencilFuncFront; + this._stencilRefFront = pass._stencilRefFront; + this._stencilMaskFront = pass._stencilMaskFront; + this._stencilFailOpFront = pass._stencilFailOpFront; + this._stencilZFailOpFront = pass._stencilZFailOpFront; + this._stencilZPassOpFront = pass._stencilZPassOpFront; + this._stencilWriteMaskFront = pass._stencilWriteMaskFront; + // back + this._stencilFuncBack = pass._stencilFuncBack; + this._stencilRefBack = pass._stencilRefBack; + this._stencilMaskBack = pass._stencilMaskBack; + this._stencilFailOpBack = pass._stencilFailOpBack; + this._stencilZFailOpBack = pass._stencilZFailOpBack; + this._stencilZPassOpBack = pass._stencilZPassOpBack; + this._stencilWriteMaskBack = pass._stencilWriteMaskBack; +}; + Pass.prototype.setCullMode = function setCullMode (cullMode) { this._cullMode = cullMode; @@ -915,49 +1090,49 @@ Object.defineProperties( Model.prototype, prototypeAccessors ); // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -var renderer$3 = window.renderer; +var renderer$4 = window.renderer; // projection -renderer$3.PROJ_PERSPECTIVE = 0; -renderer$3.PROJ_ORTHO = 1; +renderer$4.PROJ_PERSPECTIVE = 0; +renderer$4.PROJ_ORTHO = 1; // lights -renderer$3.LIGHT_DIRECTIONAL = 0; -renderer$3.LIGHT_POINT = 1; -renderer$3.LIGHT_SPOT = 2; +renderer$4.LIGHT_DIRECTIONAL = 0; +renderer$4.LIGHT_POINT = 1; +renderer$4.LIGHT_SPOT = 2; // shadows -renderer$3.SHADOW_NONE = 0; -renderer$3.SHADOW_HARD = 1; -renderer$3.SHADOW_SOFT = 2; +renderer$4.SHADOW_NONE = 0; +renderer$4.SHADOW_HARD = 1; +renderer$4.SHADOW_SOFT = 2; // parameter type -renderer$3.PARAM_INT = 0; -renderer$3.PARAM_INT2 = 1; -renderer$3.PARAM_INT3 = 2; -renderer$3.PARAM_INT4 = 3; -renderer$3.PARAM_FLOAT = 4; -renderer$3.PARAM_FLOAT2 = 5; -renderer$3.PARAM_FLOAT3 = 6; -renderer$3.PARAM_FLOAT4 = 7; -renderer$3.PARAM_COLOR3 = 8; -renderer$3.PARAM_COLOR4 = 9; -renderer$3.PARAM_MAT2 = 10; -renderer$3.PARAM_MAT3 = 11; -renderer$3.PARAM_MAT4 = 12; -renderer$3.PARAM_TEXTURE_2D = 13; -renderer$3.PARAM_TEXTURE_CUBE = 14; +renderer$4.PARAM_INT = 0; +renderer$4.PARAM_INT2 = 1; +renderer$4.PARAM_INT3 = 2; +renderer$4.PARAM_INT4 = 3; +renderer$4.PARAM_FLOAT = 4; +renderer$4.PARAM_FLOAT2 = 5; +renderer$4.PARAM_FLOAT3 = 6; +renderer$4.PARAM_FLOAT4 = 7; +renderer$4.PARAM_COLOR3 = 8; +renderer$4.PARAM_COLOR4 = 9; +renderer$4.PARAM_MAT2 = 10; +renderer$4.PARAM_MAT3 = 11; +renderer$4.PARAM_MAT4 = 12; +renderer$4.PARAM_TEXTURE_2D = 13; +renderer$4.PARAM_TEXTURE_CUBE = 14; // clear flags -renderer$3.CLEAR_COLOR = 1; -renderer$3.CLEAR_DEPTH = 2; -renderer$3.CLEAR_STENCIL = 4; -renderer$3.InputAssembler = InputAssembler; -renderer$3.config = config; -renderer$3.Effect = Effect; -renderer$3.Technique = Technique; -renderer$3.Pass = Pass; -renderer$3.Model = Model; +renderer$4.CLEAR_COLOR = 1; +renderer$4.CLEAR_DEPTH = 2; +renderer$4.CLEAR_STENCIL = 4; +renderer$4.InputAssembler = InputAssembler; +renderer$4.config = config; +renderer$4.Effect = Effect; +renderer$4.Technique = Technique; +renderer$4.Pass = Pass; +renderer$4.Model = Model; var models = []; var sizeOfModel = 13; @@ -1003,7 +1178,7 @@ var fillModelData = function() { }; // ForwardRenderer adapter -var _p$1 = renderer$3.ForwardRenderer.prototype; +var _p$1 = renderer$4.ForwardRenderer.prototype; _p$1._ctor = function(device, builtin) { this.init(device, builtin.programTemplates, builtin.defaultTexture, window.innerWidth, window.innerHeight); }; @@ -1013,15 +1188,22 @@ _p$1.render = function(scene) { models.length = 0; }; +_p$1.renderCamera = function(camera, scene) { + fillModelData(); + this.renderCameraNative(camera, scene, modelsData); + + models.length = 0; +}; // Scene -_p$1 = renderer$3.Scene.prototype; +_p$1 = renderer$4.Scene.prototype; _p$1.addModel = function(model) { models.push(model); }; _p$1.removeModel = function() {}; var chunks = { + 'skinning.vert': '\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}', }; var templates = [ @@ -1032,6 +1214,17 @@ var templates = [ defines: [ ], }, + { + name: 'mesh', + vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\n#ifdef useAttributeColor\n attribute vec4 a_color;\n varying vec4 v_color;\n#endif\n#ifdef useTexture\n attribute vec2 a_uv0;\n varying vec2 uv0;\n#endif\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useSkinning\n \nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef useSkinning\n mvp = mvp * skinMatrix();\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n #ifdef useAttributeColor\n v_color = a_color;\n #endif\n gl_Position = pos;\n}', + frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying vec2 uv0;\n#endif\n#ifdef useAttributeColor\n varying vec4 v_color;\n#endif\nuniform vec4 color;\nvoid main () {\n vec4 o = color;\n \n #ifdef useAttributeColor\n o *= v_color;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n gl_FragColor = o;\n}', + defines: [ + { name: 'useTexture', }, + { name: 'useModel', }, + { name: 'useSkinning', }, + { name: 'useJointsTexture', }, + { name: 'useAttributeColor', } ], + }, { name: 'sprite', vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', @@ -2549,7 +2742,7 @@ function murmurhash2_32_gc(str, seed) { return h >>> 0; } -var renderer$5 = window.renderer; +var renderer$6 = window.renderer; // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. @@ -2622,33 +2815,33 @@ function computeHash(material) { continue; } switch(param.type) { - case renderer$5.PARAM_INT: - case renderer$5.PARAM_FLOAT: + case renderer$6.PARAM_INT: + case renderer$6.PARAM_FLOAT: hashData += prop + ';'; break; - case renderer$5.PARAM_INT2: - case renderer$5.PARAM_FLOAT2: + case renderer$6.PARAM_INT2: + case renderer$6.PARAM_FLOAT2: hashData += prop.x + ',' + prop.y + ';'; break; - case renderer$5.PARAM_INT4: - case renderer$5.PARAM_FLOAT4: + case renderer$6.PARAM_INT4: + case renderer$6.PARAM_FLOAT4: hashData += prop.x + ',' + prop.y + ',' + prop.z + ',' + prop.w + ';'; break; - case renderer$5.PARAM_COLOR4: + case renderer$6.PARAM_COLOR4: hashData += prop.r + ',' + prop.g + ',' + prop.b + ',' + prop.a + ';'; break; - case renderer$5.PARAM_MAT2: + case renderer$6.PARAM_MAT2: hashData += prop.m00 + ',' + prop.m01 + ',' + prop.m02 + ',' + prop.m03 + ';'; break; - case renderer$5.PARAM_TEXTURE_2D: - case renderer$5.PARAM_TEXTURE_CUBE: + case renderer$6.PARAM_TEXTURE_2D: + case renderer$6.PARAM_TEXTURE_CUBE: hashData += material._texIds[propKey] + ';'; break; - case renderer$5.PARAM_INT3: - case renderer$5.PARAM_FLOAT3: - case renderer$5.PARAM_COLOR3: - case renderer$5.PARAM_MAT3: - case renderer$5.PARAM_MAT4: + case renderer$6.PARAM_INT3: + case renderer$6.PARAM_FLOAT3: + case renderer$6.PARAM_COLOR3: + case renderer$6.PARAM_MAT3: + case renderer$6.PARAM_MAT4: hashData += JSON.stringify(prop) + ';'; break; default: @@ -2700,7 +2893,7 @@ var SpriteMaterial = (function (Material$$1) { function SpriteMaterial() { Material$$1.call(this, false); - var pass = new renderer$5.Pass('sprite'); + var pass = new renderer$6.Pass('sprite'); pass.setDepth(false, false); pass.setCullMode(gfx$5.CULL_NONE); pass.setBlend( @@ -2710,18 +2903,18 @@ var SpriteMaterial = (function (Material$$1) { gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer$5.Technique( + var mainTech = new renderer$6.Technique( ['transparent'], [ - { name: 'texture', type: renderer$5.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer$5.PARAM_COLOR4 } ], + { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, + { name: 'color', type: renderer$6.PARAM_COLOR4 } ], [ pass ] ); this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer$5.Effect( + this._effect = new renderer$6.Effect( [ mainTech ], { @@ -2750,7 +2943,7 @@ var SpriteMaterial = (function (Material$$1) { }; prototypeAccessors.useTexture.get = function () { - this._effect.getDefine('useTexture'); + return this._effect.getDefine('useTexture'); }; prototypeAccessors.useTexture.set = function (val) { @@ -2758,7 +2951,7 @@ var SpriteMaterial = (function (Material$$1) { }; prototypeAccessors.useModel.get = function () { - this._effect.getDefine('useModel'); + return this._effect.getDefine('useModel'); }; prototypeAccessors.useModel.set = function (val) { @@ -2766,7 +2959,7 @@ var SpriteMaterial = (function (Material$$1) { }; prototypeAccessors.use2DPos.get = function () { - this._effect.getDefine('use2DPos'); + return this._effect.getDefine('use2DPos'); }; prototypeAccessors.use2DPos.set = function (val) { @@ -2774,7 +2967,7 @@ var SpriteMaterial = (function (Material$$1) { }; prototypeAccessors.useColor.get = function () { - this._effect.getDefine('useColor'); + return this._effect.getDefine('useColor'); }; prototypeAccessors.useColor.set = function (val) { @@ -2808,6 +3001,7 @@ var SpriteMaterial = (function (Material$$1) { SpriteMaterial.prototype.clone = function clone () { var copy = new SpriteMaterial(); + copy._mainTech.copy(this._mainTech); copy.texture = this.texture; copy.useTexture = this.useTexture; copy.useModel = this.useModel; @@ -2828,7 +3022,7 @@ var GraySpriteMaterial = (function (Material$$1) { function GraySpriteMaterial() { Material$$1.call(this, false); - var pass = new renderer$5.Pass('gray_sprite'); + var pass = new renderer$6.Pass('gray_sprite'); pass.setDepth(false, false); pass.setCullMode(gfx$5.CULL_NONE); pass.setBlend( @@ -2838,18 +3032,18 @@ var GraySpriteMaterial = (function (Material$$1) { gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer$5.Technique( + var mainTech = new renderer$6.Technique( ['transparent'], [ - { name: 'texture', type: renderer$5.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer$5.PARAM_COLOR4 } ], + { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, + { name: 'color', type: renderer$6.PARAM_COLOR4 } ], [ pass ] ); this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer$5.Effect( + this._effect = new renderer$6.Effect( [ mainTech ], { @@ -2899,6 +3093,7 @@ var GraySpriteMaterial = (function (Material$$1) { GraySpriteMaterial.prototype.clone = function clone () { var copy = new GraySpriteMaterial(); + copy._mainTech.copy(this._mainTech); copy.texture = this.texture; copy.color = this.color; copy.updateHash(); @@ -2916,7 +3111,7 @@ var StencilMaterial = (function (Material$$1) { function StencilMaterial() { Material$$1.call(this, false); - this._pass = new renderer$5.Pass('sprite'); + this._pass = new renderer$6.Pass('sprite'); this._pass.setDepth(false, false); this._pass.setCullMode(gfx$5.CULL_NONE); this._pass.setBlend( @@ -2926,18 +3121,18 @@ var StencilMaterial = (function (Material$$1) { gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer$5.Technique( + var mainTech = new renderer$6.Technique( ['transparent'], [ - { name: 'texture', type: renderer$5.PARAM_TEXTURE_2D }, - { name: 'alphaThreshold', type: renderer$5.PARAM_FLOAT }, - { name: 'color', type: renderer$5.PARAM_COLOR4 } ], + { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, + { name: 'alphaThreshold', type: renderer$6.PARAM_FLOAT }, + { name: 'color', type: renderer$6.PARAM_COLOR4 } ], [ this._pass ] ); - this._effect = new renderer$5.Effect( + this._effect = new renderer$6.Effect( [ mainTech ], { @@ -2966,7 +3161,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useTexture.get = function () { - this._effect.getDefine('useTexture'); + return this._effect.getDefine('useTexture'); }; prototypeAccessors.useTexture.set = function (val) { @@ -2974,7 +3169,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useModel.get = function () { - this._effect.getDefine('useModel'); + return this._effect.getDefine('useModel'); }; prototypeAccessors.useModel.set = function (val) { @@ -2982,7 +3177,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useColor.get = function () { - this._effect.getDefine('useColor'); + return this._effect.getDefine('useColor'); }; prototypeAccessors.useColor.set = function (val) { @@ -3011,6 +3206,7 @@ var StencilMaterial = (function (Material$$1) { StencilMaterial.prototype.clone = function clone () { var copy = new StencilMaterial(); + copy._mainTech.copy(this._mainTech); copy.useTexture = this.useTexture; copy.useModel = this.useModel; copy.useColor = this.useColor; @@ -10432,25 +10628,25 @@ var canvas = { // intenral // deps // Add stage to renderer -renderer$3.config.addStage('transparent'); +renderer$4.config.addStage('transparent'); var renderEngine = { // core classes Device: gfx$1.Device, - ForwardRenderer: renderer$3.ForwardRenderer, + ForwardRenderer: renderer$4.ForwardRenderer, Texture2D: gfx$1.Texture2D, // Canvas render support canvas: canvas, // render scene - Scene: renderer$3.Scene, - Camera: renderer$3.Camera, - View: renderer$3.View, - Model: renderer$3.Model, + Scene: renderer$4.Scene, + Camera: renderer$4.Camera, + View: renderer$4.View, + Model: renderer$4.Model, RenderData: RenderData, IARenderData: IARenderData, - InputAssembler: renderer$3.InputAssembler, + InputAssembler: renderer$4.InputAssembler, // assets Asset: Asset, @@ -10471,7 +10667,7 @@ var renderEngine = { // modules math: math, - renderer: renderer$3, + renderer: renderer$4, gfx: gfx$1, }; From bb2de78522281192645b4cbe994639f928c180d9 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 12 Oct 2018 21:47:29 +0800 Subject: [PATCH 0084/1631] fixed issues when upgrade node api (#3372) * should sync eulerAngles when change change rotation in editor * upgrade cc.RotateTo/cc.RotateBy * refine code * fixed aabb geom --- cocos2d/actions/CCActionInterval.js | 155 +++++++++++++++++++--------- cocos2d/core/3d/geom-utils/aabb.js | 2 +- cocos2d/core/CCNode.js | 4 + cocos2d/core/value-types/quat.js | 1 + 4 files changed, 112 insertions(+), 50 deletions(-) diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index a5aabc7d5d7..ee5fdda61cc 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -25,6 +25,11 @@ THE SOFTWARE. ****************************************************************************/ +const quat = cc.vmath.quat; +let _quat_tmp = cc.quat(); +let _vec3_tmp = cc.v3(); + + /** * @module cc */ @@ -871,7 +876,7 @@ cc.Spawn._actionOneTwo = function (action1, action2) { * @class RotateTo * @extends ActionInterval * @param {Number} duration duration in seconds - * @param {Number} deltaAngleX deltaAngleX in degrees. + * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees. * @param {Number} [deltaAngleY] deltaAngleY in degrees. * @example * var rotateTo = new cc.RotateTo(2, 61.0); @@ -880,27 +885,40 @@ cc.RotateTo = cc.Class({ name: 'cc.RotateTo', extends: cc.ActionInterval, - ctor:function (duration, deltaAngleX, deltaAngleY) { - this._dstAngleX = 0; - this._startAngleX = 0; - this._diffAngleX = 0; - this._dstAngleY = 0; - this._startAngleY = 0; - this._diffAngleY = 0; - deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY); + ctor:function (duration, dstAngleX, dstAngleY) { + this._angle = cc.v3(); + this._startAngle = cc.v3(); + this._dstAngle = cc.v3(); + this._need3D = false; + dstAngleX !== undefined && this.initWithDuration(duration, dstAngleX, dstAngleY); }, /* * Initializes the action. * @param {Number} duration - * @param {Number} deltaAngleX - * @param {Number} deltaAngleY + * @param {Number|Vec3} dstAngleX + * @param {Number} dstAngleY * @return {Boolean} */ - initWithDuration:function (duration, deltaAngleX, deltaAngleY) { + initWithDuration:function (duration, dstAngleX, dstAngleY) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - this._dstAngleX = deltaAngleX || 0; - this._dstAngleY = deltaAngleY !== undefined ? deltaAngleY : this._dstAngleX; + let dstAngle = this._dstAngle; + if (dstAngleX instanceof cc.Vec3) { + dstAngle.set(dstAngleX); + if (dstAngleX.x || dstAngleX.y) { + this._need3D = true; + } + } + else if (dstAngleY !== undefined) { + dstAngle.x = dstAngleX; + dstAngle.y = dstAngleY; + dstAngle.z = 0; + this._need3D = true; + } + else { + dstAngle.x = dstAngle.y = 0; + dstAngle.z = dstAngleX; + } return true; } return false; @@ -909,31 +927,31 @@ cc.RotateTo = cc.Class({ clone:function () { var action = new cc.RotateTo(); this._cloneDecoration(action); - action.initWithDuration(this._duration, this._dstAngleX, this._dstAngleY); + action.initWithDuration(this._duration, this._dstAngle); return action; }, + _formatAngle (angle) { + if (angle > 180) angle -= 360; + if (angle < -180) angle += 360; + return angle; + }, + startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - // Calculate X - var locStartAngleX = target.rotationX % 360.0; - var locDiffAngleX = this._dstAngleX - locStartAngleX; - if (locDiffAngleX > 180) - locDiffAngleX -= 360; - if (locDiffAngleX < -180) - locDiffAngleX += 360; - this._startAngleX = locStartAngleX; - this._diffAngleX = locDiffAngleX; - - // Calculate Y It's duplicated from calculating X since the rotation wrap should be the same - this._startAngleY = target.rotationY % 360.0; - var locDiffAngleY = this._dstAngleY - this._startAngleY; - if (locDiffAngleY > 180) - locDiffAngleY -= 360; - if (locDiffAngleY < -180) - locDiffAngleY += 360; - this._diffAngleY = locDiffAngleY; + this._startAngle.set(target.eulerAngles); + + let angle = this._angle; + cc.vmath.vec3.sub(angle, this._dstAngle, this._startAngle); + + angle.x = this._formatAngle(angle.x); + angle.y = this._formatAngle(angle.y); + angle.z = this._formatAngle(angle.z); + + if (this._need3D) { + target.is3DNode = true; + } }, reverse:function () { @@ -943,8 +961,18 @@ cc.RotateTo = cc.Class({ update:function (dt) { dt = this._computeEaseTime(dt); if (this.target) { - this.target.rotationX = this._startAngleX + this._diffAngleX * dt; - this.target.rotationY = this._startAngleY + this._diffAngleY * dt; + let angle = this._angle; + let startAngle = this._startAngle; + let rotationZ = -(startAngle.z + angle.z * dt); + if (this._need3D) { + let rotationX = startAngle.x + angle.x * dt; + let rotationY = startAngle.y + angle.y * dt; + quat.fromEuler(_quat_tmp, rotationX, rotationY, rotationZ); + this.target.setRotation(_quat_tmp); + } + else { + this.target.angle = rotationZ; + } } } }); @@ -974,7 +1002,7 @@ cc.rotateTo = function (duration, deltaAngleX, deltaAngleY) { * @class RotateBy * @extends ActionInterval * @param {Number} duration duration in seconds - * @param {Number} deltaAngleX deltaAngleX in degrees + * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees * @param {Number} [deltaAngleY] deltaAngleY in degrees * @example * var actionBy = new cc.RotateBy(2, 360); @@ -984,24 +1012,37 @@ cc.RotateBy = cc.Class({ extends: cc.ActionInterval, ctor: function (duration, deltaAngleX, deltaAngleY) { - this._angleX = 0; - this._startAngleX = 0; - this._angleY = 0; - this._startAngleY = 0; + this._angle = cc.v3(); + this._startAngle = cc.v3(); + this._need3D = false; deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY); }, /* * Initializes the action. * @param {Number} duration duration in seconds - * @param {Number} deltaAngleX deltaAngleX in degrees + * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees * @param {Number} [deltaAngleY=] deltaAngleY in degrees * @return {Boolean} */ initWithDuration:function (duration, deltaAngleX, deltaAngleY) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - this._angleX = deltaAngleX || 0; - this._angleY = deltaAngleY !== undefined ? deltaAngleY : this._angleX; + if (deltaAngleX instanceof cc.Vec3) { + this._angle.set(deltaAngleX); + if (deltaAngleX.x || deltaAngleX.y) { + this._need3D = true; + } + } + else if (deltaAngleY !== undefined) { + this._angle.x = deltaAngleX; + this._angle.y = deltaAngleY; + this._angle.z = 0; + this._need3D = true; + } + else { + this._angle.x = this._angle.y = 0; + this._angle.z = deltaAngleX; + } return true; } return false; @@ -1010,26 +1051,42 @@ cc.RotateBy = cc.Class({ clone:function () { var action = new cc.RotateBy(); this._cloneDecoration(action); - action.initWithDuration(this._duration, this._angleX, this._angleY); + action.initWithDuration(this._duration, this._angle); return action; }, startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - this._startAngleX = target.rotationX; - this._startAngleY = target.rotationY; + this._startAngle.set(target.eulerAngles); + if (this._need3D) { + target.is3DNode = true; + } }, update:function (dt) { dt = this._computeEaseTime(dt); if (this.target) { - this.target.rotationX = this._startAngleX + this._angleX * dt; - this.target.rotationY = this._startAngleY + this._angleY * dt; + let angle = this._angle; + let startAngle = this._startAngle; + let rotationZ = -(startAngle.z + angle.z * dt); + if (this._need3D) { + let rotationX = startAngle.x + angle.x * dt; + let rotationY = startAngle.y + angle.y * dt; + quat.fromEuler(_quat_tmp, rotationX, rotationY, rotationZ); + this.target.setRotation(_quat_tmp); + } + else { + this.target.angle = rotationZ; + } } }, reverse:function () { - var action = new cc.RotateBy(this._duration, -this._angleX, -this._angleY); + let angle = this._angle; + _vec3_tmp.x = -angle.x; + _vec3_tmp.y = -angle.y; + _vec3_tmp.z = -angle.z; + var action = new cc.RotateBy(this._duration, _vec3_tmp); this._cloneDecoration(action); this._reverseEaseList(action); return action; diff --git a/cocos2d/core/3d/geom-utils/aabb.js b/cocos2d/core/3d/geom-utils/aabb.js index 68ae79abf8c..a8c7242e2b4 100644 --- a/cocos2d/core/3d/geom-utils/aabb.js +++ b/cocos2d/core/3d/geom-utils/aabb.js @@ -78,7 +78,7 @@ aabb.create = function (px, py, pz, w, h, l) { * @return {geomUtils.Aabb} */ aabb.clone = function (a) { - return new Aabb(a.center.x, a.center.y, a.center.z, + return new aabb(a.center.x, a.center.y, a.center.z, a.halfExtents.x, a.halfExtents.y, a.halfExtents.z); } diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index f83951e460d..7b80eb63f58 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -2219,6 +2219,10 @@ let NodeDefines = { if (this._eventMask & ROTATION_ON) { this.emit(EventType.ROTATION_CHANGED); } + + if (CC_EDITOR) { + old.getEulerAngles(this._eulerAngles); + } } } }, diff --git a/cocos2d/core/value-types/quat.js b/cocos2d/core/value-types/quat.js index 2b161de83c9..3def494907e 100644 --- a/cocos2d/core/value-types/quat.js +++ b/cocos2d/core/value-types/quat.js @@ -140,6 +140,7 @@ proto.getEulerAngles = function (out) { out.x = this.getRoll(); out.y = this.getPitch(); out.z = this.getYaw(); + return out; } proto.lerp = function (to, ratio, out) { From f78835e867f5d1415560652f529dd2c0f7cb92df Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Mon, 15 Oct 2018 19:17:34 +0800 Subject: [PATCH 0085/1631] Modify the node with opacity 0 to skip rendering. (#3382) * Modify the node with opacity 0 to skip rendering. * Modify access private properties. --- cocos2d/core/renderer/render-flow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 14e020a7b6a..3aaf18b308d 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -97,7 +97,7 @@ _proto._children = function (node) { let children = node._children; for (let i = 0, l = children.length; i < l; i++) { let c = children[i]; - if (!c._activeInHierarchy) continue; + if (!c._activeInHierarchy || c._opacity === 0) continue; _cullingMask = c._cullingMask = c.groupIndex === 0 ? cullingMask : 1 << c.groupIndex; c._renderFlag |= worldTransformFlag | worldOpacityFlag; From 205df14fae7365ebfd408fd212e74655b9d060cf Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 16 Oct 2018 10:03:23 +0800 Subject: [PATCH 0086/1631] modify the node note url (#3388) --- cocos2d/core/CCNode.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index edfa56a9239..4bebbcc1d3a 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1732,7 +1732,7 @@ var Node = cc.Class({ /** * !#en Pause node related system events registered with the current Node. Node system events includes touch and mouse events. * If recursive is set to true, then this API will pause the node system events for the node and all nodes in its sub node tree. - * Reference: http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/scripting/internal-events/ + * Reference: http://docs.cocos2d-x.org/editors_and_tools/creator-chapters/scripting/internal-events/ * !#zh 暂停当前节点上注册的所有节点系统事件,节点系统事件包含触摸和鼠标事件。 * 如果传递 recursive 为 true,那么这个 API 将暂停本节点和它的子树上所有节点的节点系统事件。 * 参考:http://cocos.com/docs/creator/scripting/internal-events.html @@ -1748,7 +1748,7 @@ var Node = cc.Class({ /** * !#en Resume node related system events registered with the current Node. Node system events includes touch and mouse events. * If recursive is set to true, then this API will resume the node system events for the node and all nodes in its sub node tree. - * Reference: http://cocos2d-x.org/docs/editors_and_tools/creator-chapters/scripting/internal-events/ + * Reference: http://docs.cocos2d-x.org/editors_and_tools/creator-chapters/scripting/internal-events/ * !#zh 恢复当前节点上注册的所有节点系统事件,节点系统事件包含触摸和鼠标事件。 * 如果传递 recursive 为 true,那么这个 API 将恢复本节点和它的子树上所有节点的节点系统事件。 * 参考:http://cocos.com/docs/creator/scripting/internal-events.html From 34d161fda8bcc66fcaec1b8cb991a192d1818aff Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 16 Oct 2018 11:57:09 +0800 Subject: [PATCH 0087/1631] fix animation registered lastframe invalid (#3387) * fix animation registered lastframe invalid * refine code * refine code --- cocos2d/animation/animation-animator.js | 2 +- cocos2d/animation/animation-state.js | 2 +- cocos2d/core/components/CCAnimation.js | 79 +++++++++++++------------ 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/cocos2d/animation/animation-animator.js b/cocos2d/animation/animation-animator.js index 3d6b4ace39c..a01c195aa4b 100644 --- a/cocos2d/animation/animation-animator.js +++ b/cocos2d/animation/animation-animator.js @@ -83,7 +83,7 @@ p.addAnimation = function (anim) { this._anims.push(anim); } - anim._setListeners(this.animation); + anim._setEventTarget(this.animation); }; p.removeAnimation = function (anim) { diff --git a/cocos2d/animation/animation-state.js b/cocos2d/animation/animation-state.js index 2c2c9135a1a..fd51fe98b20 100644 --- a/cocos2d/animation/animation-state.js +++ b/cocos2d/animation/animation-state.js @@ -213,7 +213,7 @@ proto.off = function (type, callback, target) { } }; -proto._setListeners = function (target) { +proto._setEventTarget = function (target) { this._target = target; }; diff --git a/cocos2d/core/components/CCAnimation.js b/cocos2d/core/components/CCAnimation.js index d110f4e85e4..504cee75c8f 100644 --- a/cocos2d/core/components/CCAnimation.js +++ b/cocos2d/core/components/CCAnimation.js @@ -44,7 +44,7 @@ function equalClips (clip1, clip2) { * @static * @namespace Animationd */ -var EventType = cc.Enum({ +let EventType = cc.Enum({ /** * !#en Emit when begin playing animation * !#zh 开始播放时触发 @@ -87,7 +87,7 @@ var EventType = cc.Enum({ * @static */ FINISHED: 'finished' -}) +}); /** * !#en The animation component is used to play back animations. @@ -114,7 +114,7 @@ var EventType = cc.Enum({ * @extends Component * @uses EventTarget */ -var Animation = cc.Class({ +let Animation = cc.Class({ name: 'cc.Animation', extends: require('./CCComponent'), mixins: [EventTarget], @@ -170,9 +170,9 @@ var Animation = cc.Class({ return; } - var clips = this._clips; + let clips = this._clips; - for (var i = 0, l = clips.length; i < l; i++) { + for (let i = 0, l = clips.length; i < l; i++) { if (equalClips(value, clips[i])) { return; } @@ -229,9 +229,9 @@ var Animation = cc.Class({ start: function () { if (!CC_EDITOR && this.playOnLoad && this._defaultClip) { - var isPlaying = this._animator && this._animator.isPlaying; + let isPlaying = this._animator && this._animator.isPlaying; if (!isPlaying) { - var state = this.getAnimationState(this._defaultClip.name); + let state = this.getAnimationState(this._defaultClip.name); this._animator.playState(state); } } @@ -279,7 +279,7 @@ var Animation = cc.Class({ * animCtrl.play("linear"); */ play: function (name, startTime) { - var state = this.playAdditive(name, startTime); + let state = this.playAdditive(name, startTime); this._animator.stopStatesExcept(state); return state; }, @@ -301,12 +301,12 @@ var Animation = cc.Class({ */ playAdditive: function (name, startTime) { this._init(); - var state = this.getAnimationState(name || (this._defaultClip && this._defaultClip.name)); + let state = this.getAnimationState(name || (this._defaultClip && this._defaultClip.name)); if (state) { this.enabled = true; - - var animator = this._animator; + + let animator = this._animator; if (animator.isPlaying && state.isPlaying) { if (state.isPaused) { animator.resumeState(state); @@ -345,7 +345,7 @@ var Animation = cc.Class({ return; } if (name) { - var state = this._nameToState[name]; + let state = this._nameToState[name]; if (state) { this._animator.stopState(state); } @@ -366,7 +366,7 @@ var Animation = cc.Class({ return; } if (name) { - var state = this._nameToState[name]; + let state = this._nameToState[name]; if (state) { this._animator.pauseState(state); } @@ -387,7 +387,7 @@ var Animation = cc.Class({ return; } if (name) { - var state = this._nameToState[name]; + let state = this._nameToState[name]; if (state) { this._animator.resumeState(state); } @@ -407,7 +407,7 @@ var Animation = cc.Class({ setCurrentTime: function (time, name) { this._init(); if (name) { - var state = this._nameToState[name]; + let state = this._nameToState[name]; if (state) { this._animator.setStateTime(state, time); } @@ -426,7 +426,7 @@ var Animation = cc.Class({ */ getAnimationState: function (name) { this._init(); - var state = this._nameToState[name]; + let state = this._nameToState[name]; if (CC_EDITOR && (!state || !cc.js.array.contains(this._clips, state.clip))) { this._didInit = false; @@ -468,7 +468,7 @@ var Animation = cc.Class({ // replace same name clip newName = newName || clip.name; - var oldState = this._nameToState[newName]; + let oldState = this._nameToState[newName]; if (oldState) { if (oldState.clip === clip) { return oldState; @@ -482,7 +482,7 @@ var Animation = cc.Class({ } // replace state - var newState = new cc.AnimationState(clip, newName); + let newState = new cc.AnimationState(clip, newName); this._nameToState[newName] = newState; return newState; }, @@ -507,10 +507,10 @@ var Animation = cc.Class({ } this._init(); - var state; - for (var name in this._nameToState) { + let state; + for (let name in this._nameToState) { state = this._nameToState[name]; - var stateClip = state.clip; + let stateClip = state.clip; if (stateClip === clip) { break; } @@ -553,7 +553,7 @@ var Animation = cc.Class({ this._init(); if (name) { - var state = this._nameToState[name]; + let state = this._nameToState[name]; if (state) { state.sample(); } @@ -599,11 +599,14 @@ var Animation = cc.Class({ on: function (type, callback, target, useCapture) { this._init(); - var ret = this._EventTargetOn(type, callback, target, useCapture); - - var array = this._animator._anims.array; - for (var i = 0; i < array.length; ++i) { - array[i]._setListeners(this); + let ret = this._EventTargetOn(type, callback, target, useCapture); + + if (type === 'lastframe') { + let array = this._animator._anims.array; + for (let i = 0; i < array.length; ++i) { + let state = array[i]; + state._lastframeEventOn = true; + } } return ret; @@ -631,13 +634,15 @@ var Animation = cc.Class({ off: function (type, callback, target, useCapture) { this._init(); - this._EventTargetOff(type, callback, target, useCapture); - - var nameToState = this._nameToState; - for (var name in nameToState) { - var state = nameToState[name]; - state._setListeners(null); + if (type === 'lastframe') { + let nameToState = this._nameToState; + for (let name in nameToState) { + let state = nameToState[name]; + state._lastframeEventOn = false; + } } + + this._EventTargetOff(type, callback, target, useCapture); }, /////////////////////////////////////////////////////////////////////////////// @@ -660,10 +665,10 @@ var Animation = cc.Class({ this._nameToState = js.createMap(true); // create animation states - var state = null; - var defaultClipState = false; - for (var i = 0; i < this._clips.length; ++i) { - var clip = this._clips[i]; + let state = null; + let defaultClipState = false; + for (let i = 0; i < this._clips.length; ++i) { + let clip = this._clips[i]; if (clip) { state = new cc.AnimationState(clip); From 4fa1e0b1a9d094b2f2285c0df77c1faf0ecffcd8 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 16 Oct 2018 11:59:50 +0800 Subject: [PATCH 0088/1631] fixed mesh color not worked (#3389) --- cocos2d/core/mesh/CCMeshRenderer.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index c0b0f847ca6..afe267b2984 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -77,7 +77,7 @@ let MeshRenderer = cc.Class({ _createMaterial (subMesh) { let material = new renderEngine.MeshMaterial(); - material.color = cc.Color.WHITE; + material.color = this.node.color; material._mainTech._passes[0].setDepth(true, true); material.useModel = true; @@ -88,6 +88,17 @@ let MeshRenderer = cc.Class({ return material; }, + _updateColor () { + let materials = this._materials; + for (let i = 0; i < materials.length; i++) { + let material = materials[i]; + material.color = this.node.color; + material.updateHash(); + } + + this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; + }, + _reset () { this._materials.length = 0; this._material = null; From f59d3da7cc4e2d45c13970ab5ba18624f3c5ffa4 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 16 Oct 2018 15:06:38 +0800 Subject: [PATCH 0089/1631] pageView and ScrollView (#3390) --- cocos2d/core/components/CCPageView.js | 9 +++++++++ cocos2d/core/components/CCScrollView.js | 7 ++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/components/CCPageView.js b/cocos2d/core/components/CCPageView.js index 7ef276a27c8..06ced582cfe 100644 --- a/cocos2d/core/components/CCPageView.js +++ b/cocos2d/core/components/CCPageView.js @@ -553,6 +553,15 @@ var PageView = cc.Class({ }, _handleReleaseLogic: function(touch) { + this._autoScrollToPage(); + if (this._scrolling) { + this._scrolling = false; + if (!this._autoScrolling) { + this._dispatchEvent('scroll-ended'); + } + } + }, + _autoScrollToPage: function () { var bounceBackStarted = this._startBounceBackIfNeeded(); var moveOffset = this._touchBeganPosition.sub(this._touchEndPosition); if (bounceBackStarted) { diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index f83c4d0f0c7..50b509ebd3b 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -813,7 +813,7 @@ let ScrollView = cc.Class({ this._mouseWheelEventElapsedTime += dt; - //mouse wheel event is ended + // mouse wheel event is ended if (this._mouseWheelEventElapsedTime > maxElapsedTime) { this._onScrollBarTouchEnded(); this.unschedule(this._checkMouseWheel); @@ -1179,8 +1179,7 @@ let ScrollView = cc.Class({ _handleReleaseLogic (touch) { let delta = touch.getDelta(); this._gatherTouchMove(delta); - this._processInertiaScroll(); - + this._processInertiaScroll(); if (this._scrolling) { this._scrolling = false; if (!this._autoScrolling) { @@ -1260,8 +1259,10 @@ let ScrollView = cc.Class({ this._moveContent(this._clampDelta(deltaMove), reachedEnd); this._dispatchEvent('scrolling'); + // scollTo API controll move if (!this._autoScrolling) { this._isBouncing = false; + this._scrolling = false; this._dispatchEvent('scroll-ended'); } }, From 19466ee29fbe813971d7c3f6bf1d9ac334bc4951 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 16 Oct 2018 18:06:15 +0800 Subject: [PATCH 0090/1631] fix life value is 0, emissionRate value calculation error (#3394) --- cocos2d/particle/CCParticleSystem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 5e47be82a38..84e2794280b 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -993,7 +993,7 @@ var ParticleSystem = cc.Class({ this.lifeVar = parseFloat(dict["particleLifespanVariance"] || 0); // emission Rate - this.emissionRate = this.totalParticles / this.life; + this.emissionRate = Math.min(this.totalParticles / this.life, Number.MAX_VALUE); // duration this.duration = parseFloat(dict["duration"] || 0); From a4898c5dc742b66eb26e4c1f2c351ca6bbbc71e9 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Wed, 17 Oct 2018 13:42:06 +0800 Subject: [PATCH 0091/1631] modify Component extend note (#3395) --- cocos2d/core/components/CCLabel.js | 2 +- cocos2d/core/components/CCMask.js | 2 +- cocos2d/core/components/CCSprite.js | 2 +- cocos2d/core/graphics/graphics.js | 2 +- cocos2d/particle/CCParticleSystem.js | 2 +- extensions/dragonbones/ArmatureDisplay.js | 2 +- extensions/spine/Skeleton.js | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 2fe08e88a3c..c4c0eaec917 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -131,7 +131,7 @@ const Overflow = cc.Enum({ * !#en The Label Component. * !#zh 文字标签组件 * @class Label - * @extends Component + * @extends RenderComponent */ let Label = cc.Class({ name: 'cc.Label', diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 9b710e92a64..492205063b2 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -81,7 +81,7 @@ const SEGEMENTS_MAX = 10000; * !#en The Mask Component * !#zh 遮罩组件 * @class Mask - * @extends Component + * @extends RenderComponent */ let Mask = cc.Class({ name: 'cc.Mask', diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index fb943ad5bf7..041d6395d4f 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -145,7 +145,7 @@ var State = cc.Enum({ * !#en Renders a sprite in the scene. * !#zh 该组件用于在场景中渲染精灵。 * @class Sprite - * @extends Component + * @extends RenderComponent * @example * // Create a new node and add sprite components. * var node = new cc.Node("New Sprite"); diff --git a/cocos2d/core/graphics/graphics.js b/cocos2d/core/graphics/graphics.js index 39cfe49929a..c11755cf5a4 100644 --- a/cocos2d/core/graphics/graphics.js +++ b/cocos2d/core/graphics/graphics.js @@ -33,7 +33,7 @@ const LineJoin = Types.LineJoin; /** * @class Graphics - * @extends Component + * @extends RenderComponent */ let Graphics = cc.Class({ name: 'cc.Graphics', diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 84e2794280b..65796252861 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -693,7 +693,7 @@ var properties = { * emitter.startSpin = 0; * * @class ParticleSystem - * @extends Component + * @extends RenderComponent */ var ParticleSystem = cc.Class({ name: 'cc.ParticleSystem', diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 1d982ff5d06..fb7ae52a879 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -61,7 +61,7 @@ function setEnumAttr (obj, propName, enumDef) { * 多个 Armature Display 可以使用相同的骨骼数据,其中包括所有的动画,皮肤和 attachments。)
* * @class ArmatureDisplay - * @extends Component + * @extends RenderComponent */ let ArmatureDisplay = cc.Class({ name: 'dragonBones.ArmatureDisplay', diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 9eb84aff801..578c7c54c84 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -58,7 +58,7 @@ function setEnumAttr (obj, propName, enumDef) { * 多个 Skeleton 可以使用相同的骨骼数据,其中包括所有的动画,皮肤和 attachments。 * * @class Skeleton - * @extends Component + * @extends RenderComponent */ sp.Skeleton = cc.Class({ name: 'sp.Skeleton', From 237d78d0ed7664e27428e032c61750620bae3355 Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 17 Oct 2018 14:09:01 +0800 Subject: [PATCH 0092/1631] fix outline color invalid for (#3396) --- cocos2d/core/renderer/webgl/assemblers/label/ttf.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index d6503d7f7dc..ac4b35b3a93 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -26,6 +26,8 @@ const js = require('../../../../platform/js'); const ttfUtls = require('../../../utils/label/ttf'); +const WHITE = cc.color(255, 255, 255, 255); + module.exports = js.addon({ createData (comp) { let renderData = comp.requestRenderData(); @@ -49,7 +51,7 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let data = comp._renderData._data, node = comp.node, - color = node._color._val, + color = WHITE._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; From 0f080359bf0051e20cf741738c7d3bc992faeb3e Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 17 Oct 2018 14:25:37 +0800 Subject: [PATCH 0093/1631] refine 3d asset (#3384) * 1. add skeleton asset 2. support create SkinnedMeshRenderer/SkeletonAnimation from editor inspector menu 3. add BufferAsset 4. add MeshResource to manager mesh data(maybe from : model/editor/other) * fixed test * fixed sync rotaionX/rotationY * refine code --- cocos2d/core/3d/CCModel.js | 175 ++++++++++++----------- cocos2d/core/3d/CCModelMeshResource.js | 80 +++++++++++ cocos2d/core/3d/CCSkeleton.js | 50 +++++++ cocos2d/core/3d/CCSkeletonAnimation.js | 9 +- cocos2d/core/3d/CCSkinnedMeshRenderer.js | 133 +++++++++++------ cocos2d/core/3d/index.js | 2 + cocos2d/core/CCNode.js | 7 +- cocos2d/core/assets/CCBufferAsset.js | 52 +++++++ cocos2d/core/assets/index.js | 3 +- cocos2d/core/mesh/CCMesh.js | 55 ++----- cocos2d/core/mesh/CCMeshRenderer.js | 14 +- cocos2d/core/mesh/CCMeshResource.js | 34 +++++ 12 files changed, 437 insertions(+), 177 deletions(-) create mode 100644 cocos2d/core/3d/CCModelMeshResource.js create mode 100644 cocos2d/core/3d/CCSkeleton.js create mode 100644 cocos2d/core/assets/CCBufferAsset.js create mode 100644 cocos2d/core/mesh/CCMeshResource.js diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index 4b4a7f718b2..2861b336c44 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -24,6 +24,7 @@ ****************************************************************************/ const AnimationClip = require('../../animation/animation-clip'); +const BufferAsset = require('../assets/CCBufferAsset'); const renderEngine = require('../renderer/render-engine'); const renderer = require('../renderer'); @@ -63,47 +64,30 @@ const _gltfAttribMap = { WEIGHTS_0: gfx.ATTR_WEIGHTS }; -function createArray(gltf, bin, accessorID) { - let acc = gltf.accessors[accessorID]; - let bufView = gltf.bufferViews[acc.bufferView]; - - let num = _type2size[acc.type]; - let typedArray = _compType2Array[acc.componentType]; - let result = new typedArray(bin, bufView.byteOffset + acc.byteOffset, acc.count * num); - - return result; -} - -var Model = cc.Class({ +let Model = cc.Class({ name: 'cc.Model', extends: cc.Asset, - ctor() { - this._bin = null; + ctor () { + this._nodesInited = false; }, properties: { - _nativeAsset: { - get() { - return this._bin; - }, - set(bin) { - this._bin = bin.buffer || bin; - this._initNodes(); - }, - override: true - }, + _buffers: [BufferAsset], _gltf: { default: {} } }, - _initNodes() { + _initNodes () { + if (this._nodesInited) return; + this._nodesInited = true; + let nodes = this._gltf.nodes; for (let i = 0; i < nodes.length; i++) { let node = nodes[i]; - + node.path = node.parent ? node.parent.path + '/' + node.name : ''; let children = node.children; @@ -116,13 +100,46 @@ var Model = cc.Class({ } }, - _createVB(bin, gltf, accessors, attributes) { + initSkeleton (skeleton) { + let gltf = this._gltf; + let buffers = this._buffers; + let skinID = skeleton._skinID; + if (skinID >= gltf.skins.length) { + return null; + } + + let gltfSkin = gltf.skins[skinID]; + + // extract bindposes mat4 data + let accessor = gltf.accessors[gltfSkin.inverseBindMatrices]; + let bufView = gltf.bufferViews[accessor.bufferView]; + let bin = buffers[bufView.buffer]._buffer; + let data = new Float32Array(bin, bufView.byteOffset + accessor.byteOffset, accessor.count * 16); + let bindposes = new Array(accessor.count); + + for (let i = 0; i < accessor.count; ++i) { + bindposes[i] = cc.vmath.mat4.new( + data[16 * i + 0], data[16 * i + 1], data[16 * i + 2], data[16 * i + 3], + data[16 * i + 4], data[16 * i + 5], data[16 * i + 6], data[16 * i + 7], + data[16 * i + 8], data[16 * i + 9], data[16 * i + 10], data[16 * i + 11], + data[16 * i + 12], data[16 * i + 13], data[16 * i + 14], data[16 * i + 15] + ); + } + + skeleton.jointIndices = gltfSkin.joints; + skeleton.bindposes = bindposes; + }, + + _createVB (gltf, accessors, primitive) { + const buffers = this._buffers; + // create vertex-format let vfmt = []; let vcount = 0; let byteOffset = 10e7, maxByteOffset = 0; - + let bufferViewIndex = -1; + let attributes = primitive.attributes; for (let gltfAttribName in attributes) { const gfxAttribName = _gltfAttribMap[gltfAttribName]; if (gfxAttribName === undefined) { @@ -130,9 +147,10 @@ var Model = cc.Class({ return; } let acc = accessors[attributes[gltfAttribName]]; - let vbView = gltf.bufferViews[acc.bufferView]; - vcount = acc.count; + vcount = Math.max(acc.count, vcount); + let vbView = gltf.bufferViews[acc.bufferView]; + bufferViewIndex = vbView.buffer; vfmt.push({ name: gfxAttribName, type: acc.componentType, num: _type2size[acc.type], byteLength: vbView.byteLength, byteOffset: vbView.byteOffset @@ -150,6 +168,8 @@ var Model = cc.Class({ el.stride = el.bytes; } + let bin = this._buffers[bufferViewIndex]._buffer; + // create vertex-buffer let vbData = new Uint8Array(bin, byteOffset, maxByteOffset - byteOffset); let vb = new gfx.VertexBuffer( @@ -166,40 +186,40 @@ var Model = cc.Class({ }; }, - createSkinning(index) { - let gltf = this._gltf; - let bin = this._bin; - if (index >= gltf.skins.length) { - return null; + _createIB (gltf, accessors, primitive) { + let ibAcc = accessors[primitive.indices]; + let ibView = gltf.bufferViews[ibAcc.bufferView]; + let bin = this._buffers[ibView.buffer]._buffer; + let ibData = new Uint16Array(bin, ibView.byteOffset, ibView.byteLength / 2); + let ibBuffer = new gfx.IndexBuffer( + renderer.device, + ibAcc.componentType, + gfx.USAGE_STATIC, + ibData, + ibAcc.count + ); + + return { + buffer: ibBuffer, + data: ibData } + }, - let gltfSkin = gltf.skins[index]; + _createArray (gltf, accessorID) { + let acc = gltf.accessors[accessorID]; + let bufView = gltf.bufferViews[acc.bufferView]; + let bin = this._buffers[bufView.buffer]._buffer; - // extract bindposes mat4 data - let accessor = gltf.accessors[gltfSkin.inverseBindMatrices]; - let bufView = gltf.bufferViews[accessor.bufferView]; - let data = new Float32Array(bin, bufView.byteOffset + accessor.byteOffset, accessor.count * 16); - let bindposes = new Array(accessor.count); + let num = _type2size[acc.type]; + let typedArray = _compType2Array[acc.componentType]; + let result = new typedArray(bin, bufView.byteOffset + acc.byteOffset, acc.count * num); - for (let i = 0; i < accessor.count; ++i) { - bindposes[i] = cc.vmath.mat4.new( - data[16 * i + 0], data[16 * i + 1], data[16 * i + 2], data[16 * i + 3], - data[16 * i + 4], data[16 * i + 5], data[16 * i + 6], data[16 * i + 7], - data[16 * i + 8], data[16 * i + 9], data[16 * i + 10], data[16 * i + 11], - data[16 * i + 12], data[16 * i + 13], data[16 * i + 14], data[16 * i + 15] - ); - } - - return { - jointIndices: gltfSkin.joints, - bindposes: bindposes, - }; + return result; }, - initMesh(meshAsset) { + initMesh (meshAsset) { const index = meshAsset._meshID; - const bin = this._bin; const gltf = this._gltf; const gltfMesh = gltf.meshes[index]; const accessors = gltf.accessors; @@ -214,27 +234,12 @@ var Model = cc.Class({ if (primitive.indices === undefined) continue; - let vb = this._createVB(bin, gltf, accessors, primitive.attributes); - - let ibAcc = accessors[primitive.indices]; - let ibView = gltf.bufferViews[ibAcc.bufferView]; - let ibData = new Uint16Array(bin, ibView.byteOffset, ibView.byteLength/2); - let ibBuffer = new gfx.IndexBuffer( - renderer.device, - ibAcc.componentType, - gfx.USAGE_STATIC, - ibData, - ibAcc.count - ); - - let ib = { - buffer: ibBuffer, - data: ibData - } + let vb = this._createVB(gltf, accessors, primitive); + let ib = this._createIB(gltf, accessors, primitive); if (primitive.attributes.POSITION) { let gltfAccessor = accessors[primitive.attributes.POSITION]; - let minPos = meshAsset._minPos, maxPos = meshAsset._maxPos + let minPos = meshAsset._minPos, maxPos = meshAsset._maxPos, min = gltfAccessor.min, max = gltfAccessor.max; minPos.x = Math.min(minPos.x, min[0]); minPos.y = Math.min(minPos.y, min[1]); @@ -244,13 +249,15 @@ var Model = cc.Class({ maxPos.z = Math.max(maxPos.z, max[2]); } - meshAsset._subMeshes[i] = new renderEngine.InputAssembler(vb.buffer, ibBuffer); + meshAsset._subMeshes[i] = new renderEngine.InputAssembler(vb.buffer, ib.buffer); meshAsset._vbs[i] = vb; meshAsset._ibs[i] = ib; } }, - initAnimationClip(clip) { + initAnimationClip (clip) { + this._initNodes(); + let gltf = this._gltf; let bin = this._bin; @@ -273,11 +280,11 @@ var Model = cc.Class({ let gltfChannel = channels[i]; let sampler = samplers[gltfChannel.sampler]; - let inputArray = createArray(gltf, bin, sampler.input); - let outputArray = createArray(gltf, bin, sampler.output); + let inputArray = this._createArray(gltf, sampler.input); + let outputArray = this._createArray(gltf, sampler.output); let interpolation = sampler.interpolation; - + let target = gltfChannel.target; let node = nodes[target.node]; @@ -304,26 +311,26 @@ var Model = cc.Class({ if (frame > duration) { duration = frame; } - frames.push({frame: frame}); + frames.push({ frame: frame }); } if (target.path === 'translation') { for (let frameIdx = 0; frameIdx < inputArray.length; frameIdx++) { let i = frameIdx * 3; - frames[frameIdx].value = cc.v3(outputArray[i], outputArray[i+1], outputArray[i+2]); + frames[frameIdx].value = cc.v3(outputArray[i], outputArray[i + 1], outputArray[i + 2]); } curves.props.position = frames; } else if (target.path === 'rotation') { for (let frameIdx = 0; frameIdx < inputArray.length; frameIdx++) { let i = frameIdx * 4; - frames[frameIdx].value = cc.quat(outputArray[i], outputArray[i+1], outputArray[i+2], outputArray[i+3]); + frames[frameIdx].value = cc.quat(outputArray[i], outputArray[i + 1], outputArray[i + 2], outputArray[i + 3]); } curves.props.quat = frames; } else if (target.path === 'scale') { for (let frameIdx = 0; frameIdx < inputArray.length; frameIdx++) { let i = frameIdx * 3; - frames[frameIdx].value = cc.v3(outputArray[i], outputArray[i+1], outputArray[i+2]); + frames[frameIdx].value = cc.v3(outputArray[i], outputArray[i + 1], outputArray[i + 2]); } curves.props.scale = frames; } @@ -365,4 +372,4 @@ var Model = cc.Class({ } }); -module.exports = Model; +cc.Model = module.exports = Model; diff --git a/cocos2d/core/3d/CCModelMeshResource.js b/cocos2d/core/3d/CCModelMeshResource.js new file mode 100644 index 00000000000..6fb2b721e36 --- /dev/null +++ b/cocos2d/core/3d/CCModelMeshResource.js @@ -0,0 +1,80 @@ +/**************************************************************************** + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://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 Model = require('./CCModel'); + +let ModelMeshResource = cc.Class({ + name: 'ModelMeshResource', + + ctor () { + this._subMeshes = []; + this._ibs = []; + this._vbs = []; + this._inited = false; + this._minPos = cc.v3(); + this._maxPos = cc.v3(); + }, + + properties: { + _meshID: -1, + _model: { + type: Model, + default: null + }, + + meshID: { + get () { + return this._meshID; + }, + set (val) { + this._meshID = val; + } + }, + + model: { + get () { + return this._model; + }, + set (val) { + this._model = val; + } + } + }, + + flush (mesh) { + if (!this._inited) { + this._inited = true; + this.model.initMesh(this); + } + + mesh._vbs = this._vbs; + mesh._ibs = this._ibs; + mesh._subMeshes = this._subMeshes; + mesh._minPos = this._minPos; + mesh._maxPos = this._maxPos; + } +}); + +module.exports = ModelMeshResource; diff --git a/cocos2d/core/3d/CCSkeleton.js b/cocos2d/core/3d/CCSkeleton.js new file mode 100644 index 00000000000..3e65fd503f9 --- /dev/null +++ b/cocos2d/core/3d/CCSkeleton.js @@ -0,0 +1,50 @@ + +let Skeleton = cc.Class({ + name: 'cc.Skeleton', + extends: cc.Asset, + + ctor () { + this.jointIndices = []; + this.bindposes = []; + }, + + properties: { + _modelSetter: { + set: function (model) { + if (CC_EDITOR && Editor.isBuilder) { + // just building + return; + } + this._initWithModel(model); + } + }, + }, + + _initWithModel (model) { + if (!model) return; + this._model = model; + this._model.initSkeleton(this); + }, + + _serialize: CC_EDITOR && function (exporting) { + let modelUuid = this._modelUuid; + if (exporting) { + modelUuid = Editor.Utils.UuidUtils.compressUuid(modelUuid, true); + } + return { + modelUuid: modelUuid, + skinID: this._skinID, + }; + }, + + _deserialize (data, handle) { + this._modelUuid = data.modelUuid; + this._skinID = data.skinID; + + if (this._modelUuid) { + handle.result.push(this, '_modelSetter', this._modelUuid); + } + } +}); + +cc.Skeleton = module.exports = Skeleton; \ No newline at end of file diff --git a/cocos2d/core/3d/CCSkeletonAnimation.js b/cocos2d/core/3d/CCSkeletonAnimation.js index 318020a2892..fed2e01fa0f 100644 --- a/cocos2d/core/3d/CCSkeletonAnimation.js +++ b/cocos2d/core/3d/CCSkeletonAnimation.js @@ -37,17 +37,17 @@ const AnimationClip = require('../../animation/animation-clip'); * @class SkeletonAnimation * @extends Animation */ -var SkeletonAnimation = cc.Class({ +let SkeletonAnimation = cc.Class({ name: 'cc.SkeletonAnimation', extends: Animation, editor: CC_EDITOR && { inspector: 'packages://inspector/inspectors/comps/skeleton-animation.js', + menu: 'i18n:MAIN_MENU.component.others/Skeleton Animation', }, properties: { _model: Model, - _nodes: [cc.Node], _defaultClip: { override: true, @@ -77,6 +77,9 @@ var SkeletonAnimation = cc.Class({ get () { return this._model; }, + set (val) { + this._model = val; + }, type: Model }, }, @@ -84,7 +87,7 @@ var SkeletonAnimation = cc.Class({ getAnimationState (name) { let state = this._super(name); let clip = state.clip; - clip.init(this._nodes); + clip.init(); return state; }, diff --git a/cocos2d/core/3d/CCSkinnedMeshRenderer.js b/cocos2d/core/3d/CCSkinnedMeshRenderer.js index 46ad71a30f9..a9ba7a53daf 100644 --- a/cocos2d/core/3d/CCSkinnedMeshRenderer.js +++ b/cocos2d/core/3d/CCSkinnedMeshRenderer.js @@ -23,31 +23,80 @@ THE SOFTWARE. ****************************************************************************/ +const Skeleton = require('./CCSkeleton'); const MeshRenderer = require('../mesh/CCMeshRenderer'); const renderEngine = require('../renderer/render-engine'); const mat4 = cc.vmath.mat4; let _m4_tmp = mat4.create(); +function traversal (node, cb) { + cb(node); + + let children = node.children; + for (let i = 0; i < children.length; i++) { + let child = children[i]; + traversal(child, cb); + } +} + +function flatNode (rootNode) { + let nodes = []; + + traversal(rootNode, function (node) { + nodes.push(node); + }); + + return nodes; +} + let SkinnedMeshRenderer = cc.Class({ name: 'cc.SkinnedMeshRenderer', extends: MeshRenderer, - ctor() { + editor: CC_EDITOR && { + menu: 'Mesh/Skinned Mesh Renderer', + }, + + ctor () { this._jointsTextureData = null; this._jointsTexture = null; - this._skinning = null; + this._joints = []; this._matrices = []; this._assembler = MeshRenderer._assembler; }, properties: { - _joints: [cc.Node], - _skinID: -1 + _skeleton: Skeleton, + _rootBone: cc.Node, + + skeleton: { + get () { + return this._skeleton; + }, + set (val) { + this._skeleton = val; + this._initJoints(); + this._initJointsTexture(); + this.activeMaterials(true); + }, + type: Skeleton + }, + + rootBone: { + get () { + return this._rootBone; + }, + set (val) { + this._rootBone = val; + this._initJoints(); + }, + type: cc.Node + } }, - _createMaterial() { + _createMaterial () { let material = new renderEngine.MeshMaterial(); material.color = cc.Color.WHITE; material._mainTech._passes[0].setDepth(true, true); @@ -67,28 +116,44 @@ let SkinnedMeshRenderer = cc.Class({ return material; }, - _reset() { - this._super(); - this._initSkinning(); - this._initJointsTexture(); - this._initMatrices(); + activeMaterials (force) { + if (!this._jointsTextureData) { + this.disableRender(); + return; + } + + this._super(force); }, - _initSkinning() { - if (this._skinID === -1 || !this._mesh || !this._mesh._model) return; - this._skinning = this._mesh._model.createSkinning(this._skinID); + __preload () { + this._initJoints(); + this._initJointsTexture(); }, - _initJointsTexture() { - if (this._jointsTexture) { - this._jointsTexture.destroy(); - this._jointsTexture = null; + _initJoints () { + let joints = this._joints; + joints.length = 0; + + if (!this.skeleton || !this.rootBone) return; + + let jointIndices = this.skeleton.jointIndices; + let nodes = flatNode(this.rootBone); + let matrices = this._matrices; + matrices.length = 0; + for (let i = 0; i < jointIndices.length; i++) { + let jointIndex = jointIndices[i]; + joints.push(nodes[jointIndex]); + matrices.push(mat4.create()); } - let skinning = this._skinning; - if (!skinning) return; + this.updateMatrices(); + }, - let jointCount = skinning.jointIndices.length; + _initJointsTexture () { + let skeleton = this._skeleton; + if (!skeleton) return; + + let jointCount = skeleton.jointIndices.length; let ALLOW_FLOAT_TEXTURE = !!cc.renderer.device.ext('OES_texture_float'); if (ALLOW_FLOAT_TEXTURE) { @@ -105,8 +170,8 @@ let SkinnedMeshRenderer = cc.Class({ } this._jointsTextureData = new Float32Array(size * size * 4); - - let texture = new cc.Texture2D(); + + let texture = this._jointsTexture || new cc.Texture2D(); texture.initWithData(this._jointsTextureData, cc.Texture2D.PixelFormat.RGBA32F, size, size); this._jointsTexture = texture; @@ -116,19 +181,7 @@ let SkinnedMeshRenderer = cc.Class({ } }, - _initMatrices() { - let joints = this._joints; - let matrices = this._matrices; - - matrices.length = 0; - for (let i = 0; i < joints.length; i++) { - matrices.push(mat4.create()); - } - - this.updateMatrices(); - }, - - _setJointsTextureData(iMatrix, matrix) { + _setJointsTextureData (iMatrix, matrix) { let arr = this._jointsTextureData; arr[16 * iMatrix + 0] = matrix.m00; arr[16 * iMatrix + 1] = matrix.m01; @@ -150,19 +203,19 @@ let SkinnedMeshRenderer = cc.Class({ _commitJointsData () { if (this._jointsTexture) { - this._jointsTexture.update({image: this._jointsTextureData}); + this._jointsTexture.update({ image: this._jointsTextureData }); } }, - updateMatrices() { + updateMatrices () { for (let i = 0; i < this._joints.length; ++i) { this._joints[i].getWorldMatrix(this._matrices[i]); } }, - update() { - if (!this._skinning) return; - const bindposes = this._skinning.bindposes; + update () { + if (!this.skeleton || !this.rootBone) return; + const bindposes = this.skeleton.bindposes; const matrices = this._matrices; this.updateMatrices(); diff --git a/cocos2d/core/3d/index.js b/cocos2d/core/3d/index.js index b15a29b8fe2..c85054a8262 100644 --- a/cocos2d/core/3d/index.js +++ b/cocos2d/core/3d/index.js @@ -5,7 +5,9 @@ if (!CC_TEST && (!CC_EDITOR || !Editor.isMainProcess)) { } require('./CCModel'); +require('./CCSkeleton'); require('./CCSkeletonAnimationClip'); +require('./CCModelMeshResource'); if (!CC_EDITOR || !Editor.isMainProcess) { require('./CCSkeletonAnimation'); diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 7b80eb63f58..de86f691007 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1297,11 +1297,10 @@ let NodeDefines = { else { math.quat.fromEuler(quat, this._rotationX, this._rotationY, 0); } + this._rotationX = this._rotationY = undefined; } - // Update rotation from quaternion - else { - this._quat.getEulerAngles(this._eulerAngles); - } + + this._quat.getEulerAngles(this._eulerAngles); // Upgrade from 2.0.0 preview 4 & earlier versions // TODO: Remove after final version diff --git a/cocos2d/core/assets/CCBufferAsset.js b/cocos2d/core/assets/CCBufferAsset.js new file mode 100644 index 00000000000..c9d1e915d21 --- /dev/null +++ b/cocos2d/core/assets/CCBufferAsset.js @@ -0,0 +1,52 @@ +/**************************************************************************** + Copyright (c) 2013-2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://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. + ****************************************************************************/ + +/** + * @class BufferAsset + * @extends Asset + */ +var BufferAsset = cc.Class({ + name: 'cc.BufferAsset', + extends: cc.Asset, + + ctor () { + this._buffer = null; + }, + + properties: { + _nativeAsset: { + get () { + return this._buffer; + }, + set (bin) { + this._buffer = bin.buffer || bin; + }, + override: true + }, + } +}); + +cc.BufferAsset = module.exports = BufferAsset; diff --git a/cocos2d/core/assets/index.js b/cocos2d/core/assets/index.js index ab7d4dc4b55..8ed04b18186 100644 --- a/cocos2d/core/assets/index.js +++ b/cocos2d/core/assets/index.js @@ -39,4 +39,5 @@ require('./CCSpriteAtlas'); require('./CCBitmapFont'); require('./CCLabelAtlas'); require('./CCTextAsset'); -require('./CCJsonAsset'); \ No newline at end of file +require('./CCJsonAsset'); +require('./CCBufferAsset'); \ No newline at end of file diff --git a/cocos2d/core/mesh/CCMesh.js b/cocos2d/core/mesh/CCMesh.js index aea94a3a29a..f5f40cea870 100644 --- a/cocos2d/core/mesh/CCMesh.js +++ b/cocos2d/core/mesh/CCMesh.js @@ -23,6 +23,7 @@ THE SOFTWARE. ****************************************************************************/ +const MeshResource = require('./CCMeshResource'); const renderer = require('../renderer'); const renderEngine = require('../renderer/render-engine'); const gfx = renderEngine.gfx; @@ -42,7 +43,6 @@ function applyVec3 (data, offset, value) { data[offset + 2] = value.z; } - /** * @module cc */ @@ -52,19 +52,14 @@ function applyVec3 (data, offset, value) { * @class Mesh * @extends Asset */ -var Mesh = cc.Class({ +let Mesh = cc.Class({ name: 'cc.Mesh', extends: cc.Asset, properties: { - _modelSetter: { - set: function (model) { - if (CC_EDITOR && Editor.isBuilder) { - // just building - return; - } - this._initWithModel(model); - } + _resource: { + default: null, + type: MeshResource }, /** @@ -83,10 +78,6 @@ var Mesh = cc.Class({ }, ctor () { - this._modelUuid = ''; - this._meshID = -1; - this._model = null; - this._subMeshes = []; this._ibs = []; @@ -94,6 +85,15 @@ var Mesh = cc.Class({ this._minPos = cc.v3(); this._maxPos = cc.v3(); + + this._resourceInited = false; + }, + + _initResource () { + if (this._resourceInited || !this._resource) return; + this._resourceInited = true; + + this._resource.flush(this); }, /** @@ -309,34 +309,7 @@ var Mesh = cc.Class({ ib.dirty = false; } } - }, - - _initWithModel (model) { - if (!model) return; - this._model = model; - this._model.initMesh(this); - }, - - _serialize: CC_EDITOR && function (exporting) { - let modelUuid = this._modelUuid; - if (exporting) { - modelUuid = Editor.Utils.UuidUtils.compressUuid(modelUuid, true); - } - return { - modelUuid: modelUuid, - meshID: this._meshID, - }; - }, - - _deserialize (data, handle) { - this._modelUuid = data.modelUuid; - this._meshID = data.meshID; - - if (this._modelUuid) { - handle.result.push(this, '_modelSetter', this._modelUuid); - } } }); - cc.Mesh = module.exports = Mesh; diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index afe267b2984..9b3ae4ede47 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -35,7 +35,7 @@ let MeshRenderer = cc.Class({ extends: RenderComponent, editor: CC_EDITOR && { - menu: 'i18n:MAIN_MENU.component.renderers/MeshRenderer', + menu: 'Mesh/MeshRenderer', }, properties: { @@ -105,7 +105,13 @@ let MeshRenderer = cc.Class({ }, activeMaterials (force) { - if (!this._mesh || this._mesh.subMeshes.length === 0) { + let mesh = this._mesh; + // TODO: should init mesh when mesh loaded, need asset load event support + if (mesh) { + mesh._initResource(); + } + + if (!mesh || mesh.subMeshes.length === 0) { this.disableRender(); return; } @@ -115,12 +121,12 @@ let MeshRenderer = cc.Class({ } if (aabb) { - this._boundingBox = aabb.fromPoints(aabb.create(), this._mesh._minPos, this._mesh._maxPos); + this._boundingBox = aabb.fromPoints(aabb.create(), mesh._minPos, mesh._maxPos); } this._reset(); - let subMeshes = this._mesh._subMeshes; + let subMeshes = mesh._subMeshes; for (let i = 0; i < subMeshes.length; i++) { let material = this._createMaterial(subMeshes[i]); this._materials.push(material); diff --git a/cocos2d/core/mesh/CCMeshResource.js b/cocos2d/core/mesh/CCMeshResource.js new file mode 100644 index 00000000000..b54001e6d72 --- /dev/null +++ b/cocos2d/core/mesh/CCMeshResource.js @@ -0,0 +1,34 @@ +/**************************************************************************** + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://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. + ****************************************************************************/ + +let MeshResource = cc.Class({ + name: 'cc.MeshResource', + + flush (mesh) { + + } +}); + +module.exports = MeshResource; From 6e882c0ef1aac128a05df603040e9e9fd3ac723f Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 18 Oct 2018 17:59:28 +0800 Subject: [PATCH 0094/1631] remove unused code (#3402) --- cocos2d/core/platform/CCClass.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/cocos2d/core/platform/CCClass.js b/cocos2d/core/platform/CCClass.js index d3d6486b7a0..a03cc9775bb 100644 --- a/cocos2d/core/platform/CCClass.js +++ b/cocos2d/core/platform/CCClass.js @@ -151,9 +151,6 @@ function defineProp (cls, className, propName, val, es6) { for (var i = 0; i < attrs.length; i++) { var attr = attrs[i]; Attr.attr(cls, propName, attr); - if (attr['serializable'] === false) { - pushUnique(cls.__values__, propName); - } // register callback if (attr._onAfterProp) { onAfterProp.push(attr._onAfterProp); From 0ad069a9e56408efd9a40c66f3ec1d491266679b Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Thu, 18 Oct 2018 21:13:58 +0800 Subject: [PATCH 0095/1631] fixed animation quickFindIndex (#3393) * fixed animation quickFindIndex * refine code --- cocos2d/animation/animation-curves.js | 4 ++++ test/qunit/unit-es5/test-animation.js | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/cocos2d/animation/animation-curves.js b/cocos2d/animation/animation-curves.js index e883e590528..6445b07671b 100644 --- a/cocos2d/animation/animation-curves.js +++ b/cocos2d/animation/animation-curves.js @@ -98,6 +98,9 @@ function quickFindIndex (ratios, ratio) { if ((index - floorIndex) < EPSILON) { return floorIndex; } + else if ((floorIndex + 1 - index) < EPSILON) { + return floorIndex + 1; + } return ~(floorIndex + 1); } @@ -438,6 +441,7 @@ var EventAnimCurve = cc.Class({ if (CC_TEST) { cc._Test.DynamicAnimCurve = DynamicAnimCurve; cc._Test.EventAnimCurve = EventAnimCurve; + cc._Test.quickFindIndex = quickFindIndex; } module.exports = { diff --git a/test/qunit/unit-es5/test-animation.js b/test/qunit/unit-es5/test-animation.js index e23b7939ebb..b22a239d70e 100644 --- a/test/qunit/unit-es5/test-animation.js +++ b/test/qunit/unit-es5/test-animation.js @@ -1410,3 +1410,9 @@ test('animation play on load', function () { entity.parent = null; }); + +test('quickFindIndex', function () { + var ratios = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]; + var ratio = 0.7; + strictEqual(cc._Test.quickFindIndex(ratios, ratio), 7, 'should find ratio at index 7'); +}); From 4b330e2a08702dd3634f9fcf1455b55290faeed6 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Thu, 18 Oct 2018 21:19:25 +0800 Subject: [PATCH 0096/1631] Fix image blurry caused by camera parameter problems. (#3404) --- cocos2d/core/camera/CCCamera.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index f6e6991f69e..c734007d751 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -525,7 +525,7 @@ let Camera = cc.Class({ _vec3_temp_1.y = node._worldMatrix.m13; _vec3_temp_1.z = 0; - node.z = height / 1.1566; + node.z = height / (Math.tan(this._fov/2) * 2); node.lookAt(_vec3_temp_1); this._matrixDirty = false; From f70a3c07f07cdb705b1861b51407ac75f35f865c Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Fri, 19 Oct 2018 15:41:47 +0800 Subject: [PATCH 0097/1631] fixed cc.dynamicAtlasManager class lost (#3407) --- docs/apisrc.json | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/apisrc.json b/docs/apisrc.json index 053f1fd30dc..f32ceb2c682 100644 --- a/docs/apisrc.json +++ b/docs/apisrc.json @@ -53,6 +53,7 @@ "!./cocos2d/core/platform/id-generater.js", "./cocos2d/core/renderer/index.js", + "./cocos2d/core/renderer/utils/dynamic-atlas/*", "./cocos2d/core/utils/affine-transform.js", "./cocos2d/core/utils/base-node.js", From 9b163d91650f49db9eeb502c72e1ffa5e1e27c97 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 22 Oct 2018 10:05:52 +0800 Subject: [PATCH 0098/1631] fixed camera getRay (#3398) * fixed camera getRay * fixed camera worldToScreen * refine code * auto layout camera if it's a 2d camera * fixed mesh upload data * refine raycast * fixed mesh upload data --- cocos2d/core/3d/geom-utils/intersect.js | 25 +++++--- cocos2d/core/camera/CCCamera.js | 85 +++++++++++++------------ cocos2d/core/mesh/CCMesh.js | 12 +++- cocos2d/core/mesh/mesh-renderer.js | 4 +- cocos2d/core/renderer/render-engine.js | 19 ++---- 5 files changed, 78 insertions(+), 67 deletions(-) diff --git a/cocos2d/core/3d/geom-utils/intersect.js b/cocos2d/core/3d/geom-utils/intersect.js index 3ef6d8bf8e6..2a0c6cbcac6 100644 --- a/cocos2d/core/3d/geom-utils/intersect.js +++ b/cocos2d/core/3d/geom-utils/intersect.js @@ -161,6 +161,7 @@ intersect.rayMesh = (function () { * @param {geomUtils.Ray} worldRay * @param {Function} handler * @param {Function} filter + * @return [{node, distance}] */ intersect.raycast = (function () { function traversal (node, cb) { @@ -188,36 +189,41 @@ intersect.raycast = (function () { return out; } - let results = new RecyclePool(function () { + let resultsPool = new RecyclePool(function () { return { distance: 0, node: null } }, 1); + let results = []; + // temp variable let nodeAabb = aabb.create(); let minPos = vec3.create(); let maxPos = vec3.create(); let modelRay = ray.create(); - let m4 = mat4.create(); + let m4_1 = mat4.create(); + let m4_2 = mat4.create(); + let d = vec3.create(); function distanceValid (distance) { return distance > 0 && distance < Infinity; } return function (root, worldRay, handler, filter) { - results.reset(); + resultsPool.reset(); + results.length = 0; root = root || cc.director.getScene(); traversal(root, function (node) { if (filter && !filter(node)) return; // transform world ray to model ray - mat4.invert(m4, node.getWorldMatrix(m4)); - vec3.transformMat4(modelRay.o, worldRay.o, m4); - vec3.normalize(modelRay.d, transformMat4Normal(modelRay.d, worldRay.d, m4)); + mat4.invert(m4_2, node.getWorldMatrix(m4_1)); + vec3.transformMat4(modelRay.o, worldRay.o, m4_2); + vec3.normalize(modelRay.d, transformMat4Normal(modelRay.d, worldRay.d, m4_2)); // raycast with bounding box let distance = Infinity; @@ -239,9 +245,12 @@ intersect.raycast = (function () { } if (distanceValid(distance)) { - let res = results.add(); + vec3.set(d, distance, 0, 0); + transformMat4Normal(d, d, m4_1); + let res = resultsPool.add(); res.node = node; - res.distance = distance; + res.distance = cc.vmath.vec3.length(d); + results.push(res); } }); diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 0f21f25e44a..0185bdbc235 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -39,6 +39,7 @@ let _mat4_temp_2 = mat4.create(); let _v3_temp_1 = vec3.create(); let _v3_temp_2 = vec3.create(); +let _v3_temp_3 = vec3.create(); let _cameras = []; @@ -87,7 +88,7 @@ let ClearFlags = cc.Enum({ let Camera = cc.Class({ name: 'cc.Camera', extends: cc.Component, - + ctor () { if (game.renderType !== game.RENDER_TYPE_CANVAS) { let camera = new renderEngine.Camera(); @@ -125,8 +126,8 @@ let Camera = cc.Class({ _orthoSize: 10, _nearClip: 0.1, _farClip: 4096, - _ortho: false, - _rect: cc.rect(0,0,1,1), + _ortho: true, + _rect: cc.rect(0, 0, 1, 1), /** * !#en @@ -141,7 +142,6 @@ let Camera = cc.Class({ }, set (value) { this._zoomRatio = value; - this._updateFov(); } }, @@ -159,7 +159,6 @@ let Camera = cc.Class({ }, set (v) { this._fov = v; - this._updateFov(); } }, @@ -177,7 +176,6 @@ let Camera = cc.Class({ }, set (v) { this._orthoSize = v; - this._updateOrthoSize(); } }, @@ -400,7 +398,7 @@ let Camera = cc.Class({ if (game.renderType === game.RENDER_TYPE_CANVAS) return; let camera = new renderEngine.Camera(); _debugCamera = camera; - + camera.setStages([ 'transparent' ]); @@ -416,7 +414,7 @@ let Camera = cc.Class({ camera._cullingMask = camera.view._cullingMask = 1 << cc.Node.BuiltinGroupIndex.DEBUG; camera._sortDepth = cc.macro.MAX_ZINDEX; camera.setClearFlags(0); - camera.setColor(0,0,0,0); + camera.setColor(0, 0, 0, 0); let node = new cc.Node(); camera.setNode(node); @@ -438,7 +436,7 @@ let Camera = cc.Class({ _updateBackgroundColor () { if (!this._camera) return; - + let color = this._backgroundColor; this._camera.setColor( color.r / 255, @@ -455,19 +453,6 @@ let Camera = cc.Class({ this._camera._framebuffer = texture ? texture._framebuffer : null; }, - _updateFov () { - if (!this._camera) return; - - let fov = this._fov * cc.macro.RAD; - fov = Math.atan(Math.tan(fov/2) / this.zoomRatio)*2; - this._camera.setFov(fov); - }, - - _updateOrthoSize () { - if (!this._camera) return; - this._camera.setOrthoHeight(this._orthoSize); - }, - _updateClippingpPlanes () { if (!this._camera) return; this._camera.setNear(this._nearClip); @@ -497,8 +482,6 @@ let Camera = cc.Class({ this._updateBackgroundColor(); this._updateCameraMask(); this._updateTargetTexture(); - this._updateFov(); - this._updateOrthoSize(); this._updateClippingpPlanes(); this._updateProjection(); }, @@ -630,14 +613,22 @@ let Camera = cc.Class({ * !#zh * 从屏幕坐标获取一条射线 * @method getRay - * @param {Vec3} screenPos + * @param {Vec2} screenPos * @return {Ray} */ getRay (screenPos) { - this.node.getWorldPos(_v3_temp_1); - this._camera.screenToWorld(_v3_temp_2, screenPos, cc.visibleRect.width, cc.visibleRect.height); - vec3.sub(_v3_temp_2, _v3_temp_2, _v3_temp_1); - return ray.create(_v3_temp_1.x, _v3_temp_1.y, _v3_temp_1.z, _v3_temp_2.x, _v3_temp_2.y, _v3_temp_2.z); + vec3.set(_v3_temp_3, screenPos.x, screenPos.y, 1); + this._camera.screenToWorld(_v3_temp_2, _v3_temp_3, cc.visibleRect.width, cc.visibleRect.height); + + if (this.ortho) { + vec3.set(_v3_temp_3, screenPos.x, screenPos.y, -1); + this._camera.screenToWorld(_v3_temp_1, _v3_temp_3, cc.visibleRect.width, cc.visibleRect.height); + } + else { + this.node.getWorldPos(_v3_temp_1); + } + + return ray.fromPoints(ray.create(), _v3_temp_1, _v3_temp_2); }, /** @@ -672,22 +663,34 @@ let Camera = cc.Class({ renderer._forward.renderCamera(this._camera, renderer.scene); }, - beforeDraw: function () { - let node = this.node; - let camera = this._camera; - - if (!node._is3DNode) { - let height = cc.game.canvas.height / cc.view._scaleY; + _layout () { + let height = cc.game.canvas.height / cc.view._scaleY; - let targetTexture = this._targetTexture; - if (targetTexture) { - height = targetTexture.height; - } + let targetTexture = this._targetTexture; + if (targetTexture) { + height = targetTexture.height; + } + + let fov = this._fov * cc.macro.RAD; + this.node.z = height / (Math.tan(fov / 2) * 2); - node.z = height / (Math.tan( this._camera._fov/2) * 2); + fov = Math.atan(Math.tan(fov / 2) / this.zoomRatio) * 2; + this._camera.setFov(fov); + this._camera.setOrthoHeight(height / 2 / this.zoomRatio); + }, + + beforeDraw () { + if (!this._camera) return; + + if (!this.node._is3DNode) { + this._layout(); + } + else { + this._camera.setFov(this._fov * cc.macro.RAD); + this._camera.setOrthoHeight(this._orthoSize); } - camera.dirty = true; + this._camera.dirty = true; } }); diff --git a/cocos2d/core/mesh/CCMesh.js b/cocos2d/core/mesh/CCMesh.js index f5f40cea870..ee86cc823d1 100644 --- a/cocos2d/core/mesh/CCMesh.js +++ b/cocos2d/core/mesh/CCMesh.js @@ -92,7 +92,7 @@ let Mesh = cc.Class({ _initResource () { if (this._resourceInited || !this._resource) return; this._resourceInited = true; - + this._resource.flush(this); }, @@ -295,7 +295,10 @@ let Mesh = cc.Class({ let vb = vbs[i]; if (vb.dirty) { - vb.buffer.update(0, vb.data); + let buffer = vb.buffer, data = vb.data; + buffer._numVertices = data.length; + buffer._bytes = data.byteLength; + buffer.update(0, data); vb.dirty = false; } } @@ -305,7 +308,10 @@ let Mesh = cc.Class({ let ib = ibs[i]; if (ib.dirty) { - ib.buffer.update(0, ib.data); + let buffer = ib.buffer, data = ib.data; + buffer._numIndices = data.length; + buffer._bytes = data.byteLength; + buffer.update(0, data); ib.dirty = false; } } diff --git a/cocos2d/core/mesh/mesh-renderer.js b/cocos2d/core/mesh/mesh-renderer.js index 023b37a6bb2..f451b05dc2c 100644 --- a/cocos2d/core/mesh/mesh-renderer.js +++ b/cocos2d/core/mesh/mesh-renderer.js @@ -101,6 +101,8 @@ let meshRendererAssembler = { let tmpNode = renderer.node; renderer.node = comp._material.useModel ? comp.node : renderer._dummyNode; + comp.mesh._uploadData(); + let textures = comp.textures; let materials = comp._materials; for (let i = 0; i < renderDatas.length; i++) { @@ -117,8 +119,6 @@ let meshRendererAssembler = { renderer._flushIA(renderData); } - comp.mesh._uploadData(); - renderer.node = tmpNode; renderer.material = tmpMaterial; } diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 1caf85355f3..929587312df 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -11316,13 +11316,12 @@ Camera.prototype.screenToWorld = function screenToWorld (out, screenPos, width, // this._node.getWorldPos(_tmp_v3); - vec3.lerp(out, _tmp_v3, out, screenPos.z / this._far); + vec3.lerp(out, _tmp_v3, out, cc.vmath.lerp(this._near / this._far, 1, screenPos.z)); } else { - var range = this._farClip - this._nearClip; vec3.set(out, (screenPos.x - cx) * 2.0 / cw - 1.0, - (screenPos.y - cy) * 2.0 / ch - 1.0, // DISABLE: (ch - (screenPos.y - cy)) * 2.0 / ch - 1.0, - (this._far - screenPos.z) / range * 2.0 - 1.0 + (screenPos.y - cy) * 2.0 / ch - 1.0, + screenPos.z * 2 - 1 ); // transform to world @@ -11362,16 +11361,10 @@ Camera.prototype.worldToScreen = function worldToScreen (out, worldPos, width, h // view-projection mat4.mul(_matViewProj, _matProj, _matView); - // calculate w - var w = - worldPos.x * _matViewProj.m03 + - worldPos.y * _matViewProj.m07 + - worldPos.z * _matViewProj.m11 + - _matViewProj.m15; - vec3.transformMat4(out, worldPos, _matViewProj); - out.x = cx + (out.x / w + 1) * 0.5 * cw; - out.y = cy + (out.y / w + 1) * 0.5 * ch; + out.x = cx + (out.x + 1) * 0.5 * cw; + out.y = cy + (out.y + 1) * 0.5 * ch; + out.z = out.z * 0.5 + 0.5; return out; }; From f7663617a9115ff5084d7b07f48f474a2ae061fa Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 22 Oct 2018 11:29:52 +0800 Subject: [PATCH 0099/1631] modify the note (#3400) 1. Camera targetTexture 2. schedule --- cocos2d/core/CCScheduler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/CCScheduler.js b/cocos2d/core/CCScheduler.js index a404110d8c7..a9d0a843199 100644 --- a/cocos2d/core/CCScheduler.js +++ b/cocos2d/core/CCScheduler.js @@ -640,7 +640,7 @@ cc.Scheduler.prototype = { * Unschedules a callback for a callback and a given target. * If you want to unschedule the "update", use `unscheduleUpdate()` * !#zh - * 根据指定的回调函数和调用对象。 + * 取消指定对象定时器。 * 如果需要取消 update 定时器,请使用 unscheduleUpdate()。 * @method unschedule * @param {Function} callback The callback to be unscheduled From 2f9bcc9c06c949447f45b9a1142d03f6293dc7e6 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Mon, 22 Oct 2018 18:59:19 +0800 Subject: [PATCH 0100/1631] Optimize batch rendering of sliced and simple sprites. (#3381) * Optimize batch rendering of slices and simple sprites. * Optimize batch rendering of slices and simple sprites. * Optimize batch rendering of sliced and simple sprites use mesh-buffer. --- .../renderer/webgl/assemblers/sprite/simple.js | 18 ++++++++++++++---- .../renderer/webgl/assemblers/sprite/sliced.js | 5 ++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js index 930fa9ddf1f..3f140451a1e 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js @@ -58,14 +58,17 @@ module.exports = { a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; + let buffer = renderer._meshBuffer, + vertexOffset = buffer.byteOffset >> 2, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; buffer.request(4, 6); - + // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, - uintbuf = buffer._uintVData; + uintbuf = buffer._uintVData, + ibuf = buffer._iData; // get uv from sprite frame directly let uv = sprite._spriteFrame.uv; @@ -104,6 +107,13 @@ module.exports = { uintbuf[vertexOffset+9] = color; uintbuf[vertexOffset+14] = color; uintbuf[vertexOffset+19] = color; + // fill indice data + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId+1; + ibuf[indiceOffset++] = vertexId+2; + ibuf[indiceOffset++] = vertexId+1; + ibuf[indiceOffset++] = vertexId+3; + ibuf[indiceOffset++] = vertexId+2; }, createData (sprite) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js index 8ccb7940d5e..8c64a94e19c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js @@ -109,9 +109,8 @@ module.exports = { let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, - vertexCount = renderData.vertexCount; - - let indiceOffset = buffer.indiceOffset, + vertexCount = renderData.vertexCount, + indiceOffset = buffer.indiceOffset, vertexId = buffer.vertexOffset; let uvSliced = sprite.spriteFrame.uvSliced; From 1fc7fcd20c764b6870e44887a97b2c6a309f02a4 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 23 Oct 2018 11:37:44 +0800 Subject: [PATCH 0101/1631] refine api (#3409) * refine node api * refine api comment --- cocos2d/core/CCNode.js | 22 +++++++++++----------- cocos2d/core/platform/CCMacro.js | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 1ddf4407cf3..64dac7b384f 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -2379,11 +2379,11 @@ let NodeDefines = { /* * Calculate and return world position. * This is not a public API yet, its usage could be updated - * @method getWorldPos + * @method getWorldPosition * @param {Vec3} out * @return {Vec3} */ - getWorldPos (out) { + getWorldPosition (out) { math.vec3.copy(out, this._position); let curr = this._parent; while (curr) { @@ -2401,10 +2401,10 @@ let NodeDefines = { /* * Set world position. * This is not a public API yet, its usage could be updated - * @method setWorldPos + * @method setWorldPosition * @param {Vec3} pos */ - setWorldPos (pos) { + setWorldPosition (pos) { if (CC_EDITOR) { var oldPosition = new cc.Vec3(this._position); } @@ -2432,11 +2432,11 @@ let NodeDefines = { /* * Calculate and return world rotation * This is not a public API yet, its usage could be updated - * @method getWorldRot + * @method getWorldRotation * @param {Quat} out * @return {Quat} */ - getWorldRot (out) { + getWorldRotation (out) { math.quat.copy(out, this._quat); let curr = this._parent; while (curr) { @@ -2449,12 +2449,12 @@ let NodeDefines = { /* * Set world rotation with quaternion * This is not a public API yet, its usage could be updated - * @method setWorldRot + * @method setWorldRotation * @param {Quat} rot */ - setWorldRot (quat) { + setWorldRotation (quat) { if (this._parent) { - this._parent.getWorldRot(this._quat); + this._parent.getWorldRotation(this._quat); math.quat.conjugate(this._quat, this._quat); math.quat.mul(this._quat, this._quat, quat); } @@ -2494,12 +2494,12 @@ let NodeDefines = { * @param {Vec3} [up] - default is (0,1,0) */ lookAt (pos, up) { - this.getWorldPos(_vec3_temp); + this.getWorldPosition(_vec3_temp); math.vec3.sub(_vec3_temp, _vec3_temp, pos); // NOTE: we use -z for view-dir math.vec3.normalize(_vec3_temp, _vec3_temp); math.quat.fromViewUp(_quat_temp, _vec3_temp, up); - this.setWorldRot(_quat_temp); + this.setWorldRotation(_quat_temp); }, _updateLocalMatrix () { diff --git a/cocos2d/core/platform/CCMacro.js b/cocos2d/core/platform/CCMacro.js index ffbc1865291..a2e247bf59d 100644 --- a/cocos2d/core/platform/CCMacro.js +++ b/cocos2d/core/platform/CCMacro.js @@ -369,10 +369,10 @@ if (cc.sys.isMobile) { /** * !en * The image format supported by the engine defaults, and the supported formats may differ in different build platforms and device types. - * Currently all platform and device support ['.webp', '.jpg', '.jpeg', '.bmp', '.png'], ios mobile platform + * Currently all platform and device support ['.webp', '.jpg', '.jpeg', '.bmp', '.png'], The iOS mobile platform also supports the PVR format。 * !zh * 引擎默认支持的图片格式,支持的格式可能在不同的构建平台和设备类型上有所差别。 - * 目前所有平台和设备支持的格式有 ['.webp', '.jpg', '.jpeg', '.bmp', '.png']. The iOS mobile platform also supports the PVR format。 + * 目前所有平台和设备支持的格式有 ['.webp', '.jpg', '.jpeg', '.bmp', '.png']. 另外 Ios 手机平台还额外支持了 PVR 格式。 * @property {[String]} SUPPORT_TEXTURE_FORMATS */ cc.macro.SUPPORT_TEXTURE_FORMATS = SUPPORT_TEXTURE_FORMATS; From 254b7c1eb90612a10c3bee71e96d0e80c42956b3 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Tue, 23 Oct 2018 14:32:31 +0800 Subject: [PATCH 0102/1631] Fix rendering errors for pre-multiplied images using dynamicAtlas. (#3411) * Fix rendering errors for pre-multiplied images using dynamicAtlas. * Fix setting filter in RenderTexture is invalid. * Modified FilterIndex to private variable. --- cocos2d/core/assets/CCRenderTexture.js | 6 +++++- cocos2d/core/assets/CCTexture2D.js | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/assets/CCRenderTexture.js b/cocos2d/core/assets/CCRenderTexture.js index 1a3d1008715..ee5fea48947 100644 --- a/cocos2d/core/assets/CCRenderTexture.js +++ b/cocos2d/core/assets/CCRenderTexture.js @@ -37,6 +37,9 @@ let RenderTexture = cc.Class({ opts.images = undefined; opts.wrapS = this._wrapS; opts.wrapT = this._wrapT; + opts.premultiplyAlpha = this._premultiplyAlpha; + opts.minFilter = Texture2D._FilterIndex[this._minFilter]; + opts.magFilter = Texture2D._FilterIndex[this._magFilter]; if (!this._texture) { this._texture = new renderer.Texture2D(renderer.device, opts); @@ -86,7 +89,8 @@ let RenderTexture = cc.Class({ width: texture.width, height: texture.height, level: 0, - flipY: false + flipY: false, + premultiplyAlpha: texture._premultiplyAlpha }) }, diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 50a13d20e5b..d3356024d3c 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -276,6 +276,8 @@ var Texture2D = cc.Class({ PixelFormat: PixelFormat, WrapMode: WrapMode, Filter: Filter, + _FilterIndex: FilterIndex, + // predefined most common extnames extnames: ['.png', '.jpg', '.jpeg', '.bmp', '.webp', '.pvr', '.etc'], From ada2855dbeb5c2913a4f44d2947854daea9aa3f5 Mon Sep 17 00:00:00 2001 From: Hieu Bui Duc Date: Wed, 24 Oct 2018 08:47:36 +0700 Subject: [PATCH 0103/1631] Fix Image Loader on Facebook Playable Ads (#3403) * Fix Image Loader on Facebook Playable Ads * Remove macro * move to L684 --- cocos2d/core/load-pipeline/loader.js | 2 +- cocos2d/core/platform/CCSys.js | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/load-pipeline/loader.js b/cocos2d/core/load-pipeline/loader.js index 461d78c8ab9..02c2d5bb2c1 100644 --- a/cocos2d/core/load-pipeline/loader.js +++ b/cocos2d/core/load-pipeline/loader.js @@ -49,7 +49,7 @@ function loadJSON (item, callback) { } function loadImage (item, callback) { - if (sys.platform !== sys.WECHAT_GAME && sys.platform !== sys.QQ_PLAY && !(item.content instanceof Image)) { + if (sys.platform !== sys.WECHAT_GAME && sys.platform !== sys.QQ_PLAY && sys.platform !== sys.FB_PLAYABLE_ADS && !(item.content instanceof Image)) { return new Error('Image Loader: Input item doesn\'t contain Image content'); } var rawUrl = item.rawUrl; diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 36eb3873167..0b1b702c276 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -346,6 +346,12 @@ sys.WECHAT_GAME = 104; * @default 105 */ sys.QQ_PLAY = 105; +/** + * @property {Number} FB_PLAYABLE_ADS + * @readOnly + * @default 106 + */ +sys.FB_PLAYABLE_ADS = 106; /** * BROWSER_TYPE_WECHAT @@ -660,7 +666,7 @@ else { if (CC_EDITOR) { sys.isMobile = false; sys.platform = sys.EDITOR_PAGE; - } + } else { /** * Indicate whether system is mobile system @@ -675,6 +681,10 @@ else { sys.platform = sys.isMobile ? sys.MOBILE_BROWSER : sys.DESKTOP_BROWSER; } + if (typeof FbPlayableAd !== undefined) { + sys.platform = sys.FB_PLAYABLE_ADS; + } + var currLanguage = nav.language; currLanguage = currLanguage ? currLanguage : nav.browserLanguage; currLanguage = currLanguage ? currLanguage.split("-")[0] : sys.LANGUAGE_ENGLISH; From 0ddedadb1c41342b58477427fc6cfc6e67c976ff Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 24 Oct 2018 09:56:49 +0800 Subject: [PATCH 0104/1631] fix editBox bug when can't find camera (#3412) --- .../core/components/editbox/CCEditBoxImpl.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index f198c565d79..31a6053c0ee 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -349,6 +349,16 @@ let EditBoxImpl = cc.Class({ _updateMatrix () { if (!this._edTxt) return; + + let camera; + // can't find camera in editor + if (CC_EDITOR) { + camera = cc.Camera.main; + } + else { + camera = cc.Camera.findCamera(this._node); + } + if (!camera) return; let node = this._node, scaleX = cc.view._scaleX, scaleY = cc.view._scaleY, @@ -361,15 +371,6 @@ let EditBoxImpl = cc.Class({ _vec3.y = -node._anchorPoint.y * contentSize.height; math.mat4.translate(_matrix, _matrix, _vec3); - - let camera; - // can't find camera in editor - if (CC_EDITOR) { - camera = cc.Camera.main; - } - else { - camera = cc.Camera.findCamera(node); - } camera.getWorldToCameraMatrix(_matrix_temp); math.mat4.mul(_matrix_temp, _matrix_temp, _matrix); From 00e8ff8e75352f8486523a4478d10a0fbe734ac1 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Wed, 24 Oct 2018 10:49:45 +0800 Subject: [PATCH 0105/1631] fix merge --- cocos2d/core/load-pipeline/loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/load-pipeline/loader.js b/cocos2d/core/load-pipeline/loader.js index 7d023a331fc..ac481f070eb 100644 --- a/cocos2d/core/load-pipeline/loader.js +++ b/cocos2d/core/load-pipeline/loader.js @@ -55,7 +55,7 @@ function loadImage (item, callback) { } var image = item.content; - if (!CC_WECHATGAME && !CC_QQPLAY && cc.sys.platform !== sys.FB_PLAYABLE_ADS && !(image instanceof Image)) { + if (!CC_WECHATGAME && !CC_QQPLAY && cc.sys.platform !== cc.sys.FB_PLAYABLE_ADS && !(image instanceof Image)) { return new Error('Image Loader: Input item doesn\'t contain Image content'); } From 689b432b7a084c94d82d9ab572816895991d2502 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Wed, 24 Oct 2018 12:08:19 +0800 Subject: [PATCH 0106/1631] fixed the setRect useless problem (#3410) --- cocos2d/core/assets/CCSpriteFrame.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/assets/CCSpriteFrame.js b/cocos2d/core/assets/CCSpriteFrame.js index 908b0a6c13c..945415d719b 100644 --- a/cocos2d/core/assets/CCSpriteFrame.js +++ b/cocos2d/core/assets/CCSpriteFrame.js @@ -256,6 +256,8 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ */ setRotated: function (bRotated) { this._rotated = bRotated; + if (this._texture) + this._calculateUV(); }, /** @@ -276,6 +278,8 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ */ setRect: function (rect) { this._rect = rect; + if (this._texture) + this._calculateUV(); }, /** @@ -328,14 +332,14 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ self._rotated = false; w = self._texture.width; h = self._texture.height; - self.setRect(cc.rect(0, 0, w, h)); + self._rect = cc.rect(0, 0, w, h); } if (self._rect) { self._checkRect(self._texture); } else { - self.setRect(cc.rect(0, 0, w, h)); + self._rect = cc.rect(0, 0, w, h); } if (!self._originalSize) { @@ -411,7 +415,7 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ */ setTexture: function (textureOrTextureFile, rect, rotated, offset, originalSize) { if (rect) { - this.setRect(rect); + this._rect = rect; } else { this._rect = null; @@ -675,7 +679,7 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ _deserialize: function (data, handle) { let rect = data.rect; if (rect) { - this.setRect(new cc.Rect(rect[0], rect[1], rect[2], rect[3])); + this._rect = new cc.Rect(rect[0], rect[1], rect[2], rect[3]); } if (data.offset) { this.setOffset(new cc.Vec2(data.offset[0], data.offset[1])); From 73ad6eb747d37c14d7ac9718d4538ff9c09f518f Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Wed, 24 Oct 2018 19:23:26 +0800 Subject: [PATCH 0107/1631] Update the url links (#3420) --- .github/ISSUE_TEMPLATE.md | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 2 +- cocos2d/actions/index.js | 2 +- cocos2d/animation/animation-animator.js | 2 +- cocos2d/animation/animation-clip.js | 2 +- cocos2d/animation/animation-curves.js | 2 +- cocos2d/animation/animation-manager.js | 2 +- cocos2d/animation/animation-state.js | 2 +- cocos2d/animation/bezier.js | 2 +- cocos2d/animation/easing.js | 2 +- cocos2d/animation/index.js | 2 +- cocos2d/animation/motion-path-helper.js | 2 +- cocos2d/animation/playable.js | 2 +- cocos2d/animation/types.js | 2 +- cocos2d/core/CCDebug.js | 2 +- cocos2d/core/CCGame.js | 2 +- cocos2d/core/CCNode.js | 4 +- cocos2d/core/CCPrivateNode.js | 2 +- cocos2d/core/CCScheduler.js | 2 +- cocos2d/core/assets/CCAsset.js | 2 +- cocos2d/core/assets/CCAudioClip.js | 2 +- cocos2d/core/assets/CCBitmapFont.js | 2 +- cocos2d/core/assets/CCFont.js | 2 +- cocos2d/core/assets/CCJsonAsset.js | 2 +- cocos2d/core/assets/CCLabelAtlas.js | 2 +- cocos2d/core/assets/CCPrefab.js | 2 +- cocos2d/core/assets/CCRawAsset.js | 2 +- cocos2d/core/assets/CCSceneAsset.js | 2 +- cocos2d/core/assets/CCScripts.js | 2 +- cocos2d/core/assets/CCSpriteAtlas.js | 2 +- cocos2d/core/assets/CCTTFFont.js | 2 +- cocos2d/core/assets/CCTextAsset.js | 2 +- cocos2d/core/assets/CCTexture2D.js | 2 +- cocos2d/core/assets/index.js | 2 +- cocos2d/core/base-ui/CCWidgetManager.js | 2 +- cocos2d/core/camera/CCCamera.js | 2 +- cocos2d/core/collider/CCBoxCollider.js | 2 +- cocos2d/core/collider/CCCircleCollider.js | 2 +- cocos2d/core/collider/CCCollider.js | 2 +- cocos2d/core/collider/CCCollisionManager.js | 2 +- cocos2d/core/collider/CCContact.js | 2 +- cocos2d/core/collider/CCIntersection.js | 2 +- cocos2d/core/collider/CCPolygonCollider.js | 2 +- cocos2d/core/collider/index.js | 2 +- cocos2d/core/component-scheduler.js | 2 +- cocos2d/core/components/CCAnimation.js | 2 +- cocos2d/core/components/CCAudioSource.js | 2 +- cocos2d/core/components/CCBlockInputEvents.js | 2 +- cocos2d/core/components/CCButton.js | 2 +- cocos2d/core/components/CCCanvas.js | 2 +- cocos2d/core/components/CCComponent.js | 2 +- .../components/CCComponentEventHandler.js | 2 +- cocos2d/core/components/CCLabel.js | 2 +- cocos2d/core/components/CCLabelOutline.js | 2 +- cocos2d/core/components/CCLayout.js | 2 +- cocos2d/core/components/CCMask.js | 2 +- cocos2d/core/components/CCMotionStreak.js | 2 +- cocos2d/core/components/CCPageView.js | 2 +- .../core/components/CCPageViewIndicator.js | 2 +- cocos2d/core/components/CCProgressBar.js | 2 +- cocos2d/core/components/CCRenderComponent.js | 2 +- cocos2d/core/components/CCRichText.js | 2 +- cocos2d/core/components/CCScrollBar.js | 2 +- cocos2d/core/components/CCScrollView.js | 2 +- cocos2d/core/components/CCSlider.js | 2 +- cocos2d/core/components/CCSprite.js | 2 +- cocos2d/core/components/CCStudioComponent.js | 2 +- cocos2d/core/components/CCToggle.js | 2 +- cocos2d/core/components/CCToggleContainer.js | 2 +- cocos2d/core/components/CCToggleGroup.js | 2 +- cocos2d/core/components/CCViewGroup.js | 2 +- cocos2d/core/components/CCWidget.js | 2 +- cocos2d/core/components/WXSubContextView.js | 2 +- cocos2d/core/components/editbox/CCEditBox.js | 2 +- .../core/components/editbox/CCEditBoxImpl.js | 2 +- cocos2d/core/components/editbox/types.js | 2 +- cocos2d/core/components/index.js | 2 +- cocos2d/core/components/missing-script.js | 2 +- cocos2d/core/event-manager/CCEvent.js | 2 +- cocos2d/core/event-manager/CCEventListener.js | 2 +- cocos2d/core/event-manager/CCEventManager.js | 2 +- cocos2d/core/event-manager/CCTouch.js | 2 +- cocos2d/core/event-manager/index.js | 2 +- cocos2d/core/event/event-listeners.js | 2 +- cocos2d/core/event/event-target.js | 2 +- cocos2d/core/event/event.js | 2 +- cocos2d/core/event/index.js | 2 +- cocos2d/core/event/system-event.js | 2 +- cocos2d/core/graphics/graphics.js | 2 +- cocos2d/core/graphics/helper.js | 2 +- cocos2d/core/graphics/index.js | 2 +- cocos2d/core/graphics/types.js | 2 +- cocos2d/core/index.js | 2 +- cocos2d/core/load-pipeline/CCLoader.js | 2 +- cocos2d/core/load-pipeline/asset-loader.js | 2 +- cocos2d/core/load-pipeline/asset-table.js | 2 +- .../core/load-pipeline/audio-downloader.js | 2 +- .../core/load-pipeline/auto-release-utils.js | 2 +- .../core/load-pipeline/binary-downloader.js | 2 +- cocos2d/core/load-pipeline/downloader.js | 2 +- cocos2d/core/load-pipeline/font-loader.js | 2 +- cocos2d/core/load-pipeline/index.js | 2 +- cocos2d/core/load-pipeline/loader.js | 2 +- cocos2d/core/load-pipeline/loading-items.js | 2 +- cocos2d/core/load-pipeline/md5-pipe.js | 2 +- cocos2d/core/load-pipeline/pack-downloader.js | 2 +- cocos2d/core/load-pipeline/pipeline.js | 2 +- .../load-pipeline/released-asset-checker.js | 2 +- cocos2d/core/load-pipeline/text-downloader.js | 2 +- cocos2d/core/load-pipeline/unpackers.js | 2 +- cocos2d/core/load-pipeline/utils.js | 2 +- cocos2d/core/load-pipeline/uuid-loader.js | 2 +- cocos2d/core/node-activator.js | 2 +- cocos2d/core/physics/CCPhysicsContact.js | 2 +- cocos2d/core/physics/CCPhysicsManager.js | 2 +- cocos2d/core/physics/CCPhysicsTypes.js | 2 +- cocos2d/core/physics/CCPolygonSeparator.js | 2 +- cocos2d/core/physics/CCRigidBody.js | 2 +- .../physics/collider/CCPhysicsBoxCollider.js | 2 +- .../collider/CCPhysicsChainCollider.js | 2 +- .../collider/CCPhysicsCircleCollider.js | 2 +- .../physics/collider/CCPhysicsCollider.js | 2 +- .../collider/CCPhysicsPolygonCollider.js | 2 +- cocos2d/core/physics/index.js | 2 +- cocos2d/core/physics/joint/CCDistanceJoint.js | 2 +- cocos2d/core/physics/joint/CCJoint.js | 2 +- cocos2d/core/physics/joint/CCMotorJoint.js | 2 +- cocos2d/core/physics/joint/CCMouseJoint.js | 2 +- .../core/physics/joint/CCPrismaticJoint.js | 2 +- cocos2d/core/physics/joint/CCRevoluteJoint.js | 2 +- cocos2d/core/physics/joint/CCRopeJoint.js | 2 +- cocos2d/core/physics/joint/CCWeldJoint.js | 2 +- cocos2d/core/physics/joint/CCWheelJoint.js | 2 +- .../platform/CCPhysicsAABBQueryCallback.js | 2 +- .../platform/CCPhysicsContactListner.js | 2 +- .../physics/platform/CCPhysicsDebugDraw.js | 2 +- .../platform/CCPhysicsRayCastCallback.js | 2 +- cocos2d/core/physics/utils.js | 2 +- cocos2d/core/platform/BKInputManager.js | 2 +- cocos2d/core/platform/CCAssetLibrary.js | 2 +- cocos2d/core/platform/CCClass.js | 2 +- cocos2d/core/platform/CCClassDecorator.js | 2 +- cocos2d/core/platform/CCEnum.js | 2 +- cocos2d/core/platform/CCObject.js | 2 +- cocos2d/core/platform/CCSys.js | 2 +- cocos2d/core/platform/attribute.js | 2 +- cocos2d/core/platform/callbacks-invoker.js | 2 +- cocos2d/core/platform/compiler.js | 2 +- cocos2d/core/platform/deserialize.js | 2 +- cocos2d/core/platform/id-generater.js | 2 +- cocos2d/core/platform/index.js | 2 +- cocos2d/core/platform/instantiate-jit.js | 2 +- cocos2d/core/platform/instantiate.js | 2 +- cocos2d/core/platform/preprocess-class.js | 2 +- cocos2d/core/platform/requiring-frame.js | 2 +- cocos2d/core/platform/url.js | 2 +- cocos2d/core/platform/utils.js | 2 +- cocos2d/core/predefine.js | 2 +- .../renderer/canvas/canvas-render-walker.js | 2 +- .../core/renderer/canvas/forward-renderer.js | 2 +- cocos2d/core/renderer/canvas/index.js | 2 +- .../canvas/renderers/graphics/impl.js | 2 +- .../canvas/renderers/graphics/index.js | 2 +- .../core/renderer/canvas/renderers/index.js | 2 +- .../renderer/canvas/renderers/label/bmfont.js | 2 +- .../renderer/canvas/renderers/label/index.js | 2 +- .../renderer/canvas/renderers/label/ttf.js | 2 +- .../core/renderer/canvas/renderers/mask.js | 2 +- .../renderer/canvas/renderers/sprite/index.js | 2 +- .../canvas/renderers/sprite/simple.js | 2 +- .../canvas/renderers/sprite/sliced.js | 2 +- .../renderer/canvas/renderers/sprite/tiled.js | 2 +- .../core/renderer/canvas/renderers/utils.js | 2 +- cocos2d/core/renderer/index.js | 2 +- cocos2d/core/renderer/render-engine.canvas.js | 2 +- cocos2d/core/renderer/render-engine.js | 2 +- cocos2d/core/renderer/render-engine.jsb.js | 2 +- cocos2d/core/renderer/utils/label/bmfont.js | 2 +- cocos2d/core/renderer/utils/label/ttf.js | 2 +- .../renderer/webgl/assemblers/assembler.js | 2 +- .../webgl/assemblers/graphics/earcut.js | 2 +- .../webgl/assemblers/graphics/index.js | 2 +- .../core/renderer/webgl/assemblers/index.js | 2 +- .../renderer/webgl/assemblers/label/bmfont.js | 2 +- .../renderer/webgl/assemblers/label/index.js | 2 +- .../renderer/webgl/assemblers/label/ttf.js | 2 +- .../webgl/assemblers/mask-assembler.js | 2 +- .../webgl/assemblers/motion-streak.js | 2 +- .../webgl/assemblers/sprite/bar-filled.js | 2 +- .../renderer/webgl/assemblers/sprite/index.js | 2 +- .../renderer/webgl/assemblers/sprite/mesh.js | 2 +- .../webgl/assemblers/sprite/radial-filled.js | 2 +- .../webgl/assemblers/sprite/simple.js | 2 +- .../webgl/assemblers/sprite/sliced.js | 2 +- .../renderer/webgl/assemblers/sprite/tiled.js | 2 +- .../renderer/webgl/render-component-walker.js | 2 +- .../core/renderer/webgl/stencil-manager.js | 2 +- cocos2d/core/renderer/webgl/vertex-format.js | 2 +- cocos2d/core/utils/CCPath.js | 2 +- cocos2d/core/utils/base-node.js | 2 +- cocos2d/core/utils/binary-search.js | 2 +- cocos2d/core/utils/decode-uuid.js | 2 +- cocos2d/core/utils/find.js | 2 +- cocos2d/core/utils/html-text-parser.js | 2 +- cocos2d/core/utils/index.js | 2 +- cocos2d/core/utils/math-pools.js | 2 +- cocos2d/core/utils/misc.js | 2 +- .../core/utils/mutable-forward-iterator.js | 2 +- cocos2d/core/utils/polyfill-3d.js | 2 +- cocos2d/core/utils/prefab-helper.js | 2 +- cocos2d/core/utils/profiler/CCProfiler.js | 2 +- cocos2d/core/utils/text-utils.js | 2 +- cocos2d/core/utils/texture-util.js | 2 +- cocos2d/core/value-types/color.js | 2 +- cocos2d/core/value-types/index.js | 2 +- cocos2d/core/value-types/mat4.js | 2 +- cocos2d/core/value-types/quat.js | 2 +- cocos2d/core/value-types/rect.js | 2 +- cocos2d/core/value-types/size.js | 2 +- cocos2d/core/value-types/value-type.js | 2 +- cocos2d/core/value-types/vec2.js | 2 +- cocos2d/core/value-types/vec3.js | 2 +- cocos2d/deprecated.js | 2 +- cocos2d/index.js | 2 +- cocos2d/particle/CCParticleAsset.js | 2 +- cocos2d/particle/CCParticleSystem.js | 2 +- cocos2d/particle/CCTIFFReader.js | 2 +- cocos2d/particle/index.js | 2 +- cocos2d/particle/particle-simulator.js | 2 +- cocos2d/particle/particle-system-assembler.js | 2 +- cocos2d/tilemap/CCTiledLayer.js | 2 +- cocos2d/tilemap/CCTiledMap.js | 2 +- cocos2d/tilemap/CCTiledMapAsset.js | 2 +- cocos2d/tilemap/CCTiledObjectGroup.js | 2 +- cocos2d/tilemap/CCTiledTile.js | 2 +- cocos2d/tilemap/editor/tiled-map.js | 2 +- cocos2d/tilemap/index.js | 2 +- cocos2d/tilemap/tmx-layer-assembler.js | 2 +- cocos2d/videoplayer/CCVideoPlayer.js | 2 +- cocos2d/videoplayer/video-player-impl.js | 2 +- cocos2d/webview/CCWebView.js | 2 +- cocos2d/webview/webview-impl.js | 2 +- editor/i18n/en/localization.js | 52 +++++++++---------- editor/i18n/zh/localization.js | 52 +++++++++---------- extends.js | 2 +- extensions/anysdk/jsb_anysdk.js | 2 +- extensions/dragonbones/ArmatureDisplay.js | 2 +- extensions/dragonbones/DragonBonesAsset.js | 2 +- .../dragonbones/DragonBonesAtlasAsset.js | 2 +- .../editor/dragonbones-atlas-meta.js | 2 +- .../dragonbones/editor/dragonbones-meta.js | 2 +- extensions/dragonbones/webgl-assembler.js | 2 +- extensions/spine/Skeleton.js | 2 +- extensions/spine/editor/spine-meta.js | 2 +- extensions/spine/skeleton-data.js | 2 +- extensions/spine/skeleton-texture.js | 2 +- extensions/spine/spine-assembler.js | 2 +- extensions/spine/track-entry-listeners.js | 2 +- gulp/tasks/engine.js | 2 +- gulp/tasks/test.js | 2 +- gulp/util/handleErrors.js | 2 +- gulpfile.js | 2 +- index.js | 2 +- licenses/LICENSE | 2 +- predefine.js | 2 +- 265 files changed, 316 insertions(+), 316 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 893374c0a7c..1e60107c697 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,6 @@ ### Creator version?(版本号) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index b1c968eaf70..7ab44b0d7f1 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,7 +9,7 @@ Changes: - [ ] If your commit history is full of small, unimportant commits (such as "fix pep8" or "update tests"), **squash** your commits down to a few, or one, discreet changesets before submitting a pull request. - For official teams: - - [ ] Check that your javascript is following our [style guide](http://docs.cocos.com/creator/manual/zh/scripting/reference/coding-standards.html) and end files with a newline + - [ ] Check that your javascript is following our [style guide](https://docs.cocos.com/creator/manual/zh/scripting/reference/coding-standards.html) and end files with a newline - [ ] Document new code with comments in source code based on [API Docs](https://github.com/cocos-creator/fireball#api-docs) - [ ] Make sure any **runtime** log information in `cc.log`, `cc.error` or `new Error()` has been moved into `EngineErrorMap.md` with an ID, and use `cc.logID(id)` or `new Error(cc.debug.getError(id))` instead. diff --git a/cocos2d/actions/index.js b/cocos2d/actions/index.js index 52557a1c17f..e556fa5680f 100644 --- a/cocos2d/actions/index.js +++ b/cocos2d/actions/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/animation-animator.js b/cocos2d/animation/animation-animator.js index a01c195aa4b..be3f64388fb 100644 --- a/cocos2d/animation/animation-animator.js +++ b/cocos2d/animation/animation-animator.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/animation-clip.js b/cocos2d/animation/animation-clip.js index 763017e865e..4f172ca096a 100644 --- a/cocos2d/animation/animation-clip.js +++ b/cocos2d/animation/animation-clip.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/animation-curves.js b/cocos2d/animation/animation-curves.js index 6445b07671b..9f461d038c8 100644 --- a/cocos2d/animation/animation-curves.js +++ b/cocos2d/animation/animation-curves.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/animation-manager.js b/cocos2d/animation/animation-manager.js index 1edd4ec9b84..0973bcc7898 100644 --- a/cocos2d/animation/animation-manager.js +++ b/cocos2d/animation/animation-manager.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/animation-state.js b/cocos2d/animation/animation-state.js index fd51fe98b20..99e6a0bf753 100644 --- a/cocos2d/animation/animation-state.js +++ b/cocos2d/animation/animation-state.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/bezier.js b/cocos2d/animation/bezier.js index f5dea5176a0..602305e2c2b 100644 --- a/cocos2d/animation/bezier.js +++ b/cocos2d/animation/bezier.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/easing.js b/cocos2d/animation/easing.js index f17aadfde4c..923f6487922 100644 --- a/cocos2d/animation/easing.js +++ b/cocos2d/animation/easing.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/index.js b/cocos2d/animation/index.js index 224528caaa8..5379ce3e8d0 100644 --- a/cocos2d/animation/index.js +++ b/cocos2d/animation/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/motion-path-helper.js b/cocos2d/animation/motion-path-helper.js index 13deab5f6ae..a9e5b814531 100644 --- a/cocos2d/animation/motion-path-helper.js +++ b/cocos2d/animation/motion-path-helper.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/playable.js b/cocos2d/animation/playable.js index ffacf92808a..417bb6693e1 100644 --- a/cocos2d/animation/playable.js +++ b/cocos2d/animation/playable.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/animation/types.js b/cocos2d/animation/types.js index a4866e312d9..29e6139f1ff 100644 --- a/cocos2d/animation/types.js +++ b/cocos2d/animation/types.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/CCDebug.js b/cocos2d/core/CCDebug.js index 484cf48f62a..11febe776a7 100644 --- a/cocos2d/core/CCDebug.js +++ b/cocos2d/core/CCDebug.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 5c1b5c7848f..4dcaaabdfb5 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 4bebbcc1d3a..b61a3155699 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1735,7 +1735,7 @@ var Node = cc.Class({ * Reference: http://docs.cocos2d-x.org/editors_and_tools/creator-chapters/scripting/internal-events/ * !#zh 暂停当前节点上注册的所有节点系统事件,节点系统事件包含触摸和鼠标事件。 * 如果传递 recursive 为 true,那么这个 API 将暂停本节点和它的子树上所有节点的节点系统事件。 - * 参考:http://cocos.com/docs/creator/scripting/internal-events.html + * 参考:https://www.cocos.com/docs/creator/scripting/internal-events.html * @method pauseSystemEvents * @param {Boolean} recursive - Whether to pause node system events on the sub node tree. * @example @@ -1751,7 +1751,7 @@ var Node = cc.Class({ * Reference: http://docs.cocos2d-x.org/editors_and_tools/creator-chapters/scripting/internal-events/ * !#zh 恢复当前节点上注册的所有节点系统事件,节点系统事件包含触摸和鼠标事件。 * 如果传递 recursive 为 true,那么这个 API 将恢复本节点和它的子树上所有节点的节点系统事件。 - * 参考:http://cocos.com/docs/creator/scripting/internal-events.html + * 参考:https://www.cocos.com/docs/creator/scripting/internal-events.html * @method resumeSystemEvents * @param {Boolean} recursive - Whether to resume node system events on the sub node tree. * @example diff --git a/cocos2d/core/CCPrivateNode.js b/cocos2d/core/CCPrivateNode.js index f7384570aa4..f49a6df713d 100644 --- a/cocos2d/core/CCPrivateNode.js +++ b/cocos2d/core/CCPrivateNode.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/CCScheduler.js b/cocos2d/core/CCScheduler.js index a9d0a843199..a2d28076b2c 100644 --- a/cocos2d/core/CCScheduler.js +++ b/cocos2d/core/CCScheduler.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCAsset.js b/cocos2d/core/assets/CCAsset.js index fceba18b02a..12887a87a70 100644 --- a/cocos2d/core/assets/CCAsset.js +++ b/cocos2d/core/assets/CCAsset.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCAudioClip.js b/cocos2d/core/assets/CCAudioClip.js index 5bbbca5fbf8..fa7f40a081c 100644 --- a/cocos2d/core/assets/CCAudioClip.js +++ b/cocos2d/core/assets/CCAudioClip.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCBitmapFont.js b/cocos2d/core/assets/CCBitmapFont.js index 45340968c60..c5cc96f4028 100644 --- a/cocos2d/core/assets/CCBitmapFont.js +++ b/cocos2d/core/assets/CCBitmapFont.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCFont.js b/cocos2d/core/assets/CCFont.js index dc1c1eb75f6..21e147c4632 100644 --- a/cocos2d/core/assets/CCFont.js +++ b/cocos2d/core/assets/CCFont.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCJsonAsset.js b/cocos2d/core/assets/CCJsonAsset.js index 2a6eee38833..b9f4823b168 100644 --- a/cocos2d/core/assets/CCJsonAsset.js +++ b/cocos2d/core/assets/CCJsonAsset.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCLabelAtlas.js b/cocos2d/core/assets/CCLabelAtlas.js index dd4e63005ba..af8c5a9f4ed 100644 --- a/cocos2d/core/assets/CCLabelAtlas.js +++ b/cocos2d/core/assets/CCLabelAtlas.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCPrefab.js b/cocos2d/core/assets/CCPrefab.js index 21517e0f7aa..f87fe795740 100644 --- a/cocos2d/core/assets/CCPrefab.js +++ b/cocos2d/core/assets/CCPrefab.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCRawAsset.js b/cocos2d/core/assets/CCRawAsset.js index 8d1542551bd..cae9547a198 100644 --- a/cocos2d/core/assets/CCRawAsset.js +++ b/cocos2d/core/assets/CCRawAsset.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCSceneAsset.js b/cocos2d/core/assets/CCSceneAsset.js index f22c6f9fe7a..e5831d940f0 100644 --- a/cocos2d/core/assets/CCSceneAsset.js +++ b/cocos2d/core/assets/CCSceneAsset.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCScripts.js b/cocos2d/core/assets/CCScripts.js index 22f8a10e829..eba7acbe908 100644 --- a/cocos2d/core/assets/CCScripts.js +++ b/cocos2d/core/assets/CCScripts.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCSpriteAtlas.js b/cocos2d/core/assets/CCSpriteAtlas.js index 0dde4587b7a..975887dcfbf 100644 --- a/cocos2d/core/assets/CCSpriteAtlas.js +++ b/cocos2d/core/assets/CCSpriteAtlas.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCTTFFont.js b/cocos2d/core/assets/CCTTFFont.js index f93bb60d3d6..e0c78262bc0 100644 --- a/cocos2d/core/assets/CCTTFFont.js +++ b/cocos2d/core/assets/CCTTFFont.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCTextAsset.js b/cocos2d/core/assets/CCTextAsset.js index 385346ee159..dfa6c9f2df2 100644 --- a/cocos2d/core/assets/CCTextAsset.js +++ b/cocos2d/core/assets/CCTextAsset.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 39d83bcb1e9..d8f0fbdae56 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/assets/index.js b/cocos2d/core/assets/index.js index 2395baab50c..95bd670b52b 100644 --- a/cocos2d/core/assets/index.js +++ b/cocos2d/core/assets/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/base-ui/CCWidgetManager.js b/cocos2d/core/base-ui/CCWidgetManager.js index 21d700f2a6a..537b97dacc9 100644 --- a/cocos2d/core/base-ui/CCWidgetManager.js +++ b/cocos2d/core/base-ui/CCWidgetManager.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index c734007d751..6ad76444bda 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/collider/CCBoxCollider.js b/cocos2d/core/collider/CCBoxCollider.js index 25a32652112..df4aa6ee64d 100644 --- a/cocos2d/core/collider/CCBoxCollider.js +++ b/cocos2d/core/collider/CCBoxCollider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/collider/CCCircleCollider.js b/cocos2d/core/collider/CCCircleCollider.js index 54006a0c4a1..70e02dd61e6 100644 --- a/cocos2d/core/collider/CCCircleCollider.js +++ b/cocos2d/core/collider/CCCircleCollider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/collider/CCCollider.js b/cocos2d/core/collider/CCCollider.js index af9eb39ac95..4e28d92427c 100644 --- a/cocos2d/core/collider/CCCollider.js +++ b/cocos2d/core/collider/CCCollider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/collider/CCCollisionManager.js b/cocos2d/core/collider/CCCollisionManager.js index 07f9c5ca1d7..33d2ad984ba 100644 --- a/cocos2d/core/collider/CCCollisionManager.js +++ b/cocos2d/core/collider/CCCollisionManager.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/collider/CCContact.js b/cocos2d/core/collider/CCContact.js index d9751718362..923a620932c 100644 --- a/cocos2d/core/collider/CCContact.js +++ b/cocos2d/core/collider/CCContact.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/collider/CCIntersection.js b/cocos2d/core/collider/CCIntersection.js index 600077025ac..53e4855f455 100644 --- a/cocos2d/core/collider/CCIntersection.js +++ b/cocos2d/core/collider/CCIntersection.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/collider/CCPolygonCollider.js b/cocos2d/core/collider/CCPolygonCollider.js index f1f8fc3a833..83a217e30c2 100644 --- a/cocos2d/core/collider/CCPolygonCollider.js +++ b/cocos2d/core/collider/CCPolygonCollider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/collider/index.js b/cocos2d/core/collider/index.js index 98873d2ee92..c1d23405673 100644 --- a/cocos2d/core/collider/index.js +++ b/cocos2d/core/collider/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/component-scheduler.js b/cocos2d/core/component-scheduler.js index e1d2bce0a81..b6def64b81a 100644 --- a/cocos2d/core/component-scheduler.js +++ b/cocos2d/core/component-scheduler.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCAnimation.js b/cocos2d/core/components/CCAnimation.js index 504cee75c8f..7bf382f6525 100644 --- a/cocos2d/core/components/CCAnimation.js +++ b/cocos2d/core/components/CCAnimation.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCAudioSource.js b/cocos2d/core/components/CCAudioSource.js index ff525592d95..371c7aefec3 100644 --- a/cocos2d/core/components/CCAudioSource.js +++ b/cocos2d/core/components/CCAudioSource.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCBlockInputEvents.js b/cocos2d/core/components/CCBlockInputEvents.js index 62eebdf646e..6d55984f91f 100644 --- a/cocos2d/core/components/CCBlockInputEvents.js +++ b/cocos2d/core/components/CCBlockInputEvents.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index b8795590ee8..0b8515a62b2 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCCanvas.js b/cocos2d/core/components/CCCanvas.js index c4c841fa3c9..8ab27b973ba 100644 --- a/cocos2d/core/components/CCCanvas.js +++ b/cocos2d/core/components/CCCanvas.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCComponent.js b/cocos2d/core/components/CCComponent.js index 9775a43a2eb..3cdbf6a62d6 100644 --- a/cocos2d/core/components/CCComponent.js +++ b/cocos2d/core/components/CCComponent.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCComponentEventHandler.js b/cocos2d/core/components/CCComponentEventHandler.js index 5fd1265e2ac..4e5bbf69494 100644 --- a/cocos2d/core/components/CCComponentEventHandler.js +++ b/cocos2d/core/components/CCComponentEventHandler.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index c4c0eaec917..928eddee56c 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCLabelOutline.js b/cocos2d/core/components/CCLabelOutline.js index ae859c15458..95f94971a34 100644 --- a/cocos2d/core/components/CCLabelOutline.js +++ b/cocos2d/core/components/CCLabelOutline.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCLayout.js b/cocos2d/core/components/CCLayout.js index ad0c8b7ff94..4f10bd2af8b 100644 --- a/cocos2d/core/components/CCLayout.js +++ b/cocos2d/core/components/CCLayout.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 492205063b2..b8fcf9ecf58 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCMotionStreak.js b/cocos2d/core/components/CCMotionStreak.js index 2db3ef1e9b9..e097fbb2c2d 100644 --- a/cocos2d/core/components/CCMotionStreak.js +++ b/cocos2d/core/components/CCMotionStreak.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCPageView.js b/cocos2d/core/components/CCPageView.js index 06ced582cfe..cfcbb37eb29 100644 --- a/cocos2d/core/components/CCPageView.js +++ b/cocos2d/core/components/CCPageView.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCPageViewIndicator.js b/cocos2d/core/components/CCPageViewIndicator.js index db34d5a6d2f..fcbd7560468 100644 --- a/cocos2d/core/components/CCPageViewIndicator.js +++ b/cocos2d/core/components/CCPageViewIndicator.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCProgressBar.js b/cocos2d/core/components/CCProgressBar.js index a90d987d1ab..ee204c666b4 100644 --- a/cocos2d/core/components/CCProgressBar.js +++ b/cocos2d/core/components/CCProgressBar.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 4ff2a9f050a..b6874642647 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index aa4c890bb9e..5f27744bd58 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCScrollBar.js b/cocos2d/core/components/CCScrollBar.js index 070f28dbd3b..a2aeb804870 100644 --- a/cocos2d/core/components/CCScrollBar.js +++ b/cocos2d/core/components/CCScrollBar.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index 50b509ebd3b..9737a2eac36 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCSlider.js b/cocos2d/core/components/CCSlider.js index 11e0b270a0e..4b7c48dcf07 100644 --- a/cocos2d/core/components/CCSlider.js +++ b/cocos2d/core/components/CCSlider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 041d6395d4f..9d3242d80da 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCStudioComponent.js b/cocos2d/core/components/CCStudioComponent.js index e2bc96b4a34..a3b554faf65 100644 --- a/cocos2d/core/components/CCStudioComponent.js +++ b/cocos2d/core/components/CCStudioComponent.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCToggle.js b/cocos2d/core/components/CCToggle.js index 5f546d8e89a..8a42af33bbd 100644 --- a/cocos2d/core/components/CCToggle.js +++ b/cocos2d/core/components/CCToggle.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCToggleContainer.js b/cocos2d/core/components/CCToggleContainer.js index 3d5801ba213..ad400d0e108 100644 --- a/cocos2d/core/components/CCToggleContainer.js +++ b/cocos2d/core/components/CCToggleContainer.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCToggleGroup.js b/cocos2d/core/components/CCToggleGroup.js index 035598aa626..81ffa4397d8 100644 --- a/cocos2d/core/components/CCToggleGroup.js +++ b/cocos2d/core/components/CCToggleGroup.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCViewGroup.js b/cocos2d/core/components/CCViewGroup.js index 04b7b2f79f5..2561c245139 100644 --- a/cocos2d/core/components/CCViewGroup.js +++ b/cocos2d/core/components/CCViewGroup.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/CCWidget.js b/cocos2d/core/components/CCWidget.js index 5dbd84eed3b..754106d5089 100644 --- a/cocos2d/core/components/CCWidget.js +++ b/cocos2d/core/components/CCWidget.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/WXSubContextView.js b/cocos2d/core/components/WXSubContextView.js index f1da1160b25..43c31377ea1 100644 --- a/cocos2d/core/components/WXSubContextView.js +++ b/cocos2d/core/components/WXSubContextView.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/editbox/CCEditBox.js b/cocos2d/core/components/editbox/CCEditBox.js index b6b5be0ffd9..7a675442bd6 100644 --- a/cocos2d/core/components/editbox/CCEditBox.js +++ b/cocos2d/core/components/editbox/CCEditBox.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index f198c565d79..6fd60f2b113 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -4,7 +4,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/editbox/types.js b/cocos2d/core/components/editbox/types.js index ca1757d2e46..00714373ce0 100644 --- a/cocos2d/core/components/editbox/types.js +++ b/cocos2d/core/components/editbox/types.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/index.js b/cocos2d/core/components/index.js index c268c1a4bf5..b84dbb53a25 100644 --- a/cocos2d/core/components/index.js +++ b/cocos2d/core/components/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/components/missing-script.js b/cocos2d/core/components/missing-script.js index d0e43324ade..5d6bb6b95e1 100644 --- a/cocos2d/core/components/missing-script.js +++ b/cocos2d/core/components/missing-script.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event-manager/CCEvent.js b/cocos2d/core/event-manager/CCEvent.js index feb282dafa7..88da1789e13 100644 --- a/cocos2d/core/event-manager/CCEvent.js +++ b/cocos2d/core/event-manager/CCEvent.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event-manager/CCEventListener.js b/cocos2d/core/event-manager/CCEventListener.js index cd1ba37b1c8..778c4c5fe56 100644 --- a/cocos2d/core/event-manager/CCEventListener.js +++ b/cocos2d/core/event-manager/CCEventListener.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event-manager/CCEventManager.js b/cocos2d/core/event-manager/CCEventManager.js index bfd1703a1e1..4ad734bf4b1 100644 --- a/cocos2d/core/event-manager/CCEventManager.js +++ b/cocos2d/core/event-manager/CCEventManager.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event-manager/CCTouch.js b/cocos2d/core/event-manager/CCTouch.js index 76c01f95c09..97ce9ef5a1e 100644 --- a/cocos2d/core/event-manager/CCTouch.js +++ b/cocos2d/core/event-manager/CCTouch.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event-manager/index.js b/cocos2d/core/event-manager/index.js index 856a86b8389..bd26cd049d4 100644 --- a/cocos2d/core/event-manager/index.js +++ b/cocos2d/core/event-manager/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event/event-listeners.js b/cocos2d/core/event/event-listeners.js index d238cf06dc5..563f2145204 100644 --- a/cocos2d/core/event/event-listeners.js +++ b/cocos2d/core/event/event-listeners.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event/event-target.js b/cocos2d/core/event/event-target.js index bdf2c40e720..b2ab245777b 100644 --- a/cocos2d/core/event/event-target.js +++ b/cocos2d/core/event/event-target.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event/event.js b/cocos2d/core/event/event.js index 21fe7e4980e..4fffc599a35 100644 --- a/cocos2d/core/event/event.js +++ b/cocos2d/core/event/event.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event/index.js b/cocos2d/core/event/index.js index 25158f1a57c..ac196a3f523 100644 --- a/cocos2d/core/event/index.js +++ b/cocos2d/core/event/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/event/system-event.js b/cocos2d/core/event/system-event.js index 7f72f5f58a9..05e0a531b38 100644 --- a/cocos2d/core/event/system-event.js +++ b/cocos2d/core/event/system-event.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/graphics/graphics.js b/cocos2d/core/graphics/graphics.js index c11755cf5a4..ef596a8e14c 100644 --- a/cocos2d/core/graphics/graphics.js +++ b/cocos2d/core/graphics/graphics.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/graphics/helper.js b/cocos2d/core/graphics/helper.js index d20b760500f..c5fb5e6bc3c 100644 --- a/cocos2d/core/graphics/helper.js +++ b/cocos2d/core/graphics/helper.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/graphics/index.js b/cocos2d/core/graphics/index.js index eb305138a05..0f1bfb5187b 100644 --- a/cocos2d/core/graphics/index.js +++ b/cocos2d/core/graphics/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/graphics/types.js b/cocos2d/core/graphics/types.js index 07efb1473ce..eef62c7760e 100644 --- a/cocos2d/core/graphics/types.js +++ b/cocos2d/core/graphics/types.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/index.js b/cocos2d/core/index.js index b34af7e400e..9394419e1ca 100644 --- a/cocos2d/core/index.js +++ b/cocos2d/core/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/CCLoader.js b/cocos2d/core/load-pipeline/CCLoader.js index c2698d110ef..af36508414c 100644 --- a/cocos2d/core/load-pipeline/CCLoader.js +++ b/cocos2d/core/load-pipeline/CCLoader.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/asset-loader.js b/cocos2d/core/load-pipeline/asset-loader.js index 6c9d74c9273..aa11cf390b1 100644 --- a/cocos2d/core/load-pipeline/asset-loader.js +++ b/cocos2d/core/load-pipeline/asset-loader.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/asset-table.js b/cocos2d/core/load-pipeline/asset-table.js index 94a9ba0526d..fb22755fcab 100644 --- a/cocos2d/core/load-pipeline/asset-table.js +++ b/cocos2d/core/load-pipeline/asset-table.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/audio-downloader.js b/cocos2d/core/load-pipeline/audio-downloader.js index 6245ad10bb2..006c53fe5ac 100644 --- a/cocos2d/core/load-pipeline/audio-downloader.js +++ b/cocos2d/core/load-pipeline/audio-downloader.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/auto-release-utils.js b/cocos2d/core/load-pipeline/auto-release-utils.js index 095cd086511..7503503336c 100644 --- a/cocos2d/core/load-pipeline/auto-release-utils.js +++ b/cocos2d/core/load-pipeline/auto-release-utils.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/binary-downloader.js b/cocos2d/core/load-pipeline/binary-downloader.js index de4097f4ea9..ca357e0883c 100644 --- a/cocos2d/core/load-pipeline/binary-downloader.js +++ b/cocos2d/core/load-pipeline/binary-downloader.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index ae12f7490ea..681ca642e29 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/font-loader.js b/cocos2d/core/load-pipeline/font-loader.js index ffe56543082..c892019acbf 100644 --- a/cocos2d/core/load-pipeline/font-loader.js +++ b/cocos2d/core/load-pipeline/font-loader.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/index.js b/cocos2d/core/load-pipeline/index.js index b93a25525db..2b66316b041 100644 --- a/cocos2d/core/load-pipeline/index.js +++ b/cocos2d/core/load-pipeline/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/loader.js b/cocos2d/core/load-pipeline/loader.js index 20c039d0048..b40e59f9c9b 100644 --- a/cocos2d/core/load-pipeline/loader.js +++ b/cocos2d/core/load-pipeline/loader.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/loading-items.js b/cocos2d/core/load-pipeline/loading-items.js index 89d83dfe3c6..e2a18516dd5 100644 --- a/cocos2d/core/load-pipeline/loading-items.js +++ b/cocos2d/core/load-pipeline/loading-items.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/md5-pipe.js b/cocos2d/core/load-pipeline/md5-pipe.js index cc538d02420..0b536a8ed7e 100644 --- a/cocos2d/core/load-pipeline/md5-pipe.js +++ b/cocos2d/core/load-pipeline/md5-pipe.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/pack-downloader.js b/cocos2d/core/load-pipeline/pack-downloader.js index 8305c76e9fd..2c88bace92e 100644 --- a/cocos2d/core/load-pipeline/pack-downloader.js +++ b/cocos2d/core/load-pipeline/pack-downloader.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/pipeline.js b/cocos2d/core/load-pipeline/pipeline.js index 1ee2df38524..7000355f437 100644 --- a/cocos2d/core/load-pipeline/pipeline.js +++ b/cocos2d/core/load-pipeline/pipeline.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/released-asset-checker.js b/cocos2d/core/load-pipeline/released-asset-checker.js index 6092847c278..195897084aa 100644 --- a/cocos2d/core/load-pipeline/released-asset-checker.js +++ b/cocos2d/core/load-pipeline/released-asset-checker.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/text-downloader.js b/cocos2d/core/load-pipeline/text-downloader.js index a64ca7f740f..88da0a3d586 100644 --- a/cocos2d/core/load-pipeline/text-downloader.js +++ b/cocos2d/core/load-pipeline/text-downloader.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/unpackers.js b/cocos2d/core/load-pipeline/unpackers.js index 77913d55fbe..b0b7dcc88ea 100644 --- a/cocos2d/core/load-pipeline/unpackers.js +++ b/cocos2d/core/load-pipeline/unpackers.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/utils.js b/cocos2d/core/load-pipeline/utils.js index 0821ff47523..629a3b9728c 100644 --- a/cocos2d/core/load-pipeline/utils.js +++ b/cocos2d/core/load-pipeline/utils.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/load-pipeline/uuid-loader.js b/cocos2d/core/load-pipeline/uuid-loader.js index 153bb196c2e..df7b7f2186c 100644 --- a/cocos2d/core/load-pipeline/uuid-loader.js +++ b/cocos2d/core/load-pipeline/uuid-loader.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/node-activator.js b/cocos2d/core/node-activator.js index 992f3fdfb5b..43bd79ac170 100644 --- a/cocos2d/core/node-activator.js +++ b/cocos2d/core/node-activator.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/CCPhysicsContact.js b/cocos2d/core/physics/CCPhysicsContact.js index a1aaf593772..48fcf7e8844 100644 --- a/cocos2d/core/physics/CCPhysicsContact.js +++ b/cocos2d/core/physics/CCPhysicsContact.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/CCPhysicsManager.js b/cocos2d/core/physics/CCPhysicsManager.js index e13ff732ffa..dc8163a0a1f 100644 --- a/cocos2d/core/physics/CCPhysicsManager.js +++ b/cocos2d/core/physics/CCPhysicsManager.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/CCPhysicsTypes.js b/cocos2d/core/physics/CCPhysicsTypes.js index 0090e997074..2e5592af59a 100644 --- a/cocos2d/core/physics/CCPhysicsTypes.js +++ b/cocos2d/core/physics/CCPhysicsTypes.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/CCPolygonSeparator.js b/cocos2d/core/physics/CCPolygonSeparator.js index 4b5aae73454..036f7c8de9d 100644 --- a/cocos2d/core/physics/CCPolygonSeparator.js +++ b/cocos2d/core/physics/CCPolygonSeparator.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/CCRigidBody.js b/cocos2d/core/physics/CCRigidBody.js index da71792b99e..e721800a947 100644 --- a/cocos2d/core/physics/CCRigidBody.js +++ b/cocos2d/core/physics/CCRigidBody.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/collider/CCPhysicsBoxCollider.js b/cocos2d/core/physics/collider/CCPhysicsBoxCollider.js index 6cadd5a5481..5d6e01134c8 100644 --- a/cocos2d/core/physics/collider/CCPhysicsBoxCollider.js +++ b/cocos2d/core/physics/collider/CCPhysicsBoxCollider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/collider/CCPhysicsChainCollider.js b/cocos2d/core/physics/collider/CCPhysicsChainCollider.js index 52dfd2dfbab..ee83b1ccfd4 100644 --- a/cocos2d/core/physics/collider/CCPhysicsChainCollider.js +++ b/cocos2d/core/physics/collider/CCPhysicsChainCollider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/collider/CCPhysicsCircleCollider.js b/cocos2d/core/physics/collider/CCPhysicsCircleCollider.js index bc064a3a8e9..c59410321a3 100644 --- a/cocos2d/core/physics/collider/CCPhysicsCircleCollider.js +++ b/cocos2d/core/physics/collider/CCPhysicsCircleCollider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/collider/CCPhysicsCollider.js b/cocos2d/core/physics/collider/CCPhysicsCollider.js index 956967d2aaa..03a5e7a311e 100644 --- a/cocos2d/core/physics/collider/CCPhysicsCollider.js +++ b/cocos2d/core/physics/collider/CCPhysicsCollider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/collider/CCPhysicsPolygonCollider.js b/cocos2d/core/physics/collider/CCPhysicsPolygonCollider.js index dd1dc31809d..ebe0681a147 100644 --- a/cocos2d/core/physics/collider/CCPhysicsPolygonCollider.js +++ b/cocos2d/core/physics/collider/CCPhysicsPolygonCollider.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/index.js b/cocos2d/core/physics/index.js index dcaf6a1949f..fc556874671 100644 --- a/cocos2d/core/physics/index.js +++ b/cocos2d/core/physics/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/joint/CCDistanceJoint.js b/cocos2d/core/physics/joint/CCDistanceJoint.js index 5c2cc0a2b97..360816a313d 100644 --- a/cocos2d/core/physics/joint/CCDistanceJoint.js +++ b/cocos2d/core/physics/joint/CCDistanceJoint.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/joint/CCJoint.js b/cocos2d/core/physics/joint/CCJoint.js index e4f0e5521bf..96e3eed5fc8 100644 --- a/cocos2d/core/physics/joint/CCJoint.js +++ b/cocos2d/core/physics/joint/CCJoint.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/joint/CCMotorJoint.js b/cocos2d/core/physics/joint/CCMotorJoint.js index 58ab320a1f8..c2a2afc7b4e 100644 --- a/cocos2d/core/physics/joint/CCMotorJoint.js +++ b/cocos2d/core/physics/joint/CCMotorJoint.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/joint/CCMouseJoint.js b/cocos2d/core/physics/joint/CCMouseJoint.js index d6c80698907..b75bf91434c 100644 --- a/cocos2d/core/physics/joint/CCMouseJoint.js +++ b/cocos2d/core/physics/joint/CCMouseJoint.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/joint/CCPrismaticJoint.js b/cocos2d/core/physics/joint/CCPrismaticJoint.js index 0fe4867c517..46f199eaddd 100644 --- a/cocos2d/core/physics/joint/CCPrismaticJoint.js +++ b/cocos2d/core/physics/joint/CCPrismaticJoint.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/joint/CCRevoluteJoint.js b/cocos2d/core/physics/joint/CCRevoluteJoint.js index 61d3aca3ffa..4e4757ff65a 100644 --- a/cocos2d/core/physics/joint/CCRevoluteJoint.js +++ b/cocos2d/core/physics/joint/CCRevoluteJoint.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/joint/CCRopeJoint.js b/cocos2d/core/physics/joint/CCRopeJoint.js index e61c6ba4245..8c6a0c00a83 100644 --- a/cocos2d/core/physics/joint/CCRopeJoint.js +++ b/cocos2d/core/physics/joint/CCRopeJoint.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/joint/CCWeldJoint.js b/cocos2d/core/physics/joint/CCWeldJoint.js index 64357a31405..3f1fab8f174 100644 --- a/cocos2d/core/physics/joint/CCWeldJoint.js +++ b/cocos2d/core/physics/joint/CCWeldJoint.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/joint/CCWheelJoint.js b/cocos2d/core/physics/joint/CCWheelJoint.js index 203a1710e67..e22ce8a5cc6 100644 --- a/cocos2d/core/physics/joint/CCWheelJoint.js +++ b/cocos2d/core/physics/joint/CCWheelJoint.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/platform/CCPhysicsAABBQueryCallback.js b/cocos2d/core/physics/platform/CCPhysicsAABBQueryCallback.js index d922e7c7534..e2ff080ad6f 100644 --- a/cocos2d/core/physics/platform/CCPhysicsAABBQueryCallback.js +++ b/cocos2d/core/physics/platform/CCPhysicsAABBQueryCallback.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/platform/CCPhysicsContactListner.js b/cocos2d/core/physics/platform/CCPhysicsContactListner.js index efbb13ed759..aef770cc183 100644 --- a/cocos2d/core/physics/platform/CCPhysicsContactListner.js +++ b/cocos2d/core/physics/platform/CCPhysicsContactListner.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/platform/CCPhysicsDebugDraw.js b/cocos2d/core/physics/platform/CCPhysicsDebugDraw.js index 19bf79397b0..9ca184c68c7 100644 --- a/cocos2d/core/physics/platform/CCPhysicsDebugDraw.js +++ b/cocos2d/core/physics/platform/CCPhysicsDebugDraw.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/platform/CCPhysicsRayCastCallback.js b/cocos2d/core/physics/platform/CCPhysicsRayCastCallback.js index 05581e4e95d..cbda32ac9bd 100644 --- a/cocos2d/core/physics/platform/CCPhysicsRayCastCallback.js +++ b/cocos2d/core/physics/platform/CCPhysicsRayCastCallback.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/physics/utils.js b/cocos2d/core/physics/utils.js index 70316c1ef96..0d69ee9aa60 100644 --- a/cocos2d/core/physics/utils.js +++ b/cocos2d/core/physics/utils.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/BKInputManager.js b/cocos2d/core/platform/BKInputManager.js index d1c93ea41f2..295bc3503be 100644 --- a/cocos2d/core/platform/BKInputManager.js +++ b/cocos2d/core/platform/BKInputManager.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/CCAssetLibrary.js b/cocos2d/core/platform/CCAssetLibrary.js index 9d5776b28d0..dcd816203a7 100644 --- a/cocos2d/core/platform/CCAssetLibrary.js +++ b/cocos2d/core/platform/CCAssetLibrary.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/CCClass.js b/cocos2d/core/platform/CCClass.js index a03cc9775bb..a138d2f84b9 100644 --- a/cocos2d/core/platform/CCClass.js +++ b/cocos2d/core/platform/CCClass.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/CCClassDecorator.js b/cocos2d/core/platform/CCClassDecorator.js index 14aaf61e575..5f6d962ae0c 100644 --- a/cocos2d/core/platform/CCClassDecorator.js +++ b/cocos2d/core/platform/CCClassDecorator.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/CCEnum.js b/cocos2d/core/platform/CCEnum.js index 6e722f81374..5fbc6c9180e 100644 --- a/cocos2d/core/platform/CCEnum.js +++ b/cocos2d/core/platform/CCEnum.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/CCObject.js b/cocos2d/core/platform/CCObject.js index 37eb6dddbcf..a106c15b9b0 100644 --- a/cocos2d/core/platform/CCObject.js +++ b/cocos2d/core/platform/CCObject.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index d67c1ca13ed..753798edf1e 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/attribute.js b/cocos2d/core/platform/attribute.js index f60548fad00..f7f4800e030 100644 --- a/cocos2d/core/platform/attribute.js +++ b/cocos2d/core/platform/attribute.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/callbacks-invoker.js b/cocos2d/core/platform/callbacks-invoker.js index 72d38d73b3b..0f3ccd5ebfe 100644 --- a/cocos2d/core/platform/callbacks-invoker.js +++ b/cocos2d/core/platform/callbacks-invoker.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/compiler.js b/cocos2d/core/platform/compiler.js index f6672674206..c1463e1bd19 100644 --- a/cocos2d/core/platform/compiler.js +++ b/cocos2d/core/platform/compiler.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/deserialize.js b/cocos2d/core/platform/deserialize.js index 1223b531cb4..a3f90a403b1 100644 --- a/cocos2d/core/platform/deserialize.js +++ b/cocos2d/core/platform/deserialize.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/id-generater.js b/cocos2d/core/platform/id-generater.js index 4a7ae2f4994..c08a3c01f93 100644 --- a/cocos2d/core/platform/id-generater.js +++ b/cocos2d/core/platform/id-generater.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/index.js b/cocos2d/core/platform/index.js index 7c9d7d93680..99c70005567 100644 --- a/cocos2d/core/platform/index.js +++ b/cocos2d/core/platform/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/instantiate-jit.js b/cocos2d/core/platform/instantiate-jit.js index e4cf8baa927..06277f993b7 100644 --- a/cocos2d/core/platform/instantiate-jit.js +++ b/cocos2d/core/platform/instantiate-jit.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/instantiate.js b/cocos2d/core/platform/instantiate.js index 61681c5fb58..5fbe719c262 100644 --- a/cocos2d/core/platform/instantiate.js +++ b/cocos2d/core/platform/instantiate.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/preprocess-class.js b/cocos2d/core/platform/preprocess-class.js index 89778c4b843..16caa3039eb 100644 --- a/cocos2d/core/platform/preprocess-class.js +++ b/cocos2d/core/platform/preprocess-class.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/requiring-frame.js b/cocos2d/core/platform/requiring-frame.js index 2dadbe13028..2de65ca1c35 100644 --- a/cocos2d/core/platform/requiring-frame.js +++ b/cocos2d/core/platform/requiring-frame.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/url.js b/cocos2d/core/platform/url.js index 9cf37a3abe4..8451781da4e 100644 --- a/cocos2d/core/platform/url.js +++ b/cocos2d/core/platform/url.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/platform/utils.js b/cocos2d/core/platform/utils.js index 46312b0277c..752821e8b13 100644 --- a/cocos2d/core/platform/utils.js +++ b/cocos2d/core/platform/utils.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/predefine.js b/cocos2d/core/predefine.js index e58d98d930b..c552446de71 100644 --- a/cocos2d/core/predefine.js +++ b/cocos2d/core/predefine.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/canvas-render-walker.js b/cocos2d/core/renderer/canvas/canvas-render-walker.js index 42f7b7b9550..9906b1de5d2 100644 --- a/cocos2d/core/renderer/canvas/canvas-render-walker.js +++ b/cocos2d/core/renderer/canvas/canvas-render-walker.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/forward-renderer.js b/cocos2d/core/renderer/canvas/forward-renderer.js index 64c4a149d09..f5e18812270 100644 --- a/cocos2d/core/renderer/canvas/forward-renderer.js +++ b/cocos2d/core/renderer/canvas/forward-renderer.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/index.js b/cocos2d/core/renderer/canvas/index.js index a89c2fcbb00..ee89ef484ba 100644 --- a/cocos2d/core/renderer/canvas/index.js +++ b/cocos2d/core/renderer/canvas/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/graphics/impl.js b/cocos2d/core/renderer/canvas/renderers/graphics/impl.js index 92092057f25..1889656c142 100644 --- a/cocos2d/core/renderer/canvas/renderers/graphics/impl.js +++ b/cocos2d/core/renderer/canvas/renderers/graphics/impl.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/graphics/index.js b/cocos2d/core/renderer/canvas/renderers/graphics/index.js index ac8c5612c24..dc6ea51ba09 100644 --- a/cocos2d/core/renderer/canvas/renderers/graphics/index.js +++ b/cocos2d/core/renderer/canvas/renderers/graphics/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/index.js b/cocos2d/core/renderer/canvas/renderers/index.js index 2e10cbe8b21..89f465ba02d 100644 --- a/cocos2d/core/renderer/canvas/renderers/index.js +++ b/cocos2d/core/renderer/canvas/renderers/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js index 35080ebfd19..301a950090e 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js +++ b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/label/index.js b/cocos2d/core/renderer/canvas/renderers/label/index.js index bd98ca59970..58dd876686a 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/index.js +++ b/cocos2d/core/renderer/canvas/renderers/label/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/label/ttf.js b/cocos2d/core/renderer/canvas/renderers/label/ttf.js index 08094b71840..74067e53cb2 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/ttf.js +++ b/cocos2d/core/renderer/canvas/renderers/label/ttf.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/mask.js b/cocos2d/core/renderer/canvas/renderers/mask.js index ccb82cc9bc5..79df2bdde59 100644 --- a/cocos2d/core/renderer/canvas/renderers/mask.js +++ b/cocos2d/core/renderer/canvas/renderers/mask.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/index.js b/cocos2d/core/renderer/canvas/renderers/sprite/index.js index 0e7b137e63a..4ffa73820f7 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/index.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/simple.js b/cocos2d/core/renderer/canvas/renderers/sprite/simple.js index 18031b3b52c..a8f540f69b7 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/simple.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/simple.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js b/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js index f4c766f5bf5..c65dfe90713 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/tiled.js b/cocos2d/core/renderer/canvas/renderers/sprite/tiled.js index 20c9d9e62a7..9138ecb6182 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/tiled.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/tiled.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/canvas/renderers/utils.js b/cocos2d/core/renderer/canvas/renderers/utils.js index e42558ce5cb..202add731da 100644 --- a/cocos2d/core/renderer/canvas/renderers/utils.js +++ b/cocos2d/core/renderer/canvas/renderers/utils.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 314e0d3f825..a0ccc9c12a7 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js index e13bca3552f..7cac7c404e2 100644 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ b/cocos2d/core/renderer/render-engine.canvas.js @@ -3,7 +3,7 @@ Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. render-engine v1.2.0 - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 5cde5e1ff02..91369a6ac6f 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -3,7 +3,7 @@ Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. render-engine v1.2.0 - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 5fc7a5a1970..8368e2baee8 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -3,7 +3,7 @@ Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. render-engine v1.2.0 - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/utils/label/bmfont.js b/cocos2d/core/renderer/utils/label/bmfont.js index e05fad174de..4c3002add62 100644 --- a/cocos2d/core/renderer/utils/label/bmfont.js +++ b/cocos2d/core/renderer/utils/label/bmfont.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 1c4e9b56119..f4913f5202a 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/assembler.js b/cocos2d/core/renderer/webgl/assemblers/assembler.js index b9096953f69..5d3942e6812 100644 --- a/cocos2d/core/renderer/webgl/assemblers/assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/assembler.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/earcut.js b/cocos2d/core/renderer/webgl/assemblers/graphics/earcut.js index 0d445172ada..dbe5610a025 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/earcut.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/earcut.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/index.js b/cocos2d/core/renderer/webgl/assemblers/graphics/index.js index 2d38456598b..e80968dff0d 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/index.js b/cocos2d/core/renderer/webgl/assemblers/index.js index 65a9b28071f..0031335b9dc 100644 --- a/cocos2d/core/renderer/webgl/assemblers/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js index c4b985ee3ca..9b405cc4443 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/label/index.js b/cocos2d/core/renderer/webgl/assemblers/label/index.js index fe44c9af4d9..7bac03a3f00 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index 0d980acdc10..5a4373ceb3a 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js index b54e1fbe972..204cef1b00f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index f3bade69cd3..dad464aedfb 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index 474fe243802..a24131a5d4e 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/index.js b/cocos2d/core/renderer/webgl/assemblers/sprite/index.js index c59947b09c4..ea4ddb592d3 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js index e8f024b84bf..3d50d10afa7 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js index 3dca7ed1efa..cd7969dba61 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js index d684b2c0218..e6722a738eb 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js index 3279497dabd..06da24db920 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js index 9e60ca17d47..97ed6a64b18 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/render-component-walker.js index 539c2fe2dbe..db1971688c3 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/render-component-walker.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/stencil-manager.js b/cocos2d/core/renderer/webgl/stencil-manager.js index 030fe68eedd..284e65da551 100644 --- a/cocos2d/core/renderer/webgl/stencil-manager.js +++ b/cocos2d/core/renderer/webgl/stencil-manager.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/renderer/webgl/vertex-format.js b/cocos2d/core/renderer/webgl/vertex-format.js index 9947922a808..94351122408 100644 --- a/cocos2d/core/renderer/webgl/vertex-format.js +++ b/cocos2d/core/renderer/webgl/vertex-format.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/CCPath.js b/cocos2d/core/utils/CCPath.js index d0089bfe45c..56d032baa40 100644 --- a/cocos2d/core/utils/CCPath.js +++ b/cocos2d/core/utils/CCPath.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/base-node.js b/cocos2d/core/utils/base-node.js index 6cf92d337fb..fbf69401575 100644 --- a/cocos2d/core/utils/base-node.js +++ b/cocos2d/core/utils/base-node.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/binary-search.js b/cocos2d/core/utils/binary-search.js index fa5b4a847a8..02d1ceb552c 100644 --- a/cocos2d/core/utils/binary-search.js +++ b/cocos2d/core/utils/binary-search.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/decode-uuid.js b/cocos2d/core/utils/decode-uuid.js index 13e96baceaf..3af97efc9fa 100644 --- a/cocos2d/core/utils/decode-uuid.js +++ b/cocos2d/core/utils/decode-uuid.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/find.js b/cocos2d/core/utils/find.js index ea42a19c2fc..58c03290ad1 100644 --- a/cocos2d/core/utils/find.js +++ b/cocos2d/core/utils/find.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/html-text-parser.js b/cocos2d/core/utils/html-text-parser.js index 6cdce9ec8f5..b1e7fc7611d 100644 --- a/cocos2d/core/utils/html-text-parser.js +++ b/cocos2d/core/utils/html-text-parser.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/index.js b/cocos2d/core/utils/index.js index e97dc29341b..892b80d5cfc 100644 --- a/cocos2d/core/utils/index.js +++ b/cocos2d/core/utils/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/math-pools.js b/cocos2d/core/utils/math-pools.js index 23697c4d4ce..a65a2d0d851 100644 --- a/cocos2d/core/utils/math-pools.js +++ b/cocos2d/core/utils/math-pools.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/misc.js b/cocos2d/core/utils/misc.js index ea5e4fef247..f0fd427f704 100644 --- a/cocos2d/core/utils/misc.js +++ b/cocos2d/core/utils/misc.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/mutable-forward-iterator.js b/cocos2d/core/utils/mutable-forward-iterator.js index 6581ee9969a..876af049a51 100644 --- a/cocos2d/core/utils/mutable-forward-iterator.js +++ b/cocos2d/core/utils/mutable-forward-iterator.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/polyfill-3d.js b/cocos2d/core/utils/polyfill-3d.js index 7263669444d..9bca6b3171e 100644 --- a/cocos2d/core/utils/polyfill-3d.js +++ b/cocos2d/core/utils/polyfill-3d.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/prefab-helper.js b/cocos2d/core/utils/prefab-helper.js index 65c587bcffd..075e2e23365 100644 --- a/cocos2d/core/utils/prefab-helper.js +++ b/cocos2d/core/utils/prefab-helper.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/profiler/CCProfiler.js b/cocos2d/core/utils/profiler/CCProfiler.js index 01701a64abd..646c8b474c0 100644 --- a/cocos2d/core/utils/profiler/CCProfiler.js +++ b/cocos2d/core/utils/profiler/CCProfiler.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/text-utils.js b/cocos2d/core/utils/text-utils.js index 6714142a8f1..0ea9cd7c90b 100644 --- a/cocos2d/core/utils/text-utils.js +++ b/cocos2d/core/utils/text-utils.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/utils/texture-util.js b/cocos2d/core/utils/texture-util.js index a5bd5916cac..b46b35aa577 100644 --- a/cocos2d/core/utils/texture-util.js +++ b/cocos2d/core/utils/texture-util.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/value-types/color.js b/cocos2d/core/value-types/color.js index 5375baf18e1..f521c7654da 100644 --- a/cocos2d/core/value-types/color.js +++ b/cocos2d/core/value-types/color.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/value-types/index.js b/cocos2d/core/value-types/index.js index 4e44fac8c0f..59bc6c739be 100644 --- a/cocos2d/core/value-types/index.js +++ b/cocos2d/core/value-types/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/value-types/mat4.js b/cocos2d/core/value-types/mat4.js index b4521ef701c..7dcf7f7c601 100644 --- a/cocos2d/core/value-types/mat4.js +++ b/cocos2d/core/value-types/mat4.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/value-types/quat.js b/cocos2d/core/value-types/quat.js index d8dc6c9f857..5974d7c517d 100644 --- a/cocos2d/core/value-types/quat.js +++ b/cocos2d/core/value-types/quat.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/value-types/rect.js b/cocos2d/core/value-types/rect.js index 67335155b48..bce9f33d93e 100644 --- a/cocos2d/core/value-types/rect.js +++ b/cocos2d/core/value-types/rect.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/value-types/size.js b/cocos2d/core/value-types/size.js index 55de763f09c..c0687a084da 100644 --- a/cocos2d/core/value-types/size.js +++ b/cocos2d/core/value-types/size.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/value-types/value-type.js b/cocos2d/core/value-types/value-type.js index 3c24c351bf8..6acc3c17aba 100644 --- a/cocos2d/core/value-types/value-type.js +++ b/cocos2d/core/value-types/value-type.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/value-types/vec2.js b/cocos2d/core/value-types/vec2.js index 4a9c646e028..8ba14000d14 100644 --- a/cocos2d/core/value-types/vec2.js +++ b/cocos2d/core/value-types/vec2.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/core/value-types/vec3.js b/cocos2d/core/value-types/vec3.js index ee3d7d6b5a7..4bbf3e7694e 100644 --- a/cocos2d/core/value-types/vec3.js +++ b/cocos2d/core/value-types/vec3.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/deprecated.js b/cocos2d/deprecated.js index 60680344dc5..b78ac4bd48d 100644 --- a/cocos2d/deprecated.js +++ b/cocos2d/deprecated.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/index.js b/cocos2d/index.js index 2f501b7e8c4..ef792451def 100644 --- a/cocos2d/index.js +++ b/cocos2d/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/particle/CCParticleAsset.js b/cocos2d/particle/CCParticleAsset.js index 5c8f1f6ca88..0731d96886a 100644 --- a/cocos2d/particle/CCParticleAsset.js +++ b/cocos2d/particle/CCParticleAsset.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 65796252861..934a1ae7dd4 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/particle/CCTIFFReader.js b/cocos2d/particle/CCTIFFReader.js index a7549d8ff6c..eca985447d6 100644 --- a/cocos2d/particle/CCTIFFReader.js +++ b/cocos2d/particle/CCTIFFReader.js @@ -7,7 +7,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/particle/index.js b/cocos2d/particle/index.js index e61ccb4a3da..9ff83f7d8ef 100644 --- a/cocos2d/particle/index.js +++ b/cocos2d/particle/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/particle/particle-simulator.js b/cocos2d/particle/particle-simulator.js index 88cee5367ac..bc11bf39041 100644 --- a/cocos2d/particle/particle-simulator.js +++ b/cocos2d/particle/particle-simulator.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/particle/particle-system-assembler.js b/cocos2d/particle/particle-system-assembler.js index 37ab738fe45..d99be29df89 100644 --- a/cocos2d/particle/particle-system-assembler.js +++ b/cocos2d/particle/particle-system-assembler.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Chukong Technologies Inc. - http://www.cocos.com + 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, diff --git a/cocos2d/tilemap/CCTiledLayer.js b/cocos2d/tilemap/CCTiledLayer.js index eade0be1b7b..23da490a0c1 100644 --- a/cocos2d/tilemap/CCTiledLayer.js +++ b/cocos2d/tilemap/CCTiledLayer.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/tilemap/CCTiledMap.js b/cocos2d/tilemap/CCTiledMap.js index af8794d87b2..f63feab7bcc 100644 --- a/cocos2d/tilemap/CCTiledMap.js +++ b/cocos2d/tilemap/CCTiledMap.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/tilemap/CCTiledMapAsset.js b/cocos2d/tilemap/CCTiledMapAsset.js index a9213a1d2fe..230415360d2 100644 --- a/cocos2d/tilemap/CCTiledMapAsset.js +++ b/cocos2d/tilemap/CCTiledMapAsset.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/tilemap/CCTiledObjectGroup.js b/cocos2d/tilemap/CCTiledObjectGroup.js index bf472342c3c..cf88f783452 100644 --- a/cocos2d/tilemap/CCTiledObjectGroup.js +++ b/cocos2d/tilemap/CCTiledObjectGroup.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/tilemap/CCTiledTile.js b/cocos2d/tilemap/CCTiledTile.js index 344951aa5e2..537f51b7c3c 100644 --- a/cocos2d/tilemap/CCTiledTile.js +++ b/cocos2d/tilemap/CCTiledTile.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/tilemap/editor/tiled-map.js b/cocos2d/tilemap/editor/tiled-map.js index e918157bc02..741829bb849 100644 --- a/cocos2d/tilemap/editor/tiled-map.js +++ b/cocos2d/tilemap/editor/tiled-map.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/tilemap/index.js b/cocos2d/tilemap/index.js index cc3fc3d38cb..0eacab617c3 100644 --- a/cocos2d/tilemap/index.js +++ b/cocos2d/tilemap/index.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/tilemap/tmx-layer-assembler.js b/cocos2d/tilemap/tmx-layer-assembler.js index dde3eb961af..4800b8ece5a 100644 --- a/cocos2d/tilemap/tmx-layer-assembler.js +++ b/cocos2d/tilemap/tmx-layer-assembler.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/videoplayer/CCVideoPlayer.js b/cocos2d/videoplayer/CCVideoPlayer.js index 65cf28bd854..99ca1ad2370 100644 --- a/cocos2d/videoplayer/CCVideoPlayer.js +++ b/cocos2d/videoplayer/CCVideoPlayer.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 1c8fa67519a..76e093387ed 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/webview/CCWebView.js b/cocos2d/webview/CCWebView.js index b475ed6e51b..19b6dedf0ce 100644 --- a/cocos2d/webview/CCWebView.js +++ b/cocos2d/webview/CCWebView.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/cocos2d/webview/webview-impl.js b/cocos2d/webview/webview-impl.js index daaedb1d2e9..8516caecf09 100644 --- a/cocos2d/webview/webview-impl.js +++ b/cocos2d/webview/webview-impl.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 1255f501d67..b8650f64d6f 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -1,32 +1,32 @@ module.exports = { 'COMPONENT': { "help_url": { - "audiosource": "http://docs.cocos.com/creator/manual/en/components/audiosource.html", - "animation": "http://docs.cocos.com/creator/manual/en/components/animation.html", - "sprite": "http://docs.cocos.com/creator/manual/en/components/sprite.html", - "label": "http://docs.cocos.com/creator/manual/en/components/label.html", - "canvas": "http://docs.cocos.com/creator/manual/en/components/canvas.html", - "spine": "http://docs.cocos.com/creator/manual/en/components/spine.html", - "widget": "http://docs.cocos.com/creator/manual/en/components/widget.html", - "button": "http://docs.cocos.com/creator/manual/en/components/button.html", - "progressbar": "http://docs.cocos.com/creator/manual/en/components/progress.html", - "mask": "http://docs.cocos.com/creator/manual/en/components/mask.html", - "scrollview": "http://docs.cocos.com/creator/manual/en/components/scrollview.html", - "scrollbar": "http://docs.cocos.com/creator/manual/en/components/scrollbar.html", - "layout": "http://docs.cocos.com/creator/manual/en/components/layout.html", - "tiledmap": "http://docs.cocos.com/creator/manual/en/components/tiledmap.html", - "editbox": "http://docs.cocos.com/creator/manual/en/components/editbox.html", - "videoplayer": "http://docs.cocos.com/creator/manual/en/components/videoplayer.html", - "motionStreak": "http://docs.cocos.com/creator/manual/en/components/motion-streak.html", - "richtext": "http://docs.cocos.com/creator/manual/en/components/richtext.html", - "pageview": "http://docs.cocos.com/creator/manual/en/components/pageview.html", - "pageviewIndicator": "http://docs.cocos.com/creator/manual/en/components/pageviewindicator.html", - "toggle": "http://docs.cocos.com/creator/manual/en/components/toggle.html", - "toggleGroup": "http://docs.cocos.com/creator/manual/en/components/toggleGroup.html", - "toggleContainer": "http://docs.cocos.com/creator/manual/en/components/toggleContainer.html", - "slider": "http://docs.cocos.com/creator/manual/en/components/slider.html", - "block_input_events": "http://docs.cocos.com/creator/manual/en/components/block-input-events.html", - "wx_subcontext_view": "http://docs.cocos.com/creator/manual/en/publish/publish-wechatgame-sub-domain.html" + "audiosource": "https://docs.cocos.com/creator/manual/en/components/audiosource.html", + "animation": "https://docs.cocos.com/creator/manual/en/components/animation.html", + "sprite": "https://docs.cocos.com/creator/manual/en/components/sprite.html", + "label": "https://docs.cocos.com/creator/manual/en/components/label.html", + "canvas": "https://docs.cocos.com/creator/manual/en/components/canvas.html", + "spine": "https://docs.cocos.com/creator/manual/en/components/spine.html", + "widget": "https://docs.cocos.com/creator/manual/en/components/widget.html", + "button": "https://docs.cocos.com/creator/manual/en/components/button.html", + "progressbar": "https://docs.cocos.com/creator/manual/en/components/progress.html", + "mask": "https://docs.cocos.com/creator/manual/en/components/mask.html", + "scrollview": "https://docs.cocos.com/creator/manual/en/components/scrollview.html", + "scrollbar": "https://docs.cocos.com/creator/manual/en/components/scrollbar.html", + "layout": "https://docs.cocos.com/creator/manual/en/components/layout.html", + "tiledmap": "https://docs.cocos.com/creator/manual/en/components/tiledmap.html", + "editbox": "https://docs.cocos.com/creator/manual/en/components/editbox.html", + "videoplayer": "https://docs.cocos.com/creator/manual/en/components/videoplayer.html", + "motionStreak": "https://docs.cocos.com/creator/manual/en/components/motion-streak.html", + "richtext": "https://docs.cocos.com/creator/manual/en/components/richtext.html", + "pageview": "https://docs.cocos.com/creator/manual/en/components/pageview.html", + "pageviewIndicator": "https://docs.cocos.com/creator/manual/en/components/pageviewindicator.html", + "toggle": "https://docs.cocos.com/creator/manual/en/components/toggle.html", + "toggleGroup": "https://docs.cocos.com/creator/manual/en/components/toggleGroup.html", + "toggleContainer": "https://docs.cocos.com/creator/manual/en/components/toggleContainer.html", + "slider": "https://docs.cocos.com/creator/manual/en/components/slider.html", + "block_input_events": "https://docs.cocos.com/creator/manual/en/components/block-input-events.html", + "wx_subcontext_view": "https://docs.cocos.com/creator/manual/en/publish/publish-wechatgame-sub-domain.html" }, "animation": { "default_clip": "When checking, the deault animation clip is automatically played.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 9c13333c3d5..7bc3d4825ed 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -1,32 +1,32 @@ module.exports = { 'COMPONENT': { "help_url": { - "audiosource": "http://docs.cocos.com/creator/manual/zh/components/audiosource.html", - "animation": "http://docs.cocos.com/creator/manual/zh/components/animation.html", - "sprite": "http://docs.cocos.com/creator/manual/zh/components/sprite.html", - "label": "http://docs.cocos.com/creator/manual/zh/components/label.html", - "canvas": "http://docs.cocos.com/creator/manual/zh/components/canvas.html", - "spine": "http://docs.cocos.com/creator/manual/zh/components/spine.html", - "widget": "http://docs.cocos.com/creator/manual/zh/components/widget.html", - "button": "http://docs.cocos.com/creator/manual/zh/components/button.html", - "progressbar": "http://docs.cocos.com/creator/manual/zh/components/progress.html", - "mask": "http://docs.cocos.com/creator/manual/zh/components/mask.html", - "scrollview": "http://docs.cocos.com/creator/manual/zh/components/scrollview.html", - "scrollbar": "http://docs.cocos.com/creator/manual/zh/components/scrollbar.html", - "layout": "http://docs.cocos.com/creator/manual/zh/components/layout.html", - "tiledmap": "http://docs.cocos.com/creator/manual/zh/components/tiledmap.html", - "editbox": "http://docs.cocos.com/creator/manual/zh/components/editbox.html", - "videoplayer": "http://docs.cocos.com/creator/manual/zh/components/videoplayer.html", - "motionStreak": "http://docs.cocos.com/creator/manual/zh/components/motion-streak.html", - "richtext": "http://docs.cocos.com/creator/manual/zh/components/richtext.html", - "pageview": "http://docs.cocos.com/creator/manual/zh/components/pageview.html", - "pageviewIndicator": "http://docs.cocos.com/creator/manual/zh/components/pageviewindicator.html", - "toggle": "http://docs.cocos.com/creator/manual/zh/components/toggle.html", - "toggleGroup": "http://docs.cocos.com/creator/manual/zh/components/toggleGroup.html", - "toggleContainer": "http://docs.cocos.com/creator/manual/zh/components/toggleContainer.html", - "slider": "http://docs.cocos.com/creator/manual/zh/components/slider.html", - "block_input_events": "http://docs.cocos.com/creator/manual/zh/components/block-input-events.html", - "wx_subcontext_view": "http://docs.cocos.com/creator/manual/zh/publish/publish-wechatgame-sub-domain.html" + "audiosource": "https://docs.cocos.com/creator/manual/zh/components/audiosource.html", + "animation": "https://docs.cocos.com/creator/manual/zh/components/animation.html", + "sprite": "https://docs.cocos.com/creator/manual/zh/components/sprite.html", + "label": "https://docs.cocos.com/creator/manual/zh/components/label.html", + "canvas": "https://docs.cocos.com/creator/manual/zh/components/canvas.html", + "spine": "https://docs.cocos.com/creator/manual/zh/components/spine.html", + "widget": "https://docs.cocos.com/creator/manual/zh/components/widget.html", + "button": "https://docs.cocos.com/creator/manual/zh/components/button.html", + "progressbar": "https://docs.cocos.com/creator/manual/zh/components/progress.html", + "mask": "https://docs.cocos.com/creator/manual/zh/components/mask.html", + "scrollview": "https://docs.cocos.com/creator/manual/zh/components/scrollview.html", + "scrollbar": "https://docs.cocos.com/creator/manual/zh/components/scrollbar.html", + "layout": "https://docs.cocos.com/creator/manual/zh/components/layout.html", + "tiledmap": "https://docs.cocos.com/creator/manual/zh/components/tiledmap.html", + "editbox": "https://docs.cocos.com/creator/manual/zh/components/editbox.html", + "videoplayer": "https://docs.cocos.com/creator/manual/zh/components/videoplayer.html", + "motionStreak": "https://docs.cocos.com/creator/manual/zh/components/motion-streak.html", + "richtext": "https://docs.cocos.com/creator/manual/zh/components/richtext.html", + "pageview": "https://docs.cocos.com/creator/manual/zh/components/pageview.html", + "pageviewIndicator": "https://docs.cocos.com/creator/manual/zh/components/pageviewindicator.html", + "toggle": "https://docs.cocos.com/creator/manual/zh/components/toggle.html", + "toggleGroup": "https://docs.cocos.com/creator/manual/zh/components/toggleGroup.html", + "toggleContainer": "https://docs.cocos.com/creator/manual/zh/components/toggleContainer.html", + "slider": "https://docs.cocos.com/creator/manual/zh/components/slider.html", + "block_input_events": "https://docs.cocos.com/creator/manual/zh/components/block-input-events.html", + "wx_subcontext_view": "https://docs.cocos.com/creator/manual/zh/publish/publish-wechatgame-sub-domain.html" }, 'animation': { 'default_clip': '在勾选自动播放或调用 play() 时默认播放的动画 clip。', diff --git a/extends.js b/extends.js index 01e76b0151a..136f0c79c03 100644 --- a/extends.js +++ b/extends.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/anysdk/jsb_anysdk.js b/extensions/anysdk/jsb_anysdk.js index a7c73880cc1..5f0cb6523a1 100644 --- a/extensions/anysdk/jsb_anysdk.js +++ b/extensions/anysdk/jsb_anysdk.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + https://www.cocos.com/ Permission is hereby granted, free of Stringge, to any person obtaining a copy of this software and associated engine source code (the "Software"), a limited, diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index fb7ae52a879..35e7a2b6e6e 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/dragonbones/DragonBonesAsset.js b/extensions/dragonbones/DragonBonesAsset.js index 7b4b49dd8ed..c98ee7e410e 100644 --- a/extensions/dragonbones/DragonBonesAsset.js +++ b/extensions/dragonbones/DragonBonesAsset.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/dragonbones/DragonBonesAtlasAsset.js b/extensions/dragonbones/DragonBonesAtlasAsset.js index 32e55d6a6b8..a3cbae4ac0e 100644 --- a/extensions/dragonbones/DragonBonesAtlasAsset.js +++ b/extensions/dragonbones/DragonBonesAtlasAsset.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/dragonbones/editor/dragonbones-atlas-meta.js b/extensions/dragonbones/editor/dragonbones-atlas-meta.js index abc1f818c94..92a33aa6d64 100644 --- a/extensions/dragonbones/editor/dragonbones-atlas-meta.js +++ b/extensions/dragonbones/editor/dragonbones-atlas-meta.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/dragonbones/editor/dragonbones-meta.js b/extensions/dragonbones/editor/dragonbones-meta.js index c7978521ffa..76460b25ad8 100644 --- a/extensions/dragonbones/editor/dragonbones-meta.js +++ b/extensions/dragonbones/editor/dragonbones-meta.js @@ -2,7 +2,7 @@ Copyright (c) 2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 9bbdc6d36b3..f07a0a0fce7 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 578c7c54c84..a50737be299 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/spine/editor/spine-meta.js b/extensions/spine/editor/spine-meta.js index 360d0708fa3..8cd4383ffb4 100644 --- a/extensions/spine/editor/spine-meta.js +++ b/extensions/spine/editor/spine-meta.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/spine/skeleton-data.js b/extensions/spine/skeleton-data.js index 818b9b448a6..657d434ec68 100644 --- a/extensions/spine/skeleton-data.js +++ b/extensions/spine/skeleton-data.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/spine/skeleton-texture.js b/extensions/spine/skeleton-texture.js index 6a31f54ff7c..5fe4e13ac19 100644 --- a/extensions/spine/skeleton-texture.js +++ b/extensions/spine/skeleton-texture.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index fb0de3b931e..44e4303de42 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/extensions/spine/track-entry-listeners.js b/extensions/spine/track-entry-listeners.js index 170acaeeb37..a5c46dc0cad 100644 --- a/extensions/spine/track-entry-listeners.js +++ b/extensions/spine/track-entry-listeners.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index df7bc6f179b..d7449919ceb 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2013-2016 Chukong Technologies Inc. - http://www.cocos.com + 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, diff --git a/gulp/tasks/test.js b/gulp/tasks/test.js index 168cb84eb24..af191b914e2 100644 --- a/gulp/tasks/test.js +++ b/gulp/tasks/test.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2013-2016 Chukong Technologies Inc. - http://www.cocos.com + 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, diff --git a/gulp/util/handleErrors.js b/gulp/util/handleErrors.js index 62531aab57b..e98c6fc9c9a 100644 --- a/gulp/util/handleErrors.js +++ b/gulp/util/handleErrors.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2013-2016 Chukong Technologies Inc. - http://www.cocos.com + 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, diff --git a/gulpfile.js b/gulpfile.js index e130bfcf727..dbd088bde9b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/index.js b/index.js index 754e97c4f1a..ba16a62b359 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/licenses/LICENSE b/licenses/LICENSE index 81021922714..f85cc85e502 100644 --- a/licenses/LICENSE +++ b/licenses/LICENSE @@ -2,7 +2,7 @@ Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, diff --git a/predefine.js b/predefine.js index c7963f0593d..dd0c9cdb484 100644 --- a/predefine.js +++ b/predefine.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - http://www.cocos.com + 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, From 1f5777edbcf21a2faa42df8e2bf9130836336102 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 25 Oct 2018 15:55:45 +0800 Subject: [PATCH 0108/1631] use object flag instead of showInEditor property (#3421) --- cocos2d/core/CCNode.js | 5 ----- cocos2d/core/CCPrivateNode.js | 4 ++++ cocos2d/core/platform/CCObject.js | 23 ++++++++++------------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 9d727d878c3..64dac7b384f 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1121,11 +1121,6 @@ let NodeDefines = { } } }, - - showInEditor: { - default: true, - editorOnly: true - } }, /** diff --git a/cocos2d/core/CCPrivateNode.js b/cocos2d/core/CCPrivateNode.js index 613e4ce2cef..06edadb9ad3 100644 --- a/cocos2d/core/CCPrivateNode.js +++ b/cocos2d/core/CCPrivateNode.js @@ -29,6 +29,7 @@ const Node = require('./CCNode'); const RenderFlow = require('./renderer/render-flow'); const math = require('./renderer/render-engine').math; +const HideInHierarchy = cc.Object.Flags.HideInHierarchy; const LocalDirtyFlag = Node._LocalDirtyFlag; const POSITION_ON = 1 << 0; @@ -112,6 +113,9 @@ let PrivateNode = cc.Class({ ctor (name) { this._localZOrder = cc.macro.MIN_ZINDEX << 16; this._originPos = cc.v2(); + if (CC_EDITOR) { + this._objFlags |= HideInHierarchy; + } }, _posDirty (sendEvent) { diff --git a/cocos2d/core/platform/CCObject.js b/cocos2d/core/platform/CCObject.js index 37eb6dddbcf..12b7ab6fe99 100644 --- a/cocos2d/core/platform/CCObject.js +++ b/cocos2d/core/platform/CCObject.js @@ -39,7 +39,7 @@ var Destroying = 1 << 7; var Deactivating = 1 << 8; var LockedInEditor = 1 << 9; //var HideInGame = 1 << 9; -//var HideInEditor = 1 << 10; +var HideInHierarchy = 1 << 10; var IsOnEnableCalled = 1 << 11; var IsEditorOnEnableCalled = 1 << 12; @@ -54,7 +54,7 @@ var IsAnchorLocked = 1 << 19; var IsSizeLocked = 1 << 20; var IsPositionLocked = 1 << 21; -//var Hide = HideInGame | HideInEditor; +//var Hide = HideInGame | HideInHierarchy; // should not clone or serialize these flags var PersistentMask = ~(ToDestroy | Dirty | Destroying | DontDestroy | Deactivating | IsPreloadStarted | IsOnLoadStarted | IsOnLoadCalled | IsStartCalled | @@ -115,7 +115,7 @@ js.value(CCObject, 'Flags', { /** * !#en Dont destroy automatically when loading a new scene. - * !#zh 加载一个新场景时,不自动删除该对象 + * !#zh 加载一个新场景时,不自动删除该对象。 * @property DontDestroy * @private */ @@ -137,7 +137,7 @@ js.value(CCObject, 'Flags', { /** * !#en The lock node, when the node is locked, cannot be clicked in the scene. - * !#zh 锁定节点,锁定后场景内不能点击 + * !#zh 锁定节点,锁定后场景内不能点击。 * * @property LockedInEditor * @private @@ -157,12 +157,12 @@ js.value(CCObject, 'Flags', { // FLAGS FOR EDITOR - ///** - // * !#en This flag is readonly, it can only be used as an argument of scene.addEntity() or Entity.createWithFlags(). - // * !#zh 该标记只读,它只能被用作 scene.addEntity()的一个参数。 - // * @property {Number} HideInEditor - // */ - //HideInEditor: HideInEditor, + /** + * !#en Hide the object in editor. + * !#zh 在编辑器中隐藏该对象。 + * @property {Number} HideInHierarchy + */ + HideInHierarchy: HideInHierarchy, ///** // * !#en @@ -175,9 +175,6 @@ js.value(CCObject, 'Flags', { // */ //Hide: Hide, - //// UUID Registered in editor - //RegisteredInEditor: RegisteredInEditor, - // FLAGS FOR COMPONENT IsPreloadStarted, From 8611d942ea83925b6acd7c75f235a3f9d72d9798 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Thu, 25 Oct 2018 17:31:40 +0800 Subject: [PATCH 0109/1631] fixed the setContent scrollView error (#3427) --- cocos2d/core/components/CCScrollView.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index 9737a2eac36..48041b6f7b0 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -207,7 +207,6 @@ let ScrollView = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.scrollview.content', formerlySerializedAs: 'content', notify (oldValue) { - this._initView(); this._calculateBoundary(); } }, From 663db9909292603b6c5ad8d17a393e1ebf44a572 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Thu, 25 Oct 2018 18:28:01 +0800 Subject: [PATCH 0110/1631] remove the scrollView undefined function quote (#3428) --- cocos2d/core/components/CCScrollView.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index 50b509ebd3b..0174d419946 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -207,7 +207,6 @@ let ScrollView = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.scrollview.content', formerlySerializedAs: 'content', notify (oldValue) { - this._initView(); this._calculateBoundary(); } }, From 7315255ddc980bf4a6256805d3b6a70a6d111a7f Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 26 Oct 2018 00:09:49 +0800 Subject: [PATCH 0111/1631] should not invoke component if destroy() called before node activating (#3430) --- cocos2d/core/node-activator.js | 8 ++++++++ test/qunit/unit-es5/test-component-scheduler.js | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/cocos2d/core/node-activator.js b/cocos2d/core/node-activator.js index 43bd79ac170..47afcaab5b8 100644 --- a/cocos2d/core/node-activator.js +++ b/cocos2d/core/node-activator.js @@ -247,6 +247,10 @@ var NodeActivator = cc.Class({ }, activateComp: CC_EDITOR ? function (comp, preloadInvoker, onLoadInvoker, onEnableInvoker) { + if (!cc.isValid(comp, true)) { + // destroied before activating + return; + } if (cc.engine._isPlaying || comp.constructor._executeInEditMode) { if (!(comp._objFlags & IsPreloadStarted)) { comp._objFlags |= IsPreloadStarted; @@ -283,6 +287,10 @@ var NodeActivator = cc.Class({ cc.director._compScheduler.enableComp(comp, onEnableInvoker); } } : function (comp, preloadInvoker, onLoadInvoker, onEnableInvoker) { + if (!cc.isValid(comp, true)) { + // destroied before activating + return; + } if (!(comp._objFlags & IsPreloadStarted)) { comp._objFlags |= IsPreloadStarted; if (comp.__preload) { diff --git a/test/qunit/unit-es5/test-component-scheduler.js b/test/qunit/unit-es5/test-component-scheduler.js index ba3099249cd..a1fab6658a6 100644 --- a/test/qunit/unit-es5/test-component-scheduler.js +++ b/test/qunit/unit-es5/test-component-scheduler.js @@ -544,6 +544,18 @@ test('set sibling index during onDisable', function () { compOfChild.onEnable.once('child component should be re-enabled'); }); + test('component might be destroied when destroy() called before node activating', function () { + var node = new cc.Node(); + var comp = createDisabledComp(node, 'destroied'); + comp.onDestroy = new Callback().disable('onDestroy should not be called'); + comp.destroy(); + + cc.director.getScene().addChild(node); + + cc.game.step(); + strictEqual(comp.isValid, false, 'component should be destroied'); + }); + // test('could deactivate parent in onLoad', function () { // strictEqual(StillInvokeRestCompsOnSameNode, false, 'test cases not implemented if "StillInvokeRestCompsOnSameNode"'); // strictEqual(StillInvokeOnEnableOnSameComp, false, 'test cases not implemented if "StillInvokeOnEnableOnSameComp"'); From df4e0e8e2661a230139a30d811cc627f13627f0e Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Fri, 26 Oct 2018 09:27:01 +0800 Subject: [PATCH 0112/1631] fixed the link lost (#3423) --- cocos2d/core/platform/CCClassDecorator.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/platform/CCClassDecorator.js b/cocos2d/core/platform/CCClassDecorator.js index 5f6d962ae0c..f0d6773af28 100644 --- a/cocos2d/core/platform/CCClassDecorator.js +++ b/cocos2d/core/platform/CCClassDecorator.js @@ -240,9 +240,9 @@ function genProperty (ctor, properties, propName, options, desc, cache) { /** * !#en * Declare the standard [ES6 Class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) - * as CCClass, please see [Class](/docs/editors_and_tools/creator-chapters/scripting/class/) for details. + * as CCClass, please see [Class](../../../manual/en/scripting/class.html) for details. * !#zh - * 将标准写法的 [ES6 Class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) 声明为 CCClass,具体用法请参阅[类型定义](/docs/creator/scripting/class/)。 + * 将标准写法的 [ES6 Class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) 声明为 CCClass,具体用法请参阅[类型定义](../../../manual/zh/scripting/class.html)。 * * @method ccclass * @param {String} [name] - The class name used for serialization. @@ -311,9 +311,9 @@ var ccclass = checkCtorArgument(function (ctor, name) { /** * !#en - * Declare property for [CCClass](/docs/editors_and_tools/creator-chapters/scripting/class/). + * Declare property for [CCClass](../../../manual/en/scripting/reference/attributes.html). * !#zh - * 定义 [CCClass](/docs/creator/scripting/class/) 所用的属性。 + * 定义 [CCClass](../../../manual/zh/scripting/reference/attributes.html) 所用的属性。 * * @method property * @param {Object} [options] - an object with some property attributes From 445cd607a7996f850d0a6c21bd879e616663d2fb Mon Sep 17 00:00:00 2001 From: Knox Date: Sun, 28 Oct 2018 10:01:37 +0800 Subject: [PATCH 0113/1631] fix set isChecked value invaild bug (#3434) --- cocos2d/core/components/CCToggle.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCToggle.js b/cocos2d/core/components/CCToggle.js index 8a42af33bbd..0c6af89cfbb 100644 --- a/cocos2d/core/components/CCToggle.js +++ b/cocos2d/core/components/CCToggle.js @@ -52,6 +52,13 @@ var Toggle = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.toggle.isChecked', notify: function () { this._updateCheckMark(); + + var group = this.toggleGroup || this._toggleContainer; + if (group && group.enabled) { + group.updateToggles(this); + } + + this._emitToggleEvents(); } }, @@ -164,7 +171,7 @@ var Toggle = cc.Class({ group.updateToggles(this); } - this._emitToggleEvents(event); + this._emitToggleEvents(); }, _emitToggleEvents: function () { From f79499ae684eac24eff9b936090e706e46bcb4c9 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Sun, 28 Oct 2018 11:43:41 +0800 Subject: [PATCH 0114/1631] Fix rendering errors for pre-multiplied images using dynamicAtlas. (#3411) (#3436) * Fix rendering errors for pre-multiplied images using dynamicAtlas. * Fix setting filter in RenderTexture is invalid. * Modified FilterIndex to private variable. --- cocos2d/core/assets/CCRenderTexture.js | 6 +++++- cocos2d/core/assets/CCTexture2D.js | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/assets/CCRenderTexture.js b/cocos2d/core/assets/CCRenderTexture.js index 1a3d1008715..ee5fea48947 100644 --- a/cocos2d/core/assets/CCRenderTexture.js +++ b/cocos2d/core/assets/CCRenderTexture.js @@ -37,6 +37,9 @@ let RenderTexture = cc.Class({ opts.images = undefined; opts.wrapS = this._wrapS; opts.wrapT = this._wrapT; + opts.premultiplyAlpha = this._premultiplyAlpha; + opts.minFilter = Texture2D._FilterIndex[this._minFilter]; + opts.magFilter = Texture2D._FilterIndex[this._magFilter]; if (!this._texture) { this._texture = new renderer.Texture2D(renderer.device, opts); @@ -86,7 +89,8 @@ let RenderTexture = cc.Class({ width: texture.width, height: texture.height, level: 0, - flipY: false + flipY: false, + premultiplyAlpha: texture._premultiplyAlpha }) }, diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index d8f0fbdae56..01217650fbc 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -235,6 +235,8 @@ var Texture2D = cc.Class({ PixelFormat: PixelFormat, WrapMode: WrapMode, Filter: Filter, + _FilterIndex: FilterIndex, + // predefined most common extnames extnames: ['.png', '.jpg', '.jpeg', '.bmp', '.webp'] }, From 6cadbbca3e05c849ac1dcad2fcab7db64f560006 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Sun, 28 Oct 2018 11:44:26 +0800 Subject: [PATCH 0115/1631] refine apis (#3432) * getWorldPos => getWorldPosition * setVertexes => setVertices --- cocos2d/core/camera/CCCamera.js | 2 +- cocos2d/core/mesh/CCMesh.js | 4 ++-- cocos2d/core/renderer/render-engine.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 62d691ed883..56f7b6699ea 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -625,7 +625,7 @@ let Camera = cc.Class({ this._camera.screenToWorld(_v3_temp_1, _v3_temp_3, cc.visibleRect.width, cc.visibleRect.height); } else { - this.node.getWorldPos(_v3_temp_1); + this.node.getWorldPosition(_v3_temp_1); } return ray.fromPoints(ray.create(), _v3_temp_1, _v3_temp_2); diff --git a/cocos2d/core/mesh/CCMesh.js b/cocos2d/core/mesh/CCMesh.js index ee86cc823d1..3b12d85b893 100644 --- a/cocos2d/core/mesh/CCMesh.js +++ b/cocos2d/core/mesh/CCMesh.js @@ -130,12 +130,12 @@ let Mesh = cc.Class({ * Set the vertex values. * !#zh * 设置顶点数据 - * @method setVertexes + * @method setVertices * @param {String} name - the attribute name, e.g. gfx.ATTR_POSITION * @param {[Vec2|Vec3|Color|Number]} values - the vertex values * @param {Number} [index] */ - setVertexes (name, values, index) { + setVertices (name, values, index) { index = index || 0; let vb = this._vbs[index]; diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 929587312df..53f4926019d 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -11315,7 +11315,7 @@ Camera.prototype.screenToWorld = function screenToWorld (out, screenPos, width, vec3.transformMat4(out, out, _matInvViewProj); // - this._node.getWorldPos(_tmp_v3); + this._node.getWorldPosition(_tmp_v3); vec3.lerp(out, _tmp_v3, out, cc.vmath.lerp(this._near / this._far, 1, screenPos.z)); } else { vec3.set(out, From d73e538c8ba9a99184639e1ab3b5650909ac6339 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Sun, 28 Oct 2018 12:38:34 +0800 Subject: [PATCH 0116/1631] =?UTF-8?q?resolve=20spine=20=E2=80=98pause?= =?UTF-8?q?=E2=80=99=20property=20=20invalid=20problem=20and=20export=20cc?= =?UTF-8?q?.StencilManager=20for=20native=20spine=20adapter=20(#3414)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * resolve spine ‘pause’ property invalid problem and export cc.StencilManager for native spine adapter * change code behind CC_EDITOR macro --- cocos2d/core/renderer/webgl/stencil-manager.js | 2 +- extensions/spine/Skeleton.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/webgl/stencil-manager.js b/cocos2d/core/renderer/webgl/stencil-manager.js index 030fe68eedd..1a9e1f170ee 100644 --- a/cocos2d/core/renderer/webgl/stencil-manager.js +++ b/cocos2d/core/renderer/webgl/stencil-manager.js @@ -172,4 +172,4 @@ StencilManager.prototype = { StencilManager.sharedManager = new StencilManager(); StencilManager.Stage = Stage; -module.exports = StencilManager; \ No newline at end of file +module.exports = cc.StencilManager = StencilManager; \ No newline at end of file diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 578c7c54c84..432fd5d1fd7 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -382,6 +382,7 @@ sp.Skeleton = cc.Class({ update (dt) { if (CC_EDITOR) return; + if (this.paused) return; let skeleton = this._skeleton; let state = this._state; if (skeleton) { From 6f2a1075a81410526b6d25d806ae99f57d64c27d Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 29 Oct 2018 11:03:59 +0800 Subject: [PATCH 0117/1631] implement Object.getOwnPropertyDescriptors polyfill for Baidu browser (#3433) --- polyfill/object.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/polyfill/object.js b/polyfill/object.js index 3b0819887ff..8b73fd13cee 100644 --- a/polyfill/object.js +++ b/polyfill/object.js @@ -4,4 +4,20 @@ if (!Object.assign) { Object.assign = function (target, source) { cc.js.mixin(target, source); } +} + +// for Baidu browser +// Implementation reference to: +// http://2ality.com/2016/02/object-getownpropertydescriptors.html +// http://docs.w3cub.com/javascript/global_objects/reflect/ownkeys/ +if (!Object.getOwnPropertyDescriptors) { + Object.getOwnPropertyDescriptors = function (obj) { + let descriptors = {}; + let ownKeys = Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)); // equals to Reflect.ownKeys(obj) in ES6 + for(let i = 0; i < ownKeys.length; ++i){ + let key = ownKeys[i]; + descriptors[key] = Object.getOwnPropertyDescriptor(obj, key); + } + return descriptors; + } } \ No newline at end of file From 32638056d41fe489ea2ac9e5b114da7673914eb4 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 29 Oct 2018 11:19:21 +0800 Subject: [PATCH 0118/1631] fixed the richText signal content can't disappear problem (#3440) --- cocos2d/core/components/CCRichText.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index 5f27744bd58..76fc68ef577 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -449,6 +449,7 @@ let RichText = cc.Class({ } labelSegment._styleIndex = styleIndex; labelSegment._lineCount = this._lineCount; + labelSegment.active = this.node.active; labelSegment.setAnchorPoint(0, 0); this._applyTextAttribute(labelSegment); From b8abe5d83d05f1232a2062ccd6e8be3ac31ab5f0 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 29 Oct 2018 11:28:03 +0800 Subject: [PATCH 0119/1631] fixed the texture.initWithData lost renderer.texture (#3437) --- cocos2d/core/assets/CCTexture2D.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 01217650fbc..606853006b6 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -424,10 +424,24 @@ var Texture2D = cc.Class({ initWithData (data, pixelFormat, pixelsWidth, pixelsHeight) { var opts = _getSharedOptions(); opts.image = data; + // webgl texture 2d uses images + opts.images = [opts.image]; + opts.hasMipmap = this._hasMipmap; + opts.premultiplyAlpha = this._premultiplyAlpha; + opts.flipY = this._flipY; + opts.minFilter = FilterIndex[this._minFilter]; + opts.magFilter = FilterIndex[this._magFilter]; + opts.wrapS = this._wrapS; + opts.wrapT = this._wrapT; opts.format = pixelFormat; opts.width = pixelsWidth; opts.height = pixelsHeight; - this.update(opts); + if (!this._texture) { + this._texture = new renderer.Texture2D(renderer.device, opts); + } + else { + this.update(opts); + } this.width = pixelsWidth; this.height = pixelsHeight; this.loaded = true; From 45a3396a6948e918c6e9a44e4ddaf954871171b4 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Mon, 29 Oct 2018 11:42:01 +0800 Subject: [PATCH 0120/1631] =?UTF-8?q?Optimize=20the=20render=20flow=20of?= =?UTF-8?q?=20renderComponent=20when=20the=20active=20state=20of=20?= =?UTF-8?q?=E2=80=A6=20(#3431)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Optimize the render flow of renderComponent when the active state of the node is false. * Modify the decision unified to canRender method. --- cocos2d/core/components/CCRenderComponent.js | 3 ++- cocos2d/core/components/CCSprite.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index b6874642647..d5ef2d9a0bb 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -130,7 +130,8 @@ let RenderComponent = cc.Class({ }, _canRender () { - return this._enabled; + // When the node is activated, it will execute onEnable and the renderflag will also be reset. + return this._enabled && this.node._activeInHierarchy; }, markForUpdateRenderData (enable) { diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 9d3242d80da..e9e4dde4bc2 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -545,7 +545,7 @@ var Sprite = cc.Class({ if (!this._enabled) return false; } else { - if (!this._enabled || !this._material) return false; + if (!this._enabled || !this._material || !this.node._activeInHierarchy) return false; } let spriteFrame = this._spriteFrame; From 2a3e478fee82185bbb1c881afd9502bf03819461 Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 30 Oct 2018 15:54:37 +0800 Subject: [PATCH 0121/1631] add mesh component i18n support (#3445) --- cocos2d/core/3d/CCSkinnedMeshRenderer.js | 2 +- cocos2d/core/mesh/CCMeshRenderer.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/3d/CCSkinnedMeshRenderer.js b/cocos2d/core/3d/CCSkinnedMeshRenderer.js index a9ba7a53daf..cd168f20f66 100644 --- a/cocos2d/core/3d/CCSkinnedMeshRenderer.js +++ b/cocos2d/core/3d/CCSkinnedMeshRenderer.js @@ -55,7 +55,7 @@ let SkinnedMeshRenderer = cc.Class({ extends: MeshRenderer, editor: CC_EDITOR && { - menu: 'Mesh/Skinned Mesh Renderer', + menu: 'i18n:MAIN_MENU.component.mesh/Skinned Mesh Renderer', }, ctor () { diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index 9b3ae4ede47..aaab02f4da3 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -35,7 +35,7 @@ let MeshRenderer = cc.Class({ extends: RenderComponent, editor: CC_EDITOR && { - menu: 'Mesh/MeshRenderer', + menu: 'i18n:MAIN_MENU.component.mesh/MeshRenderer', }, properties: { From 62f666f4c6ada4abcb5d65b74d21c15454cba563 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 30 Oct 2018 16:09:02 +0800 Subject: [PATCH 0122/1631] add the getSafeAreaRect impletement (#3448) --- cocos2d/core/platform/CCSys.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 753798edf1e..7aa3c4fd4d3 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -1142,6 +1142,20 @@ function initSys () { // N/A in web }; + /** + * !#en + * Return the safe area rect. only available on the iOS device.
+ * when the safeArea rect is unavailable, it will return a rect with design resolution size. + * !#zh + * 返回手机屏幕安全区域,目前仅在 iOS 设备上有效。其它平台将默认返回设计分辨率尺寸。 + * @method getSafeAreaRect + * @return {Rect} + */ + sys.getSafeAreaRect = function () { + let designSize = cc.view.getDesignResolutionSize(); + return cc.rect(0, 0, designSize.width, designSize.height); + }; + /** * Check whether an object is valid, * In web engine, it will return true if the object exist From f84b2d40d09c27e21374eb4649258e88ffcaef67 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 30 Oct 2018 18:26:25 +0800 Subject: [PATCH 0123/1631] rollback toggle isChecked code (#3443) * fix isChecked no need to trigger event * rollback toggle isChecked code --- cocos2d/core/components/CCToggle.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/cocos2d/core/components/CCToggle.js b/cocos2d/core/components/CCToggle.js index 0c6af89cfbb..7a34233182d 100644 --- a/cocos2d/core/components/CCToggle.js +++ b/cocos2d/core/components/CCToggle.js @@ -52,13 +52,6 @@ var Toggle = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.toggle.isChecked', notify: function () { this._updateCheckMark(); - - var group = this.toggleGroup || this._toggleContainer; - if (group && group.enabled) { - group.updateToggles(this); - } - - this._emitToggleEvents(); } }, @@ -175,6 +168,7 @@ var Toggle = cc.Class({ }, _emitToggleEvents: function () { + if (CC_EDITOR) { return; } this.node.emit('toggle', this); if (this.checkEvents) { cc.Component.EventHandler.emitEvents(this.checkEvents, this); From 9d201b691f633ddeac11bcdb33e6f819bebb2106 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 31 Oct 2018 18:13:05 +0800 Subject: [PATCH 0124/1631] V2.1 release world scale (#3447) * add getWorldScale/setWorldScale * refine code * fixed mat4 --- cocos2d/core/CCNode.js | 35 ++++++++++++++++++++++++++++++++ cocos2d/core/value-types/mat4.js | 4 +++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index f85271fa053..bb1c01972d3 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -2461,9 +2461,44 @@ let NodeDefines = { else { math.quat.copy(this._quat, quat); } + this._quat.getEulerAngles(this._eulerAngles); this.setLocalDirty(LocalDirtyFlag.ROTATION); }, + /* + * Calculate and return world scale + * This is not a public API yet, its usage could be updated + * @method getWorldScale + * @param {Vec3} out + * @return {Vec3} + */ + getWorldScale (out) { + math.vec3.copy(out, this._scale); + let curr = this._parent; + while (curr) { + math.vec3.mul(out, out, curr._scale); + curr = curr._parent; + } + return out; + }, + + /* + * Set world scale with vec3 + * This is not a public API yet, its usage could be updated + * @method setWorldScale + * @param {Vec3} scale + */ + setWorldScale (scale) { + if (this._parent) { + this._parent.getWorldScale(this._scale); + math.vec3.div(this._scale, scale, this._scale); + } + else { + math.vec3.copy(this._scale, scale); + } + this.setLocalDirty(LocalDirtyFlag.SCALE); + }, + getWorldRT (out) { let opos = _vec3_temp; let orot = _quat_temp; diff --git a/cocos2d/core/value-types/mat4.js b/cocos2d/core/value-types/mat4.js index 7dcf7f7c601..2e4e7d940de 100644 --- a/cocos2d/core/value-types/mat4.js +++ b/cocos2d/core/value-types/mat4.js @@ -393,4 +393,6 @@ js.mixin(Mat4.prototype, { */ cc.mat4 = function mat4 (m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { return new Mat4(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33); -}; \ No newline at end of file +}; + +module.exports = cc.Mat4 = Mat4; From 1ec6b4ef2d7a1c6be2199e926123ba36172d3f49 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 1 Nov 2018 14:18:42 +0800 Subject: [PATCH 0125/1631] node should remove from scene after destroy (#3456) --- cocos2d/core/utils/base-node.js | 23 +---------------------- test/qunit/lib/polyfill-for-phantom.js | 8 +++++++- test/qunit/unit-es5/test-node.js | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/cocos2d/core/utils/base-node.js b/cocos2d/core/utils/base-node.js index 3866d9cac59..6b9b45e2c79 100644 --- a/cocos2d/core/utils/base-node.js +++ b/cocos2d/core/utils/base-node.js @@ -1089,30 +1089,9 @@ var BaseNode = cc.Class({ } }, - _disableChildComps () { - // leave this._activeInHierarchy unmodified - var i, len = this._components.length; - for (i = 0; i < len; ++i) { - var component = this._components[i]; - if (component._enabled) { - cc.director._compScheduler.disableComp(component); - } - } - // deactivate recursively - for (i = 0, len = this._children.length; i < len; ++i) { - var node = this._children[i]; - if (node._active) { - node._disableChildComps(); - } - } - }, - destroy () { if (cc.Object.prototype.destroy.call(this)) { - // disable hierarchy - if (this._activeInHierarchy) { - this._disableChildComps(); - } + this.parent = null; } }, diff --git a/test/qunit/lib/polyfill-for-phantom.js b/test/qunit/lib/polyfill-for-phantom.js index 227c70e68cc..9752b43255e 100644 --- a/test/qunit/lib/polyfill-for-phantom.js +++ b/test/qunit/lib/polyfill-for-phantom.js @@ -151,4 +151,10 @@ if (!Object.assign) { return to; } }); - } \ No newline at end of file +} + +if (!Object.getOwnPropertySymbols) { + Object.getOwnPropertySymbols = function () { + return []; + }; +} diff --git a/test/qunit/unit-es5/test-node.js b/test/qunit/unit-es5/test-node.js index 82d23cfe9b7..f842c983ef6 100644 --- a/test/qunit/unit-es5/test-node.js +++ b/test/qunit/unit-es5/test-node.js @@ -123,6 +123,20 @@ test('activeInHierarchy', function () { strictEqual(child.activeInHierarchy, false, 'child should not activeInHierarchy after remove from scene'); }); +test('activeInHierarchy should be false after destroy', function () { + var parent = new cc.Node(); + var child = new cc.Node(); + child.parent = parent; + + cc.director.getScene().addChild(parent); + + parent.destroy(); + cc.game.step(); + + strictEqual(parent.activeInHierarchy, false, 'parent should not activeInHierarchy after destroy'); + strictEqual(child.activeInHierarchy, false, 'child should not activeInHierarchy after destroy'); +}); + test('activation logic for component', function () { // 这里主要测试node,不是测试component From 8b3631a5334cac6f54cfc72a4061382581dd4d45 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Thu, 1 Nov 2018 15:24:06 +0800 Subject: [PATCH 0126/1631] refine model prefab (#3454) * add readonly property to prefab asset * use joint path to find joint instead of joint index * refine code --- cocos2d/core/3d/CCModel.js | 14 ++++++-- cocos2d/core/3d/CCSkeleton.js | 2 +- cocos2d/core/3d/CCSkinnedMeshRenderer.js | 42 ++++++++---------------- cocos2d/core/assets/CCPrefab.js | 9 +++++ 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index 2861b336c44..42156c1a84a 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -101,6 +101,8 @@ let Model = cc.Class({ }, initSkeleton (skeleton) { + this._initNodes(); + let gltf = this._gltf; let buffers = this._buffers; let skinID = skeleton._skinID; @@ -126,13 +128,19 @@ let Model = cc.Class({ ); } - skeleton.jointIndices = gltfSkin.joints; + let jointIndices = gltfSkin.joints; + let jointPaths = skeleton.jointPaths; + jointPaths.length = 0; + let nodes = this._gltf.nodes; + for (let i = 0; i < jointIndices.length; i++) { + let node = nodes[jointIndices[i]]; + jointPaths.push(node.path); + } + skeleton.jointPaths = jointPaths; skeleton.bindposes = bindposes; }, _createVB (gltf, accessors, primitive) { - const buffers = this._buffers; - // create vertex-format let vfmt = []; let vcount = 0; diff --git a/cocos2d/core/3d/CCSkeleton.js b/cocos2d/core/3d/CCSkeleton.js index 3e65fd503f9..5ef31c5296f 100644 --- a/cocos2d/core/3d/CCSkeleton.js +++ b/cocos2d/core/3d/CCSkeleton.js @@ -4,7 +4,7 @@ let Skeleton = cc.Class({ extends: cc.Asset, ctor () { - this.jointIndices = []; + this.jointPaths = []; this.bindposes = []; }, diff --git a/cocos2d/core/3d/CCSkinnedMeshRenderer.js b/cocos2d/core/3d/CCSkinnedMeshRenderer.js index cd168f20f66..bcc8715e08e 100644 --- a/cocos2d/core/3d/CCSkinnedMeshRenderer.js +++ b/cocos2d/core/3d/CCSkinnedMeshRenderer.js @@ -30,26 +30,6 @@ const mat4 = cc.vmath.mat4; let _m4_tmp = mat4.create(); -function traversal (node, cb) { - cb(node); - - let children = node.children; - for (let i = 0; i < children.length; i++) { - let child = children[i]; - traversal(child, cb); - } -} - -function flatNode (rootNode) { - let nodes = []; - - traversal(rootNode, function (node) { - nodes.push(node); - }); - - return nodes; -} - let SkinnedMeshRenderer = cc.Class({ name: 'cc.SkinnedMeshRenderer', extends: MeshRenderer, @@ -136,13 +116,16 @@ let SkinnedMeshRenderer = cc.Class({ if (!this.skeleton || !this.rootBone) return; - let jointIndices = this.skeleton.jointIndices; - let nodes = flatNode(this.rootBone); + let jointPaths = this.skeleton.jointPaths; + let rootBone = this.rootBone; let matrices = this._matrices; matrices.length = 0; - for (let i = 0; i < jointIndices.length; i++) { - let jointIndex = jointIndices[i]; - joints.push(nodes[jointIndex]); + for (let i = 0; i < jointPaths.length; i++) { + let bone = cc.find(jointPaths[i], rootBone); + if (!bone) { + cc.warn('Can not find joint in root bone [%s] with path [%s]', rootBone.name, jointPaths[i]); + } + joints.push(bone); matrices.push(mat4.create()); } @@ -150,10 +133,9 @@ let SkinnedMeshRenderer = cc.Class({ }, _initJointsTexture () { - let skeleton = this._skeleton; - if (!skeleton) return; + if (!this._skeleton) return; - let jointCount = skeleton.jointIndices.length; + let jointCount = this._joints.length; let ALLOW_FLOAT_TEXTURE = !!cc.renderer.device.ext('OES_texture_float'); if (ALLOW_FLOAT_TEXTURE) { @@ -209,7 +191,9 @@ let SkinnedMeshRenderer = cc.Class({ updateMatrices () { for (let i = 0; i < this._joints.length; ++i) { - this._joints[i].getWorldMatrix(this._matrices[i]); + let joint = this._joints[i]; + if (!joint || !joint.activeInHierarchy) continue; + joint.getWorldMatrix(this._matrices[i]); } }, diff --git a/cocos2d/core/assets/CCPrefab.js b/cocos2d/core/assets/CCPrefab.js index f87fe795740..d882584df39 100644 --- a/cocos2d/core/assets/CCPrefab.js +++ b/cocos2d/core/assets/CCPrefab.js @@ -117,6 +117,15 @@ var Prefab = cc.Class({ * @default false */ asyncLoadAssets: false, + + /** + * @property {Boolean} readonly + * @default false + */ + readonly: { + default: false, + editorOnly: true + } }, statics: { From 7b574ee4f67dd3d56d321cf3a749aaa7845bced2 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 1 Nov 2018 17:11:10 +0800 Subject: [PATCH 0127/1631] fix bmFontOriginalSize unable to display in prefab (#3453) * fix bmFontOriginalSize unable to display in prefab * refine code * refine code --- cocos2d/core/components/CCLabel.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 928eddee56c..69d7a1cbc86 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -343,7 +343,6 @@ let Label = cc.Class({ } this._N$file = value; - this._bmFontOriginalSize = -1; if (value && this._isSystemFontUsed) this._isSystemFontUsed = false; @@ -351,10 +350,6 @@ let Label = cc.Class({ cc.warnID(4000); } - if (value instanceof cc.BitmapFont) { - this._bmFontOriginalSize = value.fontSize; - } - if (this._renderData) { this.destroyRenderData(this._renderData); this._renderData = null; @@ -412,9 +407,14 @@ let Label = cc.Class({ _bmFontOriginalSize: { displayName: 'BMFont Original Size', - default: -1, - serializable: false, - readonly: true, + get () { + if (this._N$file instanceof cc.BitmapFont) { + return this._N$file.fontSize; + } + else { + return -1; + } + }, visible: true, animatable: false }, From 46d4901b1be5a91bdeee2effee91233c9442dabc Mon Sep 17 00:00:00 2001 From: PP Date: Sun, 4 Nov 2018 11:19:50 +0800 Subject: [PATCH 0128/1631] fix different editbox blur behaviour in iOS and Android (#3446) --- cocos2d/core/components/editbox/CCEditBoxImpl.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index a9a657a417c..2cc9d985a1d 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -495,6 +495,7 @@ function _inputValueHandle (input, editBoxImpl) { function registerInputEventListener (tmpEdTxt, editBoxImpl, isTextarea) { let inputLock = false; + let blurWhenComposition = false; let cbs = editBoxImpl.__eventListeners; cbs.compositionstart = function () { inputLock = true; @@ -503,6 +504,11 @@ function registerInputEventListener (tmpEdTxt, editBoxImpl, isTextarea) { cbs.compositionend = function () { inputLock = false; + if (blurWhenComposition) { + // restore input value when composition not complete and blur input + this.value = editBoxImpl._text; + blurWhenComposition = false; + } _inputValueHandle(this, editBoxImpl); }; tmpEdTxt.addEventListener('compositionend', cbs.compositionend); @@ -551,7 +557,12 @@ function registerInputEventListener (tmpEdTxt, editBoxImpl, isTextarea) { tmpEdTxt.addEventListener('keypress', cbs.keypress); cbs.blur = function () { - editBoxImpl._text = this.value; + if (inputLock) { + blurWhenComposition = true; + } + else { + editBoxImpl._text = this.value; + } editBoxImpl._endEditing(); }; tmpEdTxt.addEventListener('blur', cbs.blur); From bd3942c0493ebd1e81f1d01b4eff5a9d84c13bac Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 5 Nov 2018 09:53:48 +0800 Subject: [PATCH 0129/1631] improve video player and webview (#3463) * improve video player and webview * refine code * refine code --- cocos2d/core/platform/CCView.js | 4 +--- cocos2d/videoplayer/video-player-impl.js | 14 ++++++++++++-- cocos2d/webview/webview-impl.js | 5 +++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 01547c16947..429b88be2d8 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -1125,9 +1125,7 @@ cc.ContentStrategy = cc.Class({ Math.abs(containerW - contentW) < 2 && (contentW = containerW); Math.abs(containerH - contentH) < 2 && (contentH = containerH); - var viewport = cc.rect(Math.round((containerW - contentW) / 2), - Math.round((containerH - contentH) / 2), - contentW, contentH); + var viewport = cc.rect((containerW - contentW) / 2, (containerH - contentH) / 2, contentW, contentH); // Translate the content if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS){ diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 76e093387ed..abf4b5fa653 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -167,6 +167,7 @@ let VideoPlayerImpl = cc.Class({ let orientation = cc.winSize.width > cc.winSize.height ? "landscape" : "portrait"; video.setAttribute("x5-playsinline", ""); video.setAttribute("x5-video-player-type", "h5"); + video.setAttribute("x5-video-player-fullscreen", "false"); video.setAttribute("x5-video-orientation", orientation); this._video = video; @@ -278,7 +279,7 @@ let VideoPlayerImpl = cc.Class({ video.pause(); }, - _resume: function () { + resume: function () { this.play(); }, @@ -356,6 +357,9 @@ let VideoPlayerImpl = cc.Class({ }, setKeepAspectRatioEnabled: function () { + if (CC_EDITOR) { + return; + } cc.logID(7700); }, @@ -368,8 +372,8 @@ let VideoPlayerImpl = cc.Class({ if (!video) { return; } + this._fullScreenEnabled = enable; if (sys.os === sys.OS_IOS && sys.isBrowser) { - this._fullScreenEnabled = enable; if (this._loadedmeta) { triggerFullScene(video, enable); } @@ -381,6 +385,7 @@ let VideoPlayerImpl = cc.Class({ else { cc.screen.exitFullScreen(video); } + video.setAttribute("x5-video-player-fullscreen", enable ? "true" : "false"); } }, @@ -483,6 +488,11 @@ let VideoPlayerImpl = cc.Class({ let appx = (w * _mat4_temp.m00) * node._anchorPoint.x; let appy = (h * _mat4_temp.m05) * node._anchorPoint.y; + + let viewport = cc.view._viewportRect; + offsetX += viewport.x / dpr; + offsetY += viewport.y / dpr; + let tx = _mat4_temp.m12 * scaleX - appx + offsetX, ty = _mat4_temp.m13 * scaleY - appy + offsetY; let matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")"; diff --git a/cocos2d/webview/webview-impl.js b/cocos2d/webview/webview-impl.js index 96198012320..9df5c8ccae8 100644 --- a/cocos2d/webview/webview-impl.js +++ b/cocos2d/webview/webview-impl.js @@ -377,6 +377,11 @@ let WebViewImpl = cc.Class({ let h = this._div.clientHeight * scaleY; let appx = (w * _mat4_temp.m00) * node._anchorPoint.x; let appy = (h * _mat4_temp.m05) * node._anchorPoint.y; + + let viewport = cc.view._viewportRect; + offsetX += viewport.x / dpr; + offsetY += viewport.y / dpr; + let tx = _mat4_temp.m12 * scaleX - appx + offsetX, ty = _mat4_temp.m13 * scaleY - appy + offsetY; let matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")"; From ef745b9bc8ab12e1e84879ce5b3f4b45e0b79fd7 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 5 Nov 2018 16:56:18 +0800 Subject: [PATCH 0130/1631] remove __orientationChanged listener on editbox destroyed (#3464) --- .../core/components/editbox/CCEditBoxImpl.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index 6fd60f2b113..624e402e419 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -245,6 +245,10 @@ let EditBoxImpl = cc.Class({ this._node = null; this.setDelegate(null); this.removeDom(); + if (this.__orientationChanged) { + window.removeEventListener('orientationchange', this.__orientationChanged); + this.__orientationChanged = null; + } }, _onTouchBegan (touch) { @@ -433,10 +437,12 @@ _p.createInput = function() { // Called before editbox focus to register cc.view status _p._beginEditingOnMobile = function () { let self = this; - this.__orientationChanged = function () { - self._adjustEditBoxPosition(); - }; - window.addEventListener('orientationchange', this.__orientationChanged); + if (!this.__orientationChanged) { + this.__orientationChanged = function () { + self._adjustEditBoxPosition(); + }; + window.addEventListener('orientationchange', this.__orientationChanged); + } if (cc.view.isAutoFullScreenEnabled()) { this.__fullscreen = true; @@ -465,7 +471,10 @@ _p._endEditingOnMobile = function () { this.__rotateScreen = false; } - window.removeEventListener('orientationchange', this.__orientationChanged); + if (this.__orientationChanged) { + window.removeEventListener('orientationchange', this.__orientationChanged); + this.__orientationChanged = null; + } if(this.__fullscreen) { cc.view.enableAutoFullScreen(true); From cf2d4d15203a4ce540f6dadb9d2b19cc80e21b26 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Mon, 5 Nov 2018 19:35:48 +0800 Subject: [PATCH 0131/1631] Add label API to update contentSize immediately. (#3452) * Add label API to update contentSize immediately. * Modify comment * Remove updateimmediately API. --- cocos2d/core/components/CCLabel.js | 5 ++--- cocos2d/core/renderer/utils/label/ttf.js | 7 ++----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 5188d1c83c7..90023d840f9 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -467,8 +467,7 @@ let Label = cc.Class({ this.node.on(cc.Node.EventType.ANCHOR_CHANGED, this._updateRenderData, this); this._checkStringEmpty(); - this._updateAssembler(); - this._activateMaterial(); + this._updateRenderData(true); }, onDisable () { @@ -486,7 +485,7 @@ let Label = cc.Class({ } this._super(); }, - + _canRender () { let result = this._super(); let font = this.font; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index f4913f5202a..a9810d8de0a 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -118,7 +118,7 @@ module.exports = { updateRenderData (comp) { if (!comp._renderData.vertDirty) return; - this._updateFontFamly(comp); + this._updateFontFamily(comp); this._updateProperties(comp); this._calculateLabelFont(); this._calculateSplitedStrings(); @@ -141,7 +141,7 @@ module.exports = { _updateVerts () { }, - _updateFontFamly (comp) { + _updateFontFamily (comp) { if (!comp.useSystemFont) { if (comp.font) { if (comp.font._nativeAsset) { @@ -418,7 +418,6 @@ module.exports = { let paragraphedStrings = _string.split('\n'); let paragraphLength = this._calculateParagraphLength(paragraphedStrings, _context); - _splitedStrings = paragraphedStrings; let i = 0; let totalHeight = 0; let maxLength = 0; @@ -453,7 +452,6 @@ module.exports = { _fontDesc = this._getFontDesc(); _context.font = _fontDesc; - _splitedStrings = []; totalHeight = 0; for (i = 0; i < paragraphedStrings.length; ++i) { let j = 0; @@ -468,7 +466,6 @@ module.exports = { totalHeight += this._getLineHeight(); ++j; } - _splitedStrings = _splitedStrings.concat(textFragment); } if (tryDivideByTwo) { From b568f39240758380974368414cb8f14eb0ab58a6 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 5 Nov 2018 19:37:01 +0800 Subject: [PATCH 0132/1631] fix error when set volume as a string value (#3455) --- cocos2d/audio/CCAudioEngine.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/cocos2d/audio/CCAudioEngine.js b/cocos2d/audio/CCAudioEngine.js index 8a44b64c0ae..40cf85031f1 100644 --- a/cocos2d/audio/CCAudioEngine.js +++ b/cocos2d/audio/CCAudioEngine.js @@ -90,6 +90,17 @@ let getAudioFromId = function (id) { return _id2audio[id]; }; +let handleVolume = function (volume) { + if (!volume) { + // set default volume as 1 + volume = 1; + } + else if (typeof volume === 'string') { + volume = Number.parseFloat(volume); + } + return volume; +}; + /** * !#en cc.audioEngine is the singleton object, it provide simple audio APIs. * !#zh @@ -150,9 +161,7 @@ var audioEngine = { } audio.setLoop(loop || false); - if (typeof volume !== 'number') { - volume = 1; - } + volume = handleVolume(volume); audio.setVolume(volume); audio.play(); @@ -647,6 +656,7 @@ var audioEngine = { * cc.audioEngine.setMusicVolume(0.5); */ setMusicVolume: function (volume) { + volume = handleVolume(volume); var music = this._music; music.volume = volume; this.setVolume(music.id, music.volume); @@ -690,6 +700,7 @@ var audioEngine = { * cc.audioEngine.setEffectsVolume(0.5); */ setEffectsVolume: function (volume) { + volume = handleVolume(volume); var musicId = this._music.id; this._effect.volume = volume; for (var id in _id2audio) { From d316a5c9019b60245160bb7e7d6befa36463580d Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 5 Nov 2018 19:37:52 +0800 Subject: [PATCH 0133/1631] modify the sys.getSafeAreaRect API (#3462) --- cocos2d/core/platform/CCSys.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 7aa3c4fd4d3..60cf45f68dd 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -1144,16 +1144,16 @@ function initSys () { /** * !#en - * Return the safe area rect. only available on the iOS device.
- * when the safeArea rect is unavailable, it will return a rect with design resolution size. + * Return the safe area rect.
+ * only available on the iOS native platform, otherwise it will return a rect with design resolution size. * !#zh - * 返回手机屏幕安全区域,目前仅在 iOS 设备上有效。其它平台将默认返回设计分辨率尺寸。 + * 返回手机屏幕安全区域,目前仅在 iOS 原生平台有效。其它平台将默认返回设计分辨率尺寸。 * @method getSafeAreaRect * @return {Rect} */ sys.getSafeAreaRect = function () { - let designSize = cc.view.getDesignResolutionSize(); - return cc.rect(0, 0, designSize.width, designSize.height); + let visibleSize = cc.view.getVisibleSize(); + return cc.rect(0, 0, visibleSize.width, visibleSize.height); }; /** From efa1a9350ddd7abe0d7990e077a9a8b6b9098e20 Mon Sep 17 00:00:00 2001 From: FengXuner <32702270+FengXuner@users.noreply.github.com> Date: Mon, 5 Nov 2018 19:43:20 +0800 Subject: [PATCH 0134/1631] Add onTouchCancel function to CCMouseJoint (#3380) * Add onTouchCancel function to CCMouseJoint * Use onTouchEnd function to process TOUCH_CANCEL event --- cocos2d/core/physics/joint/CCMouseJoint.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/physics/joint/CCMouseJoint.js b/cocos2d/core/physics/joint/CCMouseJoint.js index b75bf91434c..f16869cf51e 100644 --- a/cocos2d/core/physics/joint/CCMouseJoint.js +++ b/cocos2d/core/physics/joint/CCMouseJoint.js @@ -211,6 +211,7 @@ var MouseJoint = cc.Class({ mouseRegion.on(cc.Node.EventType.TOUCH_START, this.onTouchBegan, this); mouseRegion.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this); mouseRegion.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this); + mouseRegion.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this); }, onEnable: function () { From 240d54e5998627cece95a8b05029a4f2ce09b6e1 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 5 Nov 2018 19:44:39 +0800 Subject: [PATCH 0135/1631] fix this.target is null (#3458) --- cocos2d/core/components/CCButton.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 9d06ae19ef8..96e2cb3961f 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -221,7 +221,7 @@ let Button = cc.Class({ displayName: 'Normal', tooltip: CC_DEV && 'i18n:COMPONENT.button.normal_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL) { + if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL && this.target) { this.target.opacity = this.normalColor.a; } this._updateState(); @@ -238,7 +238,7 @@ let Button = cc.Class({ displayName: 'Pressed', tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED) { + if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED && this.target) { this.target.opacity = this.pressedColor.a; } this._updateState(); @@ -255,7 +255,7 @@ let Button = cc.Class({ displayName: 'Hover', tooltip: CC_DEV && 'i18n:COMPONENT.button.hover_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.HOVER) { + if (this.transition === Transition.Color && this._getButtonState() === State.HOVER && this.target) { this.target.opacity = this.hoverColor.a; } this._updateState(); @@ -272,7 +272,7 @@ let Button = cc.Class({ displayName: 'Disabled', tooltip: CC_DEV && 'i18n:COMPONENT.button.disabled_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED) { + if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED && this.target) { this.target.opacity = this.disabledColor.a; } this._updateState(); @@ -417,6 +417,9 @@ let Button = cc.Class({ this._hovered = false; // // Restore button status let target = this.target; + if (!target) { + return; + } let transition = this.transition; if (transition === Transition.COLOR && this.interactable) { this._setTargetColor(this.normalColor); @@ -544,6 +547,9 @@ let Button = cc.Class({ update (dt) { let target = this.target; + if (!target) { + return; + } if (this._transitionFinished) return; if (this.transition !== Transition.COLOR && this.transition !== Transition.SCALE) return; @@ -700,8 +706,11 @@ let Button = cc.Class({ this._updateColorTransitionImmediately(state); } else { - let color = this._getStateColor(state); let target = this.target; + if (!target) { + return; + } + let color = this._getStateColor(state); this._fromColor = target.color.clone(); this._toColor = color; this.time = 0; @@ -732,6 +741,9 @@ let Button = cc.Class({ }, _zoomBack () { + if (!this.target) { + return; + } this._fromScale = this.target.scale; this._toScale = this._originalScale; this.time = 0; From 8ba63820973d2816df6936fb85d9ca706744ac31 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 5 Nov 2018 19:45:21 +0800 Subject: [PATCH 0136/1631] add scale calculate in layout when child scale changed (#3467) --- cocos2d/core/components/CCLayout.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/core/components/CCLayout.js b/cocos2d/core/components/CCLayout.js index 4f10bd2af8b..435675eea94 100644 --- a/cocos2d/core/components/CCLayout.js +++ b/cocos2d/core/components/CCLayout.js @@ -462,6 +462,7 @@ var Layout = cc.Class({ child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); + child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, @@ -473,6 +474,7 @@ var Layout = cc.Class({ child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); + child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, @@ -481,6 +483,7 @@ var Layout = cc.Class({ child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); + child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); @@ -490,6 +493,7 @@ var Layout = cc.Class({ child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); + child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); From 7b999cda4468aa316573afe4bde78581f4af0eb8 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 7 Nov 2018 10:49:24 +0800 Subject: [PATCH 0137/1631] refine quad fromEuler/toEuler (#3457) --- cocos2d/core/CCNode.js | 8 ++-- cocos2d/core/renderer/render-engine.js | 42 ++++++++++++++++++++- cocos2d/core/value-types/quat.js | 52 ++++++++++++++------------ 3 files changed, 72 insertions(+), 30 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index bb1c01972d3..819a99d0ff0 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1300,7 +1300,7 @@ let NodeDefines = { this._rotationX = this._rotationY = undefined; } - this._quat.getEulerAngles(this._eulerAngles); + this._quat.toEuler(this._eulerAngles); // Upgrade from 2.0.0 preview 4 & earlier versions // TODO: Remove after final version @@ -2220,7 +2220,7 @@ let NodeDefines = { } if (CC_EDITOR) { - old.getEulerAngles(this._eulerAngles); + old.toEuler(this._eulerAngles); } } } @@ -2461,7 +2461,7 @@ let NodeDefines = { else { math.quat.copy(this._quat, quat); } - this._quat.getEulerAngles(this._eulerAngles); + this._quat.toEuler(this._eulerAngles); this.setLocalDirty(LocalDirtyFlag.ROTATION); }, @@ -3132,7 +3132,7 @@ let NodeDefines = { this._localMatDirty = LocalDirtyFlag.ALL; this._worldMatDirty = true; - this._quat.getEulerAngles(this._eulerAngles); + this._quat.toEuler(this._eulerAngles); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._renderComponent) { diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 0be11d3bcf9..ce0fde66ebf 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -4012,14 +4012,52 @@ quat.fromEuler = function (out, x, y, z) { var sz = Math.sin(z); var cz = Math.cos(z); - out.x = sx * cy * cz - cx * sy * sz; + out.x = sx * cy * cz + cx * sy * sz; out.y = cx * sy * cz + sx * cy * sz; out.z = cx * cy * sz - sx * sy * cz; - out.w = cx * cy * cz + sx * sy * sz; + out.w = cx * cy * cz - sx * sy * sz; return out; }; +/** + * Convert a quaternion back to euler angle (in degrees). + * + * @param {vec3} out - Euler angle stored as a vec3 + * @param {number} q - the quaternion to be converted + * @returns {vec3} out. + */ +quat.toEuler = function (out, q) { + var x = q.x, y = q.y, z = q.z, w = q.w; + var heading, attitude, bank; + var test = x * y + z * w; + if (test > 0.499) { // singularity at north pole + heading = 2 * Math.atan2(x,w); + attitude = Math.PI/2; + bank = 0; + } + if (test < -0.499) { // singularity at south pole + heading = -2 * Math.atan2(x,w); + attitude = - Math.PI/2; + bank = 0; + } + if(isNaN(heading)){ + var sqx = x*x; + var sqy = y*y; + var sqz = z*z; + heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // heading + attitude = Math.asin(2*test); // attitude + bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank + } + + out.y = toDegree(heading); + out.z = toDegree(attitude); + out.x = toDegree(bank); + + return out; +} + + /** * Returns a string representation of a quatenion * diff --git a/cocos2d/core/value-types/quat.js b/cocos2d/core/value-types/quat.js index c96554dce74..aeeca3b04d2 100644 --- a/cocos2d/core/value-types/quat.js +++ b/cocos2d/core/value-types/quat.js @@ -115,34 +115,38 @@ proto.equals = function (other) { return other && this.x === other.x && this.y === other.y && this.z === other.z && this.w === other.w; }; -proto.getRoll = function () { - var sinr = 2.0 * (this.w * this.x + this.y * this.z); - var cosr = 1.0 - 2.0 * (this.x * this.x + this.y * this.y); - return 180 * Math.atan2(sinr, cosr) / Math.PI; -}; - -proto.getPitch = function () { - var sinp = 2.0 * (this.w * this.y - this.z * this.x); - var pitch = sinp > 1 ? 1 : sinp; - pitch = sinp < -1 ? -1 : sinp; - pitch = 180 * Math.asin(pitch) / Math.PI; - return pitch; +/** + * !#en Convert quaternion to euler + * !#zh 转换四元数到欧拉角 + * @method toEuler + * @param {Vec3} out + * @return {Vec3} + */ +proto.toEuler = function (out) { + cc.vmath.quat.toEuler(out, this); + return out; }; -proto.getYaw = function () { - var siny = 2.0 * (this.w * this.z + this.x * this.y); - var cosy = 1.0 - 2.0 * (this.y * this.y + this.z * this.z); - return 180 * Math.atan2(siny, cosy) / Math.PI; +/** + * !#en Convert euler to quaternion + * !#zh 转换欧拉角到四元数 + * @method fromEuler + * @param {Vec3} euler + * @return {Quat} + */ +proto.fromEuler = function (euler) { + cc.vmath.quat.fromEuler(this, euler.x, euler.y, euler.z); + return this; }; -proto.getEulerAngles = function (out) { - out = out || cc.v3(); - out.x = this.getRoll(); - out.y = this.getPitch(); - out.z = this.getYaw(); - return out; -} - +/** + * !#en Calculate the interpolation result between this quaternion and another one with given ratio + * !#zh 计算四元数的插值结果 + * @member lerp + * @param {Quat} to + * @param {Number} ratio + * @param {Quat} out + */ proto.lerp = function (to, ratio, out) { out = out || new cc.Quat(); cc.vmath.quat.slerp(out, this, to, ratio); From fdd1590d69abcd4bb1eacc120a7d29f788c3f64c Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 18 Sep 2018 17:16:32 +0800 Subject: [PATCH 0138/1631] Support switch 2D/3D edit mode (#3266) --- cocos2d/core/CCNode.js | 5 +++ cocos2d/core/CCPrivateNode.js | 5 +++ cocos2d/core/renderer/index.js | 39 ------------------- .../renderer/webgl/render-component-walker.js | 4 +- 4 files changed, 12 insertions(+), 41 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 819a99d0ff0..5c913d0f7de 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1121,6 +1121,11 @@ let NodeDefines = { } } }, + + showInEditor: { + default: true, + editorOnly: true + } }, /** diff --git a/cocos2d/core/CCPrivateNode.js b/cocos2d/core/CCPrivateNode.js index f49a6df713d..bcdbecbcdab 100644 --- a/cocos2d/core/CCPrivateNode.js +++ b/cocos2d/core/CCPrivateNode.js @@ -98,6 +98,11 @@ let PrivateNode = cc.Class({ }, override: true }, + showInEditor: { + default: false, + editorOnly: true, + override: true + } }, /** diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 292c33a3098..0909c3ee251 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -26,8 +26,6 @@ const renderEngine = require('./render-engine'); const math = renderEngine.math; -let _pos = math.vec3.create(); - function _initBuiltins(device) { let defaultTexture = new renderEngine.Texture2D(device, { images: [], @@ -116,29 +114,6 @@ cc.renderer = module.exports = { this._walker = new RenderComponentWalker(this.device, this.scene); - if (CC_EDITOR) { - this._cameraNode = new cc.Node(); - - this._camera = new renderEngine.Camera(); - this._camera.setColor(0, 0, 0, 1); - this._camera.setFov(Math.PI * 60 / 180); - this._camera.setNear(0.1); - this._camera.setFar(1024); - this._camera.setNode(this._cameraNode); - - let view = new renderEngine.View(); - this._camera.view = view; - this._camera.dirty = true; - - if (CC_EDITOR) { - this._camera.setColor(0, 0, 0, 0); - } - this._camera.setStages([ - 'transparent' - ]); - this.scene.addCamera(this._camera); - } - let builtins = _initBuiltins(this.device); this._forward = new renderEngine.ForwardRenderer(this.device, builtins); }, @@ -178,20 +153,6 @@ cc.renderer = module.exports = { this._camera.tx = vp.x; this._camera.ty = vp.y + vp.height; } - else if (CC_EDITOR && this.canvas) { - let canvas = this.canvas; - let scaleX = cc.view.getScaleX(); - let scaleY = cc.view.getScaleY(); - - let node = this._cameraNode; - _pos.x = node.x = canvas.width / scaleX / 2; - _pos.y = node.y = canvas.height / scaleY / 2; - _pos.z = 0; - - node.z = canvas.height / scaleY / 1.1566; - node.lookAt(_pos); - this._camera.dirty = true; - } }, render (ecScene) { diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/render-component-walker.js index 4338799396f..2065f47200e 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/render-component-walker.js @@ -149,7 +149,7 @@ RenderComponentWalker.prototype = { let model = this._modelPool.add(); this._batchedModels.push(model); model.sortKey = this._sortKey++; - model._cullingMask = CC_EDITOR ? 1 : this.cullingMask; + model._cullingMask = this.cullingMask; model.setNode(this.node); model.addEffect(effect); model.addInputAssembler(ia); @@ -177,7 +177,7 @@ RenderComponentWalker.prototype = { let model = this._modelPool.add(); this._batchedModels.push(model); model.sortKey = this._sortKey++; - model._cullingMask = CC_EDITOR ? 1 : this.cullingMask; + model._cullingMask = this.cullingMask; model.setNode(this.node); model.addEffect(effect); model.addInputAssembler(iaRenderData.ia); From 13fd427ae2e9b950f907860a7080b37dcfb963a9 Mon Sep 17 00:00:00 2001 From: kenshin <420373550@qq.com> Date: Sat, 29 Sep 2018 14:30:34 +0800 Subject: [PATCH 0139/1631] fix motion streak index count error. (#3336) * fix motion streak index count error. * change --- cocos2d/core/renderer/webgl/assemblers/motion-streak.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index 4d0d4c68f99..4d94c81d15a 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -186,7 +186,7 @@ var motionStreakAssembler = { } renderData.vertexCount = renderData.dataLength; - renderData.indiceCount = (renderData.vertexCount - 2)*3; + renderData.indiceCount = renderData.vertexCount === 0 ? 0 : (renderData.vertexCount - 2)*3; }, fillBuffers (comp, renderer) { From 726ee5a3d7f88f96c6c34f46f2ca1c7522aab197 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 11 Oct 2018 19:35:22 +0800 Subject: [PATCH 0140/1631] Use RenderFlow to drive scene visit process (#3370) * Use RenderFlow to drive scene visit process * Fix tests * Remove useless code --- cocos2d/core/3d/polyfill-3d.js | 2 - cocos2d/core/camera/CCCamera.js | 3 +- cocos2d/core/renderer/canvas/index.js | 2 +- ...r-walker.js => render-component-handle.js} | 39 +++++------ cocos2d/core/renderer/index.js | 18 ++--- cocos2d/core/renderer/render-flow.js | 65 ++++++++++--------- .../webgl/assemblers/graphics/impl.js | 2 +- cocos2d/core/renderer/webgl/mesh-buffer.js | 14 ++-- ...r-component-walker.js => model-batcher.js} | 36 +++------- cocos2d/deprecated.js | 4 +- cocos2d/particle/particle-system-assembler.js | 2 +- modules.json | 2 +- test/qunit/lib/polyfill-for-phantom.js | 18 +++++ test/qunit/unit-es5/test-spriteRenderer.js | 13 ++-- 14 files changed, 109 insertions(+), 111 deletions(-) rename cocos2d/core/renderer/canvas/{canvas-render-walker.js => render-component-handle.js} (84%) rename cocos2d/core/renderer/webgl/{render-component-walker.js => model-batcher.js} (88%) diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index cd8cf773862..ffe00a49362 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -29,8 +29,6 @@ const EventType = Node.EventType; const DirtyFlag = Node._LocalDirtyFlag; const math = require('../renderer/render-engine').math; const RenderFlow = require('../renderer/render-flow'); -const misc = require('../utils/misc'); -const vec3 = cc.vmath.vec3; // ====== Node transform polyfills ====== const ONE_DEGREE = Math.PI / 180; diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 42f8902545f..c45909331a4 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -27,6 +27,7 @@ const AffineTrans = require('../utils/affine-transform'); const renderEngine = require('../renderer/render-engine'); const renderer = require('../renderer/index'); +const RenderFlow = require('../renderer/render-flow'); const game = require('../CCGame'); const ray = require('../3d/geom-utils/ray'); @@ -659,7 +660,7 @@ let Camera = cc.Class({ // force update node world matrix this.node.getWorldMatrix(_mat4_temp_1); this.beforeDraw(); - renderer._walker.visit(root); + RenderFlow.visit(root); renderer._forward.renderCamera(this._camera, renderer.scene); }, diff --git a/cocos2d/core/renderer/canvas/index.js b/cocos2d/core/renderer/canvas/index.js index ee89ef484ba..73e553b574e 100644 --- a/cocos2d/core/renderer/canvas/index.js +++ b/cocos2d/core/renderer/canvas/index.js @@ -25,6 +25,6 @@ module.exports = { ForwardRenderer: require('./forward-renderer'), - RenderComponentWalker: require('./canvas-render-walker'), + RenderComponentHandle: require('./render-component-handle'), _renderers: require('./renderers') }; \ No newline at end of file diff --git a/cocos2d/core/renderer/canvas/canvas-render-walker.js b/cocos2d/core/renderer/canvas/render-component-handle.js similarity index 84% rename from cocos2d/core/renderer/canvas/canvas-render-walker.js rename to cocos2d/core/renderer/canvas/render-component-handle.js index 9906b1de5d2..c42d9f48d23 100644 --- a/cocos2d/core/renderer/canvas/canvas-render-walker.js +++ b/cocos2d/core/renderer/canvas/render-component-handle.js @@ -23,11 +23,9 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('../../platform/js'); -const RenderFlow = require('../render-flow'); require('./renderers'); -let RenderComponentWalker = function (device, defaultCamera) { +let RenderComponentHandle = function (device, defaultCamera) { this._device = device; // let vx = this._device._vx; // let vy = this._device._vy; @@ -37,36 +35,35 @@ let RenderComponentWalker = function (device, defaultCamera) { this.parentOpacity = 1; this.parentOpacityDirty = 0; this.worldMatDirty = 0; - - RenderFlow.init(this); + this.walking = false; }; -RenderComponentWalker.prototype = { - constructor: RenderComponentWalker, +RenderComponentHandle.prototype = { + constructor: RenderComponentHandle, - reset() {}, - - _commitComp (comp, assembler) { - let ctx = this._device._ctx; - let cam = this._camera; - ctx.setTransform(cam.a, cam.b, cam.c, cam.d, cam.tx, cam.ty); - ctx.scale(1, -1); - assembler.draw(ctx, comp); - }, - - visit (scene) { + reset() { let ctx = this._device._ctx; let canvas = this._device._canvas; - let color = cc.Camera.main.backgroundColor; + var color = cc.Camera.main ? cc.Camera.main.backgroundColor : cc.color(); let rgba = `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a/255})`; ctx.fillStyle = rgba; ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height); this._device._stats.drawcalls = 0; + }, + + terminate () { - RenderFlow.render(scene); + }, + + _commitComp (comp, assembler) { + let ctx = this._device._ctx; + let cam = this._camera; + ctx.setTransform(cam.a, cam.b, cam.c, cam.d, cam.tx, cam.ty); + ctx.scale(1, -1); + assembler.draw(ctx, comp); } }; -module.exports = RenderComponentWalker; \ No newline at end of file +module.exports = RenderComponentHandle; \ No newline at end of file diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 0909c3ee251..9568e45218a 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -24,7 +24,7 @@ ****************************************************************************/ const renderEngine = require('./render-engine'); -const math = renderEngine.math; +const RenderFlow = require('./render-flow'); function _initBuiltins(device) { let defaultTexture = new renderEngine.Texture2D(device, { @@ -90,14 +90,15 @@ cc.renderer = module.exports = { * @type {Number} */ drawCalls: 0, - _walker: null, + // Render component handler + _handle: null, _cameraNode: null, _camera: null, _forward: null, initWebGL (canvas, opts) { require('./webgl/assemblers'); - const RenderComponentWalker = require('./webgl/render-component-walker'); + const ModelBatcher = require('./webgl/model-batcher'); this.Texture2D = renderEngine.Texture2D; @@ -112,8 +113,8 @@ cc.renderer = module.exports = { this.scene = new renderEngine.Scene(); - this._walker = new RenderComponentWalker(this.device, this.scene); - + this._handle = new ModelBatcher(this.device, this.scene); + RenderFlow.init(this._handle); let builtins = _initBuiltins(this.device); this._forward = new renderEngine.ForwardRenderer(this.device, builtins); }, @@ -134,7 +135,8 @@ cc.renderer = module.exports = { this._camera = { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }; - this._walker = new canvasRenderer.RenderComponentWalker(this.device, this._camera); + this._handle = new canvasRenderer.RenderComponentHandle(this.device, this._camera); + RenderFlow.init(this._handle); this._forward = new canvasRenderer.ForwardRenderer(); }, @@ -159,7 +161,7 @@ cc.renderer = module.exports = { this.device._stats.drawcalls = 0; if (ecScene) { // walk entity component scene to generate models - this._walker.visit(ecScene); + RenderFlow.visit(ecScene); // Render models in renderer scene this._forward.render(this.scene); this.drawCalls = this.device._stats.drawcalls; @@ -167,7 +169,7 @@ cc.renderer = module.exports = { }, clear () { - this._walker.reset(); + this._handle.reset(); this._forward._reset(); } }; \ No newline at end of file diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 3aaf18b308d..2eb9a25dfb7 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -12,7 +12,7 @@ const POST_UPDATE_RENDER_DATA = 1 << 8; const POST_RENDER = 1 << 9; const FINAL = 1 << 10; -let _walker = null; +let _batcher; let _cullingMask = 0; // @@ -32,7 +32,7 @@ _proto._localTransform = function (node) { }; _proto._worldTransform = function (node) { - _walker.worldMatDirty ++; + _batcher.worldMatDirty ++; let t = node._matrix; let position = node._position; @@ -43,7 +43,7 @@ _proto._worldTransform = function (node) { node._renderFlag &= ~WORLD_TRANSFORM; this._next._func(node); - _walker.worldMatDirty --; + _batcher.worldMatDirty --; }; _proto._color = function (node) { @@ -58,12 +58,12 @@ _proto._color = function (node) { }; _proto._opacity = function (node) { - _walker.parentOpacityDirty++; + _batcher.parentOpacityDirty++; node._renderFlag &= ~OPACITY; this._next._func(node); - _walker.parentOpacityDirty--; + _batcher.parentOpacityDirty--; }; _proto._updateRenderData = function (node) { @@ -75,24 +75,25 @@ _proto._updateRenderData = function (node) { _proto._render = function (node) { let comp = node._renderComponent; - _walker._commitComp(comp, comp._assembler, node._cullingMask); + _batcher._commitComp(comp, comp._assembler, node._cullingMask); this._next._func(node); }; _proto._customIARender = function (node) { let comp = node._renderComponent; - _walker._commitIA(comp, comp._assembler, node._cullingMask); + _batcher._commitIA(comp, comp._assembler, node._cullingMask); this._next._func(node); }; _proto._children = function (node) { let cullingMask = _cullingMask; + let batcher = _batcher; - let parentOpacity = _walker.parentOpacity; - _walker.parentOpacity *= (node._opacity / 255); + let parentOpacity = batcher.parentOpacity; + batcher.parentOpacity *= (node._opacity / 255); - let worldTransformFlag = _walker.worldMatDirty ? WORLD_TRANSFORM : 0; - let worldOpacityFlag = _walker.parentOpacityDirty ? COLOR : 0; + let worldTransformFlag = batcher.worldMatDirty ? WORLD_TRANSFORM : 0; + let worldOpacityFlag = batcher.parentOpacityDirty ? COLOR : 0; let children = node._children; for (let i = 0, l = children.length; i < l; i++) { @@ -102,12 +103,12 @@ _proto._children = function (node) { c._renderFlag |= worldTransformFlag | worldOpacityFlag; // TODO: Maybe has better way to implement cascade opacity - c._color.a = c._opacity * _walker.parentOpacity; + c._color.a = c._opacity * batcher.parentOpacity; flows[c._renderFlag]._func(c); c._color.a = 255; } - _walker.parentOpacity = parentOpacity; + batcher.parentOpacity = parentOpacity; this._next._func(node); @@ -123,7 +124,7 @@ _proto._postUpdateRenderData = function (node) { _proto._postRender = function (node) { let comp = node._renderComponent; - _walker._commitComp(comp, comp._postAssembler, node._cullingMask); + _batcher._commitComp(comp, comp._postAssembler, node._cullingMask); this._next._func(node); }; @@ -187,40 +188,42 @@ function getFlow (flag) { return flow; } +// +function init (node) { + let flag = node._renderFlag; + let r = flows[flag] = getFlow(flag); + r._func(node); +} + +RenderFlow.flows = flows; +RenderFlow.createFlow = createFlow; +RenderFlow.visit = function (scene) { + _batcher.reset(); + _batcher.walking = true; -function render (scene) { _cullingMask = 1 << scene.groupIndex; if (scene._renderFlag & WORLD_TRANSFORM) { - _walker.worldMatDirty ++; + _batcher.worldMatDirty ++; scene._calculWorldMatrix(); scene._renderFlag &= ~WORLD_TRANSFORM; flows[scene._renderFlag]._func(scene); - _walker.worldMatDirty --; + _batcher.worldMatDirty --; } else { flows[scene._renderFlag]._func(scene); } -} -// -function init (node) { - let flag = node._renderFlag; - let r = flows[flag] = getFlow(flag); - r._func(node); -} - -RenderFlow.flows = flows; -RenderFlow.createFlow = createFlow; -RenderFlow.render = render; + _batcher.terminate(); + _batcher.walking = false; +}; -RenderFlow.init = function (walker) { - _walker = walker; +RenderFlow.init = function (batcher) { + _batcher = batcher; flows[0] = EMPTY_FLOW; - for (let i = 1; i < FINAL; i++) { flows[i] = new RenderFlow(); } diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js index f66d48931bb..76946c8a764 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js @@ -217,7 +217,7 @@ cc.js.mixin(Impl.prototype, { requestRenderData () { let renderData = new IARenderData(); - let meshbuffer = new MeshBuffer(renderer._walker, vfmtPosColor); + let meshbuffer = new MeshBuffer(renderer._handle, vfmtPosColor); renderData.meshbuffer = meshbuffer; this._renderDatas.push(renderData); diff --git a/cocos2d/core/renderer/webgl/mesh-buffer.js b/cocos2d/core/renderer/webgl/mesh-buffer.js index e8e7e3a530a..0d49d4bc915 100644 --- a/cocos2d/core/renderer/webgl/mesh-buffer.js +++ b/cocos2d/core/renderer/webgl/mesh-buffer.js @@ -3,7 +3,7 @@ const gfx = renderEngine.gfx; let MeshBuffer = cc.Class({ name: 'cc.MeshBuffer', - ctor (renderer, vertexFormat) { + ctor (batcher, vertexFormat) { this.byteStart = 0; this.byteOffset = 0; this.indiceStart = 0; @@ -15,7 +15,7 @@ let MeshBuffer = cc.Class({ this._vertexBytes = this._vertexFormat._bytes; this._vb = new gfx.VertexBuffer( - renderer._device, + batcher._device, vertexFormat, gfx.USAGE_DYNAMIC, new ArrayBuffer(), @@ -23,7 +23,7 @@ let MeshBuffer = cc.Class({ ); this._ib = new gfx.IndexBuffer( - renderer._device, + batcher._device, gfx.INDEX_FMT_UINT16, gfx.USAGE_STATIC, new ArrayBuffer(), @@ -34,7 +34,7 @@ let MeshBuffer = cc.Class({ this._iData = null; this._uintVData = null; - this._renderer = renderer; + this._batcher = batcher; this._initVDataCount = 256 * vertexFormat._bytes; // actually 256 * 4 * (vertexFormat._bytes / 4) this._initIDataCount = 256 * 6; @@ -87,9 +87,9 @@ let MeshBuffer = cc.Class({ }, request (vertexCount, indiceCount) { - if (this._renderer._buffer !== this) { - this._renderer._flush(); - this._renderer._buffer = this; + if (this._batcher._buffer !== this) { + this._batcher._flush(); + this._batcher._buffer = this; } this.requestStatic(vertexCount, indiceCount); diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/model-batcher.js similarity index 88% rename from cocos2d/core/renderer/webgl/render-component-walker.js rename to cocos2d/core/renderer/webgl/model-batcher.js index 2065f47200e..99fa8f53389 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/model-batcher.js @@ -23,34 +23,23 @@ THE SOFTWARE. ****************************************************************************/ -const macro = require('../../platform/CCMacro'); const renderEngine = require('../render-engine'); const defaultVertexFormat = require('./vertex-format').vfmtPosUvColor; const StencilManager = require('./stencil-manager'); -const dynamicAtlasManager = require('../utils/dynamic-atlas/manager'); -const RenderFlow = require('../render-flow'); const QuadBuffer = require('./quad-buffer'); const MeshBuffer = require('./mesh-buffer'); let idGenerater = new (require('../../platform/id-generater'))('VertextFormat'); -const gfx = renderEngine.gfx; const RecyclePool = renderEngine.RecyclePool; const InputAssembler = renderEngine.InputAssembler; -const FLOATS_PER_VERT = defaultVertexFormat._bytes / 4; -const BYTE_PER_INDEX = 2; -const MAX_VERTEX = macro.BATCH_VERTEX_COUNT; -const MAX_VERTEX_BYTES = MAX_VERTEX * defaultVertexFormat._bytes; -const MAX_INDICE = MAX_VERTEX * BYTE_PER_INDEX; -const MAX_INDICE_BYTES = MAX_INDICE * 2; - let _buffers = {}; const empty_material = new renderEngine.Material(); empty_material.updateHash(); -var RenderComponentWalker = function (device, renderScene) { +var ModelBatcher = function (device, renderScene) { this._renderScene = renderScene; this._device = device; this._stencilMgr = StencilManager.sharedManager; @@ -81,12 +70,10 @@ var RenderComponentWalker = function (device, renderScene) { this.parentOpacity = 1; this.parentOpacityDirty = 0; this.worldMatDirty = 0; - - RenderFlow.init(this); }; -RenderComponentWalker.prototype = { - constructor: RenderComponentWalker, +ModelBatcher.prototype = { + constructor: ModelBatcher, reset() { // Reset pools @@ -207,22 +194,17 @@ RenderComponentWalker.prototype = { assembler.renderIA(comp, this); }, - visit (scene) { - this.reset(); - this.walking = true; - - RenderFlow.render(scene); - - if (dynamicAtlasManager) { - dynamicAtlasManager.update(); + terminate () { + if (cc.dynamicAtlasManager && cc.dynamicAtlasManager.enabled) { + cc.dynamicAtlasManager.update(); } - + + // flush current rest Model this._flush(); for (let key in _buffers) { _buffers[key].uploadData(); } - this.walking = false; }, getBuffer (type, vertextFormat) { @@ -251,4 +233,4 @@ RenderComponentWalker.prototype = { } } -module.exports = RenderComponentWalker; \ No newline at end of file +module.exports = ModelBatcher; \ No newline at end of file diff --git a/cocos2d/deprecated.js b/cocos2d/deprecated.js index 3c2888325dd..3e6beaedae9 100644 --- a/cocos2d/deprecated.js +++ b/cocos2d/deprecated.js @@ -83,7 +83,7 @@ if (CC_DEBUG) { }, function (v) { cc.warnID(1400, `${ownerName}.${deprecatedProp}`, `${ownerName}.${newProp}`); descriptor.set.call(this, v); - }) + }); }) } @@ -354,7 +354,7 @@ if (CC_DEBUG) { ['rotationX', 'eulerAngles'], ['rotationY', 'eulerAngles'], ['rotation', 'angle'], - ]) + ]); markFunctionWarning(cc.Node.prototype, { getNodeToParentTransform: 'getLocalMatrix', diff --git a/cocos2d/particle/particle-system-assembler.js b/cocos2d/particle/particle-system-assembler.js index d99be29df89..d9968d1229c 100644 --- a/cocos2d/particle/particle-system-assembler.js +++ b/cocos2d/particle/particle-system-assembler.js @@ -38,7 +38,7 @@ var particleSystemAssembler = { comp._vertexFormat = vfmtPosUvColor; // Create quad buffer for vertex and index - comp._buffer = new QuadBuffer(renderer._walker, vfmtPosUvColor); + comp._buffer = new QuadBuffer(renderer._handle, vfmtPosUvColor); comp._ia = new renderEngine.InputAssembler(); comp._ia._vertexBuffer = comp._buffer._vb; diff --git a/modules.json b/modules.json index b475bfb33b8..4b3669fbb00 100644 --- a/modules.json +++ b/modules.json @@ -35,7 +35,7 @@ { "name": "WebGL Renderer", "entries": [ - "./cocos2d/core/renderer/webgl/render-component-walker.js", + "./cocos2d/core/renderer/webgl/model-batcher.js", "./cocos2d/core/renderer/webgl/assemblers/index.js", "./extensions/dragonbones/webgl-assembler.js" ] diff --git a/test/qunit/lib/polyfill-for-phantom.js b/test/qunit/lib/polyfill-for-phantom.js index 9752b43255e..f9946938d95 100644 --- a/test/qunit/lib/polyfill-for-phantom.js +++ b/test/qunit/lib/polyfill-for-phantom.js @@ -151,6 +151,24 @@ if (!Object.assign) { return to; } }); + } + + if (!Object.getOwnPropertyDescriptors) { + Object.defineProperty(Object, 'getOwnPropertyDescriptors', { + enumerable: false, + configurable: true, + writable: true, + value: function (target) { + var res = {}; + var props = Object.getOwnPropertyNames(target); + for (var i = 0; i < props.length; i++) { + var name = props[i]; + res[name] = Object.getOwnPropertyDescriptor(target, name); + } + return res; + } + }); + } } if (!Object.getOwnPropertySymbols) { diff --git a/test/qunit/unit-es5/test-spriteRenderer.js b/test/qunit/unit-es5/test-spriteRenderer.js index b39de423b70..effca1ff55f 100644 --- a/test/qunit/unit-es5/test-spriteRenderer.js +++ b/test/qunit/unit-es5/test-spriteRenderer.js @@ -190,6 +190,7 @@ if (!isPhantomJS) { sprite._assembler.updateRenderData(sprite); var vertices = sprite._renderData._data; + var uvs = sprite._spriteFrame.uv; strictEqual(vertices.length == 8, true, 'have 8 vertices'); strictEqual(vertices[0].x, 0, 'x0 test success'); @@ -200,14 +201,10 @@ if (!isPhantomJS) { strictEqual(vertices[1].y, 60, 'y1 test success'); strictEqual(vertices[2].y, 100, 'y2 test success'); // - deepClose(vertices[0].u, 10 / 100, 0.01, 'full quad u0 test success'); - deepClose(vertices[0].v, 70 / 100, 0.01, 'full quad v0 test success'); - deepClose(vertices[3].u, 50 / 100, 0.01, 'full quad u1 test success'); - deepClose(vertices[3].v, 10 / 100, 0.01, 'full quad v1 test success'); - deepClose(vertices[4].u, 10 / 100, 0.01, 'part quad u0 test success'); - deepClose(vertices[4].v, 70 / 100, 0.01, 'part quad v0 test success'); - deepClose(vertices[7].u, 30 / 100, 0.01, 'part quad u1 test success'); - deepClose(vertices[7].v, 30 / 100, 0.01, 'part quad v1 test success'); + deepClose(uvs[0], 10 / 100, 0.01, 'full quad u0 test success'); + deepClose(uvs[1], 70 / 100, 0.01, 'full quad v0 test success'); + deepClose(uvs[6], 50 / 100, 0.01, 'full quad u1 test success'); + deepClose(uvs[7], 10 / 100, 0.01, 'full quad v1 test success'); }; if (spriteFrame.textureLoaded()) { testCallBack(); From 5607f805353af0117be89886a2964edace7f3d90 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 12 Oct 2018 18:23:38 +0800 Subject: [PATCH 0141/1631] Upgrade render engine for native renderer (#3378) * Upgrade render engine * Fix Camera._node usage for JSB --- cocos2d/core/camera/CCCamera.js | 2 +- cocos2d/core/renderer/render-engine.js | 12 +- cocos2d/core/renderer/render-engine.jsb.js | 378 ++++++++++++++++----- 3 files changed, 294 insertions(+), 98 deletions(-) diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index c45909331a4..2a33b0a3256 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -49,7 +49,7 @@ let _debugCamera = null; function repositionDebugCamera () { if (!_debugCamera) return; - let node = _debugCamera._node; + let node = _debugCamera.getNode(); let canvas = cc.game.canvas; node.z = canvas.height / 1.1566; node.x = canvas.width / 2; diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index ce0fde66ebf..42562d48ad4 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -14239,7 +14239,7 @@ var SpriteMaterial = (function (Material$$1) { prototypeAccessors.useTexture.set = function (val) { this._effect.define('useTexture', val); }; - + prototypeAccessors.useModel.get = function () { return this._effect.getDefine('useModel'); }; @@ -14451,7 +14451,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useTexture.get = function () { - this._effect.getDefine('useTexture'); + return this._effect.getDefine('useTexture'); }; prototypeAccessors.useTexture.set = function (val) { @@ -14459,7 +14459,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useModel.get = function () { - this._effect.getDefine('useModel'); + return this._effect.getDefine('useModel'); }; prototypeAccessors.useModel.set = function (val) { @@ -14467,7 +14467,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useColor.get = function () { - this._effect.getDefine('useColor'); + return this._effect.getDefine('useColor'); }; prototypeAccessors.useColor.set = function (val) { @@ -14690,8 +14690,8 @@ var MeshMaterial = (function (Material$$1) { return MeshMaterial; }(Material)); -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + var Device$2 = function Device(canvasEL) { var ctx; diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 8368e2baee8..827c5a0ba09 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -372,6 +372,13 @@ VertexFormat.prototype.element = function element (attrName) { var gl$1 = window.__gl; var gfx$1 = window.gfx; +var _tmpGetSetDesc = { + get: undefined, + set: undefined, + enumerable: true, + configurable: true +}; + window.device = gfx$1.Device.getInstance(); window.device._gl = window.__gl; @@ -398,14 +405,18 @@ _p._ctor = function(device, format, usage, data, numVertices) { this.init(device, format._nativeObj, usage, data, numVertices); this._nativePtr = this.self(); }; -cc.defineGetterSetter(_p, "count", _p.getCount); +_tmpGetSetDesc.get = _p.getCount; +_tmpGetSetDesc.set = undefined; +Object.defineProperty(_p, "count", _tmpGetSetDesc); _p = gfx$1.IndexBuffer.prototype; _p._ctor = function(device, format, usage, data, numIndices) { this.init(device, format, usage, data, numIndices); this._nativePtr = this.self(); }; -cc.defineGetterSetter(_p, "count", _p.getCount); +_tmpGetSetDesc.get = _p.getCount; +_tmpGetSetDesc.set = undefined; +Object.defineProperty(_p, "count", _tmpGetSetDesc); gfx$1.VertexFormat = VertexFormat; Object.assign(gfx$1, enums); @@ -491,8 +502,11 @@ _p.updateSubImage = function(option) { this.updateSubImageNative(data); }; -cc.defineGetterSetter(_p, "_width", _p.getWidth); -cc.defineGetterSetter(_p, "_height", _p.getHeight); +_tmpGetSetDesc.get = _p.getWidth; +_tmpGetSetDesc.set = undefined; +Object.defineProperty(_p, "_width", _tmpGetSetDesc); +_tmpGetSetDesc.get = _p.getHeight; +Object.defineProperty(_p, "_height", _tmpGetSetDesc); _p = gfx$1.FrameBuffer.prototype; _p._ctor = function(device, width, height, options) { @@ -572,8 +586,106 @@ var config = { }; // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - + var renderer$1 = window.renderer; + +var Effect = function Effect(techniques, properties, defines) { + if ( properties === void 0 ) properties = {}; + if ( defines === void 0 ) defines = []; + + this._techniques = techniques; + this._properties = properties; + this._defines = defines; + + var techniqueObjs = []; + var techniqueObj; + for (var i = 0, len = techniques.length; i < len; ++i) { + techniqueObj = techniques[i]._nativeObj; + techniqueObjs.push(techniqueObj); + } + + this._nativeObj = new renderer$1.EffectNative(); + this._nativeObj.init(techniqueObjs, properties, defines); + this._nativePtr = this._nativeObj.self(); + + // TODO: check if params is valid for current technique??? +}; + +Effect.prototype.clear = function clear () { + this._techniques.length = 0; + this._properties = null; + this._defines.length = 0; +}; + +Effect.prototype.getTechnique = function getTechnique (stage) { + var this$1 = this; + + var stageID = config.stageID(stage); + for (var i = 0; i < this._techniques.length; ++i) { + var tech = this$1._techniques[i]; + if (tech.stageIDs & stageID) { + return tech; + } + } + + return null; +}; + +Effect.prototype.getProperty = function getProperty (name) { + return this._properties[name]; +}; + +Effect.prototype.setProperty = function setProperty (name, value) { + // TODO: check if params is valid for current technique??? + this._properties[name] = value; + this._nativeObj.setProperty(name, value); +}; + +Effect.prototype.getDefine = function getDefine (name) { + var this$1 = this; + + for (var i = 0; i < this._defines.length; ++i) { + var def = this$1._defines[i]; + if ( def.name === name ) { + return def.value; + } + } + + console.warn(("Failed to get define " + name + ", define not found.")); + return null; +}; + +Effect.prototype.define = function define (name, value) { + var this$1 = this; + + for (var i = 0; i < this._defines.length; ++i) { + var def = this$1._defines[i]; + if ( def.name === name ) { + def.value = value; + return; + } + } + + this._nativeObj.setDefine(name, value); + + console.warn(("Failed to set define " + name + ", define not found.")); +}; + +Effect.prototype.extractDefines = function extractDefines (out) { + var this$1 = this; + if ( out === void 0 ) out = {}; + + for (var i = 0; i < this._defines.length; ++i) { + var def = this$1._defines[i]; + out[def.name] = def.value; + } + + return out; +}; + +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +var renderer$2 = window.renderer; var _genID = 0; var Technique = function Technique(stages, parameters, passes, layer) { @@ -593,10 +705,34 @@ var Technique = function Technique(stages, parameters, passes, layer) { for (var i = 0, len = passes.length; i < len; ++i) { passesNative.push(passes[i]._native); } - this._nativeObj = new renderer$1.TechniqueNative(stages, parameters, passesNative, layer); + this._nativeObj = new renderer$2.TechniqueNative(stages, parameters, passesNative, layer); }; +Technique.prototype.copy = function copy (technique) { + var this$1 = this; + + this._id = technique._id; + this._stageIDs = technique._stageIDs; + + this._parameters = []; + for (var i = 0; i < technique._parameters.length; ++i) { + var parameter = technique._parameters[i]; + this$1._parameters.push({name: parameter.name, type: parameter.type}); + } + + for (var i$1 = 0; i$1 < technique._passes.length; ++i$1) { + var pass = this$1._passes[i$1]; + if (!pass) { + pass = new renderer$2.Pass(); + this$1._passes.push(pass); + } + pass.copy(technique._passes[i$1]); + } + this._passes.length = technique._passes.length; + this._layer = technique._layer; +}; + Technique.prototype.setStages = function setStages (stages) { this._stageIDs = config.stageIDs(stages); this._stages = stages; @@ -607,7 +743,7 @@ Technique.prototype.setStages = function setStages (stages) { // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. var gfx$4 = window.gfx; -var renderer$2 = window.renderer; +var renderer$3 = window.renderer; var Pass = function Pass(name) { this._programName = name; @@ -628,7 +764,10 @@ var Pass = function Pass(name) { // depth this._depthTest = false; this._depthWrite = false; - this._depthFunc = gfx$4.DS_FUNC_LESS, this._stencilTest = false; + this._depthFunc = gfx$4.DS_FUNC_LESS; + + // stencil + this._stencilTest = false; // front this._stencilFuncFront = gfx$4.DS_FUNC_ALWAYS; this._stencilRefFront = 0; @@ -672,10 +811,46 @@ var Pass = function Pass(name) { binary[22] = this._stencilZFailOpBack; binary[23] = this._stencilZPassOpBack; binary[24] = this._stencilWriteMaskBack; - this._native = new renderer$2.PassNative(); + this._native = new renderer$3.PassNative(); this._native.init(this._programName, binary); }; +Pass.prototype.copy = function copy (pass) { + this._programName = pass._programName; + // cullmode + this._cullMode = pass._cullMode; + // blending + this._blend = pass._blend; + this._blendEq = pass._blendEq; + this._blendAlphaEq = pass._blendAlphaEq; + this._blendSrc = pass._blendSrc; + this._blendDst = pass._blendDst; + this._blendSrcAlpha = pass._blendSrcAlpha; + this._blendDstAlpha = pass._blendDstAlpha; + this._blendColor = pass._blendColor; + // depth + this._depthTest = pass._depthTest; + this._depthWrite = pass._depthWrite; + this._depthFunc = pass._depthFunc; + this._stencilTest = pass._stencilTest; + // front + this._stencilFuncFront = pass._stencilFuncFront; + this._stencilRefFront = pass._stencilRefFront; + this._stencilMaskFront = pass._stencilMaskFront; + this._stencilFailOpFront = pass._stencilFailOpFront; + this._stencilZFailOpFront = pass._stencilZFailOpFront; + this._stencilZPassOpFront = pass._stencilZPassOpFront; + this._stencilWriteMaskFront = pass._stencilWriteMaskFront; + // back + this._stencilFuncBack = pass._stencilFuncBack; + this._stencilRefBack = pass._stencilRefBack; + this._stencilMaskBack = pass._stencilMaskBack; + this._stencilFailOpBack = pass._stencilFailOpBack; + this._stencilZFailOpBack = pass._stencilZFailOpBack; + this._stencilZPassOpBack = pass._stencilZPassOpBack; + this._stencilWriteMaskBack = pass._stencilWriteMaskBack; +}; + Pass.prototype.setCullMode = function setCullMode (cullMode) { this._cullMode = cullMode; @@ -915,49 +1090,49 @@ Object.defineProperties( Model.prototype, prototypeAccessors ); // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -var renderer$3 = window.renderer; +var renderer$4 = window.renderer; // projection -renderer$3.PROJ_PERSPECTIVE = 0; -renderer$3.PROJ_ORTHO = 1; +renderer$4.PROJ_PERSPECTIVE = 0; +renderer$4.PROJ_ORTHO = 1; // lights -renderer$3.LIGHT_DIRECTIONAL = 0; -renderer$3.LIGHT_POINT = 1; -renderer$3.LIGHT_SPOT = 2; +renderer$4.LIGHT_DIRECTIONAL = 0; +renderer$4.LIGHT_POINT = 1; +renderer$4.LIGHT_SPOT = 2; // shadows -renderer$3.SHADOW_NONE = 0; -renderer$3.SHADOW_HARD = 1; -renderer$3.SHADOW_SOFT = 2; +renderer$4.SHADOW_NONE = 0; +renderer$4.SHADOW_HARD = 1; +renderer$4.SHADOW_SOFT = 2; // parameter type -renderer$3.PARAM_INT = 0; -renderer$3.PARAM_INT2 = 1; -renderer$3.PARAM_INT3 = 2; -renderer$3.PARAM_INT4 = 3; -renderer$3.PARAM_FLOAT = 4; -renderer$3.PARAM_FLOAT2 = 5; -renderer$3.PARAM_FLOAT3 = 6; -renderer$3.PARAM_FLOAT4 = 7; -renderer$3.PARAM_COLOR3 = 8; -renderer$3.PARAM_COLOR4 = 9; -renderer$3.PARAM_MAT2 = 10; -renderer$3.PARAM_MAT3 = 11; -renderer$3.PARAM_MAT4 = 12; -renderer$3.PARAM_TEXTURE_2D = 13; -renderer$3.PARAM_TEXTURE_CUBE = 14; +renderer$4.PARAM_INT = 0; +renderer$4.PARAM_INT2 = 1; +renderer$4.PARAM_INT3 = 2; +renderer$4.PARAM_INT4 = 3; +renderer$4.PARAM_FLOAT = 4; +renderer$4.PARAM_FLOAT2 = 5; +renderer$4.PARAM_FLOAT3 = 6; +renderer$4.PARAM_FLOAT4 = 7; +renderer$4.PARAM_COLOR3 = 8; +renderer$4.PARAM_COLOR4 = 9; +renderer$4.PARAM_MAT2 = 10; +renderer$4.PARAM_MAT3 = 11; +renderer$4.PARAM_MAT4 = 12; +renderer$4.PARAM_TEXTURE_2D = 13; +renderer$4.PARAM_TEXTURE_CUBE = 14; // clear flags -renderer$3.CLEAR_COLOR = 1; -renderer$3.CLEAR_DEPTH = 2; -renderer$3.CLEAR_STENCIL = 4; -renderer$3.InputAssembler = InputAssembler; -renderer$3.config = config; -renderer$3.Effect = Effect; -renderer$3.Technique = Technique; -renderer$3.Pass = Pass; -renderer$3.Model = Model; +renderer$4.CLEAR_COLOR = 1; +renderer$4.CLEAR_DEPTH = 2; +renderer$4.CLEAR_STENCIL = 4; +renderer$4.InputAssembler = InputAssembler; +renderer$4.config = config; +renderer$4.Effect = Effect; +renderer$4.Technique = Technique; +renderer$4.Pass = Pass; +renderer$4.Model = Model; var models = []; var sizeOfModel = 13; @@ -1003,7 +1178,7 @@ var fillModelData = function() { }; // ForwardRenderer adapter -var _p$1 = renderer$3.ForwardRenderer.prototype; +var _p$1 = renderer$4.ForwardRenderer.prototype; _p$1._ctor = function(device, builtin) { this.init(device, builtin.programTemplates, builtin.defaultTexture, window.innerWidth, window.innerHeight); }; @@ -1013,15 +1188,22 @@ _p$1.render = function(scene) { models.length = 0; }; +_p$1.renderCamera = function(camera, scene) { + fillModelData(); + this.renderCameraNative(camera, scene, modelsData); + + models.length = 0; +}; // Scene -_p$1 = renderer$3.Scene.prototype; +_p$1 = renderer$4.Scene.prototype; _p$1.addModel = function(model) { models.push(model); }; _p$1.removeModel = function() {}; var chunks = { + 'skinning.vert': '\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}', }; var templates = [ @@ -1032,6 +1214,17 @@ var templates = [ defines: [ ], }, + { + name: 'mesh', + vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\n#ifdef useAttributeColor\n attribute vec4 a_color;\n varying vec4 v_color;\n#endif\n#ifdef useTexture\n attribute vec2 a_uv0;\n varying vec2 uv0;\n#endif\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useSkinning\n \nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef useSkinning\n mvp = mvp * skinMatrix();\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n #ifdef useAttributeColor\n v_color = a_color;\n #endif\n gl_Position = pos;\n}', + frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying vec2 uv0;\n#endif\n#ifdef useAttributeColor\n varying vec4 v_color;\n#endif\nuniform vec4 color;\nvoid main () {\n vec4 o = color;\n \n #ifdef useAttributeColor\n o *= v_color;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n gl_FragColor = o;\n}', + defines: [ + { name: 'useTexture', }, + { name: 'useModel', }, + { name: 'useSkinning', }, + { name: 'useJointsTexture', }, + { name: 'useAttributeColor', } ], + }, { name: 'sprite', vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', @@ -2549,7 +2742,7 @@ function murmurhash2_32_gc(str, seed) { return h >>> 0; } -var renderer$5 = window.renderer; +var renderer$6 = window.renderer; // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. @@ -2622,33 +2815,33 @@ function computeHash(material) { continue; } switch(param.type) { - case renderer$5.PARAM_INT: - case renderer$5.PARAM_FLOAT: + case renderer$6.PARAM_INT: + case renderer$6.PARAM_FLOAT: hashData += prop + ';'; break; - case renderer$5.PARAM_INT2: - case renderer$5.PARAM_FLOAT2: + case renderer$6.PARAM_INT2: + case renderer$6.PARAM_FLOAT2: hashData += prop.x + ',' + prop.y + ';'; break; - case renderer$5.PARAM_INT4: - case renderer$5.PARAM_FLOAT4: + case renderer$6.PARAM_INT4: + case renderer$6.PARAM_FLOAT4: hashData += prop.x + ',' + prop.y + ',' + prop.z + ',' + prop.w + ';'; break; - case renderer$5.PARAM_COLOR4: + case renderer$6.PARAM_COLOR4: hashData += prop.r + ',' + prop.g + ',' + prop.b + ',' + prop.a + ';'; break; - case renderer$5.PARAM_MAT2: + case renderer$6.PARAM_MAT2: hashData += prop.m00 + ',' + prop.m01 + ',' + prop.m02 + ',' + prop.m03 + ';'; break; - case renderer$5.PARAM_TEXTURE_2D: - case renderer$5.PARAM_TEXTURE_CUBE: + case renderer$6.PARAM_TEXTURE_2D: + case renderer$6.PARAM_TEXTURE_CUBE: hashData += material._texIds[propKey] + ';'; break; - case renderer$5.PARAM_INT3: - case renderer$5.PARAM_FLOAT3: - case renderer$5.PARAM_COLOR3: - case renderer$5.PARAM_MAT3: - case renderer$5.PARAM_MAT4: + case renderer$6.PARAM_INT3: + case renderer$6.PARAM_FLOAT3: + case renderer$6.PARAM_COLOR3: + case renderer$6.PARAM_MAT3: + case renderer$6.PARAM_MAT4: hashData += JSON.stringify(prop) + ';'; break; default: @@ -2700,7 +2893,7 @@ var SpriteMaterial = (function (Material$$1) { function SpriteMaterial() { Material$$1.call(this, false); - var pass = new renderer$5.Pass('sprite'); + var pass = new renderer$6.Pass('sprite'); pass.setDepth(false, false); pass.setCullMode(gfx$5.CULL_NONE); pass.setBlend( @@ -2710,18 +2903,18 @@ var SpriteMaterial = (function (Material$$1) { gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer$5.Technique( + var mainTech = new renderer$6.Technique( ['transparent'], [ - { name: 'texture', type: renderer$5.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer$5.PARAM_COLOR4 } ], + { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, + { name: 'color', type: renderer$6.PARAM_COLOR4 } ], [ pass ] ); this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer$5.Effect( + this._effect = new renderer$6.Effect( [ mainTech ], { @@ -2750,7 +2943,7 @@ var SpriteMaterial = (function (Material$$1) { }; prototypeAccessors.useTexture.get = function () { - this._effect.getDefine('useTexture'); + return this._effect.getDefine('useTexture'); }; prototypeAccessors.useTexture.set = function (val) { @@ -2758,7 +2951,7 @@ var SpriteMaterial = (function (Material$$1) { }; prototypeAccessors.useModel.get = function () { - this._effect.getDefine('useModel'); + return this._effect.getDefine('useModel'); }; prototypeAccessors.useModel.set = function (val) { @@ -2766,7 +2959,7 @@ var SpriteMaterial = (function (Material$$1) { }; prototypeAccessors.use2DPos.get = function () { - this._effect.getDefine('use2DPos'); + return this._effect.getDefine('use2DPos'); }; prototypeAccessors.use2DPos.set = function (val) { @@ -2774,7 +2967,7 @@ var SpriteMaterial = (function (Material$$1) { }; prototypeAccessors.useColor.get = function () { - this._effect.getDefine('useColor'); + return this._effect.getDefine('useColor'); }; prototypeAccessors.useColor.set = function (val) { @@ -2808,6 +3001,7 @@ var SpriteMaterial = (function (Material$$1) { SpriteMaterial.prototype.clone = function clone () { var copy = new SpriteMaterial(); + copy._mainTech.copy(this._mainTech); copy.texture = this.texture; copy.useTexture = this.useTexture; copy.useModel = this.useModel; @@ -2828,7 +3022,7 @@ var GraySpriteMaterial = (function (Material$$1) { function GraySpriteMaterial() { Material$$1.call(this, false); - var pass = new renderer$5.Pass('gray_sprite'); + var pass = new renderer$6.Pass('gray_sprite'); pass.setDepth(false, false); pass.setCullMode(gfx$5.CULL_NONE); pass.setBlend( @@ -2838,18 +3032,18 @@ var GraySpriteMaterial = (function (Material$$1) { gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer$5.Technique( + var mainTech = new renderer$6.Technique( ['transparent'], [ - { name: 'texture', type: renderer$5.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer$5.PARAM_COLOR4 } ], + { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, + { name: 'color', type: renderer$6.PARAM_COLOR4 } ], [ pass ] ); this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer$5.Effect( + this._effect = new renderer$6.Effect( [ mainTech ], { @@ -2899,6 +3093,7 @@ var GraySpriteMaterial = (function (Material$$1) { GraySpriteMaterial.prototype.clone = function clone () { var copy = new GraySpriteMaterial(); + copy._mainTech.copy(this._mainTech); copy.texture = this.texture; copy.color = this.color; copy.updateHash(); @@ -2916,7 +3111,7 @@ var StencilMaterial = (function (Material$$1) { function StencilMaterial() { Material$$1.call(this, false); - this._pass = new renderer$5.Pass('sprite'); + this._pass = new renderer$6.Pass('sprite'); this._pass.setDepth(false, false); this._pass.setCullMode(gfx$5.CULL_NONE); this._pass.setBlend( @@ -2926,18 +3121,18 @@ var StencilMaterial = (function (Material$$1) { gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer$5.Technique( + var mainTech = new renderer$6.Technique( ['transparent'], [ - { name: 'texture', type: renderer$5.PARAM_TEXTURE_2D }, - { name: 'alphaThreshold', type: renderer$5.PARAM_FLOAT }, - { name: 'color', type: renderer$5.PARAM_COLOR4 } ], + { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, + { name: 'alphaThreshold', type: renderer$6.PARAM_FLOAT }, + { name: 'color', type: renderer$6.PARAM_COLOR4 } ], [ this._pass ] ); - this._effect = new renderer$5.Effect( + this._effect = new renderer$6.Effect( [ mainTech ], { @@ -2966,7 +3161,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useTexture.get = function () { - this._effect.getDefine('useTexture'); + return this._effect.getDefine('useTexture'); }; prototypeAccessors.useTexture.set = function (val) { @@ -2974,7 +3169,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useModel.get = function () { - this._effect.getDefine('useModel'); + return this._effect.getDefine('useModel'); }; prototypeAccessors.useModel.set = function (val) { @@ -2982,7 +3177,7 @@ var StencilMaterial = (function (Material$$1) { }; prototypeAccessors.useColor.get = function () { - this._effect.getDefine('useColor'); + return this._effect.getDefine('useColor'); }; prototypeAccessors.useColor.set = function (val) { @@ -3011,6 +3206,7 @@ var StencilMaterial = (function (Material$$1) { StencilMaterial.prototype.clone = function clone () { var copy = new StencilMaterial(); + copy._mainTech.copy(this._mainTech); copy.useTexture = this.useTexture; copy.useModel = this.useModel; copy.useColor = this.useColor; @@ -10432,25 +10628,25 @@ var canvas = { // intenral // deps // Add stage to renderer -renderer$3.config.addStage('transparent'); +renderer$4.config.addStage('transparent'); var renderEngine = { // core classes Device: gfx$1.Device, - ForwardRenderer: renderer$3.ForwardRenderer, + ForwardRenderer: renderer$4.ForwardRenderer, Texture2D: gfx$1.Texture2D, // Canvas render support canvas: canvas, // render scene - Scene: renderer$3.Scene, - Camera: renderer$3.Camera, - View: renderer$3.View, - Model: renderer$3.Model, + Scene: renderer$4.Scene, + Camera: renderer$4.Camera, + View: renderer$4.View, + Model: renderer$4.Model, RenderData: RenderData, IARenderData: IARenderData, - InputAssembler: renderer$3.InputAssembler, + InputAssembler: renderer$4.InputAssembler, // assets Asset: Asset, @@ -10471,7 +10667,7 @@ var renderEngine = { // modules math: math, - renderer: renderer$3, + renderer: renderer$4, gfx: gfx$1, }; From 98d72f8fa91bf331b8cd73d2f196f4e80902832c Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 24 Oct 2018 16:58:49 +0800 Subject: [PATCH 0142/1631] Small tweaks --- cocos2d/core/CCNode.js | 1 - cocos2d/core/renderer/index.js | 7 +++---- cocos2d/core/renderer/render-engine.jsb.js | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 5c913d0f7de..d8ee1710697 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -32,7 +32,6 @@ const math = require('./renderer/render-engine').math; const AffineTrans = require('./utils/affine-transform'); const eventManager = require('./event-manager'); const macro = require('./platform/CCMacro'); -const misc = require('./utils/misc'); const js = require('./platform/js'); const Event = require('./event/event'); const EventTarget = require('./event/event-target'); diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 9568e45218a..0039990d0ce 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -24,7 +24,6 @@ ****************************************************************************/ const renderEngine = require('./render-engine'); -const RenderFlow = require('./render-flow'); function _initBuiltins(device) { let defaultTexture = new renderEngine.Texture2D(device, { @@ -114,7 +113,7 @@ cc.renderer = module.exports = { this.scene = new renderEngine.Scene(); this._handle = new ModelBatcher(this.device, this.scene); - RenderFlow.init(this._handle); + cc.RenderFlow.init(this._handle); let builtins = _initBuiltins(this.device); this._forward = new renderEngine.ForwardRenderer(this.device, builtins); }, @@ -136,7 +135,7 @@ cc.renderer = module.exports = { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }; this._handle = new canvasRenderer.RenderComponentHandle(this.device, this._camera); - RenderFlow.init(this._handle); + cc.RenderFlow.init(this._handle); this._forward = new canvasRenderer.ForwardRenderer(); }, @@ -161,7 +160,7 @@ cc.renderer = module.exports = { this.device._stats.drawcalls = 0; if (ecScene) { // walk entity component scene to generate models - RenderFlow.visit(ecScene); + cc.RenderFlow.visit(ecScene); // Render models in renderer scene this._forward.render(this.scene); this.drawCalls = this.device._stats.drawcalls; diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 827c5a0ba09..1e3caff6f0d 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -466,7 +466,7 @@ function convertOptions(options) { options.glType = gltf.pixelType; options.bpp = gltf.bpp; options.compressed = options.glFormat >= enums.TEXTURE_FMT_RGB_DXT1 && - options.gltf <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1; + options.glFormat <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1; } convertImages(options.images); From 267ec607020dc5d0ce463b396e03d4828d9a2cd1 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 24 Oct 2018 19:38:14 +0800 Subject: [PATCH 0143/1631] Create node proxy for native renderer --- cocos2d/core/CCNode.js | 31 ++++++++++++++++++++++++++++++- cocos2d/core/platform/CCMacro.js | 2 -- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index d8ee1710697..6a1995ef449 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -287,6 +287,13 @@ var EventType = cc.Enum({ * @static */ GROUP_CHANGED: 'group-changed', + /** + * !#en The event type for node's sibling order changed. + * !#zh 当节点在兄弟节点中的顺序发生变化时触发的事件。 + * @property {String} SIBLING_ORDER_CHANGED + * @static + */ + SIBLING_ORDER_CHANGED: 'sibling-order-changed', }); var _touchEvents = [ @@ -1113,6 +1120,7 @@ let NodeDefines = { if (this._zIndex !== value) { this._zIndex = value; this._localZOrder = (this._localZOrder & 0x0000ffff) | (value << 16); + this.emit(EventType.SIBLING_ORDER_CHANGED); if (this._parent) { this._parent._delaySort(); @@ -1160,6 +1168,12 @@ let NodeDefines = { this._cullingMask = 1 << this.groupIndex; this._eulerAngles = cc.v3(); + + // Proxy + if (CC_JSB) { + this._proxy = new renderer.NodeProxy(); + this._proxy.bind(this); + } }, statics: { @@ -1169,7 +1183,6 @@ let NodeDefines = { isNode (obj) { return obj instanceof Node && (obj.constructor === Node || !(obj instanceof cc.Scene)); }, - BuiltinGroupIndex }, @@ -1232,6 +1245,10 @@ let NodeDefines = { this._parent = null; } } + + if (CC_JSB) { + this._proxy.unbind(); + } }, _onPostActivated (active) { @@ -1269,6 +1286,11 @@ let NodeDefines = { if (cc._widgetManager) { cc._widgetManager._nodesOrderDirty = true; } + + // Node proxy + if (CC_JSB) { + this._parent && this._proxy.updateParent(this._parent._proxy); + } }, // INTERNAL @@ -2654,11 +2676,17 @@ let NodeDefines = { }, setLocalDirty (flag) { + if (CC_JSB) { + this._proxy.setMatrixDirty(); + } this._localMatDirty = this._localMatDirty | flag; this._worldMatDirty = true; }, setWorldDirty () { + if (CC_JSB) { + this._proxy.setMatrixDirty(); + } this._worldMatDirty = true; }, @@ -3024,6 +3052,7 @@ let NodeDefines = { _updateOrderOfArrival () { var arrivalOrder = ++_globalOrderOfArrival; this._localZOrder = (this._localZOrder & 0xffff0000) | arrivalOrder; + this.emit(EventType.SIBLING_ORDER_CHANGED); }, /** diff --git a/cocos2d/core/platform/CCMacro.js b/cocos2d/core/platform/CCMacro.js index a2e247bf59d..c00dfcb4de6 100644 --- a/cocos2d/core/platform/CCMacro.js +++ b/cocos2d/core/platform/CCMacro.js @@ -25,8 +25,6 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('./js'); - /** * Predefined constants * @class macro From b48e0f4d2f46b717aaffad5438c249107a657eb4 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 25 Oct 2018 18:27:04 +0800 Subject: [PATCH 0144/1631] Fix native renderer issues --- cocos2d/core/renderer/render-engine.canvas.js | 4 +- cocos2d/core/renderer/render-engine.js | 216 +++++++++--------- cocos2d/core/renderer/render-engine.jsb.js | 7 +- 3 files changed, 115 insertions(+), 112 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js index 7cac7c404e2..a5a7b19a6d7 100644 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ b/cocos2d/core/renderer/render-engine.canvas.js @@ -2,8 +2,8 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - render-engine v1.2.0 - https://www.cocos.com/ + render-engine v1.2.1 + http://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, diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 42562d48ad4..84071bc5d1c 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -2,8 +2,8 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - render-engine v1.2.0 - https://www.cocos.com/ + render-engine v1.2.1 + http://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, @@ -10339,6 +10339,8 @@ var Pass = function Pass(name) { this._depthTest = false; this._depthWrite = false; this._depthFunc = gfx.DS_FUNC_LESS; + + // stencil this._stencilTest = false; // front this._stencilFuncFront = gfx.DS_FUNC_ALWAYS; @@ -10358,42 +10360,6 @@ var Pass = function Pass(name) { this._stencilWriteMaskBack = 0xff; }; -Pass.prototype.copy = function (pass) { - this._programName = pass._programName; - // cullmode - this._cullMode = pass._cullMode; - // blending - this._blend = pass._blend; - this._blendEq = pass._blendEq; - this._blendAlphaEq = pass._blendAlphaEq; - this._blendSrc = pass._blendSrc; - this._blendDst = pass._blendDst; - this._blendSrcAlpha = pass._blendSrcAlpha; - this._blendDstAlpha = pass._blendDstAlpha; - this._blendColor = pass._blendColor; - // depth - this._depthTest = pass._depthTest; - this._depthWrite = pass._depthWrite; - this._depthFunc = pass._depthFunc; - this._stencilTest = pass._stencilTest; - // front - this._stencilFuncFront = pass._stencilFuncFront; - this._stencilRefFront = pass._stencilRefFront; - this._stencilMaskFront = pass._stencilMaskFront; - this._stencilFailOpFront = pass._stencilFailOpFront; - this._stencilZFailOpFront = pass._stencilZFailOpFront; - this._stencilZPassOpFront = pass._stencilZPassOpFront; - this._stencilWriteMaskFront = pass._stencilWriteMaskFront; - // back - this._stencilFuncBack = pass._stencilFuncBack; - this._stencilRefBack = pass._stencilRefBack; - this._stencilMaskBack = pass._stencilMaskBack; - this._stencilFailOpBack = pass._stencilFailOpBack; - this._stencilZFailOpBack = pass._stencilZFailOpBack; - this._stencilZPassOpBack = pass._stencilZPassOpBack; - this._stencilWriteMaskBack = pass._stencilWriteMaskBack; -}; - Pass.prototype.setCullMode = function setCullMode (cullMode) { this._cullMode = cullMode; }; @@ -10497,6 +10463,42 @@ Pass.prototype.disableStencilTest = function disableStencilTest () { this._stencilTest = false; }; +Pass.prototype.copy = function copy (pass) { + this._programName = pass._programName; + // cullmode + this._cullMode = pass._cullMode; + // blending + this._blend = pass._blend; + this._blendEq = pass._blendEq; + this._blendAlphaEq = pass._blendAlphaEq; + this._blendSrc = pass._blendSrc; + this._blendDst = pass._blendDst; + this._blendSrcAlpha = pass._blendSrcAlpha; + this._blendDstAlpha = pass._blendDstAlpha; + this._blendColor = pass._blendColor; + // depth + this._depthTest = pass._depthTest; + this._depthWrite = pass._depthWrite; + this._depthFunc = pass._depthFunc; + this._stencilTest = pass._stencilTest; + // front + this._stencilFuncFront = pass._stencilFuncFront; + this._stencilRefFront = pass._stencilRefFront; + this._stencilMaskFront = pass._stencilMaskFront; + this._stencilFailOpFront = pass._stencilFailOpFront; + this._stencilZFailOpFront = pass._stencilZFailOpFront; + this._stencilZPassOpFront = pass._stencilZPassOpFront; + this._stencilWriteMaskFront = pass._stencilWriteMaskFront; + // back + this._stencilFuncBack = pass._stencilFuncBack; + this._stencilRefBack = pass._stencilRefBack; + this._stencilMaskBack = pass._stencilMaskBack; + this._stencilFailOpBack = pass._stencilFailOpBack; + this._stencilZFailOpBack = pass._stencilZFailOpBack; + this._stencilZPassOpBack = pass._stencilZPassOpBack; + this._stencilWriteMaskBack = pass._stencilWriteMaskBack; +}; + // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. var _stageOffset = 0; @@ -10552,26 +10554,36 @@ var Technique = function Technique(stages, parameters, passes, layer) { var prototypeAccessors$3 = { passes: { configurable: true },stageIDs: { configurable: true } }; -Technique.prototype.copy = function (technique) { +prototypeAccessors$3.passes.get = function () { + return this._passes; +}; + +prototypeAccessors$3.stageIDs.get = function () { + return this._stageIDs; +}; + +Technique.prototype.copy = function copy (technique) { + var this$1 = this; + this._id = technique._id; this._stageIDs = technique._stageIDs; - + this._parameters = []; - for (let i = 0; i < technique._parameters.length; ++i) { - let parameter = technique._parameters[i]; - this._parameters.push({name: parameter.name, type: parameter.type}); + for (var i = 0; i < technique._parameters.length; ++i) { + var parameter = technique._parameters[i]; + this$1._parameters.push({name: parameter.name, type: parameter.type}); } - - for (let i = 0; i < technique._passes.length; ++i) { - let pass = this._passes[i]; + + for (var i$1 = 0; i$1 < technique._passes.length; ++i$1) { + var pass = this$1._passes[i$1]; if (!pass) { pass = new renderer.Pass(); - this._passes.push(pass); + this$1._passes.push(pass); } - pass.copy(technique._passes[i]); + pass.copy(technique._passes[i$1]); } this._passes.length = technique._passes.length; - + this._layer = technique._layer; }; @@ -10579,14 +10591,6 @@ Technique.prototype.setStages = function setStages (stages) { this._stageIDs = config.stageIDs(stages); }; -prototypeAccessors$3.passes.get = function () { - return this._passes; -}; - -prototypeAccessors$3.stageIDs.get = function () { - return this._stageIDs; -}; - Object.defineProperties( Technique.prototype, prototypeAccessors$3 ); // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. @@ -13644,7 +13648,7 @@ Base.prototype._draw = function _draw (item) { } }; -var renderer = { +var renderer$1 = { // config addStage: config.addStage, @@ -13666,7 +13670,7 @@ var renderer = { Base: Base, ProgramLib: ProgramLib, }; -Object.assign(renderer, enums); +Object.assign(renderer$1, enums); // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. @@ -13746,7 +13750,7 @@ var ForwardRenderer = (function (superclass) { }; return ForwardRenderer; -}(renderer.Base)); +}(renderer$1.Base)); var chunks = { 'skinning.vert': '\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}', @@ -14107,33 +14111,33 @@ function computeHash(material) { continue; } switch(param.type) { - case renderer.PARAM_INT: - case renderer.PARAM_FLOAT: + case renderer$1.PARAM_INT: + case renderer$1.PARAM_FLOAT: hashData += prop + ';'; break; - case renderer.PARAM_INT2: - case renderer.PARAM_FLOAT2: + case renderer$1.PARAM_INT2: + case renderer$1.PARAM_FLOAT2: hashData += prop.x + ',' + prop.y + ';'; break; - case renderer.PARAM_INT4: - case renderer.PARAM_FLOAT4: + case renderer$1.PARAM_INT4: + case renderer$1.PARAM_FLOAT4: hashData += prop.x + ',' + prop.y + ',' + prop.z + ',' + prop.w + ';'; break; - case renderer.PARAM_COLOR4: + case renderer$1.PARAM_COLOR4: hashData += prop.r + ',' + prop.g + ',' + prop.b + ',' + prop.a + ';'; break; - case renderer.PARAM_MAT2: + case renderer$1.PARAM_MAT2: hashData += prop.m00 + ',' + prop.m01 + ',' + prop.m02 + ',' + prop.m03 + ';'; break; - case renderer.PARAM_TEXTURE_2D: - case renderer.PARAM_TEXTURE_CUBE: + case renderer$1.PARAM_TEXTURE_2D: + case renderer$1.PARAM_TEXTURE_CUBE: hashData += material._texIds[propKey] + ';'; break; - case renderer.PARAM_INT3: - case renderer.PARAM_FLOAT3: - case renderer.PARAM_COLOR3: - case renderer.PARAM_MAT3: - case renderer.PARAM_MAT4: + case renderer$1.PARAM_INT3: + case renderer$1.PARAM_FLOAT3: + case renderer$1.PARAM_COLOR3: + case renderer$1.PARAM_MAT3: + case renderer$1.PARAM_MAT4: hashData += JSON.stringify(prop) + ';'; break; default: @@ -14183,7 +14187,7 @@ var SpriteMaterial = (function (Material$$1) { function SpriteMaterial() { Material$$1.call(this, false); - var pass = new renderer.Pass('sprite'); + var pass = new renderer$1.Pass('sprite'); pass.setDepth(false, false); pass.setCullMode(gfx.CULL_NONE); pass.setBlend( @@ -14193,18 +14197,18 @@ var SpriteMaterial = (function (Material$$1) { gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer.Technique( + var mainTech = new renderer$1.Technique( ['transparent'], [ - { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer.PARAM_COLOR4 } ], + { name: 'texture', type: renderer$1.PARAM_TEXTURE_2D }, + { name: 'color', type: renderer$1.PARAM_COLOR4 } ], [ pass ] ); this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer.Effect( + this._effect = new renderer$1.Effect( [ mainTech ], { @@ -14312,7 +14316,7 @@ var GraySpriteMaterial = (function (Material$$1) { function GraySpriteMaterial() { Material$$1.call(this, false); - var pass = new renderer.Pass('gray_sprite'); + var pass = new renderer$1.Pass('gray_sprite'); pass.setDepth(false, false); pass.setCullMode(gfx.CULL_NONE); pass.setBlend( @@ -14322,18 +14326,18 @@ var GraySpriteMaterial = (function (Material$$1) { gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer.Technique( + var mainTech = new renderer$1.Technique( ['transparent'], [ - { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer.PARAM_COLOR4 } ], + { name: 'texture', type: renderer$1.PARAM_TEXTURE_2D }, + { name: 'color', type: renderer$1.PARAM_COLOR4 } ], [ pass ] ); this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer.Effect( + this._effect = new renderer$1.Effect( [ mainTech ], { @@ -14401,7 +14405,7 @@ var StencilMaterial = (function (Material$$1) { function StencilMaterial() { Material$$1.call(this, false); - this._pass = new renderer.Pass('sprite'); + this._pass = new renderer$1.Pass('sprite'); this._pass.setDepth(false, false); this._pass.setCullMode(gfx.CULL_NONE); this._pass.setBlend( @@ -14411,18 +14415,18 @@ var StencilMaterial = (function (Material$$1) { gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer.Technique( + var mainTech = new renderer$1.Technique( ['transparent'], [ - { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'alphaThreshold', type: renderer.PARAM_FLOAT }, - { name: 'color', type: renderer.PARAM_COLOR4 } ], + { name: 'texture', type: renderer$1.PARAM_TEXTURE_2D }, + { name: 'alphaThreshold', type: renderer$1.PARAM_FLOAT }, + { name: 'color', type: renderer$1.PARAM_COLOR4 } ], [ this._pass ] ); - this._effect = new renderer.Effect( + this._effect = new renderer$1.Effect( [ mainTech ], { @@ -14517,7 +14521,7 @@ var MeshMaterial = (function (Material$$1) { function MeshMaterial() { Material$$1.call(this, false); - var pass = new renderer.Pass('mesh'); + var pass = new renderer$1.Pass('mesh'); pass.setDepth(false, false); pass.setCullMode(gfx.CULL_NONE); pass.setBlend( @@ -14527,21 +14531,21 @@ var MeshMaterial = (function (Material$$1) { gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer.Technique( + var mainTech = new renderer$1.Technique( ['transparent'], [ - { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer.PARAM_COLOR4 }, + { name: 'texture', type: renderer$1.PARAM_TEXTURE_2D }, + { name: 'color', type: renderer$1.PARAM_COLOR4 }, - { name: 'u_jointsTexture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'u_jointsTextureSize', type: renderer.PARAM_FLOAT }, - { name: 'u_jointMatrices', type: renderer.PARAM_MAT4 } ], + { name: 'u_jointsTexture', type: renderer$1.PARAM_TEXTURE_2D }, + { name: 'u_jointsTextureSize', type: renderer$1.PARAM_FLOAT }, + { name: 'u_jointMatrices', type: renderer$1.PARAM_MAT4 } ], [ pass ] ); - this._effect = new renderer.Effect( + this._effect = new renderer$1.Effect( [ mainTech ], { @@ -14820,15 +14824,15 @@ var canvas = { // intenral // deps -var Scene$2 = renderer.Scene; -var Camera$2 = renderer.Camera; -var View$2 = renderer.View; +var Scene$2 = renderer$1.Scene; +var Camera$2 = renderer$1.Camera; +var View$2 = renderer$1.View; var Texture2D$4 = gfx.Texture2D; var Device$4 = gfx.Device; -var Model$2 = renderer.Model; -var InputAssembler$2 = renderer.InputAssembler; +var Model$2 = renderer$1.Model; +var InputAssembler$2 = renderer$1.InputAssembler; -renderer.addStage('transparent'); +renderer$1.addStage('transparent'); var renderEngine = { // core classes @@ -14868,7 +14872,7 @@ var renderEngine = { // modules math: math, - renderer: renderer, + renderer: renderer$1, gfx: gfx, }; diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 1e3caff6f0d..b100370244b 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -2,8 +2,8 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - render-engine v1.2.0 - https://www.cocos.com/ + render-engine v1.2.1 + http://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, @@ -662,12 +662,11 @@ Effect.prototype.define = function define (name, value) { var def = this$1._defines[i]; if ( def.name === name ) { def.value = value; + this$1._nativeObj.setDefineValue(name, value); return; } } - this._nativeObj.setDefine(name, value); - console.warn(("Failed to set define " + name + ", define not found.")); }; From 73e700acae8f71417e81859007670ceb24c74b8a Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 31 Oct 2018 18:15:21 +0800 Subject: [PATCH 0145/1631] Move _renderData from RenderComponent to sub classes --- cocos2d/core/components/CCLabel.js | 1 + cocos2d/core/components/CCMask.js | 1 + cocos2d/core/components/CCMotionStreak.js | 1 + cocos2d/core/components/CCRenderComponent.js | 5 +---- cocos2d/core/components/CCSprite.js | 1 + cocos2d/particle/CCParticleSystem.js | 3 ++- cocos2d/tilemap/CCTiledLayer.js | 2 +- 7 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 90023d840f9..506c0a76f79 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -142,6 +142,7 @@ let Label = cc.Class({ this._userDefinedFont = null; } + this._renderData = null; this._actualFontSize = 0; this._assemblerData = null; diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index b8fcf9ecf58..3cbd2a74f6e 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -94,6 +94,7 @@ let Mask = cc.Class({ }, ctor () { + this._renderData = null; this._graphics = null; this._clearGraphics = null; }, diff --git a/cocos2d/core/components/CCMotionStreak.js b/cocos2d/core/components/CCMotionStreak.js index e097fbb2c2d..817918a097c 100644 --- a/cocos2d/core/components/CCMotionStreak.js +++ b/cocos2d/core/components/CCMotionStreak.js @@ -59,6 +59,7 @@ var MotionStreak = cc.Class({ }, ctor () { + this._renderData = null; this._points = []; }, diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 5f054168258..18048d4897e 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -98,11 +98,9 @@ let RenderComponent = cc.Class({ }, ctor () { - this._material = null; - this._renderData = null; this.__allocedDatas = []; + this._material = null; this._vertexFormat = null; - this._toPostHandle = false; this._assembler = this.constructor._assembler; this._postAssembler = this.constructor._postAssembler; }, @@ -126,7 +124,6 @@ let RenderComponent = cc.Class({ } this.__allocedDatas.length = 0; this._material = null; - this._renderData = null; }, _canRender () { diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 578549dd156..68918111cc2 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -158,6 +158,7 @@ var Sprite = cc.Class({ ctor () { this._assembler = null; + this._renderData = null; this._graySpriteMaterial = null; this._spriteMaterial = null; }, diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 934a1ae7dd4..ddc4eea09bb 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -705,10 +705,11 @@ var ParticleSystem = cc.Class({ executeInEditMode: true }, - ctor: function () { + ctor () { this._previewTimer = null; this._focused = false; this._texture = null; + this._renderData = null; this._simulator = new ParticleSimulator(this); diff --git a/cocos2d/tilemap/CCTiledLayer.js b/cocos2d/tilemap/CCTiledLayer.js index 23da490a0c1..9e081f7bf93 100644 --- a/cocos2d/tilemap/CCTiledLayer.js +++ b/cocos2d/tilemap/CCTiledLayer.js @@ -45,11 +45,11 @@ let TiledLayer = cc.Class({ this._texGrids = []; this._textures = []; this._spriteTiles = {}; - this._tiledTiles = []; this._layerName = ''; this._layerOrientation = null; + this._renderData = null; }, /** From 605cbc1e1c00e22e17bd4499bb45caebf667c68a Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 31 Oct 2018 18:15:34 +0800 Subject: [PATCH 0146/1631] Remove useless render data generation in mask --- cocos2d/core/renderer/webgl/assemblers/mask-assembler.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js index 204cef1b00f..ea254495a7e 100644 --- a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js @@ -40,10 +40,6 @@ let maskFrontAssembler = { if (mask._type === Mask.Type.IMAGE_STENCIL) { mask._renderData = spriteAssembler.createData(mask); } - else { - // for updateGraphics calculation - mask._renderData = mask.requestRenderData(); - } } let renderData = mask._renderData; From bfa394165dce0763c2cd0f7fae5ed0dac83b88dd Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 6 Nov 2018 14:43:59 +0800 Subject: [PATCH 0147/1631] Remove vertDirty & uvDirty --- cocos2d/core/components/CCLabel.js | 71 +++++---- cocos2d/core/components/CCLabelOutline.js | 2 +- cocos2d/core/components/CCMask.js | 3 +- cocos2d/core/components/CCRenderComponent.js | 12 ++ cocos2d/core/components/CCSprite.js | 36 +---- .../canvas/renderers/graphics/impl.js | 1 - .../canvas/renderers/sprite/simple.js | 12 +- .../canvas/renderers/sprite/sliced.js | 5 - cocos2d/core/renderer/utils/label/bmfont.js | 4 +- cocos2d/core/renderer/utils/label/ttf.js | 4 +- .../webgl/assemblers/mask-assembler.js | 3 - .../webgl/assemblers/motion-streak.js | 6 +- .../webgl/assemblers/sprite/bar-filled.js | 26 +--- .../renderer/webgl/assemblers/sprite/mesh.js | 26 +--- .../webgl/assemblers/sprite/radial-filled.js | 146 +++++++++--------- .../webgl/assemblers/sprite/simple.js | 9 +- .../webgl/assemblers/sprite/sliced.js | 12 +- .../renderer/webgl/assemblers/sprite/tiled.js | 14 +- cocos2d/tilemap/tmx-layer-assembler.js | 6 +- extensions/dragonbones/webgl-assembler.js | 6 - 20 files changed, 164 insertions(+), 240 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 506c0a76f79..b8e0892c7d4 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -176,7 +176,7 @@ let Label = cc.Class({ this._string = value.toString(); if (this.string !== oldValue) { - this._updateRenderData(); + this.markForUpdateRenderData(true); } this._checkStringEmpty(); @@ -196,7 +196,7 @@ let Label = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.label.horizontal_align', notify (oldValue) { if (this.horizontalAlign === oldValue) return; - this._updateRenderData(); + this.markForUpdateRenderData(true); }, animatable: false }, @@ -212,7 +212,7 @@ let Label = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.label.vertical_align', notify (oldValue) { if (this.verticalAlign === oldValue) return; - this._updateRenderData(); + this.markForUpdateRenderData(true); }, animatable: false }, @@ -246,7 +246,7 @@ let Label = cc.Class({ if (this._fontSize === value) return; this._fontSize = value; - this._updateRenderData(); + this.markForUpdateRenderData(true); }, tooltip: CC_DEV && 'i18n:COMPONENT.label.font_size', }, @@ -261,7 +261,7 @@ let Label = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.label.font_family', notify (oldValue) { if (this.fontFamily === oldValue) return; - this._updateRenderData(); + this.markForUpdateRenderData(true); }, animatable: false }, @@ -279,7 +279,7 @@ let Label = cc.Class({ set (value) { if (this._lineHeight === value) return; this._lineHeight = value; - this._updateRenderData(); + this.markForUpdateRenderData(true); }, tooltip: CC_DEV && 'i18n:COMPONENT.label.line_height', }, @@ -294,7 +294,7 @@ let Label = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.label.overflow', notify (oldValue) { if (this.overflow === oldValue) return; - this._updateRenderData(); + this.markForUpdateRenderData(true); }, animatable: false }, @@ -313,7 +313,7 @@ let Label = cc.Class({ if (this._enableWrapText === value) return; this._enableWrapText = value; - this._updateRenderData(); + this.markForUpdateRenderData(true); }, animatable: false, tooltip: CC_DEV && 'i18n:COMPONENT.label.wrap', @@ -363,7 +363,7 @@ let Label = cc.Class({ this._fontAtlas = null; this._updateAssembler(); this._activateMaterial(true); - this._updateRenderData(); + this.markForUpdateRenderData(true); }, type: cc.Font, tooltip: CC_DEV && 'i18n:COMPONENT.label.font', @@ -399,7 +399,7 @@ let Label = cc.Class({ if (value) { this.font = null; this._updateAssembler(); - this._updateRenderData(); + this.markForUpdateRenderData(true); this._checkStringEmpty(); } else if (!this._userDefinedFont) { @@ -427,7 +427,7 @@ let Label = cc.Class({ }, set (value) { this._spacingX = value; - this._updateRenderData(); + this.markForUpdateRenderData(true); } }, @@ -463,20 +463,10 @@ let Label = cc.Class({ this.fontFamily = 'Arial'; } - // Keep track of Node size - this.node.on(cc.Node.EventType.SIZE_CHANGED, this._updateRenderData, this); - this.node.on(cc.Node.EventType.ANCHOR_CHANGED, this._updateRenderData, this); - this._checkStringEmpty(); this._updateRenderData(true); }, - onDisable () { - this._super(); - this.node.off(cc.Node.EventType.SIZE_CHANGED, this._updateRenderData, this); - this.node.off(cc.Node.EventType.ANCHOR_CHANGED, this._updateRenderData, this); - }, - onDestroy () { this._assembler._resetAssemblerData && this._assembler._resetAssemblerData(this._assemblerData); this._assemblerData = null; @@ -486,7 +476,27 @@ let Label = cc.Class({ } this._super(); }, - + + markForUpdateRenderData (enable) { + if (enable) { + this._vertsDirty = true; + } + if (this._renderData) { + if (enable && this._canRender()) { + this.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; + } + else if (!enable) { + this.node._renderFlag &= ~RenderFlow.FLAG_UPDATE_RENDER_DATA; + } + } + + if (CC_EDITOR) { + this._updateAssembler(); + this._activateMaterial(true); + this._assembler.updateRenderData(this); + } + }, + _canRender () { let result = this._super(); let font = this.font; @@ -585,22 +595,17 @@ let Label = cc.Class({ this._super(); } else { - this._updateRenderData(); + this.markForUpdateRenderData(true); this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; } }, - _updateRenderData (force) { - let renderData = this._renderData; - if (renderData) { - renderData.vertDirty = true; - renderData.uvDirty = true; - this.markForUpdateRenderData(true); - } - - if (CC_EDITOR || force) { + _forceUpdateRenderData () { + this.markForUpdateRenderData(true); + // In editor it will automatically be updated in markForUpdateRenderData + if (!CC_EDITOR) { this._updateAssembler(); - this._activateMaterial(force); + this._activateMaterial(true); this._assembler.updateRenderData(this); } }, diff --git a/cocos2d/core/components/CCLabelOutline.js b/cocos2d/core/components/CCLabelOutline.js index 95f94971a34..c5d69c3cf9b 100644 --- a/cocos2d/core/components/CCLabelOutline.js +++ b/cocos2d/core/components/CCLabelOutline.js @@ -90,7 +90,7 @@ let LabelOutline = cc.Class({ _updateRenderData () { let label = this.node.getComponent(cc.Label); if (label) { - label._updateRenderData(true); + label._forceUpdateRenderData(); } } diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 3cbd2a74f6e..d6841192e47 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -319,9 +319,8 @@ let Mask = cc.Class({ _onTextureLoaded () { // Mark render data dirty + this._vertsDirty = true; if (this._renderData) { - this._renderData.uvDirty = true; - this._renderData.vertDirty = true; this.markForUpdateRenderData(true); } // Reactivate material diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 18048d4897e..b2e34e09fe0 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -99,6 +99,7 @@ let RenderComponent = cc.Class({ ctor () { this.__allocedDatas = []; + this._vertsDirty = true; this._material = null; this._vertexFormat = null; this._assembler = this.constructor._assembler; @@ -110,11 +111,17 @@ let RenderComponent = cc.Class({ this.node._renderComponent.enabled = false; } this.node._renderComponent = this; + + this.node.on(NodeEvent.SIZE_CHANGED, this._onNodeSizeDirty, this); + this.node.on(NodeEvent.ANCHOR_CHANGED, this._onNodeSizeDirty, this); + this.node._renderFlag |= RenderFlow.FLAG_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_COLOR; }, onDisable () { this.node._renderComponent = null; + this.node.off(NodeEvent.SIZE_CHANGED, this._onNodeSizeDirty, this); + this.node.off(NodeEvent.ANCHOR_CHANGED, this._onNodeSizeDirty, this); this.disableRender(); }, @@ -125,6 +132,11 @@ let RenderComponent = cc.Class({ this.__allocedDatas.length = 0; this._material = null; }, + + _onNodeSizeDirty () { + this._vertsDirty = true; + this.markForUpdateRenderData(true); + }, _canRender () { // When the node is activated, it will execute onEnable and the renderflag will also be reset. diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 68918111cc2..143fedfca0d 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -272,6 +272,7 @@ var Sprite = cc.Class({ this._renderData = null; } else if (this._renderData) { + this._vertsDirty = true; this.markForUpdateRenderData(true); } this._fillType = value; @@ -300,6 +301,7 @@ var Sprite = cc.Class({ this._fillCenter.x = value.x; this._fillCenter.y = value.y; if (this._type === SpriteType.FILLED && this._renderData) { + this._vertsDirty = true; this.markForUpdateRenderData(true); } }, @@ -324,6 +326,7 @@ var Sprite = cc.Class({ set: function(value) { this._fillStart = misc.clampf(value, -1, 1); if (this._type === SpriteType.FILLED && this._renderData) { + this._vertsDirty = true; this.markForUpdateRenderData(true); } }, @@ -348,6 +351,7 @@ var Sprite = cc.Class({ set: function(value) { this._fillRange = misc.clampf(value, -1, 1); if (this._type === SpriteType.FILLED && this._renderData) { + this._vertsDirty = true; this.markForUpdateRenderData(true); } }, @@ -370,6 +374,7 @@ var Sprite = cc.Class({ this._isTrimmedMode = value; if ((this._type === SpriteType.SIMPLE || this._type === SpriteType.MESH) && this._renderData) { + this._vertsDirty = true; this.markForUpdateRenderData(true); } } @@ -450,21 +455,6 @@ var Sprite = cc.Class({ this._updateAssembler(); this._activateMaterial(); - - this.node.on(NodeEvent.SIZE_CHANGED, this._onNodeSizeDirty, this); - this.node.on(NodeEvent.ANCHOR_CHANGED, this._onNodeSizeDirty, this); - }, - - onDisable: function () { - this._super(); - - this.node.off(NodeEvent.SIZE_CHANGED, this._onNodeSizeDirty, this); - this.node.off(NodeEvent.ANCHOR_CHANGED, this._onNodeSizeDirty, this); - }, - - _onNodeSizeDirty () { - if (!this._renderData) return; - this.markForUpdateRenderData(true); }, _updateAssembler: function () { @@ -478,6 +468,7 @@ var Sprite = cc.Class({ if (!this._renderData) { this._renderData = this._assembler.createData(this); this._renderData.material = this._material; + this._vertsDirty = true; this.markForUpdateRenderData(true); } }, @@ -558,21 +549,6 @@ var Sprite = cc.Class({ return true; }, - markForUpdateRenderData (enable) { - if (enable && this._canRender()) { - this.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; - - let renderData = this._renderData; - if (renderData) { - renderData.uvDirty = true; - renderData.vertDirty = true; - } - } - else if (!enable) { - this.node._renderFlag &= ~RenderFlow.FLAG_UPDATE_RENDER_DATA; - } - }, - _applySpriteSize: function () { if (this._spriteFrame) { if (SizeMode.RAW === this._sizeMode) { diff --git a/cocos2d/core/renderer/canvas/renderers/graphics/impl.js b/cocos2d/core/renderer/canvas/renderers/graphics/impl.js index 1889656c142..168fc0fe9f5 100644 --- a/cocos2d/core/renderer/canvas/renderers/graphics/impl.js +++ b/cocos2d/core/renderer/canvas/renderers/graphics/impl.js @@ -26,7 +26,6 @@ const Helper = require('../../../../graphics/helper'); const Types = require('../../../../graphics/types'); const js = require('../../../../platform/js'); -const PointFlags = Types.PointFlags; const LineJoin = Types.LineJoin; const LineCap = Types.LineCap; diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/simple.js b/cocos2d/core/renderer/canvas/renderers/sprite/simple.js index a8f540f69b7..52c0fc931c1 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/simple.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/simple.js @@ -39,13 +39,10 @@ let renderer = { sprite._activateMaterial(); } - let renderData = sprite._renderData; - if (renderData.uvDirty) { + if (sprite._vertsDirty) { this.updateUVs(sprite); - } - - if (renderData.vertDirty) { this.updateVerts(sprite); + sprite._vertsDirty = false; } }, @@ -54,7 +51,6 @@ let renderer = { let renderData = sprite._renderData; let data = renderData._data; let rect = frame._rect; - let texture = frame._texture; if (frame._rotated) { let l = rect.x; @@ -76,8 +72,6 @@ let renderer = { data[1].u = r; data[1].v = t; } - - renderData.uvDirty = false; }, updateVerts (sprite) { @@ -113,8 +107,6 @@ let renderer = { data[0].y = b; data[1].x = r; data[1].y = t; - - renderData.vertDirty = false; }, draw (ctx, comp) { diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js b/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js index c65dfe90713..4b4eb141fba 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js @@ -40,7 +40,6 @@ let renderer = { let frame = sprite.spriteFrame; let renderData = sprite._renderData; let rect = frame._rect; - let texture = frame._texture; // caculate texture coordinate let leftWidth = frame.insetLeft; @@ -72,7 +71,6 @@ let renderer = { data[1].v = topHeight + centerHeight + rect.y; data[0].v = rect.y + rect.height; } - renderData.uvDirty = false; }, updateVerts (sprite) { @@ -83,7 +81,6 @@ let renderer = { appx = node.anchorX * width, appy = node.anchorY * height; let frame = sprite.spriteFrame; - let rect = frame._rect; let leftWidth = frame.insetLeft; let rightWidth = frame.insetRight; let topHeight = frame.insetTop; @@ -106,8 +103,6 @@ let renderer = { data[2].y = data[1].y + sizableHeight; data[3].x = width - appx; data[3].y = height - appy; - - renderData.vertDirty = false; }, draw (ctx, comp) { diff --git a/cocos2d/core/renderer/utils/label/bmfont.js b/cocos2d/core/renderer/utils/label/bmfont.js index 4c3002add62..1851862331b 100644 --- a/cocos2d/core/renderer/utils/label/bmfont.js +++ b/cocos2d/core/renderer/utils/label/bmfont.js @@ -134,7 +134,7 @@ let _maxLineWidth = 0; module.exports = { updateRenderData (comp) { - if (!comp._renderData.vertDirty) return; + if (!comp._vertsDirty) return; if (_comp === comp) return; _comp = comp; @@ -145,7 +145,7 @@ module.exports = { _comp._actualFontSize = _fontSize; _comp.node.setContentSize(_contentSize); - _comp._renderData.vertDirty = _comp._renderData.uvDirty = false; + _comp._vertsDirty = false; _comp = null; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index a9810d8de0a..500b0d31e50 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -116,7 +116,7 @@ module.exports = { }, updateRenderData (comp) { - if (!comp._renderData.vertDirty) return; + if (!comp._vertsDirty) return; this._updateFontFamily(comp); this._updateProperties(comp); @@ -131,7 +131,7 @@ module.exports = { this._updateVerts(comp); - comp._renderData.vertDirty = comp._renderData.uvDirty = false; + comp._vertsDirty = false; _context = null; _canvas = null; diff --git a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js index ea254495a7e..5a1be7222f3 100644 --- a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js @@ -45,9 +45,6 @@ let maskFrontAssembler = { if (mask._type === Mask.Type.IMAGE_STENCIL) { if (mask.spriteFrame) { - let size = mask.node._contentSize; - let anchor = mask.node._anchorPoint; - renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y); renderData.dataLength = 4; spriteAssembler.updateRenderData(mask); renderData.material = mask._material; diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index 4d94c81d15a..b87bf6f1ff3 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -81,9 +81,6 @@ var motionStreakAssembler = { this.update(comp, dt); let renderData = comp._renderData; - let size = comp.node._contentSize; - let anchor = comp.node._anchorPoint; - renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y); renderData.material = comp.getMaterial(); }, @@ -190,8 +187,7 @@ var motionStreakAssembler = { }, fillBuffers (comp, renderer) { - let node = comp.node, - renderData = comp._renderData, + let renderData = comp._renderData, data = renderData._data; let buffer = renderer._meshBuffer, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index 9c16d92cc98..09d4204df2e 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -44,15 +44,12 @@ module.exports = { } } + if (!sprite._vertsDirty) { + return sprite.__allocedDatas; + } + let renderData = sprite._renderData; if (renderData && frame) { - let uvDirty = renderData.uvDirty, - vertDirty = renderData.vertDirty; - - if (!uvDirty && !vertDirty) { - return sprite.__allocedDatas; - } - let fillStart = sprite._fillStart; let fillRange = sprite._fillRange; @@ -74,13 +71,10 @@ module.exports = { let fillEnd = fillStart + fillRange; fillEnd = fillEnd > 1 ? 1 : fillEnd; - if (uvDirty) { - this.updateUVs(sprite, fillStart, fillEnd); - } - if (vertDirty) { - this.updateVerts(sprite, fillStart, fillEnd); - this.updateWorldVerts(sprite); - } + this.updateUVs(sprite, fillStart, fillEnd); + this.updateVerts(sprite, fillStart, fillEnd); + this.updateWorldVerts(sprite); + sprite._vertsDirty = false; } }, @@ -144,8 +138,6 @@ module.exports = { cc.errorID(2626); break; } - - renderData.uvDirty = false; }, updateVerts (sprite, fillStart, fillEnd) { @@ -187,8 +179,6 @@ module.exports = { data[6].y = t; data[7].x = r; data[7].y = t; - - renderData.vertDirty = false; }, createData (sprite) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js index ada3e2f5381..204d04eebc0 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js @@ -57,27 +57,24 @@ module.exports = { // 1 for world vertices, 2 for local vertices renderData.dataLength = renderData.vertexCount * 2; - renderData.uvDirty = renderData.vertDirty = true; + sprite._vertsDirty = true; } - if (renderData.uvDirty) { + if (sprite._vertsDirty) { this.updateUVs(sprite); - } - let vertDirty = renderData.vertDirty; - if (vertDirty) { this.updateVerts(sprite); this.updateWorldVerts(sprite); + sprite._vertsDirty = false; + } + // update world verts + else if (renderer.worldMatDirty) { + this.updateWorldVerts(sprite); } } } }, updateUVs (sprite) { - let material = sprite.getMaterial(); - let texture = material.effect.getProperty('texture'); - let texw = texture._width, - texh = texture._height; - let vertices = sprite.spriteFrame.vertices, u = vertices.nu, v = vertices.nv; @@ -89,8 +86,6 @@ module.exports = { vertice.u = u[i]; vertice.v = v[i]; } - - renderData.uvDirty = false; }, updateVerts (sprite) { @@ -133,8 +128,6 @@ module.exports = { vertice.y = (originalHeight - y[i] - trimY) * scaleY - appy; } } - - renderData.vertDirty = false; }, updateWorldVerts (sprite) { @@ -163,11 +156,6 @@ module.exports = { if (!vertices) { return; } - - // update world verts - if (renderer.worldMatDirty) { - this.updateWorldVerts(sprite); - } // buffer let buffer = renderer._meshBuffer, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js index 302d203cb6e..9118c0cc1ba 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js @@ -57,98 +57,96 @@ module.exports = { } let renderData = sprite._renderData; - if (renderData && frame) { - if (renderData.vertDirty || renderData.uvDirty) { - let data = renderData._data; - - let fillStart = sprite._fillStart; - let fillRange = sprite._fillRange; - if (fillRange < 0) { - fillStart += fillRange; - fillRange = -fillRange; - } + if (renderData && frame && sprite._vertsDirty) { + let data = renderData._data; + + let fillStart = sprite._fillStart; + let fillRange = sprite._fillRange; + if (fillRange < 0) { + fillStart += fillRange; + fillRange = -fillRange; + } - //do round fill start [0,1), include 0, exclude 1 - while (fillStart >= 1.0) fillStart -= 1.0; - while (fillStart < 0.0) fillStart += 1.0; + //do round fill start [0,1), include 0, exclude 1 + while (fillStart >= 1.0) fillStart -= 1.0; + while (fillStart < 0.0) fillStart += 1.0; - fillStart *= PI_2; - fillRange *= PI_2; - let fillEnd = fillStart + fillRange; + fillStart *= PI_2; + fillRange *= PI_2; + let fillEnd = fillStart + fillRange; - //build vertices - this._calculateVertices(sprite); - //build uvs - this._calculateUVs(frame); + //build vertices + this._calculateVertices(sprite); + //build uvs + this._calculateUVs(frame); - let center = this._center; + let center = this._center; - let vertPos = this._vertPos, - vertices = this._vertices; + let vertPos = this._vertPos, + vertices = this._vertices; - let triangles = this._triangles; + let triangles = this._triangles; - this._calcInsectedPoints(vertices[0], vertices[2], vertices[1], vertices[3], center, fillStart, this._intersectPoint_1); - this._calcInsectedPoints(vertices[0], vertices[2], vertices[1], vertices[3], center, fillStart + fillRange, this._intersectPoint_2); + this._calcInsectedPoints(vertices[0], vertices[2], vertices[1], vertices[3], center, fillStart, this._intersectPoint_1); + this._calcInsectedPoints(vertices[0], vertices[2], vertices[1], vertices[3], center, fillStart + fillRange, this._intersectPoint_2); - let offset = 0; - for (let triangleIndex = 0; triangleIndex < 4; ++triangleIndex) { - let triangle = triangles[triangleIndex]; - if (!triangle) { - continue; - } - //all in - if (fillRange >= PI_2) { + let offset = 0; + for (let triangleIndex = 0; triangleIndex < 4; ++triangleIndex) { + let triangle = triangles[triangleIndex]; + if (!triangle) { + continue; + } + //all in + if (fillRange >= PI_2) { + renderData.dataLength = offset + 3; + this._generateTriangle(data, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); + offset += 3; + continue; + } + //test against + let startAngle = this._getVertAngle(center, vertPos[triangle[0]]); + let endAngle = this._getVertAngle(center, vertPos[triangle[1]]); + if(endAngle < startAngle) endAngle += PI_2; + startAngle -= PI_2; + endAngle -= PI_2; + //testing + for(let testIndex = 0; testIndex < 3; ++testIndex) { + if(startAngle >= fillEnd) { + //all out + } else if (startAngle >= fillStart) { renderData.dataLength = offset + 3; - this._generateTriangle(data, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); + if(endAngle >= fillEnd) { + //startAngle to fillEnd + this._generateTriangle(data, offset, center, vertPos[triangle[0]], this._intersectPoint_2[triangleIndex]); + } else { + //startAngle to endAngle + this._generateTriangle(data, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); + } offset += 3; - continue; - } - //test against - let startAngle = this._getVertAngle(center, vertPos[triangle[0]]); - let endAngle = this._getVertAngle(center, vertPos[triangle[1]]); - if(endAngle < startAngle) endAngle += PI_2; - startAngle -= PI_2; - endAngle -= PI_2; - //testing - for(let testIndex = 0; testIndex < 3; ++testIndex) { - if(startAngle >= fillEnd) { + } else { + //startAngle < fillStart + if(endAngle <= fillStart) { //all out - } else if (startAngle >= fillStart) { + } else if(endAngle <= fillEnd) { renderData.dataLength = offset + 3; - if(endAngle >= fillEnd) { - //startAngle to fillEnd - this._generateTriangle(data, offset, center, vertPos[triangle[0]], this._intersectPoint_2[triangleIndex]); - } else { - //startAngle to endAngle - this._generateTriangle(data, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); - } + //fillStart to endAngle + this._generateTriangle(data, offset, center, this._intersectPoint_1[triangleIndex], vertPos[triangle[1]]); offset += 3; } else { - //startAngle < fillStart - if(endAngle <= fillStart) { - //all out - } else if(endAngle <= fillEnd) { - renderData.dataLength = offset + 3; - //fillStart to endAngle - this._generateTriangle(data, offset, center, this._intersectPoint_1[triangleIndex], vertPos[triangle[1]]); - offset += 3; - } else { - renderData.dataLength = offset + 3; - //fillStart to fillEnd - this._generateTriangle(data, offset, center, this._intersectPoint_1[triangleIndex], this._intersectPoint_2[triangleIndex]); - offset += 3; - } + renderData.dataLength = offset + 3; + //fillStart to fillEnd + this._generateTriangle(data, offset, center, this._intersectPoint_1[triangleIndex], this._intersectPoint_2[triangleIndex]); + offset += 3; } - //add 2 * PI - startAngle += PI_2; - endAngle += PI_2; } + //add 2 * PI + startAngle += PI_2; + endAngle += PI_2; } - - renderData.indiceCount = renderData.vertexCount = offset; - renderData.vertDirty = renderData.uvDirty = false; } + + renderData.indiceCount = renderData.vertexCount = offset; + sprite._vertsDirty = false; } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js index e4e50878b4c..edfe9b2692b 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js @@ -43,10 +43,9 @@ module.exports = { } let renderData = sprite._renderData; - if (renderData && frame) { - if (renderData.vertDirty) { - this.updateVerts(sprite); - } + if (renderData && frame && sprite._vertsDirty) { + this.updateVerts(sprite); + sprite._vertsDirty = false; } }, @@ -161,7 +160,5 @@ module.exports = { // data[2].y = t; data[3].x = r; data[3].y = t; - - renderData.vertDirty = false; } }; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js index 821aa6bcc25..73addf0bf2c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js @@ -54,12 +54,10 @@ module.exports = { } let renderData = sprite._renderData; - if (renderData && frame) { - let vertDirty = renderData.vertDirty; - if (vertDirty) { - this.updateVerts(sprite); - this.updateWorldVerts(sprite); - } + if (renderData && frame && sprite._vertsDirty) { + this.updateVerts(sprite); + this.updateWorldVerts(sprite); + sprite._vertsDirty = false; } }, @@ -93,8 +91,6 @@ module.exports = { data[2].y = data[1].y + sizableHeight; data[3].x = width - appx; data[3].y = height - appy; - - renderData.vertDirty = false; }, fillBuffers (sprite, renderer) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js index 55d0cf7b49d..34667b82526 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js @@ -47,22 +47,17 @@ module.exports = { } let renderData = sprite._renderData; - if (!frame || !renderData || - !(renderData.uvDirty || renderData.vertDirty)) + if (!frame || !renderData || !sprite._vertsDirty) return; - let texture = frame._texture; - let texw = texture.width, - texh = texture.height, - rect = frame._rect; - let node = sprite.node, contentWidth = Math.abs(node.width), contentHeight = Math.abs(node.height), appx = node.anchorX * contentWidth, appy = node.anchorY * contentHeight; - let rectWidth = rect.width, + let rect = frame._rect, + rectWidth = rect.width, rectHeight = rect.height, hRepeat = contentWidth / rectWidth, vRepeat = contentHeight / rectHeight, @@ -82,8 +77,7 @@ module.exports = { // update data property renderData.vertexCount = row * col * 4; renderData.indiceCount = row * col * 6; - renderData.uvDirty = false; - renderData.vertDirty = false; + sprite._vertsDirty = false; }, fillBuffers (sprite, renderer) { diff --git a/cocos2d/tilemap/tmx-layer-assembler.js b/cocos2d/tilemap/tmx-layer-assembler.js index 6ab948cee7e..b9a34a93a2d 100644 --- a/cocos2d/tilemap/tmx-layer-assembler.js +++ b/cocos2d/tilemap/tmx-layer-assembler.js @@ -49,12 +49,8 @@ let tmxAssembler = { if (!renderData) { renderData = comp._renderData = comp.requestRenderData(); } - - let size = comp.node._contentSize; - let anchor = comp.node._anchorPoint; - renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y); renderData.material = comp.getMaterial(); - + this.updateVertices(comp); }, diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 0e36d66762d..73b8feb5895 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -33,14 +33,12 @@ const js = require('../../cocos2d/core/platform/js'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); let _matrix = math.mat4.create(); -let _v3 = cc.v3(); let _vbuf, _uintbuf, _vertexId, _ibuf, _vertexOffset, _indiceOffset, _a, _b, _c, _d, _tx, _ty, _nodeR, _nodeG, _nodeB, _nodeA, - _renderData, _worldMatrix; let armatureAssembler = { @@ -55,11 +53,7 @@ let armatureAssembler = { renderData = comp._renderData = comp.requestRenderData(); } - let size = comp.node._contentSize; - let anchor = comp.node._anchorPoint; - renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y); renderData.material = comp.getMaterial(); - renderData.vertexCount = 0; renderData.indiceCount = 0; From 8f2d991312673226f6398268782de3c7bc2ca9fa Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 6 Nov 2018 17:01:13 +0800 Subject: [PATCH 0148/1631] Improve RenderData --- cocos2d/core/renderer/render-engine.canvas.js | 51 +++++-------------- cocos2d/core/renderer/render-engine.js | 51 +++++-------------- cocos2d/core/renderer/render-engine.jsb.js | 51 +++++-------------- 3 files changed, 42 insertions(+), 111 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js index a5a7b19a6d7..1de8f2b0638 100644 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ b/cocos2d/core/renderer/render-engine.canvas.js @@ -1296,7 +1296,7 @@ var BaseRenderData = function BaseRenderData () { // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. var _pool; -var _dataPool = new Pool(function () { +var _vertsPool = new Pool(function () { return { x: 0.0, y: 0.0, @@ -1316,16 +1316,9 @@ var _dataPool = new Pool(function () { var RenderData = (function (BaseRenderData$$1) { function RenderData () { BaseRenderData$$1.call(this); - this._data = []; - this._indices = []; - - this._pivotX = 0; - this._pivotY = 0; - this._width = 0; - this._height = 0; - - this.uvDirty = true; - this.vertDirty = true; + this.vertices = []; + this.indices = []; + this.material = null; } if ( BaseRenderData$$1 ) RenderData.__proto__ = BaseRenderData$$1; @@ -1343,31 +1336,17 @@ var RenderData = (function (BaseRenderData$$1) { }; prototypeAccessors.dataLength.set = function (length) { - var data = this._data; - if (data.length !== length) { + var verts = this.vertices; + if (verts.length !== length) { // Free extra data - for (var i = length; i < data.length; i++) { - _dataPool.free(data[i]); + for (var i = length; i < verts.length; i++) { + _vertsPool.free(verts[i]); } // Alloc needed data - for (var i$1 = data.length; i$1 < length; i$1++) { - data[i$1] = _dataPool.alloc(); + for (var i$1 = verts.length; i$1 < length; i$1++) { + verts[i$1] = _vertsPool.alloc(); } - data.length = length; - } - }; - - RenderData.prototype.updateSizeNPivot = function updateSizeNPivot (width, height, pivotX, pivotY) { - if (width !== this._width || - height !== this._height || - pivotX !== this._pivotX || - pivotY !== this._pivotY) - { - this._width = width; - this._height = height; - this._pivotX = pivotX; - this._pivotY = pivotY; - this.vertDirty = true; + verts.length = length; } }; @@ -1378,13 +1357,11 @@ var RenderData = (function (BaseRenderData$$1) { RenderData.free = function free (data) { if (data instanceof RenderData) { for (var i = data.length-1; i > 0; i--) { - _dataPool.free(data._data[i]); + _vertsPool.free(data.vertices[i]); } - data._data.length = 0; - data._indices.length = 0; + data.vertices.length = 0; + data.indices.length = 0; data.material = null; - data.uvDirty = true; - data.vertDirty = true; data.vertexCount = 0; data.indiceCount = 0; _pool.free(data); diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 84071bc5d1c..b990dc511f0 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -13808,7 +13808,7 @@ var BaseRenderData = function BaseRenderData () { // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. var _pool; -var _dataPool = new Pool(function () { +var _vertsPool = new Pool(function () { return { x: 0.0, y: 0.0, @@ -13828,16 +13828,9 @@ var _dataPool = new Pool(function () { var RenderData = (function (BaseRenderData$$1) { function RenderData () { BaseRenderData$$1.call(this); - this._data = []; - this._indices = []; - - this._pivotX = 0; - this._pivotY = 0; - this._width = 0; - this._height = 0; - - this.uvDirty = true; - this.vertDirty = true; + this.vertices = []; + this.indices = []; + this.material = null; } if ( BaseRenderData$$1 ) RenderData.__proto__ = BaseRenderData$$1; @@ -13855,31 +13848,17 @@ var RenderData = (function (BaseRenderData$$1) { }; prototypeAccessors.dataLength.set = function (length) { - var data = this._data; - if (data.length !== length) { + var verts = this.vertices; + if (verts.length !== length) { // Free extra data - for (var i = length; i < data.length; i++) { - _dataPool.free(data[i]); + for (var i = length; i < verts.length; i++) { + _vertsPool.free(verts[i]); } // Alloc needed data - for (var i$1 = data.length; i$1 < length; i$1++) { - data[i$1] = _dataPool.alloc(); + for (var i$1 = verts.length; i$1 < length; i$1++) { + verts[i$1] = _vertsPool.alloc(); } - data.length = length; - } - }; - - RenderData.prototype.updateSizeNPivot = function updateSizeNPivot (width, height, pivotX, pivotY) { - if (width !== this._width || - height !== this._height || - pivotX !== this._pivotX || - pivotY !== this._pivotY) - { - this._width = width; - this._height = height; - this._pivotX = pivotX; - this._pivotY = pivotY; - this.vertDirty = true; + verts.length = length; } }; @@ -13890,13 +13869,11 @@ var RenderData = (function (BaseRenderData$$1) { RenderData.free = function free (data) { if (data instanceof RenderData) { for (var i = data.length-1; i > 0; i--) { - _dataPool.free(data._data[i]); + _vertsPool.free(data.vertices[i]); } - data._data.length = 0; - data._indices.length = 0; + data.vertices.length = 0; + data.indices.length = 0; data.material = null; - data.uvDirty = true; - data.vertDirty = true; data.vertexCount = 0; data.indiceCount = 0; _pool.free(data); diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index b100370244b..a89ed794029 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -2509,7 +2509,7 @@ var BaseRenderData = function BaseRenderData () { // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. var _pool; -var _dataPool = new Pool(function () { +var _vertsPool = new Pool(function () { return { x: 0.0, y: 0.0, @@ -2529,16 +2529,9 @@ var _dataPool = new Pool(function () { var RenderData = (function (BaseRenderData$$1) { function RenderData () { BaseRenderData$$1.call(this); - this._data = []; - this._indices = []; - - this._pivotX = 0; - this._pivotY = 0; - this._width = 0; - this._height = 0; - - this.uvDirty = true; - this.vertDirty = true; + this.vertices = []; + this.indices = []; + this.material = null; } if ( BaseRenderData$$1 ) RenderData.__proto__ = BaseRenderData$$1; @@ -2556,31 +2549,17 @@ var RenderData = (function (BaseRenderData$$1) { }; prototypeAccessors.dataLength.set = function (length) { - var data = this._data; - if (data.length !== length) { + var verts = this.vertices; + if (verts.length !== length) { // Free extra data - for (var i = length; i < data.length; i++) { - _dataPool.free(data[i]); + for (var i = length; i < verts.length; i++) { + _vertsPool.free(verts[i]); } // Alloc needed data - for (var i$1 = data.length; i$1 < length; i$1++) { - data[i$1] = _dataPool.alloc(); + for (var i$1 = verts.length; i$1 < length; i$1++) { + verts[i$1] = _vertsPool.alloc(); } - data.length = length; - } - }; - - RenderData.prototype.updateSizeNPivot = function updateSizeNPivot (width, height, pivotX, pivotY) { - if (width !== this._width || - height !== this._height || - pivotX !== this._pivotX || - pivotY !== this._pivotY) - { - this._width = width; - this._height = height; - this._pivotX = pivotX; - this._pivotY = pivotY; - this.vertDirty = true; + verts.length = length; } }; @@ -2591,13 +2570,11 @@ var RenderData = (function (BaseRenderData$$1) { RenderData.free = function free (data) { if (data instanceof RenderData) { for (var i = data.length-1; i > 0; i--) { - _dataPool.free(data._data[i]); + _vertsPool.free(data.vertices[i]); } - data._data.length = 0; - data._indices.length = 0; + data.vertices.length = 0; + data.indices.length = 0; data.material = null; - data.uvDirty = true; - data.vertDirty = true; data.vertexCount = 0; data.indiceCount = 0; _pool.free(data); From 8843386e68264e06aaa17004998d341ac14963e9 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 6 Nov 2018 23:05:22 +0800 Subject: [PATCH 0149/1631] Fix label recursive invocation --- cocos2d/core/components/CCLabel.js | 57 +++++++++++------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index b8e0892c7d4..1b859d24f19 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -176,7 +176,7 @@ let Label = cc.Class({ this._string = value.toString(); if (this.string !== oldValue) { - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); } this._checkStringEmpty(); @@ -196,7 +196,7 @@ let Label = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.label.horizontal_align', notify (oldValue) { if (this.horizontalAlign === oldValue) return; - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); }, animatable: false }, @@ -212,7 +212,7 @@ let Label = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.label.vertical_align', notify (oldValue) { if (this.verticalAlign === oldValue) return; - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); }, animatable: false }, @@ -246,7 +246,7 @@ let Label = cc.Class({ if (this._fontSize === value) return; this._fontSize = value; - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); }, tooltip: CC_DEV && 'i18n:COMPONENT.label.font_size', }, @@ -261,7 +261,7 @@ let Label = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.label.font_family', notify (oldValue) { if (this.fontFamily === oldValue) return; - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); }, animatable: false }, @@ -279,7 +279,7 @@ let Label = cc.Class({ set (value) { if (this._lineHeight === value) return; this._lineHeight = value; - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); }, tooltip: CC_DEV && 'i18n:COMPONENT.label.line_height', }, @@ -294,7 +294,7 @@ let Label = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.label.overflow', notify (oldValue) { if (this.overflow === oldValue) return; - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); }, animatable: false }, @@ -313,7 +313,7 @@ let Label = cc.Class({ if (this._enableWrapText === value) return; this._enableWrapText = value; - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); }, animatable: false, tooltip: CC_DEV && 'i18n:COMPONENT.label.wrap', @@ -363,7 +363,7 @@ let Label = cc.Class({ this._fontAtlas = null; this._updateAssembler(); this._activateMaterial(true); - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); }, type: cc.Font, tooltip: CC_DEV && 'i18n:COMPONENT.label.font', @@ -399,7 +399,7 @@ let Label = cc.Class({ if (value) { this.font = null; this._updateAssembler(); - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); this._checkStringEmpty(); } else if (!this._userDefinedFont) { @@ -427,7 +427,7 @@ let Label = cc.Class({ }, set (value) { this._spacingX = value; - this.markForUpdateRenderData(true); + this._lazyUpdateRenderData(); } }, @@ -477,26 +477,6 @@ let Label = cc.Class({ this._super(); }, - markForUpdateRenderData (enable) { - if (enable) { - this._vertsDirty = true; - } - if (this._renderData) { - if (enable && this._canRender()) { - this.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; - } - else if (!enable) { - this.node._renderFlag &= ~RenderFlow.FLAG_UPDATE_RENDER_DATA; - } - } - - if (CC_EDITOR) { - this._updateAssembler(); - this._activateMaterial(true); - this._assembler.updateRenderData(this); - } - }, - _canRender () { let result = this._super(); let font = this.font; @@ -600,14 +580,17 @@ let Label = cc.Class({ } }, + _lazyUpdateRenderData () { + this._vertsDirty = true; + this.markForUpdateRenderData(true); + }, + _forceUpdateRenderData () { + this._vertsDirty = true; this.markForUpdateRenderData(true); - // In editor it will automatically be updated in markForUpdateRenderData - if (!CC_EDITOR) { - this._updateAssembler(); - this._activateMaterial(true); - this._assembler.updateRenderData(this); - } + this._updateAssembler(); + this._activateMaterial(true); + this._assembler.updateRenderData(this); }, _enableBold (enabled) { From 4676016e123ab9df726e8bf1e93b6ddc1890e2a0 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 6 Nov 2018 23:05:45 +0800 Subject: [PATCH 0150/1631] Fix RenderComponent issue --- cocos2d/core/components/CCRenderComponent.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index b2e34e09fe0..a05798e61ca 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -112,16 +112,16 @@ let RenderComponent = cc.Class({ } this.node._renderComponent = this; - this.node.on(NodeEvent.SIZE_CHANGED, this._onNodeSizeDirty, this); - this.node.on(NodeEvent.ANCHOR_CHANGED, this._onNodeSizeDirty, this); + this.node.on(cc.Node.EventType.SIZE_CHANGED, this._onNodeSizeDirty, this); + this.node.on(cc.Node.EventType.ANCHOR_CHANGED, this._onNodeSizeDirty, this); this.node._renderFlag |= RenderFlow.FLAG_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_COLOR; }, onDisable () { this.node._renderComponent = null; - this.node.off(NodeEvent.SIZE_CHANGED, this._onNodeSizeDirty, this); - this.node.off(NodeEvent.ANCHOR_CHANGED, this._onNodeSizeDirty, this); + this.node.off(cc.Node.EventType.SIZE_CHANGED, this._onNodeSizeDirty, this); + this.node.off(cc.Node.EventType.ANCHOR_CHANGED, this._onNodeSizeDirty, this); this.disableRender(); }, From cdb082613c8fdaa37647614953a18155ad52970b Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 6 Nov 2018 23:06:06 +0800 Subject: [PATCH 0151/1631] Update RenderData API usage --- .../renderer/canvas/renderers/label/bmfont.js | 48 +++++++------ .../renderer/canvas/renderers/label/ttf.js | 20 +++--- .../canvas/renderers/sprite/simple.js | 46 ++++++------- .../canvas/renderers/sprite/sliced.js | 62 ++++++++--------- .../renderer/webgl/assemblers/label/bmfont.js | 54 +++++++-------- .../renderer/webgl/assemblers/label/ttf.js | 40 +++++------ .../webgl/assemblers/motion-streak.js | 28 ++++---- .../webgl/assemblers/sprite/bar-filled.js | 67 +++++++++---------- .../renderer/webgl/assemblers/sprite/mesh.js | 20 +++--- .../webgl/assemblers/sprite/radial-filled.js | 48 ++++++------- .../webgl/assemblers/sprite/simple.js | 22 +++--- .../webgl/assemblers/sprite/sliced.js | 30 ++++----- .../renderer/webgl/assemblers/sprite/tiled.js | 16 ++--- cocos2d/tilemap/tmx-layer-assembler.js | 46 ++++++------- extensions/spine/spine-assembler.js | 10 +-- test/qunit/unit-es5/test-spriteRenderer.js | 14 ++-- 16 files changed, 283 insertions(+), 288 deletions(-) diff --git a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js index 301a950090e..ecd320bc0fa 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js +++ b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js @@ -37,9 +37,7 @@ module.exports = js.addon({ renderData.dataLength += 2; - let data = renderData._data; - let texw = texture.width, - texh = texture.height; + let verts = renderData.vertices; let rectWidth = rect.width, rectHeight = rect.height; @@ -51,26 +49,26 @@ module.exports = js.addon({ b = rect.y; t = rect.y + rectHeight; - data[dataOffset].u = l; - data[dataOffset].v = b; - data[dataOffset+1].u = r; - data[dataOffset+1].v = t; + verts[dataOffset].u = l; + verts[dataOffset].v = b; + verts[dataOffset+1].u = r; + verts[dataOffset+1].v = t; } else { l = rect.x; r = rect.x + rectHeight; b = rect.y; t = rect.y + rectWidth; - data[dataOffset].u = l; - data[dataOffset].v = t; - data[dataOffset+1].u = l; - data[dataOffset+1].v = b; + verts[dataOffset].u = l; + verts[dataOffset].v = t; + verts[dataOffset+1].u = l; + verts[dataOffset+1].v = b; } - data[dataOffset].x = x; - data[dataOffset].y = y - rectHeight * scale; - data[dataOffset+1].x = x + rectWidth * scale; - data[dataOffset+1].y = y; + verts[dataOffset].x = x; + verts[dataOffset].y = y - rectHeight * scale; + verts[dataOffset+1].x = x + rectWidth * scale; + verts[dataOffset+1].y = y; }, draw (ctx, comp) { @@ -88,21 +86,21 @@ module.exports = js.addon({ ctx.globalAlpha = node.opacity / 255; let tex = comp._texture, - data = comp._renderData._data; + verts = comp._renderData.vertices; let image = tex.getHtmlElementObj(); - for (let i = 0, l = data.length; i < l; i+=2) { - let x = data[i].x; - let y = data[i].y; - let w = data[i+1].x - x; - let h = data[i+1].y - y; + for (let i = 0, l = verts.length; i < l; i+=2) { + let x = verts[i].x; + let y = verts[i].y; + let w = verts[i+1].x - x; + let h = verts[i+1].y - y; y = - y - h; - let sx = data[i].u; - let sy = data[i].v; - let sw = data[i+1].u - sx; - let sh = data[i+1].v - sy; + let sx = verts[i].u; + let sy = verts[i].v; + let sw = verts[i+1].u - sx; + let sh = verts[i+1].v - sy; ctx.drawImage(image, sx, sy, sw, sh, diff --git a/cocos2d/core/renderer/canvas/renderers/label/ttf.js b/cocos2d/core/renderer/canvas/renderers/label/ttf.js index 74067e53cb2..66ba2fadc2d 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/ttf.js +++ b/cocos2d/core/renderer/canvas/renderers/label/ttf.js @@ -44,11 +44,11 @@ module.exports = js.addon({ appx = node.anchorX * width, appy = node.anchorY * height; - let data = renderData._data; - data[0].x = -appx; - data[0].y = -appy; - data[1].x = width - appx; - data[1].y = height - appy; + let verts = renderData.vertices; + verts[0].x = -appx; + verts[0].y = -appy; + verts[1].x = width - appx; + verts[1].y = height - appy; }, _updateTexture (comp) { @@ -71,14 +71,14 @@ module.exports = js.addon({ ctx.globalAlpha = node.opacity / 255; let tex = comp._texture, - data = comp._renderData._data; + verts = comp._renderData.vertices; let image = tex.getHtmlElementObj(); - let x = data[0].x; - let y = data[0].y; - let w = data[1].x - x; - let h = data[1].y - y; + let x = verts[0].x; + let y = verts[0].y; + let w = verts[1].x - x; + let h = verts[1].y - y; y = - y - h; ctx.drawImage(image, x, y, w, h); diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/simple.js b/cocos2d/core/renderer/canvas/renderers/sprite/simple.js index 52c0fc931c1..38ec1d2f6fb 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/simple.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/simple.js @@ -49,7 +49,7 @@ let renderer = { updateUVs (sprite) { let frame = sprite.spriteFrame; let renderData = sprite._renderData; - let data = renderData._data; + let verts = renderData.vertices; let rect = frame._rect; if (frame._rotated) { @@ -57,27 +57,27 @@ let renderer = { let r = rect.height; let b = rect.y; let t = rect.width; - data[0].u = l; - data[0].v = t; - data[1].u = r; - data[1].v = b; + verts[0].u = l; + verts[0].v = t; + verts[1].u = r; + verts[1].v = b; } else { let l = rect.x; let r = rect.width; let b = rect.y; let t = rect.height; - data[0].u = l; - data[0].v = b; - data[1].u = r; - data[1].v = t; + verts[0].u = l; + verts[0].v = b; + verts[1].u = r; + verts[1].v = t; } }, updateVerts (sprite) { let renderData = sprite._renderData, node = sprite.node, - data = renderData._data, + verts = renderData.vertices, cw = node.width, ch = node.height, appx = node.anchorX * cw, appy = node.anchorY * ch, l, b, r, t; @@ -103,10 +103,10 @@ let renderer = { t = ch; } - data[0].x = l; - data[0].y = b; - data[1].x = r; - data[1].y = t; + verts[0].x = l; + verts[0].y = b; + verts[1].x = r; + verts[1].y = t; }, draw (ctx, comp) { @@ -124,20 +124,20 @@ let renderer = { ctx.globalAlpha = node.opacity / 255; let tex = comp._spriteFrame._texture, - data = comp._renderData._data; + verts = comp._renderData.vertices; let image = utils.getColorizedImage(tex, node._color); - let x = data[0].x; - let y = data[0].y; - let w = data[1].x; - let h = data[1].y; + let x = verts[0].x; + let y = verts[0].y; + let w = verts[1].x; + let h = verts[1].y; y = - y - h; - let sx = data[0].u; - let sy = data[0].v; - let sw = data[1].u; - let sh = data[1].v; + let sx = verts[0].u; + let sy = verts[0].v; + let sw = verts[1].u; + let sh = verts[1].v; ctx.drawImage(image, sx, sy, sw, sh, diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js b/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js index 4b4eb141fba..03c6f41601d 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js @@ -50,32 +50,32 @@ let renderer = { let centerHeight = rect.height - topHeight - bottomHeight; // uv computation should take spritesheet into account. - let data = renderData._data; + let verts = renderData.vertices; if (frame._rotated) { - data[0].u = rect.x; - data[1].u = bottomHeight + rect.x; - data[2].u = bottomHeight + centerHeight + rect.x; - data[3].u = rect.x + rect.height; - data[3].v = rect.y; - data[2].v = leftWidth + rect.y; - data[1].v = leftWidth + centerWidth + rect.y; - data[0].v = rect.y + rect.width; + verts[0].u = rect.x; + verts[1].u = bottomHeight + rect.x; + verts[2].u = bottomHeight + centerHeight + rect.x; + verts[3].u = rect.x + rect.height; + verts[3].v = rect.y; + verts[2].v = leftWidth + rect.y; + verts[1].v = leftWidth + centerWidth + rect.y; + verts[0].v = rect.y + rect.width; } else { - data[0].u = rect.x; - data[1].u = leftWidth + rect.x; - data[2].u = leftWidth + centerWidth + rect.x; - data[3].u = rect.x + rect.width; - data[3].v = rect.y; - data[2].v = topHeight + rect.y; - data[1].v = topHeight + centerHeight + rect.y; - data[0].v = rect.y + rect.height; + verts[0].u = rect.x; + verts[1].u = leftWidth + rect.x; + verts[2].u = leftWidth + centerWidth + rect.x; + verts[3].u = rect.x + rect.width; + verts[3].v = rect.y; + verts[2].v = topHeight + rect.y; + verts[1].v = topHeight + centerHeight + rect.y; + verts[0].v = rect.y + rect.height; } }, updateVerts (sprite) { let renderData = sprite._renderData, - data = renderData._data, + verts = renderData.vertices, node = sprite.node, width = node.width, height = node.height, appx = node.anchorX * width, appy = node.anchorY * height; @@ -95,14 +95,14 @@ let renderer = { sizableWidth = sizableWidth < 0 ? 0 : sizableWidth; sizableHeight = sizableHeight < 0 ? 0 : sizableHeight; - data[0].x = -appx; - data[0].y = -appy; - data[1].x = leftWidth * xScale - appx; - data[1].y = bottomHeight * yScale - appy; - data[2].x = data[1].x + sizableWidth; - data[2].y = data[1].y + sizableHeight; - data[3].x = width - appx; - data[3].y = height - appy; + verts[0].x = -appx; + verts[0].y = -appy; + verts[1].x = leftWidth * xScale - appx; + verts[1].y = bottomHeight * yScale - appy; + verts[2].x = verts[1].x + sizableWidth; + verts[2].y = verts[1].y + sizableHeight; + verts[3].x = width - appx; + verts[3].y = height - appy; }, draw (ctx, comp) { @@ -120,7 +120,7 @@ let renderer = { ctx.globalAlpha = node.opacity / 255; let tex = comp._spriteFrame._texture, - data = comp._renderData._data; + verts = comp._renderData.vertices; let image = utils.getColorizedImage(tex, node._color); @@ -129,11 +129,11 @@ let renderer = { x, y, w, h, sx, sy, sw, sh; for (let r = 0; r < 3; ++r) { - bd = data[r]; - td = data[r+1]; + bd = verts[r]; + td = verts[r+1]; for (let c = 0; c < 3; ++c) { - ld = data[c]; - rd = data[c+1]; + ld = verts[c]; + rd = verts[c+1]; x = ld.x; y = bd.y; w = rd.x - x; diff --git a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js index 11b6e1296a9..74e042ed3fb 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js @@ -34,7 +34,7 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let node = comp.node, renderData = comp._renderData, - data = renderData._data, + verts = renderData.vertices, color = node._color._val; let matrix = node._worldMatrix, @@ -52,7 +52,7 @@ module.exports = js.addon({ uintbuf = buffer._uintVData; for (let i = 0; i < vertexCount; i++) { - let vert = data[i]; + let vert = verts[i]; vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset++] = vert.u; @@ -68,7 +68,7 @@ module.exports = js.addon({ renderData.vertexCount = renderData.dataLength; renderData.indiceCount = renderData.dataLength / 2 * 3; - let data = renderData._data; + let verts = renderData.vertices; let texw = texture.width, texh = texture.height; @@ -82,37 +82,37 @@ module.exports = js.addon({ b = (rect.y + rectHeight) / texh; t = (rect.y) / texh; - data[dataOffset].u = l; - data[dataOffset].v = b; - data[dataOffset+1].u = r; - data[dataOffset+1].v = b; - data[dataOffset+2].u = l; - data[dataOffset+2].v = t; - data[dataOffset+3].u = r; - data[dataOffset+3].v = t; + verts[dataOffset].u = l; + verts[dataOffset].v = b; + verts[dataOffset+1].u = r; + verts[dataOffset+1].v = b; + verts[dataOffset+2].u = l; + verts[dataOffset+2].v = t; + verts[dataOffset+3].u = r; + verts[dataOffset+3].v = t; } else { l = (rect.x) / texw; r = (rect.x + rectHeight) / texw; b = (rect.y + rectWidth) / texh; t = (rect.y) / texh; - data[dataOffset].u = l; - data[dataOffset].v = t; - data[dataOffset+1].u = l; - data[dataOffset+1].v = b; - data[dataOffset+2].u = r; - data[dataOffset+2].v = t; - data[dataOffset+3].u = r; - data[dataOffset+3].v = b; + verts[dataOffset].u = l; + verts[dataOffset].v = t; + verts[dataOffset+1].u = l; + verts[dataOffset+1].v = b; + verts[dataOffset+2].u = r; + verts[dataOffset+2].v = t; + verts[dataOffset+3].u = r; + verts[dataOffset+3].v = b; } - data[dataOffset].x = x; - data[dataOffset].y = y - rectHeight * scale; - data[dataOffset+1].x = x + rectWidth * scale; - data[dataOffset+1].y = y - rectHeight * scale; - data[dataOffset+2].x = x; - data[dataOffset+2].y = y; - data[dataOffset+3].x = x + rectWidth * scale; - data[dataOffset+3].y = y; + verts[dataOffset].x = x; + verts[dataOffset].y = y - rectHeight * scale; + verts[dataOffset+1].x = x + rectWidth * scale; + verts[dataOffset+1].y = y - rectHeight * scale; + verts[dataOffset+2].x = x; + verts[dataOffset+2].y = y; + verts[dataOffset+3].x = x + rectWidth * scale; + verts[dataOffset+3].y = y; }, }, bmfontUtls); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index 7fe92c669df..237ebc7ce3e 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -36,20 +36,20 @@ module.exports = js.addon({ renderData.vertexCount = 4; renderData.indiceCount = 6; - let data = renderData._data; - data[0].u = 0; - data[0].v = 1; - data[1].u = 1; - data[1].v = 1; - data[2].u = 0; - data[2].v = 0; - data[3].u = 1; - data[3].v = 0; + let verts = renderData.vertices; + verts[0].u = 0; + verts[0].v = 1; + verts[1].u = 1; + verts[1].v = 1; + verts[2].u = 0; + verts[2].v = 0; + verts[3].u = 1; + verts[3].v = 0; return renderData; }, fillBuffers (comp, renderer) { - let data = comp._renderData._data, + let verts = comp._renderData.vertices, node = comp.node, color = WHITE._val, matrix = node._worldMatrix, @@ -67,7 +67,7 @@ module.exports = js.addon({ // vertex for (let i = 0; i < 4; i++) { - let vert = data[i]; + let vert = verts[i]; vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset++] = vert.u; @@ -85,14 +85,14 @@ module.exports = js.addon({ appx = node.anchorX * width, appy = node.anchorY * height; - let data = renderData._data; - data[0].x = -appx; - data[0].y = -appy; - data[1].x = width - appx; - data[1].y = -appy; - data[2].x = -appx; - data[2].y = height - appy; - data[3].x = width - appx; - data[3].y = height - appy; + let verts = renderData.vertices; + verts[0].x = -appx; + verts[0].y = -appy; + verts[1].x = width - appx; + verts[1].y = -appy; + verts[2].x = -appx; + verts[2].y = height - appy; + verts[3].x = width - appx; + verts[3].y = height - appy; } }, ttfUtls); diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index b87bf6f1ff3..72f425660ed 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -123,7 +123,7 @@ var motionStreakAssembler = { return; } - let data = renderData._data; + let verts = renderData.vertices; let color = comp._color, cr = color.r, cg = color.g, cb = color.b, ca = color.a; @@ -168,18 +168,18 @@ var motionStreakAssembler = { let da = progress*ca; let c = ((da<<24) >>> 0) + (cb<<16) + (cg<<8) + cr; - let dataIndex = data.length - 1; - data[dataIndex].x = point.x - _normal.x * stroke; - data[dataIndex].y = point.y - _normal.y * stroke; - data[dataIndex].u = 0; - data[dataIndex].v = progress; - data[dataIndex].color = c; + let dataIndex = verts.length - 1; + verts[dataIndex].x = point.x - _normal.x * stroke; + verts[dataIndex].y = point.y - _normal.y * stroke; + verts[dataIndex].u = 0; + verts[dataIndex].v = progress; + verts[dataIndex].color = c; dataIndex--; - data[dataIndex].x = point.x + _normal.x * stroke; - data[dataIndex].y = point.y + _normal.y * stroke; - data[dataIndex].u = 1; - data[dataIndex].v = progress; - data[dataIndex].color = c; + verts[dataIndex].x = point.x + _normal.x * stroke; + verts[dataIndex].y = point.y + _normal.y * stroke; + verts[dataIndex].u = 1; + verts[dataIndex].v = progress; + verts[dataIndex].color = c; } renderData.vertexCount = renderData.dataLength; @@ -188,7 +188,7 @@ var motionStreakAssembler = { fillBuffers (comp, renderer) { let renderData = comp._renderData, - data = renderData._data; + verts = renderData.vertices; let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, @@ -207,7 +207,7 @@ var motionStreakAssembler = { // vertex buffer let vert; for (let i = 0, l = renderData.vertexCount; i < l; i++) { - vert = data[i]; + vert = verts[i]; vbuf[vertexOffset++] = vert.x; vbuf[vertexOffset++] = vert.y; vbuf[vertexOffset++] = vert.u; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index 09d4204df2e..b9e89a3d036 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -81,7 +81,7 @@ module.exports = { updateUVs (sprite, fillStart, fillEnd) { let spriteFrame = sprite._spriteFrame, renderData = sprite._renderData, - data = renderData._data; + verts = renderData.vertices; //build uvs let atlasWidth = spriteFrame._texture.width; @@ -115,24 +115,24 @@ module.exports = { switch (sprite._fillType) { case FillType.HORIZONTAL: - data[0].u = quadUV0 + (quadUV2 - quadUV0) * fillStart; - data[0].v = quadUV1; - data[1].u = quadUV0 + (quadUV2 - quadUV0) * fillEnd; - data[1].v = quadUV3; - data[2].u = quadUV4 + (quadUV6 - quadUV4) * fillStart; - data[2].v = quadUV5; - data[3].u = quadUV4 + (quadUV6 - quadUV4) * fillEnd; - data[3].v = quadUV7; + verts[0].u = quadUV0 + (quadUV2 - quadUV0) * fillStart; + verts[0].v = quadUV1; + verts[1].u = quadUV0 + (quadUV2 - quadUV0) * fillEnd; + verts[1].v = quadUV3; + verts[2].u = quadUV4 + (quadUV6 - quadUV4) * fillStart; + verts[2].v = quadUV5; + verts[3].u = quadUV4 + (quadUV6 - quadUV4) * fillEnd; + verts[3].v = quadUV7; break; case FillType.VERTICAL: - data[0].u = quadUV0; - data[0].v = quadUV1 + (quadUV5 - quadUV1) * fillStart; - data[1].u = quadUV2; - data[1].v = quadUV3 + (quadUV7 - quadUV3) * fillStart; - data[2].u = quadUV4; - data[2].v = quadUV1 + (quadUV5 - quadUV1) * fillEnd; - data[3].u = quadUV6; - data[3].v = quadUV3 + (quadUV7 - quadUV3) * fillEnd; + verts[0].u = quadUV0; + verts[0].v = quadUV1 + (quadUV5 - quadUV1) * fillStart; + verts[1].u = quadUV2; + verts[1].v = quadUV3 + (quadUV7 - quadUV3) * fillStart; + verts[2].u = quadUV4; + verts[2].v = quadUV1 + (quadUV5 - quadUV1) * fillEnd; + verts[3].u = quadUV6; + verts[3].v = quadUV3 + (quadUV7 - quadUV3) * fillEnd; break; default: cc.errorID(2626); @@ -142,7 +142,7 @@ module.exports = { updateVerts (sprite, fillStart, fillEnd) { let renderData = sprite._renderData, - data = renderData._data, + verts = renderData.vertices, node = sprite.node, width = node.width, height = node.height, appx = node.anchorX * width, appy = node.anchorY * height; @@ -171,14 +171,14 @@ module.exports = { break; } - data[4].x = l; - data[4].y = b; - data[5].x = r; - data[5].y = b; - data[6].x = l; - data[6].y = t; - data[7].x = r; - data[7].y = t; + verts[4].x = l; + verts[4].y = b; + verts[5].x = r; + verts[5].y = b; + verts[6].x = l; + verts[6].y = t; + verts[7].x = r; + verts[7].y = t; }, createData (sprite) { @@ -193,15 +193,15 @@ module.exports = { updateWorldVerts (sprite) { let node = sprite.node, - data = sprite._renderData._data; + verts = sprite._renderData.verticess; let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; for (let i = 0; i < 4; i++) { - let local = data[i+4]; - let world = data[i]; + let local = verts[i+4]; + let world = verts[i]; world.x = local.x * a + local.y * c + tx; world.y = local.x * b + local.y * d + ty; } @@ -212,12 +212,9 @@ module.exports = { this.updateWorldVerts(sprite); } - let data = sprite._renderData._data, + let verts = sprite._renderData.vertices, node = sprite.node, - color = node._color._val, - matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; + color = node._color._val; let buffer = renderer._quadBuffer, vertexOffset = buffer.byteOffset >> 2; @@ -230,7 +227,7 @@ module.exports = { // vertex for (let i = 0; i < 4; i++) { - let vert = data[i]; + let vert = verts[i]; vbuf[vertexOffset++] = vert.x; vbuf[vertexOffset++] = vert.y; vbuf[vertexOffset++] = vert.u; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js index 204d04eebc0..d9701bc097f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js @@ -80,9 +80,9 @@ module.exports = { v = vertices.nv; let renderData = sprite._renderData; - let data = renderData._data; + let verts = renderData.vertices; for (let i = 0, l = u.length; i < l; i++) { - let vertice = data[i]; + let vertice = verts[i]; vertice.u = u[i]; vertice.v = v[i]; } @@ -112,18 +112,18 @@ module.exports = { scaleY = contentHeight / (sprite.trim ? rectHeight : originalHeight); let renderData = sprite._renderData; - let data = renderData._data; + let verts = renderData.vertices; if (!sprite.trim) { for (let i = 0, l = x.length; i < l; i++) { - let vertice = data[i+l]; + let vertice = verts[i+l]; vertice.x = (x[i]) * scaleX - appx; vertice.y = (originalHeight - y[i]) * scaleY - appy; } } else { for (let i = 0, l = x.length; i < l; i++) { - let vertice = data[i+l]; + let vertice = verts[i+l]; vertice.x = (x[i] - trimX) * scaleX - appx; vertice.y = (originalHeight - y[i] - trimY) * scaleY - appy; } @@ -133,14 +133,14 @@ module.exports = { updateWorldVerts (sprite) { let node = sprite.node, renderData = sprite._renderData, - data = renderData._data; + verts = renderData.vertices; let matrix = node._worldMatrix; let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; for (let i = 0, l = renderData.vertexCount; i < l; i++) { - let local = data[i+l]; - let world = data[i]; + let local = verts[i+l]; + let world = verts[i]; world.x = local.x * a + local.y * c + tx; world.y = local.x * b + local.y * d + ty; } @@ -150,7 +150,7 @@ module.exports = { let node = sprite.node, color = node._color._val, renderData = sprite._renderData, - data = renderData._data; + verts = renderData.vertices; let vertices = sprite.spriteFrame.vertices; if (!vertices) { @@ -172,7 +172,7 @@ module.exports = { ibuf = buffer._iData; for (let i = 0, l = renderData.vertexCount; i < l; i++) { - let vertice = data[i]; + let vertice = verts[i]; vbuf[vertexOffset++] = vertice.x; vbuf[vertexOffset++] = vertice.y; vbuf[vertexOffset++] = vertice.u; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js index 9118c0cc1ba..e9984b580d8 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js @@ -58,7 +58,7 @@ module.exports = { let renderData = sprite._renderData; if (renderData && frame && sprite._vertsDirty) { - let data = renderData._data; + let verts = renderData.vertices; let fillStart = sprite._fillStart; let fillRange = sprite._fillRange; @@ -83,7 +83,7 @@ module.exports = { let center = this._center; let vertPos = this._vertPos, - vertices = this._vertices; + vertices = this.vertices; let triangles = this._triangles; @@ -99,7 +99,7 @@ module.exports = { //all in if (fillRange >= PI_2) { renderData.dataLength = offset + 3; - this._generateTriangle(data, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); + this._generateTriangle(verts, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); offset += 3; continue; } @@ -117,10 +117,10 @@ module.exports = { renderData.dataLength = offset + 3; if(endAngle >= fillEnd) { //startAngle to fillEnd - this._generateTriangle(data, offset, center, vertPos[triangle[0]], this._intersectPoint_2[triangleIndex]); + this._generateTriangle(verts, offset, center, vertPos[triangle[0]], this._intersectPoint_2[triangleIndex]); } else { //startAngle to endAngle - this._generateTriangle(data, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); + this._generateTriangle(verts, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); } offset += 3; } else { @@ -130,12 +130,12 @@ module.exports = { } else if(endAngle <= fillEnd) { renderData.dataLength = offset + 3; //fillStart to endAngle - this._generateTriangle(data, offset, center, this._intersectPoint_1[triangleIndex], vertPos[triangle[1]]); + this._generateTriangle(verts, offset, center, this._intersectPoint_1[triangleIndex], vertPos[triangle[1]]); offset += 3; } else { renderData.dataLength = offset + 3; //fillStart to fillEnd - this._generateTriangle(data, offset, center, this._intersectPoint_1[triangleIndex], this._intersectPoint_2[triangleIndex]); + this._generateTriangle(verts, offset, center, this._intersectPoint_1[triangleIndex], this._intersectPoint_2[triangleIndex]); offset += 3; } } @@ -173,41 +173,41 @@ module.exports = { } }, - _generateTriangle: function(data, offset, vert0, vert1, vert2) { - let vertices = this._vertices; + _generateTriangle: function(verts, offset, vert0, vert1, vert2) { + let vertices = this.vertices; let v0x = vertices[0]; let v0y = vertices[1]; let v1x = vertices[2]; let v1y = vertices[3]; - data[offset].x = vert0.x; - data[offset].y = vert0.y; - data[offset+1].x = vert1.x; - data[offset+1].y = vert1.y; - data[offset+2].x = vert2.x; - data[offset+2].y = vert2.y; + verts[offset].x = vert0.x; + verts[offset].y = vert0.y; + verts[offset+1].x = vert1.x; + verts[offset+1].y = vert1.y; + verts[offset+2].x = vert2.x; + verts[offset+2].y = vert2.y; let progressX, progressY; progressX = (vert0.x - v0x) / (v1x - v0x); progressY = (vert0.y - v0y) / (v1y - v0y); - this._generateUV(progressX, progressY, data, offset); + this._generateUV(progressX, progressY, verts, offset); progressX = (vert1.x - v0x) / (v1x - v0x); progressY = (vert1.y - v0y) / (v1y - v0y); - this._generateUV(progressX, progressY, data, offset + 1); + this._generateUV(progressX, progressY, verts, offset + 1); progressX = (vert2.x - v0x) / (v1x - v0x); progressY = (vert2.y - v0y) / (v1y - v0y); - this._generateUV(progressX, progressY, data, offset + 2); + this._generateUV(progressX, progressY, verts, offset + 2); }, - _generateUV : function(progressX, progressY, data, offset) { + _generateUV : function(progressX, progressY, verts, offset) { let uvs = this._uvs; let px1 = uvs[0] + (uvs[2] - uvs[0]) * progressX; let px2 = uvs[4] + (uvs[6] - uvs[4]) * progressX; let py1 = uvs[1] + (uvs[3] - uvs[1]) * progressX; let py2 = uvs[5] + (uvs[7] - uvs[5]) * progressX; - let uv = data[offset]; + let uv = verts[offset]; uv.u = px1 + (px2 - px1) * progressY; uv.v = py1 + (py2 - py1) * progressY; }, @@ -259,7 +259,7 @@ module.exports = { let l = -appx, b = -appy, r = width-appx, t = height-appy; - let vertices = this._vertices; + let vertices = this.vertices; vertices[0] = l; vertices[1] = b; vertices[2] = r; @@ -328,7 +328,7 @@ module.exports = { fillBuffers (sprite, renderer) { let renderData = sprite._renderData, - data = renderData._data, + verts = renderData.vertices, node = sprite.node, color = node._color._val; @@ -348,9 +348,9 @@ module.exports = { buffer.request(renderData.vertexCount, renderData.indiceCount); - let count = data.length; + let count = verts.length; for (let i = 0; i < count; i++) { - let vert = data[i]; + let vert = verts[i]; vbuf[vertexOffset ++] = vert.x * a + vert.y * c + tx; vbuf[vertexOffset ++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset ++] = vert.u; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js index edfe9b2692b..7571d30cfc1 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js @@ -50,7 +50,7 @@ module.exports = { }, fillBuffers (sprite, renderer) { - let data = sprite._renderData._data, + let verts = sprite._renderData.vertices, node = sprite.node, color = node._color._val, matrix = node._worldMatrix, @@ -80,7 +80,7 @@ module.exports = { vbuf[vertexOffset+17] = uv[6]; vbuf[vertexOffset+18] = uv[7]; - let data0 = data[0], data3 = data[3], + let data0 = verts[0], data3 = verts[3], vl = data0.x, vr = data3.x, vb = data0.y, vt = data3.y; @@ -126,7 +126,7 @@ module.exports = { updateVerts (sprite) { let renderData = sprite._renderData, node = sprite.node, - data = renderData._data, + verts = renderData.vertices, cw = node.width, ch = node.height, appx = node.anchorX * cw, appy = node.anchorY * ch, l, b, r, t; @@ -152,13 +152,13 @@ module.exports = { t = ch + trimTop * scaleY - appy; } - data[0].x = l; - data[0].y = b; - // data[1].x = r; - // data[1].y = b; - // data[2].x = l; - // data[2].y = t; - data[3].x = r; - data[3].y = t; + verts[0].x = l; + verts[0].y = b; + // verts[1].x = r; + // verts[1].y = b; + // verts[2].x = l; + // verts[2].y = t; + verts[3].x = r; + verts[3].y = t; } }; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js index 73addf0bf2c..dc3b05d8466 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js @@ -63,7 +63,7 @@ module.exports = { updateVerts (sprite) { let renderData = sprite._renderData, - data = renderData._data, + verts = renderData.vertices, node = sprite.node, width = node.width, height = node.height, appx = node.anchorX * width, appy = node.anchorY * height; @@ -83,14 +83,14 @@ module.exports = { sizableWidth = sizableWidth < 0 ? 0 : sizableWidth; sizableHeight = sizableHeight < 0 ? 0 : sizableHeight; - data[0].x = -appx; - data[0].y = -appy; - data[1].x = leftWidth * xScale - appx; - data[1].y = bottomHeight * yScale - appy; - data[2].x = data[1].x + sizableWidth; - data[2].y = data[1].y + sizableHeight; - data[3].x = width - appx; - data[3].y = height - appy; + verts[0].x = -appx; + verts[0].y = -appy; + verts[1].x = leftWidth * xScale - appx; + verts[1].y = bottomHeight * yScale - appy; + verts[2].x = verts[1].x + sizableWidth; + verts[2].y = verts[1].y + sizableHeight; + verts[3].x = width - appx; + verts[3].y = height - appy; }, fillBuffers (sprite, renderer) { @@ -101,7 +101,7 @@ module.exports = { let renderData = sprite._renderData, node = sprite.node, color = node._color._val, - data = renderData._data; + verts = renderData.vertices; let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, @@ -119,7 +119,7 @@ module.exports = { ibuf = buffer._iData; for (let i = 4; i < 20; ++i) { - let vert = data[i]; + let vert = verts[i]; let uvs = uvSliced[i - 4]; vbuf[vertexOffset++] = vert.x; @@ -144,17 +144,17 @@ module.exports = { updateWorldVerts (sprite) { let node = sprite.node, - data = sprite._renderData._data; + verts = sprite._renderData.vertices; let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; for (let row = 0; row < 4; ++row) { - let rowD = data[row]; + let rowD = verts[row]; for (let col = 0; col < 4; ++col) { - let colD = data[col]; - let world = data[4 + row*4 + col]; + let colD = verts[col]; + let world = verts[4 + row*4 + col]; world.x = colD.x*a + rowD.y*c + tx; world.y = colD.x*b + rowD.y*d + ty; } diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js index 34667b82526..bfed943e2cd 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js @@ -64,14 +64,14 @@ module.exports = { row = Math.ceil(vRepeat), col = Math.ceil(hRepeat); - let data = renderData._data; + let verts = renderData.vertices; renderData.dataLength = Math.max(8, row+1, col+1); for (let i = 0; i <= col; ++i) { - data[i].x = Math.min(rectWidth * i, contentWidth) - appx; + verts[i].x = Math.min(rectWidth * i, contentWidth) - appx; } for (let i = 0; i <= row; ++i) { - data[i].y = Math.min(rectHeight * i, contentHeight) - appy; + verts[i].y = Math.min(rectHeight * i, contentHeight) - appy; } // update data property @@ -84,7 +84,7 @@ module.exports = { let node = sprite.node, color = node._color._val, renderData = sprite._renderData, - data = renderData._data; + verts = renderData.vertices; // buffer let buffer = renderer._meshBuffer, @@ -116,13 +116,13 @@ module.exports = { let x, x1, y, y1, coefu, coefv; for (let yindex = 0, ylength = row; yindex < ylength; ++yindex) { - y = data[yindex].y; - y1 = data[yindex+1].y; + y = verts[yindex].y; + y1 = verts[yindex+1].y; coefv = Math.min(1, vRepeat - yindex); for (let xindex = 0, xlength = col; xindex < xlength; ++xindex) { coefu = Math.min(1, hRepeat - xindex); - x = data[xindex].x; - x1 = data[xindex+1].x; + x = verts[xindex].x; + x1 = verts[xindex+1].x; // Vertex // lb diff --git a/cocos2d/tilemap/tmx-layer-assembler.js b/cocos2d/tilemap/tmx-layer-assembler.js index b9a34a93a2d..6476b739c77 100644 --- a/cocos2d/tilemap/tmx-layer-assembler.js +++ b/cocos2d/tilemap/tmx-layer-assembler.js @@ -56,7 +56,7 @@ let tmxAssembler = { fillBuffers (comp, renderer) { let renderData = comp._renderData; - let data = renderData._data; + let verts = renderData.vertices; let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, @@ -73,7 +73,7 @@ let tmxAssembler = { uintbuf = buffer._uintVData; for (let i = 0, l = renderData.vertexCount; i < l; i++) { - let vert = data[i]; + let vert = verts[i]; vbuf[vertexOffset++] = vert.x; vbuf[vertexOffset++] = vert.y; vbuf[vertexOffset++] = vert.u; @@ -97,7 +97,7 @@ let tmxAssembler = { updateVertices (comp) { let node = comp.node; let renderData = comp._renderData; - let data = renderData._data; + let verts = renderData.vertices; let color = node._color._val; let opacity = node._color.a; @@ -298,35 +298,35 @@ let tmxAssembler = { renderData.dataLength = renderData.vertexCount; // tl - data[dataOffset].x = left * a + top * c + tx; - data[dataOffset].y = left * b + top * d + ty; - data[dataOffset].u = flippedX ? grid.r : grid.l; - data[dataOffset].v = flippedY ? grid.b : grid.t; - data[dataOffset].color = color; + verts[dataOffset].x = left * a + top * c + tx; + verts[dataOffset].y = left * b + top * d + ty; + verts[dataOffset].u = flippedX ? grid.r : grid.l; + verts[dataOffset].v = flippedY ? grid.b : grid.t; + verts[dataOffset].color = color; dataOffset++; // bl - data[dataOffset].x = left * a + bottom * c + tx; - data[dataOffset].y = left * b + bottom * d + ty; - data[dataOffset].u = flippedX ? grid.r : grid.l; - data[dataOffset].v = flippedY ? grid.t : grid.b; - data[dataOffset].color = color; + verts[dataOffset].x = left * a + bottom * c + tx; + verts[dataOffset].y = left * b + bottom * d + ty; + verts[dataOffset].u = flippedX ? grid.r : grid.l; + verts[dataOffset].v = flippedY ? grid.t : grid.b; + verts[dataOffset].color = color; dataOffset++; // tr - data[dataOffset].x = right * a + top * c + tx; - data[dataOffset].y = right * b + top * d + ty; - data[dataOffset].u = flippedX ? grid.l : grid.r; - data[dataOffset].v = flippedY ? grid.b : grid.t; - data[dataOffset].color = color; + verts[dataOffset].x = right * a + top * c + tx; + verts[dataOffset].y = right * b + top * d + ty; + verts[dataOffset].u = flippedX ? grid.l : grid.r; + verts[dataOffset].v = flippedY ? grid.b : grid.t; + verts[dataOffset].color = color; dataOffset++; // br - data[dataOffset].x = right * a + bottom * c + tx; - data[dataOffset].y = right * b + bottom * d + ty; - data[dataOffset].u = flippedX ? grid.l : grid.r; - data[dataOffset].v = flippedY ? grid.t : grid.b; - data[dataOffset].color = color; + verts[dataOffset].x = right * a + bottom * c + tx; + verts[dataOffset].y = right * b + bottom * d + ty; + verts[dataOffset].u = flippedX ? grid.l : grid.r; + verts[dataOffset].v = flippedY ? grid.t : grid.b; + verts[dataOffset].color = color; dataOffset++; if (tiledTile) { diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index d705085ca3c..731389bb2bc 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -110,7 +110,7 @@ var spineAssembler = { let vertexCount = vertices.length / 8; // augment render data size to ensure capacity renderData.dataLength += vertexCount; - let data = renderData._data; + let verts = renderData.vertices; let nodeColor = comp.node._color; let nodeR = nodeColor.r, nodeG = nodeColor.g, @@ -122,7 +122,7 @@ var spineAssembler = { b = vertices[i + 4] * nodeB, a = vertices[i + 5] * nodeA; let color = ((a<<24) >>> 0) + (b<<16) + (g<<8) + r; - let content = data[dataOffset]; + let content = verts[dataOffset]; content.x = vertices[i]; content.y = vertices[i + 1]; content.color = color; @@ -232,7 +232,7 @@ var spineAssembler = { } // Fill up indices - indices = data._indices; + indices = data.indices; if (isRegion) { indices[indiceOffset] = vertexOffset; indices[indiceOffset + 1] = vertexOffset + 1; @@ -321,8 +321,8 @@ var spineAssembler = { renderer.material = data.material; } - let vertexs = data._data; - let indices = data._indices; + let vertexs = data.vertices; + let indices = data.indices; let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, diff --git a/test/qunit/unit-es5/test-spriteRenderer.js b/test/qunit/unit-es5/test-spriteRenderer.js index effca1ff55f..0e52233f798 100644 --- a/test/qunit/unit-es5/test-spriteRenderer.js +++ b/test/qunit/unit-es5/test-spriteRenderer.js @@ -58,7 +58,7 @@ if (!isPhantomJS) { cc.director.getScene().addChild(node); sprite._assembler.updateRenderData(sprite); - var vertices = sprite._renderData._data; + var vertices = sprite._renderData.vertices; var uvs = sprite._spriteFrame.uv; strictEqual(vertices[0].x, -contentSize.width / 2, 'vertex-bl-x test success'); @@ -97,7 +97,7 @@ if (!isPhantomJS) { cc.director.getScene().addChild(node); sprite._assembler.updateRenderData(sprite); - var vertices = sprite._renderData._data; + var vertices = sprite._renderData.vertices; var uvs = sprite._spriteFrame.uv; var anchorX = node.width * node.anchorX; var anchorY = node.height * node.anchorY; @@ -140,7 +140,7 @@ if (!isPhantomJS) { cc.director.getScene().addChild(node); sprite._assembler.updateRenderData(sprite); - var vertices = sprite._renderData._data; + var vertices = sprite._renderData.vertices; var uvs = sprite._spriteFrame.uvSliced; strictEqual(uvs.length == 16, true, 'have 16 uvs'); @@ -189,7 +189,7 @@ if (!isPhantomJS) { cc.director.getScene().addChild(node); sprite._assembler.updateRenderData(sprite); - var vertices = sprite._renderData._data; + var vertices = sprite._renderData.vertices; var uvs = sprite._spriteFrame.uv; strictEqual(vertices.length == 8, true, 'have 8 vertices'); @@ -235,7 +235,7 @@ if (!isPhantomJS) { cc.director.getScene().addChild(node); sprite._assembler.updateRenderData(sprite); - var vertices = sprite._renderData._data; + var vertices = sprite._renderData.vertices; strictEqual(vertices[4].x, 10, 'vertex-bl-x test success'); strictEqual(vertices[4].y, 0, 'vertex-bl-y test success'); @@ -290,7 +290,7 @@ if (!isPhantomJS) { cc.director.getScene().addChild(node); sprite._assembler.updateRenderData(sprite); - var vertices = sprite._renderData._data; + var vertices = sprite._renderData.vertices; strictEqual(vertices[4].x, 0, 'vertex-bl-x test success'); strictEqual(vertices[4].y, 10, 'vertex-bl-y test success'); @@ -346,7 +346,7 @@ if (!isPhantomJS) { cc.director.getScene().addChild(node); sprite._assembler.updateRenderData(sprite); - var vertices = sprite._renderData._data; + var vertices = sprite._renderData.vertices; var center = cc.v2(50, 50); var p0 = cc.v2(100, 50); From f38940b24cf46fe94400541a20036c9d8dfa799e Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 7 Nov 2018 16:14:33 +0800 Subject: [PATCH 0152/1631] FIx label update issue --- cocos2d/core/components/CCLabel.js | 2 +- cocos2d/core/components/CCRichText.js | 2 +- cocos2d/core/renderer/utils/label/ttf.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 1b859d24f19..cc8492e892d 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -464,7 +464,7 @@ let Label = cc.Class({ } this._checkStringEmpty(); - this._updateRenderData(true); + this._forceUpdateRenderData(); }, onDestroy () { diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index 76fc68ef577..9a557f6961b 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -836,7 +836,7 @@ let RichText = cc.Class({ labelComponent.fontSize = this.fontSize; } - labelComponent._updateRenderData(true); + labelComponent._forceUpdateRenderData(); if (textStyle && textStyle.event) { if (textStyle.event.click) { diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 500b0d31e50..2ff7a26642a 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -150,7 +150,7 @@ module.exports = { else { cc.loader.load(comp.font.nativeUrl, function (err, fontFamily) { _fontFamily = fontFamily || 'Arial'; - comp._updateRenderData(true); + comp._forceUpdateRenderData(); }); } } From 1b4bce43c2f3c9a714dd99207905f148c69a08d4 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 7 Nov 2018 16:14:48 +0800 Subject: [PATCH 0153/1631] Fix RenderData vertices usage issue --- cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js | 2 +- .../core/renderer/webgl/assemblers/sprite/radial-filled.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index b9e89a3d036..d6bac15bf90 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -193,7 +193,7 @@ module.exports = { updateWorldVerts (sprite) { let node = sprite.node, - verts = sprite._renderData.verticess; + verts = sprite._renderData.vertices; let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js index e9984b580d8..17c1a72b87a 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js @@ -83,7 +83,7 @@ module.exports = { let center = this._center; let vertPos = this._vertPos, - vertices = this.vertices; + vertices = this._vertices; let triangles = this._triangles; @@ -174,7 +174,7 @@ module.exports = { }, _generateTriangle: function(verts, offset, vert0, vert1, vert2) { - let vertices = this.vertices; + let vertices = this._vertices; let v0x = vertices[0]; let v0y = vertices[1]; let v1x = vertices[2]; @@ -259,7 +259,7 @@ module.exports = { let l = -appx, b = -appy, r = width-appx, t = height-appy; - let vertices = this.vertices; + let vertices = this._vertices; vertices[0] = l; vertices[1] = b; vertices[2] = r; From 111f832c245fe90cde71438330e61783bbc1ee90 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Thu, 8 Nov 2018 10:23:05 +0800 Subject: [PATCH 0154/1631] fixed game creator.t.ds decorator (#3473) --- cocos2d/core/CCGame.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index b16db60889d..ce07b5986d2 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -39,7 +39,6 @@ const dynamicAtlasManager = require('../core/renderer/utils/dynamic-atlas/manage * !#en An object to boot the game. * !#zh 包含游戏主体信息并负责驱动游戏的游戏对象。 * @class Game - * @static * @extends EventTarget */ var game = { From 66082d74a520cb76d6254ff56725347d619e1885 Mon Sep 17 00:00:00 2001 From: Ben Long Date: Thu, 8 Nov 2018 10:23:53 +0800 Subject: [PATCH 0155/1631] fix typo (#3469) --- cocos2d/tilemap/CCTiledMap.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/tilemap/CCTiledMap.js b/cocos2d/tilemap/CCTiledMap.js index f63feab7bcc..865d36df588 100644 --- a/cocos2d/tilemap/CCTiledMap.js +++ b/cocos2d/tilemap/CCTiledMap.js @@ -465,11 +465,11 @@ let TiledMap = cc.Class({ this._buildWithMapInfo(mapInfo); } else { - this._relseasMapInfo() + this._releaseMapInfo() } }, - _relseasMapInfo () { + _releaseMapInfo () { // remove the layers & object groups added before let layers = this._layers; for (let i = 0, l = layers.length; i < l; i++) { @@ -498,7 +498,7 @@ let TiledMap = cc.Class({ this._properties = mapInfo.properties; this._tileProperties = mapInfo.getTileProperties(); - this._relseasMapInfo(); + this._releaseMapInfo(); let layers = this._layers; let groups = this._groups; From 07323b6279bbd0e3a9b9eb5e14fd854d3c16a135 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 8 Nov 2018 10:57:59 +0800 Subject: [PATCH 0156/1631] fix button transition serialized value error for 2d-tasks/issues/755 (#3474) --- cocos2d/core/components/CCButton.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 96e2cb3961f..30f530614cd 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -207,6 +207,7 @@ let Button = cc.Class({ notify (oldValue) { this._updateTransition(oldValue); }, + formerlySerializedAs: 'transition' }, // color transition @@ -242,7 +243,8 @@ let Button = cc.Class({ this.target.opacity = this.pressedColor.a; } this._updateState(); - } + }, + formerlySerializedAs: 'pressedColor' }, /** @@ -259,7 +261,8 @@ let Button = cc.Class({ this.target.opacity = this.hoverColor.a; } this._updateState(); - } + }, + formerlySerializedAs: 'hoverColor' }, /** From 821e634690334033f010f9ca4bb66f2f7940504e Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 8 Nov 2018 14:24:31 +0800 Subject: [PATCH 0157/1631] fix button _resetState error, the isvalid of the button target must be true (#3476) --- cocos2d/core/components/CCButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 30f530614cd..e9612033cc1 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -420,7 +420,7 @@ let Button = cc.Class({ this._hovered = false; // // Restore button status let target = this.target; - if (!target) { + if (!target || !target.isValid) { return; } let transition = this.transition; From ba266a9372f27dd013728e3c51bfa69c7101c98c Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Fri, 9 Nov 2018 14:43:49 +0800 Subject: [PATCH 0158/1631] fixed the FbPlayableAd make the sys.platform mislead error (#3478) --- cocos2d/core/platform/CCSys.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index ae25a79364f..a0a4fbc682f 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -757,7 +757,7 @@ else { * Indicate the running platform * @property {Number} platform */ - if (typeof FbPlayableAd !== undefined) { + if (typeof FbPlayableAd !== "undefined") { sys.platform = sys.FB_PLAYABLE_ADS; } else { From e8bc5474decd73fb6909ec981346e8e827ed3222 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 9 Nov 2018 16:14:34 +0800 Subject: [PATCH 0159/1631] nodes should be destroyed with the scene. fix #3456 (#3483) --- cocos2d/core/CCScene.js | 8 +++++++- cocos2d/core/node-activator.js | 4 ++-- cocos2d/core/utils/base-node.js | 2 +- test/qunit/unit-es5/test-component-scheduler.js | 6 +++--- test/qunit/unit-es5/test-node.js | 11 +++++++++++ 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/CCScene.js b/cocos2d/core/CCScene.js index f5c4cbe2dff..1fd709917e2 100644 --- a/cocos2d/core/CCScene.js +++ b/cocos2d/core/CCScene.js @@ -74,7 +74,13 @@ cc.Scene = cc.Class({ }, destroy: function () { - this._super(); + if (cc.Object.prototype.destroy.call(this)) { + var children = this._children; + for (var i = 0; i < children.length; ++i) { + children[i].active = false; + } + } + this._active = false; this._activeInHierarchy = false; }, diff --git a/cocos2d/core/node-activator.js b/cocos2d/core/node-activator.js index 47afcaab5b8..77f171cb1c1 100644 --- a/cocos2d/core/node-activator.js +++ b/cocos2d/core/node-activator.js @@ -248,7 +248,7 @@ var NodeActivator = cc.Class({ activateComp: CC_EDITOR ? function (comp, preloadInvoker, onLoadInvoker, onEnableInvoker) { if (!cc.isValid(comp, true)) { - // destroied before activating + // destroyed before activating return; } if (cc.engine._isPlaying || comp.constructor._executeInEditMode) { @@ -288,7 +288,7 @@ var NodeActivator = cc.Class({ } } : function (comp, preloadInvoker, onLoadInvoker, onEnableInvoker) { if (!cc.isValid(comp, true)) { - // destroied before activating + // destroyed before activating return; } if (!(comp._objFlags & IsPreloadStarted)) { diff --git a/cocos2d/core/utils/base-node.js b/cocos2d/core/utils/base-node.js index 6b9b45e2c79..b39572d2ffe 100644 --- a/cocos2d/core/utils/base-node.js +++ b/cocos2d/core/utils/base-node.js @@ -1091,7 +1091,7 @@ var BaseNode = cc.Class({ destroy () { if (cc.Object.prototype.destroy.call(this)) { - this.parent = null; + this.active = false; } }, diff --git a/test/qunit/unit-es5/test-component-scheduler.js b/test/qunit/unit-es5/test-component-scheduler.js index a1fab6658a6..5ec0d7d464e 100644 --- a/test/qunit/unit-es5/test-component-scheduler.js +++ b/test/qunit/unit-es5/test-component-scheduler.js @@ -544,16 +544,16 @@ test('set sibling index during onDisable', function () { compOfChild.onEnable.once('child component should be re-enabled'); }); - test('component might be destroied when destroy() called before node activating', function () { + test('component might be destroyed when destroy() called before node activating', function () { var node = new cc.Node(); - var comp = createDisabledComp(node, 'destroied'); + var comp = createDisabledComp(node, 'destroyed'); comp.onDestroy = new Callback().disable('onDestroy should not be called'); comp.destroy(); cc.director.getScene().addChild(node); cc.game.step(); - strictEqual(comp.isValid, false, 'component should be destroied'); + strictEqual(comp.isValid, false, 'component should be destroyed'); }); // test('could deactivate parent in onLoad', function () { diff --git a/test/qunit/unit-es5/test-node.js b/test/qunit/unit-es5/test-node.js index f842c983ef6..a9657f1e84b 100644 --- a/test/qunit/unit-es5/test-node.js +++ b/test/qunit/unit-es5/test-node.js @@ -137,6 +137,17 @@ test('activeInHierarchy should be false after destroy', function () { strictEqual(child.activeInHierarchy, false, 'child should not activeInHierarchy after destroy'); }); +test('nodes should be destroyed with the scene', function () { + var child = new cc.Node(); + var scene = cc.director.getScene(); + child.parent = scene; + + cc.director.runSceneImmediate(new cc.Scene()); + + strictEqual(child.activeInHierarchy, false, 'nodes should not activeInHierarchy after destroy'); + strictEqual(child.isValid, false, 'nodes should be destroyed with the scene'); +}); + test('activation logic for component', function () { // 这里主要测试node,不是测试component From c749ba8ec1bf490940983083fc51e76417c32a7f Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 9 Nov 2018 18:09:48 +0800 Subject: [PATCH 0160/1631] revert #3476, already fixed in #3483 (#3490) --- cocos2d/core/components/CCButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index e9612033cc1..30f530614cd 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -420,7 +420,7 @@ let Button = cc.Class({ this._hovered = false; // // Restore button status let target = this.target; - if (!target || !target.isValid) { + if (!target) { return; } let transition = this.transition; From 6b0e185762bc5cb3c0f1548616e7e936f4a7101a Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 12 Nov 2018 15:28:56 +0800 Subject: [PATCH 0161/1631] set button.node for default button.target (#3491) --- cocos2d/core/components/CCButton.js | 65 +++++++++++------------------ 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 30f530614cd..8afc509c016 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -222,8 +222,8 @@ let Button = cc.Class({ displayName: 'Normal', tooltip: CC_DEV && 'i18n:COMPONENT.button.normal_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL && this.target) { - this.target.opacity = this.normalColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL) { + this._getTarget().opacity = this.normalColor.a; } this._updateState(); } @@ -239,8 +239,8 @@ let Button = cc.Class({ displayName: 'Pressed', tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED && this.target) { - this.target.opacity = this.pressedColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED) { + this._getTarget().opacity = this.pressedColor.a; } this._updateState(); }, @@ -257,8 +257,8 @@ let Button = cc.Class({ displayName: 'Hover', tooltip: CC_DEV && 'i18n:COMPONENT.button.hover_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.HOVER && this.target) { - this.target.opacity = this.hoverColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.HOVER) { + this._getTarget().opacity = this.hoverColor.a; } this._updateState(); }, @@ -275,8 +275,8 @@ let Button = cc.Class({ displayName: 'Disabled', tooltip: CC_DEV && 'i18n:COMPONENT.button.disabled_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED && this.target) { - this.target.opacity = this.disabledColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED) { + this._getTarget().opacity = this.disabledColor.a; } this._updateState(); } @@ -408,9 +408,6 @@ let Button = cc.Class({ }, __preload () { - if (!this.target) { - this.target = this.node; - } this._applyTarget(); this._updateState(); }, @@ -419,10 +416,7 @@ let Button = cc.Class({ this._pressed = false; this._hovered = false; // // Restore button status - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); let transition = this.transition; if (transition === Transition.COLOR && this.interactable) { this._setTargetColor(this.normalColor); @@ -463,11 +457,12 @@ let Button = cc.Class({ } }, + _getTarget () { + return this.target ? this.target : this.node; + }, + _setTargetColor(color) { - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); target.color = color; target.opacity = color.a; }, @@ -549,10 +544,7 @@ let Button = cc.Class({ }, update (dt) { - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); if (this._transitionFinished) return; if (this.transition !== Transition.COLOR && this.transition !== Transition.SCALE) return; @@ -595,10 +587,9 @@ let Button = cc.Class({ }, _applyTarget () { - this._sprite = this._getTargetSprite(this.target); - if (this.target) { - this._originalScale = this.target.scale; - } + let target = this._getTarget(); + this._sprite = this._getTargetSprite(target); + this._originalScale = target.scale; }, // touch event handler @@ -616,8 +607,9 @@ let Button = cc.Class({ // so we have to do hit test when touch moving let touch = event.touch; let hit = this.node._hitTest(touch.getLocation()); + let target = this._getTarget(); - if (this.transition === Transition.SCALE && this.target) { + if (this.transition === Transition.SCALE) { if (hit) { this._fromScale = this._originalScale; this._toScale = this._originalScale * this.zoomScale; @@ -625,7 +617,7 @@ let Button = cc.Class({ } else { this.time = 0; this._transitionFinished = true; - this.target.scale = this._originalScale; + target.scale = this._originalScale; } } else { let state; @@ -709,10 +701,7 @@ let Button = cc.Class({ this._updateColorTransitionImmediately(state); } else { - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); let color = this._getStateColor(state); this._fromColor = target.color.clone(); this._toColor = color; @@ -744,10 +733,8 @@ let Button = cc.Class({ }, _zoomBack () { - if (!this.target) { - return; - } - this._fromScale = this.target.scale; + let target = this._getTarget(); + this._fromScale = target.scale; this._toScale = this._originalScale; this.time = 0; this._transitionFinished = false; @@ -776,9 +763,7 @@ let Button = cc.Class({ }, _resizeNodeToTargetNode: CC_EDITOR && function () { - if (this.target) { - this.node.setContentSize(this.target.getContentSize()); - } + this.node.setContentSize(this._getTarget().getContentSize()); }, _updateDisabledState () { From 5934b82b0b5045949729bdbbcedb2937f5b91c7f Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 12 Nov 2018 18:49:04 +0800 Subject: [PATCH 0162/1631] add the transform render update when the node opacity change from 0 (#3482) --- cocos2d/core/renderer/render-flow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 3aaf18b308d..a873053cd33 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -97,9 +97,9 @@ _proto._children = function (node) { let children = node._children; for (let i = 0, l = children.length; i < l; i++) { let c = children[i]; + c._renderFlag |= worldTransformFlag | worldOpacityFlag; if (!c._activeInHierarchy || c._opacity === 0) continue; _cullingMask = c._cullingMask = c.groupIndex === 0 ? cullingMask : 1 << c.groupIndex; - c._renderFlag |= worldTransformFlag | worldOpacityFlag; // TODO: Maybe has better way to implement cascade opacity c._color.a = c._opacity * _walker.parentOpacity; From 61990940a239af4eaa6d516f913e04f9917bf26c Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Mon, 12 Nov 2018 18:51:36 +0800 Subject: [PATCH 0163/1631] fix bug #334 spine use premultipliedAlpha,set opacity zero, but still show (#3487) --- cocos2d/core/renderer/render-flow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 4c709b12f45..98cca2d1f8a 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -118,7 +118,7 @@ _proto._children = function (node) { let children = node._children; for (let i = 0, l = children.length; i < l; i++) { let c = children[i]; - if (!c._activeInHierarchy) continue; + if (!c._activeInHierarchy || c._opacity === 0) continue; _cullingMask = c._cullingMask = c.groupIndex === 0 ? cullingMask : 1 << c.groupIndex; c._renderFlag |= worldTransformFlag | worldOpacityFlag; From 941add9d840c073e36a105dc81d85187e7ed38e2 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 12 Nov 2018 18:54:36 +0800 Subject: [PATCH 0164/1631] fix delay load ttf font bug (#3484) --- cocos2d/core/renderer/utils/label/ttf.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index f4913f5202a..bfe352bcc5b 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -150,6 +150,7 @@ module.exports = { else { cc.loader.load(comp.font.nativeUrl, function (err, fontFamily) { _fontFamily = fontFamily || 'Arial'; + comp.font._nativeAsset = fontFamily; comp._updateRenderData(true); }); } From 1f5151eab5b43a9695d9d250c2be6113badb9f1e Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 12 Nov 2018 18:56:43 +0800 Subject: [PATCH 0165/1631] fixed some issues (#3494) * fixed eulerAngles * remove unused code * fixed cut 3d modules * fixed mesh init min/max position --- cocos2d/core/3d/CCModel.js | 3 ++- cocos2d/core/3d/polyfill-3d.js | 8 ++------ cocos2d/core/camera/CCCamera.js | 2 ++ cocos2d/core/index.js | 1 + modules.json | 4 +++- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index 42156c1a84a..0b827277d33 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -23,7 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const AnimationClip = require('../../animation/animation-clip'); const BufferAsset = require('../assets/CCBufferAsset'); const renderEngine = require('../renderer/render-engine'); @@ -237,6 +236,8 @@ let Model = cc.Class({ meshAsset._ibs.length = length; meshAsset._vbs.length = length; meshAsset._subMeshes.length = length; + vec3.set(meshAsset._minPos, Infinity, Infinity, Infinity); + vec3.set(meshAsset._maxPos, -Infinity, -Infinity, -Infinity); for (let i = 0; i < length; ++i) { let primitive = gltfMesh.primitives[i]; diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index cd8cf773862..e8c1e7c4b5d 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -29,15 +29,12 @@ const EventType = Node.EventType; const DirtyFlag = Node._LocalDirtyFlag; const math = require('../renderer/render-engine').math; const RenderFlow = require('../renderer/render-flow'); -const misc = require('../utils/misc'); -const vec3 = cc.vmath.vec3; // ====== Node transform polyfills ====== const ONE_DEGREE = Math.PI / 180; const POSITION_ON = 1 << 0; const SCALE_ON = 1 << 1; -const ROTATION_ON = 1 << 2; function _updateLocalMatrix3d () { if (this._localMatDirty) { @@ -174,7 +171,6 @@ const _updateLocalMatrix2d = proto._updateLocalMatrix; const _calculWorldMatrix2d = proto._calculWorldMatrix; const _upgrade_1x_to_2x_2d = proto._upgrade_1x_to_2x; const _mulMat2d = proto._mulMat; -const _onBatchCreated2d = proto._onBatchCreated; proto.setPosition = setPosition; proto.setScale = setScale; @@ -231,14 +227,14 @@ cc.js.getset(proto, 'eulerAngles', function () { return this._eulerAngles; } else { - return this._quat.getEulerAngles(cc.v3()); + return this._quat.toEuler(cc.v3()); } }, function (v) { if (CC_EDITOR) { this._eulerAngles.set(v); } - math.quat.fromEuler(this._quat, v.x, v.y, v.z); + this._quat.fromEuler(v); this.setLocalDirty(DirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; }); diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 42f8902545f..ba6bd907df0 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -617,6 +617,8 @@ let Camera = cc.Class({ * @return {Ray} */ getRay (screenPos) { + if (!ray) return screenPos; + vec3.set(_v3_temp_3, screenPos.x, screenPos.y, 1); this._camera.screenToWorld(_v3_temp_2, _v3_temp_3, cc.visibleRect.width, cc.visibleRect.height); diff --git a/cocos2d/core/index.js b/cocos2d/core/index.js index 2ea06d0e34a..c5b9097f704 100644 --- a/cocos2d/core/index.js +++ b/cocos2d/core/index.js @@ -43,5 +43,6 @@ if (!CC_EDITOR || !Editor.isMainProcess) { require('./mesh'); require('./3d'); +require('./3d/polyfill-3d'); require('./base-ui/CCWidgetManager'); diff --git a/modules.json b/modules.json index b475bfb33b8..daabd6403ac 100644 --- a/modules.json +++ b/modules.json @@ -267,7 +267,9 @@ { "name": "3D", "entries": [ - "./cocos2d/core/3d/index.js" + "./cocos2d/core/3d/index.js", + "./cocos2d/core/3d/geom-utils/aabb.js", + "./cocos2d/core/3d/geom-utils/ray.js" ], "dependencies": ["Mesh", "WebGL Renderer"] }, From 6846cfd8fbf03aed75086b59f851704a4ac9a648 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 12 Nov 2018 18:57:47 +0800 Subject: [PATCH 0166/1631] fix set -webkit-transform style failed in wechat sub domain (#3495) --- cocos2d/core/platform/CCView.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index eb616f38be7..3ca58d9220c 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -362,8 +362,10 @@ var View = cc._Class.extend({ // Because 'transform' style adds canvas (the top-element of container) to a new stack context. // That causes the DOM Input was hidden under canvas. // This should be done after container rotated, instead of in style-mobile.css. - cc.game.canvas.style['-webkit-transform'] = 'translateZ(0px)'; - cc.game.canvas.style.transform = 'translateZ(0px)'; + if (cc.game.canvas.style) { + cc.game.canvas.style['-webkit-transform'] = 'translateZ(0px)'; + cc.game.canvas.style.transform = 'translateZ(0px)'; + } } if (this._orientationChanging) { setTimeout(function () { From 3c898da3daff830f2788e38f08e0fcba29ae7d78 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 13 Nov 2018 01:07:45 +0800 Subject: [PATCH 0167/1631] modify the pageView calculate boundary relative target (#3468) --- cocos2d/core/components/CCPageView.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cocos2d/core/components/CCPageView.js b/cocos2d/core/components/CCPageView.js index cfcbb37eb29..b7b7242d683 100644 --- a/cocos2d/core/components/CCPageView.js +++ b/cocos2d/core/components/CCPageView.js @@ -401,12 +401,12 @@ var PageView = cc.Class({ var lastPage = this._pages[this._pages.length - 1]; if (this.sizeMode === SizeMode.Free) { if (this.direction === Direction.Horizontal) { - layout.paddingLeft = (this.node.width - this._pages[0].width) / 2; - layout.paddingRight = (this.node.width - lastPage.width) / 2; + layout.paddingLeft = (this._view.width - this._pages[0].width) / 2; + layout.paddingRight = (this._view.width - lastPage.width) / 2; } else if (this.direction === Direction.Vertical) { - layout.paddingTop = (this.node.height - this._pages[0].height) / 2; - layout.paddingBottom = (this.node.height - lastPage.height) / 2; + layout.paddingTop = (this._view.height - this._pages[0].height) / 2; + layout.paddingBottom = (this._view.height - lastPage.height) / 2; } } } @@ -451,7 +451,7 @@ var PageView = cc.Class({ return; } var locPages = CC_EDITOR ? this.content.children : this._pages; - var selfSize = this.node.getContentSize(); + var selfSize = this._view.getContentSize(); for (var i = 0, len = locPages.length; i < len; i++) { locPages[i].setContentSize(selfSize); } @@ -495,10 +495,10 @@ var PageView = cc.Class({ } else { if (this.direction === Direction.Horizontal) { - return Math.abs(offset.x) >= this.node.width * this.scrollThreshold; + return Math.abs(offset.x) >= this._view.width * this.scrollThreshold; } else if (this.direction === Direction.Vertical) { - return Math.abs(offset.y) >= this.node.height * this.scrollThreshold; + return Math.abs(offset.y) >= this._view.height * this.scrollThreshold; } } }, @@ -531,10 +531,10 @@ var PageView = cc.Class({ } else { if (this.direction === Direction.Horizontal) { - offset.x = idx * this.node.width; + offset.x = idx * this._view.width; } else if (this.direction === Direction.Vertical) { - offset.y = idx * this.node.height; + offset.y = idx * this._view.height; } } return offset; From 2d1bb1eabc5581243562f3018a2847dd73bfc957 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 13 Nov 2018 14:03:35 +0800 Subject: [PATCH 0168/1631] fixed skeletion animation clip depends (#3498) --- cocos2d/core/3d/CCSkeletonAnimationClip.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/3d/CCSkeletonAnimationClip.js b/cocos2d/core/3d/CCSkeletonAnimationClip.js index ad1419bb5b0..f2df240637b 100644 --- a/cocos2d/core/3d/CCSkeletonAnimationClip.js +++ b/cocos2d/core/3d/CCSkeletonAnimationClip.js @@ -24,6 +24,7 @@ ****************************************************************************/ const Model = require('./CCModel'); +const AnimationClip = require('../../animation/animation-clip'); /** * @module cc @@ -36,7 +37,7 @@ const Model = require('./CCModel'); */ var SkeletonAnimationClip = cc.Class({ name: 'cc.SkeletonAnimationClip', - extends: cc.AnimationClip, + extends: AnimationClip, properties: { _modelSetter: { From 37cd8ffdc25ced66c7d1b9ed8b5161a03728545f Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 14 Nov 2018 10:33:47 +0800 Subject: [PATCH 0169/1631] update particle system for 2d-tasks/issues/783 (#3493) --- cocos2d/particle/CCParticleAsset.js | 6 +++--- cocos2d/particle/CCParticleSystem.js | 22 +++++++++++++++------- cocos2d/particle/particle-simulator.js | 4 ++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/cocos2d/particle/CCParticleAsset.js b/cocos2d/particle/CCParticleAsset.js index 0731d96886a..0a8c20ade69 100644 --- a/cocos2d/particle/CCParticleAsset.js +++ b/cocos2d/particle/CCParticleAsset.js @@ -25,7 +25,7 @@ ****************************************************************************/ const Asset = require('../core/assets/CCAsset'); -const Texture2D = require('../core/assets/CCTexture2D'); +const CCSpriteFrame = require('../core/assets/CCSpriteFrame'); /** * Class for particle asset handling. @@ -37,9 +37,9 @@ var ParticleAsset = cc.Class({ extends: Asset, properties: { - texture: { + spriteFrame: { default: null, - type: Texture2D + type: CCSpriteFrame } } }); diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 934a1ae7dd4..f2ead2eba80 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -218,7 +218,7 @@ var properties = { return this._spriteFrame; }, set: function (value, force) { - var lastSprite = this._spriteFrame; + var lastSprite = this._renderSpriteFrame; if (CC_EDITOR) { if (!force && lastSprite === value) { return; @@ -229,7 +229,12 @@ var properties = { return; } } - this._spriteFrame = value; + this._renderSpriteFrame = value; + + if (value._uuid) { + this._spriteFrame = value; + } + if ((lastSprite && lastSprite.getTexture()) !== (value && value.getTexture())) { this._texture = null; this._applySpriteFrame(lastSprite); @@ -717,6 +722,9 @@ var ParticleSystem = cc.Class({ this._startColorVar = cc.color(0, 0, 0, 0); this._endColor = cc.color(255, 255, 255, 0); this._endColorVar = cc.color(0, 0, 0, 0); + + // The temporary SpriteFrame object used for the renderer. Because there is no corresponding asset, it can't be serialized. + this._renderSpriteFrame = null; }, properties: properties, @@ -922,8 +930,8 @@ var ParticleSystem = cc.Class({ self._initWithDictionary(content); } if (!self.spriteFrame) { - if (file.texture) { - self.spriteFrame = new cc.SpriteFrame(file.texture); + if (file.spriteFrame) { + self.spriteFrame = file.spriteFrame; } else if (self._custom) { self._initTextureWithDictionary(content); @@ -1097,7 +1105,7 @@ var ParticleSystem = cc.Class({ }, _onTextureLoaded: function () { - this._texture = this._spriteFrame.getTexture(); + this._texture = this._renderSpriteFrame.getTexture(); this._simulator.updateUVs(true); // Reactivate material this._activateMaterial(); @@ -1108,7 +1116,7 @@ var ParticleSystem = cc.Class({ oldFrame.off('load', this._onTextureLoaded, this); } - var spriteFrame = this._spriteFrame; + var spriteFrame = this._renderSpriteFrame = this._renderSpriteFrame || this._spriteFrame; if (spriteFrame) { if (spriteFrame.textureLoaded()) { this._onTextureLoaded(null); @@ -1130,7 +1138,7 @@ var ParticleSystem = cc.Class({ if (!this._texture || !this._texture.loaded) { this.markForCustomIARender(false); - if (this._spriteFrame) { + if (this._renderSpriteFrame) { this._applySpriteFrame(); } } diff --git a/cocos2d/particle/particle-simulator.js b/cocos2d/particle/particle-simulator.js index bc11bf39041..8caf1d90029 100644 --- a/cocos2d/particle/particle-simulator.js +++ b/cocos2d/particle/particle-simulator.js @@ -193,10 +193,10 @@ Simulator.prototype.emitParticle = function (pos) { Simulator.prototype.updateUVs = function (force) { let particleCount = this.particles.length; - if (this.sys._buffer && this.sys._spriteFrame) { + if (this.sys._buffer && this.sys._renderSpriteFrame) { const FLOAT_PER_PARTICLE = 4 * this.sys._vertexFormat._bytes / 4; let vbuf = this.sys._buffer._vData; - let uv = this.sys._spriteFrame.uv; + let uv = this.sys._renderSpriteFrame.uv; let start = force ? 0 : this._uvFilled; for (let i = start; i < particleCount; i++) { From fcbccac277dc6513d1bab82006fc8557f5a6b160 Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 14 Nov 2018 14:02:51 +0800 Subject: [PATCH 0170/1631] add audio destroy for qqplay (#3504) --- cocos2d/audio/CCAudio.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/audio/CCAudio.js b/cocos2d/audio/CCAudio.js index 43d794fcd5a..9b3a60c998a 100644 --- a/cocos2d/audio/CCAudio.js +++ b/cocos2d/audio/CCAudio.js @@ -168,7 +168,7 @@ Audio.State = { }; proto.destroy = function () { - if (CC_WECHATGAME) { + if (CC_WECHATGAME || CC_QQPLAY) { this._element && this._element.destroy(); } this._element = null; From ba00b7b084ca0eb0fdeff617df8aa4dce4455510 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Wed, 14 Nov 2018 14:56:56 +0800 Subject: [PATCH 0171/1631] Modify the material's hash value judgment to be strictly. (#3506) --- cocos2d/core/renderer/webgl/render-component-walker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/render-component-walker.js index 4338799396f..b4607819121 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/render-component-walker.js @@ -186,7 +186,7 @@ RenderComponentWalker.prototype = { }, _commitComp (comp, assembler, cullingMask) { - if (this.material._hash != comp._material._hash || + if (this.material._hash !== comp._material._hash || this.cullingMask !== cullingMask) { this._flush(); From 91ed6b83115bc629f5b1fa74a39b4e0aaf322b67 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Wed, 14 Nov 2018 16:49:24 +0800 Subject: [PATCH 0172/1631] fix WebGL detection on Android browsers (#3510) * fix version matching in the webview of MIUI mini game * fix WebGL detection on Android browsers --- cocos2d/core/platform/CCSys.js | 51 ++++------------------------------ 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index e4ffa06ccd2..6f8d03fa426 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -830,7 +830,7 @@ function initSys () { sys.browserVersion = ""; /* Determine the browser version number */ (function(){ - var versionReg1 = /(mqqbrowser|micromessenger|qq|sogou|qzone|liebao|maxthon|uc|ucbs|360 aphone|360|baiduboxapp|baidu|maxthon|mxbrowser|miui)(mobile)?(browser)?\/?([\d.]+)/i; + var versionReg1 = /(mqqbrowser|micromessenger|qq|sogou|qzone|liebao|maxthon|uc|ucbs|360 aphone|360|baiduboxapp|baidu|maxthon|mxbrowser|miui(?:.hybrid)?)(mobile)?(browser)?\/?([\d.]+)/i; var versionReg2 = /(qqbrowser|chrome|safari|firefox|trident|opera|opr\/|oupeng)(mobile)?(browser)?\/?([\d.]+)/i; var tmp = ua.match(versionReg1); if(!tmp) tmp = ua.match(versionReg2); @@ -898,53 +898,14 @@ function initSys () { var _supportWebp = _tmpCanvas1.toDataURL('image/webp').startsWith('data:image/webp'); var _supportCanvas = !!_tmpCanvas1.getContext("2d"); var _supportWebGL = false; - if (sys.browserType === sys.BROWSER_TYPE_WECHAT_GAME) { + if (CC_TEST) { + _supportWebGL = false; + } + else if (sys.browserType === sys.BROWSER_TYPE_WECHAT_GAME) { _supportWebGL = true; } else if (win.WebGLRenderingContext) { - if (create3DContext(document.createElement("CANVAS"))) { - _supportWebGL = true; - } - if (_supportWebGL && sys.os === sys.OS_ANDROID) { - var browserVer = parseFloat(sys.browserVersion); - switch (sys.browserType) { - case sys.BROWSER_TYPE_MOBILE_QQ: - case sys.BROWSER_TYPE_BAIDU: - case sys.BROWSER_TYPE_BAIDU_APP: - // QQ & Baidu Brwoser 6.2+ (using blink kernel) - if (browserVer >= 6.2) { - _supportWebGL = true; - } - else { - _supportWebGL = false; - } - break; - case sys.BROWSER_TYPE_ANDROID: - // Android 5+ default browser - if (sys.osMainVersion && sys.osMainVersion >= 5) { - _supportWebGL = true; - } - break; - case sys.BROWSER_TYPE_CHROME: - // Chrome on android supports WebGL from v. 30 - if (browserVer >= 30.0) { - _supportWebGL = true; - } else { - _supportWebGL = false; - } - break; - case sys.BROWSER_TYPE_UC: - if (browserVer > 11.0) { - _supportWebGL = true; - } else { - _supportWebGL = false; - } - break; - case sys.BROWSER_TYPE_360: - _supportWebGL = false; - break; - } - } + _supportWebGL = true; } /** From a84a1aa6c7422b60224d38efd68b3dea9d87b484 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 14 Nov 2018 23:01:21 +0800 Subject: [PATCH 0173/1631] refine quad fromEuler/toEuler (#3512) --- cocos2d/core/renderer/render-engine.canvas.js | 42 ++++++++++++++++++- cocos2d/core/renderer/render-engine.jsb.js | 41 +++++++++++++++++- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js index 7cac7c404e2..9979860ce52 100644 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ b/cocos2d/core/renderer/render-engine.canvas.js @@ -5386,14 +5386,52 @@ quat.fromEuler = function (out, x, y, z) { var sz = Math.sin(z); var cz = Math.cos(z); - out.x = sx * cy * cz - cx * sy * sz; + out.x = sx * cy * cz + cx * sy * sz; out.y = cx * sy * cz + sx * cy * sz; out.z = cx * cy * sz - sx * sy * cz; - out.w = cx * cy * cz + sx * sy * sz; + out.w = cx * cy * cz - sx * sy * sz; return out; }; +/** + * Convert a quaternion back to euler angle (in degrees). + * + * @param {vec3} out - Euler angle stored as a vec3 + * @param {number} q - the quaternion to be converted + * @returns {vec3} out. + */ +quat.toEuler = function (out, q) { + var x = q.x, y = q.y, z = q.z, w = q.w; + var heading, attitude, bank; + var test = x * y + z * w; + if (test > 0.499) { // singularity at north pole + heading = 2 * Math.atan2(x,w); + attitude = Math.PI/2; + bank = 0; + } + if (test < -0.499) { // singularity at south pole + heading = -2 * Math.atan2(x,w); + attitude = - Math.PI/2; + bank = 0; + } + if(isNaN(heading)){ + var sqx = x*x; + var sqy = y*y; + var sqz = z*z; + heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // heading + attitude = Math.asin(2*test); // attitude + bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank + } + + out.y = toDegree(heading); + out.z = toDegree(attitude); + out.x = toDegree(bank); + + return out; +} + + /** * Returns a string representation of a quatenion * diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 8368e2baee8..89665ed2a8f 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -7009,14 +7009,51 @@ quat.fromEuler = function (out, x, y, z) { var sz = Math.sin(z); var cz = Math.cos(z); - out.x = sx * cy * cz - cx * sy * sz; + out.x = sx * cy * cz + cx * sy * sz; out.y = cx * sy * cz + sx * cy * sz; out.z = cx * cy * sz - sx * sy * cz; - out.w = cx * cy * cz + sx * sy * sz; + out.w = cx * cy * cz - sx * sy * sz; return out; }; +/** + * Convert a quaternion back to euler angle (in degrees). + * + * @param {vec3} out - Euler angle stored as a vec3 + * @param {number} q - the quaternion to be converted + * @returns {vec3} out. + */ +quat.toEuler = function (out, q) { + var x = q.x, y = q.y, z = q.z, w = q.w; + var heading, attitude, bank; + var test = x * y + z * w; + if (test > 0.499) { // singularity at north pole + heading = 2 * Math.atan2(x,w); + attitude = Math.PI/2; + bank = 0; + } + if (test < -0.499) { // singularity at south pole + heading = -2 * Math.atan2(x,w); + attitude = - Math.PI/2; + bank = 0; + } + if(isNaN(heading)){ + var sqx = x*x; + var sqy = y*y; + var sqz = z*z; + heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // heading + attitude = Math.asin(2*test); // attitude + bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank + } + + out.y = toDegree(heading); + out.z = toDegree(attitude); + out.x = toDegree(bank); + + return out; +} + /** * Returns a string representation of a quatenion * From bc9a461f7adf5d9545b29faed85fbeea45e57d58 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 15 Nov 2018 13:48:17 +0800 Subject: [PATCH 0174/1631] fix video play fullscreen bug for 2d-tasks/issues/749/421/337 (#3496) * fix video play fullscreen bug for 2d-tasks/issues/749/421/337 * improve code * update className to tagName --- cocos2d/core/platform/CCScreen.js | 21 ++++- cocos2d/videoplayer/video-player-impl.js | 114 ++++++++++------------- 2 files changed, 69 insertions(+), 66 deletions(-) diff --git a/cocos2d/core/platform/CCScreen.js b/cocos2d/core/platform/CCScreen.js index 553c18bdf93..2247e57238e 100644 --- a/cocos2d/core/platform/CCScreen.js +++ b/cocos2d/core/platform/CCScreen.js @@ -116,6 +116,16 @@ cc.screen = /** @lends cc.screen# */{ * @param {Function} onFullScreenChange */ requestFullScreen: function (element, onFullScreenChange) { + if (element.tagName.toLowerCase() === "video") { + if (cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && element.readyState > 0) { + element.webkitEnterFullscreen && element.webkitEnterFullscreen(); + return; + } + else { + element.setAttribute("x5-video-player-fullscreen", "true"); + } + } + if (!this._supportsFullScreen) { return; } @@ -139,7 +149,16 @@ cc.screen = /** @lends cc.screen# */{ * @method exitFullScreen * @return {Boolean} */ - exitFullScreen: function () { + exitFullScreen: function (element) { + if (element.tagName.toLowerCase() === "video") { + if (cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser) { + element.webkitExitFullscreen && element.webkitExitFullscreen(); + return; + } + else { + element.setAttribute("x5-video-player-fullscreen", "false"); + } + } return this._supportsFullScreen ? document[this._fn.exitFullscreen]() : true; }, diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index abf4b5fa653..83f9ef1e4fd 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -28,20 +28,16 @@ const sys = require('../core/platform/CCSys'); const renderEngine = require('../core/renderer/render-engine'); const math = renderEngine.math; -let _mat4_temp = math.mat4.create(); - -// ios brower need to wait until the video's loadedmetadata event -// has been fired before calling webkitEnterFullScreen() -function triggerFullScene (video, enable) { - if (!video) return; - if (enable) { - video.webkitEnterFullscreen && video.webkitEnterFullscreen(); - } - else { - video.webkitExitFullscreen && video.webkitExitFullscreen(); - } +const READY_STATE = { + HAVE_NOTHING: 0, + HAVE_METADATA: 1, + HAVE_CURRENT_DATA: 2, + HAVE_FUTURE_DATA: 3, + HAVE_ENOUGH_DATA: 4 } +let _mat4_temp = math.mat4.create(); + let VideoPlayerImpl = cc.Class({ name: 'VideoPlayerImpl', @@ -57,8 +53,6 @@ let VideoPlayerImpl = cc.Class({ this._loadedmeta = false; this._loaded = false; this._visible = false; - // 有一些浏览器第一次播放视频需要特殊处理,这个标记用来标识是否播放过 - this._played = false; this._playing = false; this._ignorePause = false; @@ -82,8 +76,11 @@ let VideoPlayerImpl = cc.Class({ let cbs = this.__eventListeners; cbs.loadedmetadata = function () { self._loadedmeta = true; - if (sys.os === sys.OS_IOS && sys.isBrowser) { - triggerFullScene(video, self._fullScreenEnabled); + if (self._fullScreenEnabled) { + cc.screen.requestFullScreen(video); + } + else { + cc.screen.exitFullScreen(video); } self._dispatchEvent(VideoPlayerImpl.EventType.META_LOADED); }; @@ -95,12 +92,21 @@ let VideoPlayerImpl = cc.Class({ cbs.play = function () { if (self._video !== video) return; self._playing = true; + self._updateVisibility(); self._dispatchEvent(VideoPlayerImpl.EventType.PLAYING); }; + // pause and stop callback cbs.pause = function () { - if (self._ignorePause || self._video !== video) return; + if (self._video !== video) { + return; + } self._playing = false; - self._dispatchEvent(VideoPlayerImpl.EventType.PAUSED); + if (self._ignorePause) { + return; + } + else { + self._dispatchEvent(VideoPlayerImpl.EventType.PAUSED); + } }; cbs.click = function () { self._dispatchEvent(VideoPlayerImpl.EventType.CLICKED); @@ -113,36 +119,37 @@ let VideoPlayerImpl = cc.Class({ video.addEventListener("click", cbs.click); function onCanPlay () { - if (this._loaded) + if (self._loaded || self._loadedmeta || self._playing) return; - let video = this._video; - if (video.readyState === 4) { - this._loaded = true; - // node.setContentSize(node._contentSize.width, node._contentSize.height); + let video = self._video; + if (video.readyState === READY_STATE.HAVE_ENOUGH_DATA) { video.currentTime = 0; - this._dispatchEvent(VideoPlayerImpl.EventType.READY_TO_PLAY); - this._updateVisibility(); + self._loaded = true; + self._dispatchEvent(VideoPlayerImpl.EventType.READY_TO_PLAY); + self._updateVisibility(); } } - cbs.onCanPlay = onCanPlay.bind(this); + cbs.onCanPlay = onCanPlay; video.addEventListener('canplay', cbs.onCanPlay); video.addEventListener('canplaythrough', cbs.onCanPlay); video.addEventListener('suspend', cbs.onCanPlay); }, _updateVisibility () { - if (!this._video) return; let video = this._video; + if (!video) return; + if (this._visible) { video.style.visibility = 'visible'; + this._forceUpdate = true; } else { video.style.visibility = 'hidden'; video.pause(); this._playing = false; + this._forceUpdate = false; } - this._forceUpdate = true; }, _updateSize (width, height) { @@ -164,10 +171,10 @@ let VideoPlayerImpl = cc.Class({ video.setAttribute('playsinline', ''); // Stupid tencent x5 adaptation - let orientation = cc.winSize.width > cc.winSize.height ? "landscape" : "portrait"; video.setAttribute("x5-playsinline", ""); video.setAttribute("x5-video-player-type", "h5"); - video.setAttribute("x5-video-player-fullscreen", "false"); + video.setAttribute("x5-video-player-fullscreen", this._fullScreenEnabled ? "true" : "false"); + let orientation = cc.winSize.width > cc.winSize.height ? "landscape" : "portrait"; video.setAttribute("x5-video-orientation", orientation); this._video = video; @@ -223,7 +230,6 @@ let VideoPlayerImpl = cc.Class({ let video = this._video; video.style["visibility"] = "hidden"; this._loaded = false; - this._played = false; this._playing = false; this._loadedmeta = false; @@ -248,34 +254,22 @@ let VideoPlayerImpl = cc.Class({ play: function () { let video = this._video; - if (!video || !this._visible) return; - - this._played = true; - if (this._playing) { - return; - } + if (!video || !this._visible || this._playing) return; if (VideoPlayerImpl._polyfill.autoplayAfterOperation) { let self = this; setTimeout(function () { video.play(); - self._playing = !video.paused; }, 20); } else { video.play(); - this._playing = !video.paused; } }, pause: function () { let video = this._video; - if (!this._playing) return; - - this._playing = false; - if (!video) { - return; - } + if (!this._playing || !video) return; video.pause(); }, @@ -287,15 +281,13 @@ let VideoPlayerImpl = cc.Class({ let video = this._video; if (!video || !this._visible) return; this._ignorePause = true; + video.currentTime = 0; video.pause(); - let self = this; setTimeout(function () { - self._dispatchEvent(VideoPlayerImpl.EventType.STOPPED); - self._ignorePause = false; - }, 0); - // 恢复到视频起始位置 - video.currentTime = 0; - this._playing = false; + this._dispatchEvent(VideoPlayerImpl.EventType.STOPPED); + this._ignorePause = false; + }.bind(this), 0); + }, setVolume: function (volume) { @@ -368,24 +360,16 @@ let VideoPlayerImpl = cc.Class({ }, setFullScreenEnabled: function (enable) { - let video = this._video; + let video = this._video; if (!video) { return; } this._fullScreenEnabled = enable; - if (sys.os === sys.OS_IOS && sys.isBrowser) { - if (this._loadedmeta) { - triggerFullScene(video, enable); - } + if (enable) { + cc.screen.requestFullScreen(video); } else { - if (enable) { - cc.screen.requestFullScreen(video); - } - else { - cc.screen.exitFullScreen(video); - } - video.setAttribute("x5-video-player-fullscreen", enable ? "true" : "false"); + cc.screen.exitFullScreen(video); } }, @@ -481,9 +465,9 @@ let VideoPlayerImpl = cc.Class({ h = this._h * scaleY; } else { - this._updateSize(this._w, this._h); w = this._w * scaleX; h = this._h * scaleY; + this._updateSize(this._w, this._h); } let appx = (w * _mat4_temp.m00) * node._anchorPoint.x; From d282bffb5fa2ea599afaf1f2d8616100cf280995 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 15 Nov 2018 16:01:18 +0800 Subject: [PATCH 0175/1631] https://github.com/cocos-creator/2d-tasks/issues/799 (#3516) fix audio resume failed when game back to foreground --- cocos2d/audio/CCAudio.js | 2 +- cocos2d/core/components/CCAudioSource.js | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cocos2d/audio/CCAudio.js b/cocos2d/audio/CCAudio.js index 9b3a60c998a..68845a4a536 100644 --- a/cocos2d/audio/CCAudio.js +++ b/cocos2d/audio/CCAudio.js @@ -264,7 +264,7 @@ Audio.State = { }; proto.getState = function () { - if (!CC_WECHATGAME) { + if (!CC_WECHATGAME && !CC_QQPLAY) { let elem = this._element; if (elem && Audio.State.PLAYING === this._state && elem.paused) { this._state = Audio.State.PAUSED; diff --git a/cocos2d/core/components/CCAudioSource.js b/cocos2d/core/components/CCAudioSource.js index 371c7aefec3..1337ac27918 100644 --- a/cocos2d/core/components/CCAudioSource.js +++ b/cocos2d/core/components/CCAudioSource.js @@ -208,10 +208,11 @@ var AudioSource = cc.Class({ }, _pausedCallback: function () { - var audio = this.audio; - if (audio.paused) return; - this.audio.pause(); - this._pausedFlag = true; + var state = this.audio.getState(); + if (state === cc.Audio.State.PLAYING) { + this.audio.pause(); + this._pausedFlag = true; + } }, _restoreCallback: function () { From 07dbdc9397942fb473dfd1a1ed43d0fe5eb5491d Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 15 Nov 2018 16:38:24 +0800 Subject: [PATCH 0176/1631] fix label bmfont delay load bug (#3499) --- cocos2d/core/components/CCLabel.js | 47 ++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 69d7a1cbc86..6a2ee91f3c6 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -356,7 +356,7 @@ let Label = cc.Class({ } this._fontAtlas = null; this._updateAssembler(); - this._activateMaterial(true); + this._applyFontTexture(true); this._updateRenderData(); }, type: cc.Font, @@ -468,7 +468,7 @@ let Label = cc.Class({ this._checkStringEmpty(); this._updateAssembler(); - this._activateMaterial(); + this._applyFontTexture(); }, onDisable () { @@ -517,28 +517,32 @@ let Label = cc.Class({ } }, - _activateMaterial (force) { - let material = this._material; - if (material && !force) { - return; - } - + _applyFontTexture (force) { let font = this.font; if (font instanceof cc.BitmapFont) { let spriteFrame = font.spriteFrame; + let self = this; + let onBMFontTextureLoaded = function () { + // TODO: old texture in material have been released by loader + self._texture = spriteFrame._texture; + self._activateMaterial(force); + + if (CC_EDITOR || force) { + this._assembler && this._assembler.updateRenderData(this); + } + }; // cannot be activated if texture not loaded yet - if (!spriteFrame || !spriteFrame.textureLoaded()) { + if (spriteFrame && spriteFrame.textureLoaded()) { + onBMFontTextureLoaded(); + } + else { this.disableRender(); if (spriteFrame) { - spriteFrame.once('load', this._activateMaterial, this); + spriteFrame.once('load', onBMFontTextureLoaded, this); spriteFrame.ensureLoadTexture(); } - return; } - - // TODO: old texture in material have been released by loader - this._texture = spriteFrame._texture; } else { if (!this._ttfTexture) { @@ -551,6 +555,18 @@ let Label = cc.Class({ this._ttfTexture.initWithElement(this._assemblerData.canvas); } this._texture = this._ttfTexture; + this._activateMaterial(force); + + if (CC_EDITOR || force) { + this._assembler && this._assembler.updateRenderData(this); + } + } + }, + + _activateMaterial (force) { + let material = this._material; + if (material && !force) { + return; } // Canvas @@ -598,8 +614,7 @@ let Label = cc.Class({ if (CC_EDITOR || force) { this._updateAssembler(); - this._activateMaterial(force); - this._assembler.updateRenderData(this); + this._applyFontTexture(force); } }, From 4431a433758ad1af16decb09def9b36c2742aae7 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Thu, 15 Nov 2018 17:00:11 +0800 Subject: [PATCH 0177/1631] fix spine texture leakage and material may be invalid when reload spine resource (#3502) * fix spine texture leakage and material may be invalid when reload spine resource * support spine change material * Modify variable name to avoid ambiguity * modify code style --- extensions/spine/Skeleton.js | 12 ++++++++++-- extensions/spine/spine-assembler.js | 30 +++++++++++++++++++---------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index a50737be299..078556be73f 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -314,7 +314,7 @@ sp.Skeleton = cc.Class({ notify () { this._initDebugDraw(); } - } + }, }, // CONSTRUCTOR @@ -324,11 +324,17 @@ sp.Skeleton = cc.Class({ this._listener = null; this._boundingBox = cc.rect(); this._material = new SpriteMaterial(); + this._materials = {}; this._renderDatas = []; - this._debugRenderer = null; }, + // override + _updateMaterial (material) { + this._super(material); + this._materials = {}; + }, + /** * !#en * Sets runtime skeleton data to sp.Skeleton.
@@ -382,6 +388,7 @@ sp.Skeleton = cc.Class({ update (dt) { if (CC_EDITOR) return; + if (this.paused) return; let skeleton = this._skeleton; let state = this._state; if (skeleton) { @@ -398,6 +405,7 @@ sp.Skeleton = cc.Class({ // Destroyed and restored in Editor if (!this._material) { this._boundingBox = cc.rect(); + this._materials = {}; this._material = new SpriteMaterial(); this._renderDatas = []; } diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index d705085ca3c..64c3f7159dd 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -34,8 +34,6 @@ const SpriteMaterial = renderEngine.SpriteMaterial; const STENCIL_SEP = '@'; -let _sharedMaterials = {}; - let _slotColor = cc.color(0, 0, 255, 255); let _boneColor = cc.color(255, 0, 0, 255); let _originColor = cc.color(0, 255, 0, 255); @@ -49,7 +47,7 @@ function _updateKeyWithStencilRef (key, stencilRef) { return key.replace(/@\d+$/, STENCIL_SEP + stencilRef); } -function _getSlotMaterial (slot, tex, premultiAlpha) { +function _getSlotMaterial (comp, slot, tex, premultiAlpha) { let src, dst; switch (slot.data.blendMode) { case spine.BlendMode.Additive: @@ -72,9 +70,19 @@ function _getSlotMaterial (slot, tex, premultiAlpha) { } let key = tex.url + src + dst + STENCIL_SEP + '0'; - let material = _sharedMaterials[key]; + comp._material = comp._material || new SpriteMaterial(); + let baseMaterial = comp._material; + let materials = comp._materials; + let material = materials[key]; if (!material) { - material = new SpriteMaterial(); + + var baseKey = baseMaterial._hash; + if (!materials[baseKey]) { + material = baseMaterial; + } else { + material = baseMaterial.clone(); + } + material.useModel = true; // update texture material.texture = tex; @@ -88,7 +96,7 @@ function _getSlotMaterial (slot, tex, premultiAlpha) { gfx.BLEND_FUNC_ADD, src, dst ); - _sharedMaterials[key] = material; + materials[key] = material; material.updateHash(key); } else if (material.texture !== tex) { @@ -168,6 +176,7 @@ var spineAssembler = { let material = null, currMaterial = null; let vertexCount = 0, vertexOffset = 0; let indiceCount = 0, indiceOffset = 0; + let materials = comp._materials; for (let i = 0, n = locSkeleton.drawOrder.length; i < n; i++) { slot = locSkeleton.drawOrder[i]; if (!slot.attachment) @@ -196,7 +205,7 @@ var spineAssembler = { } newData = false; - material = _getSlotMaterial(slot, attachment.region.texture._texture, premultiAlpha); + material = _getSlotMaterial(comp, slot, attachment.region.texture._texture, premultiAlpha); if (!material) { continue; } @@ -300,6 +309,7 @@ var spineAssembler = { fillBuffers (comp, renderer) { let renderDatas = comp._renderDatas; + let materials = comp._materials; for (let index = 0, length = renderDatas.length; index < length; index++) { let data = renderDatas[index]; @@ -308,10 +318,10 @@ var spineAssembler = { let key = data.material._hash; let newKey = _updateKeyWithStencilRef(key, StencilManager.getStencilRef()); if (key !== newKey) { - data.material = _sharedMaterials[newKey] || data.material.clone(); + data.material = materials[newKey] || data.material.clone(); data.material.updateHash(newKey); - if (!_sharedMaterials[newKey]) { - _sharedMaterials[newKey] = data.material; + if (!materials[newKey]) { + materials[newKey] = data.material; } } From ac8d7f32eafb641e3c00e59924bff9397c544cbb Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 15 Nov 2018 17:17:40 +0800 Subject: [PATCH 0178/1631] Add RenderComponent setVertsDirty for verts update notif --- cocos2d/core/components/CCLabel.js | 4 ++-- cocos2d/core/components/CCMask.js | 2 +- cocos2d/core/components/CCRenderComponent.js | 9 ++++++++- cocos2d/core/components/CCSprite.js | 12 ++++++------ 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index cc8492e892d..fcf9ae42f36 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -581,12 +581,12 @@ let Label = cc.Class({ }, _lazyUpdateRenderData () { - this._vertsDirty = true; + this.setVertsDirty(); this.markForUpdateRenderData(true); }, _forceUpdateRenderData () { - this._vertsDirty = true; + this.setVertsDirty(); this.markForUpdateRenderData(true); this._updateAssembler(); this._activateMaterial(true); diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index d6841192e47..34340112322 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -319,7 +319,7 @@ let Mask = cc.Class({ _onTextureLoaded () { // Mark render data dirty - this._vertsDirty = true; + this.setVertsDirty(); if (this._renderData) { this.markForUpdateRenderData(true); } diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index a05798e61ca..c477be5d529 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -133,8 +133,15 @@ let RenderComponent = cc.Class({ this._material = null; }, - _onNodeSizeDirty () { + setVertsDirty () { this._vertsDirty = true; + if (CC_JSB) { + this._renderHandle.setVertsDirty(); + } + }, + + _onNodeSizeDirty () { + this.setVertsDirty(); this.markForUpdateRenderData(true); }, diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 143fedfca0d..520d2aa60cc 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -272,7 +272,7 @@ var Sprite = cc.Class({ this._renderData = null; } else if (this._renderData) { - this._vertsDirty = true; + this.setVertsDirty(); this.markForUpdateRenderData(true); } this._fillType = value; @@ -301,7 +301,7 @@ var Sprite = cc.Class({ this._fillCenter.x = value.x; this._fillCenter.y = value.y; if (this._type === SpriteType.FILLED && this._renderData) { - this._vertsDirty = true; + this.setVertsDirty(); this.markForUpdateRenderData(true); } }, @@ -326,7 +326,7 @@ var Sprite = cc.Class({ set: function(value) { this._fillStart = misc.clampf(value, -1, 1); if (this._type === SpriteType.FILLED && this._renderData) { - this._vertsDirty = true; + this.setVertsDirty(); this.markForUpdateRenderData(true); } }, @@ -351,7 +351,7 @@ var Sprite = cc.Class({ set: function(value) { this._fillRange = misc.clampf(value, -1, 1); if (this._type === SpriteType.FILLED && this._renderData) { - this._vertsDirty = true; + this.setVertsDirty(); this.markForUpdateRenderData(true); } }, @@ -374,7 +374,7 @@ var Sprite = cc.Class({ this._isTrimmedMode = value; if ((this._type === SpriteType.SIMPLE || this._type === SpriteType.MESH) && this._renderData) { - this._vertsDirty = true; + this.setVertsDirty(); this.markForUpdateRenderData(true); } } @@ -468,7 +468,7 @@ var Sprite = cc.Class({ if (!this._renderData) { this._renderData = this._assembler.createData(this); this._renderData.material = this._material; - this._vertsDirty = true; + this.setVertsDirty(); this.markForUpdateRenderData(true); } }, From 767c843fc977bec2d9b76846f365c8beb124d77a Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 15 Nov 2018 17:18:40 +0800 Subject: [PATCH 0179/1631] Improve batcher walking setting --- cocos2d/core/renderer/canvas/render-component-handle.js | 2 +- cocos2d/core/renderer/render-flow.js | 1 - cocos2d/core/renderer/webgl/model-batcher.js | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/renderer/canvas/render-component-handle.js b/cocos2d/core/renderer/canvas/render-component-handle.js index c42d9f48d23..78b87d9e153 100644 --- a/cocos2d/core/renderer/canvas/render-component-handle.js +++ b/cocos2d/core/renderer/canvas/render-component-handle.js @@ -54,7 +54,7 @@ RenderComponentHandle.prototype = { }, terminate () { - + this.walking = false; }, _commitComp (comp, assembler) { diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 2eb9a25dfb7..4f3066406f1 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -217,7 +217,6 @@ RenderFlow.visit = function (scene) { } _batcher.terminate(); - _batcher.walking = false; }; RenderFlow.init = function (batcher) { diff --git a/cocos2d/core/renderer/webgl/model-batcher.js b/cocos2d/core/renderer/webgl/model-batcher.js index 99fa8f53389..d59bb0196b6 100644 --- a/cocos2d/core/renderer/webgl/model-batcher.js +++ b/cocos2d/core/renderer/webgl/model-batcher.js @@ -205,6 +205,8 @@ ModelBatcher.prototype = { for (let key in _buffers) { _buffers[key].uploadData(); } + + this.walking = false; }, getBuffer (type, vertextFormat) { From bc652c8f4042a3dbda9c5e0207a85666af6f9209 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 15 Nov 2018 17:19:33 +0800 Subject: [PATCH 0180/1631] Small improvements --- cocos2d/core/renderer/render-flow.js | 4 ++-- cocos2d/core/renderer/webgl/mesh-buffer.js | 1 + cocos2d/core/renderer/webgl/model-batcher.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 4f3066406f1..8ff5db09788 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -98,10 +98,10 @@ _proto._children = function (node) { let children = node._children; for (let i = 0, l = children.length; i < l; i++) { let c = children[i]; - if (!c._activeInHierarchy || c._opacity === 0) continue; - _cullingMask = c._cullingMask = c.groupIndex === 0 ? cullingMask : 1 << c.groupIndex; c._renderFlag |= worldTransformFlag | worldOpacityFlag; + if (!c._activeInHierarchy || c._opacity === 0) continue; + _cullingMask = c._cullingMask = c.groupIndex === 0 ? cullingMask : 1 << c.groupIndex; // TODO: Maybe has better way to implement cascade opacity c._color.a = c._opacity * batcher.parentOpacity; flows[c._renderFlag]._func(c); diff --git a/cocos2d/core/renderer/webgl/mesh-buffer.js b/cocos2d/core/renderer/webgl/mesh-buffer.js index 0d49d4bc915..f7f3da0e41e 100644 --- a/cocos2d/core/renderer/webgl/mesh-buffer.js +++ b/cocos2d/core/renderer/webgl/mesh-buffer.js @@ -10,6 +10,7 @@ let MeshBuffer = cc.Class({ this.indiceOffset = 0; this.vertexStart = 0; this.vertexOffset = 0; + this._dirty = false; this._vertexFormat = vertexFormat; this._vertexBytes = this._vertexFormat._bytes; diff --git a/cocos2d/core/renderer/webgl/model-batcher.js b/cocos2d/core/renderer/webgl/model-batcher.js index d59bb0196b6..04940bddf6f 100644 --- a/cocos2d/core/renderer/webgl/model-batcher.js +++ b/cocos2d/core/renderer/webgl/model-batcher.js @@ -173,7 +173,7 @@ ModelBatcher.prototype = { }, _commitComp (comp, assembler, cullingMask) { - if (this.material._hash != comp._material._hash || + if (this.material._hash !== comp._material._hash || this.cullingMask !== cullingMask) { this._flush(); From e149c07c83b6b684cc717b50bcce57d20711f9a3 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 15 Nov 2018 17:20:05 +0800 Subject: [PATCH 0181/1631] Init default vertex format --- cocos2d/core/components/CCRenderComponent.js | 2 +- cocos2d/core/renderer/webgl/vertex-format.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index c477be5d529..2c66ec0b43d 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -101,7 +101,7 @@ let RenderComponent = cc.Class({ this.__allocedDatas = []; this._vertsDirty = true; this._material = null; - this._vertexFormat = null; + this._vertexFormat = gfx.VertexFormat.XY_UV_Color; this._assembler = this.constructor._assembler; this._postAssembler = this.constructor._postAssembler; }, diff --git a/cocos2d/core/renderer/webgl/vertex-format.js b/cocos2d/core/renderer/webgl/vertex-format.js index 94351122408..4d0169467f7 100644 --- a/cocos2d/core/renderer/webgl/vertex-format.js +++ b/cocos2d/core/renderer/webgl/vertex-format.js @@ -32,6 +32,7 @@ var vfmt3D = new gfx.VertexFormat([ { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true }, ]); vfmt3D.name = 'vfmt3D'; +gfx.VertexFormat.XYZ_UV_Color = vfmt3D; var vfmtPosUvColor = new gfx.VertexFormat([ { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, @@ -39,18 +40,21 @@ var vfmtPosUvColor = new gfx.VertexFormat([ { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true }, ]); vfmtPosUvColor.name = 'vfmtPosUvColor'; +gfx.VertexFormat.XY_UV_Color = vfmtPosUvColor; var vfmtPosUv = new gfx.VertexFormat([ { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 } ]); vfmtPosUv.name = 'vfmtPosUv'; +gfx.VertexFormat.XY_UV = vfmtPosUv; var vfmtPosColor = new gfx.VertexFormat([ { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true }, ]); vfmtPosColor.name = 'vfmtPosColor'; +gfx.VertexFormat.XY_Color = vfmtPosColor; module.exports = { vfmt3D, From 0e6ff7a2aabc2668d6a921a6a8deb4e8289aaaca Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Thu, 15 Nov 2018 17:28:40 +0800 Subject: [PATCH 0182/1631] fix spine texture leakage and material may be invalid when reload spine resource (#3501) * fix bug #334 spine use premultipliedAlpha,set opacity zero, but still show * fix spine texture leakage and material may be invalid when reload spine resource * support spine change material * modify code style * Modify variable name to avoid ambiguity --- extensions/spine/Skeleton.js | 14 +++++++++++--- extensions/spine/spine-assembler.js | 30 +++++++++++++++++++---------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index a50737be299..218db733d18 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -314,7 +314,7 @@ sp.Skeleton = cc.Class({ notify () { this._initDebugDraw(); } - } + }, }, // CONSTRUCTOR @@ -324,11 +324,17 @@ sp.Skeleton = cc.Class({ this._listener = null; this._boundingBox = cc.rect(); this._material = new SpriteMaterial(); + this._materials = {}; this._renderDatas = []; - this._debugRenderer = null; }, + // override + _updateMaterial (material) { + this._super(material); + this._materials = {}; + }, + /** * !#en * Sets runtime skeleton data to sp.Skeleton.
@@ -382,6 +388,7 @@ sp.Skeleton = cc.Class({ update (dt) { if (CC_EDITOR) return; + if (this.paused) return; let skeleton = this._skeleton; let state = this._state; if (skeleton) { @@ -398,7 +405,8 @@ sp.Skeleton = cc.Class({ // Destroyed and restored in Editor if (!this._material) { this._boundingBox = cc.rect(); - this._material = new SpriteMaterial(); + this._material = new SpriteMaterial(); + this._materials = {}; this._renderDatas = []; } }, diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 44e4303de42..470ac676fcb 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -35,8 +35,6 @@ const SpriteMaterial = renderEngine.SpriteMaterial; const STENCIL_SEP = '@'; -let _sharedMaterials = {}; - let _slotColor = cc.color(0, 0, 255, 255); let _boneColor = cc.color(255, 0, 0, 255); let _originColor = cc.color(0, 255, 0, 255); @@ -50,7 +48,7 @@ function _updateKeyWithStencilRef (key, stencilRef) { return key.replace(/@\d+$/, STENCIL_SEP + stencilRef); } -function _getSlotMaterial (slot, tex, premultiAlpha) { +function _getSlotMaterial (comp, slot, tex, premultiAlpha) { let src, dst; switch (slot.data.blendMode) { case spine.BlendMode.Additive: @@ -73,9 +71,19 @@ function _getSlotMaterial (slot, tex, premultiAlpha) { } let key = tex.url + src + dst + STENCIL_SEP + '0'; - let material = _sharedMaterials[key]; + comp._material = comp._material || new SpriteMaterial(); + let baseMaterial = comp._material; + let materials = comp._materials; + let material = materials[key]; if (!material) { - material = new SpriteMaterial(); + + var baseKey = baseMaterial._hash; + if (!materials[baseKey]) { + material = baseMaterial; + } else { + material = baseMaterial.clone(); + } + material.useModel = true; // update texture material.texture = tex; @@ -89,7 +97,7 @@ function _getSlotMaterial (slot, tex, premultiAlpha) { gfx.BLEND_FUNC_ADD, src, dst ); - _sharedMaterials[key] = material; + materials[key] = material; material.updateHash(key); } else if (material.texture !== tex) { @@ -169,6 +177,7 @@ var spineAssembler = { let material = null, currMaterial = null; let vertexCount = 0, vertexOffset = 0; let indiceCount = 0, indiceOffset = 0; + let materials = comp._materials; for (let i = 0, n = locSkeleton.drawOrder.length; i < n; i++) { slot = locSkeleton.drawOrder[i]; if (!slot.attachment) @@ -197,7 +206,7 @@ var spineAssembler = { } newData = false; - material = _getSlotMaterial(slot, attachment.region.texture._texture, premultiAlpha); + material = _getSlotMaterial(comp, slot, attachment.region.texture._texture, premultiAlpha); if (!material) { continue; } @@ -301,6 +310,7 @@ var spineAssembler = { fillBuffers (comp, renderer) { let renderDatas = comp._renderDatas; + let materials = comp._materials; for (let index = 0, length = renderDatas.length; index < length; index++) { let data = renderDatas[index]; @@ -309,10 +319,10 @@ var spineAssembler = { let key = data.material._hash; let newKey = _updateKeyWithStencilRef(key, StencilManager.getStencilRef()); if (key !== newKey) { - data.material = _sharedMaterials[newKey] || data.material.clone(); + data.material = materials[newKey] || data.material.clone(); data.material.updateHash(newKey); - if (!_sharedMaterials[newKey]) { - _sharedMaterials[newKey] = data.material; + if (!materials[newKey]) { + materials[newKey] = data.material; } } From ca9df665260be5402954c76b72fff669df36d494 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 15 Nov 2018 17:57:19 +0800 Subject: [PATCH 0183/1631] Adapt render handle for JSB --- cocos2d/core/components/CCLabel.js | 4 ++++ cocos2d/core/components/CCRenderComponent.js | 24 ++++++++++++++++++++ cocos2d/core/components/CCSprite.js | 4 ++++ cocos2d/core/renderer/render-engine.jsb.js | 3 +++ 4 files changed, 35 insertions(+) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index fcf9ae42f36..b64599d5982 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -505,6 +505,10 @@ let Label = cc.Class({ if (!this._renderData) { this._renderData = this._assembler.createData(this); } + + if (CC_JSB) { + this._renderHandle.setUseModel(!!assembler.useModel); + } }, _activateMaterial (force) { diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 2c66ec0b43d..115b00307d0 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -104,6 +104,12 @@ let RenderComponent = cc.Class({ this._vertexFormat = gfx.VertexFormat.XY_UV_Color; this._assembler = this.constructor._assembler; this._postAssembler = this.constructor._postAssembler; + + // Render handle for native system + if (CC_JSB) { + this._renderHandle = new renderer.RenderHandle(); + this._renderHandle.bind(this); + } }, onEnable () { @@ -116,12 +122,20 @@ let RenderComponent = cc.Class({ this.node.on(cc.Node.EventType.ANCHOR_CHANGED, this._onNodeSizeDirty, this); this.node._renderFlag |= RenderFlow.FLAG_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_COLOR; + + if (CC_JSB) { + this.node.on(cc.Node.EventType.COLOR_CHANGED, this._updateColor, this); + this._renderHandle.setEnable(true); + } }, onDisable () { this.node._renderComponent = null; this.node.off(cc.Node.EventType.SIZE_CHANGED, this._onNodeSizeDirty, this); this.node.off(cc.Node.EventType.ANCHOR_CHANGED, this._onNodeSizeDirty, this); + if (CC_JSB) { + this.node.off(cc.Node.EventType.COLOR_CHANGED, this._updateColor, this); + } this.disableRender(); }, @@ -162,9 +176,15 @@ let RenderComponent = cc.Class({ markForRender (enable) { if (enable && this._canRender()) { this.node._renderFlag |= RenderFlow.FLAG_RENDER; + if (CC_JSB) { + this._renderHandle.setEnable(true); + } } else if (!enable) { this.node._renderFlag &= ~RenderFlow.FLAG_RENDER; + if (CC_JSB) { + this._renderHandle.setEnable(false); + } } }, @@ -179,6 +199,10 @@ let RenderComponent = cc.Class({ disableRender () { this.node._renderFlag &= ~(RenderFlow.FLAG_RENDER | RenderFlow.FLAG_CUSTOM_IA_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_COLOR); + + if (CC_JSB) { + this._renderHandle.setEnable(false); + } }, requestRenderData () { diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 520d2aa60cc..6b1dd137c94 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -471,6 +471,10 @@ var Sprite = cc.Class({ this.setVertsDirty(); this.markForUpdateRenderData(true); } + + if (CC_JSB) { + this._renderHandle.setUseModel(!!assembler.useModel); + } }, _activateMaterial: function () { diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index a89ed794029..25462c760e2 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -2854,6 +2854,9 @@ var Material = (function (Asset$$1) { Material.prototype.updateHash = function updateHash (value) { this._hash = value || computeHash(this); + if (CC_JSB && this._effect) { + this._effect.updateHash(this._hash); + } }; Object.defineProperties( Material.prototype, prototypeAccessors ); From 3decc79f5882de4b30b97fac1c5931505521cbb0 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Thu, 15 Nov 2018 20:14:25 +0800 Subject: [PATCH 0184/1631] Fix the problem that vertexCount of motion-streak is negative. (#3520) --- cocos2d/core/renderer/webgl/assemblers/motion-streak.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index dad464aedfb..6ea30f8b819 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -187,7 +187,7 @@ var motionStreakAssembler = { } renderData.vertexCount = renderData.dataLength; - renderData.indiceCount = (renderData.vertexCount - 2)*3; + renderData.indiceCount = renderData.vertexCount < 2 ? 0 : (renderData.vertexCount - 2)*3; }, fillBuffers (comp, renderer) { From 4d35aba85bf3d7dd50c0d2d8e8b0441dfd07661d Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Thu, 15 Nov 2018 20:31:15 +0800 Subject: [PATCH 0185/1631] when node hasColor and material useColor false, material will still updateHash (#3522) --- cocos2d/core/components/CCRenderComponent.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index d5ef2d9a0bb..5f054168258 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -182,8 +182,11 @@ let RenderComponent = cc.Class({ _updateColor () { let material = this._material; if (material) { - material.color = this.node.color; - material.updateHash(); + // For batch rendering, update the color only when useColor is set to true. + if (material.useColor) { + material.color = this.node.color; + material.updateHash(); + } // reset flag when set color to material successfully this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; From bf5227e49d9a9d9d78b92118850179b343d12054 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 14 Nov 2018 23:01:21 +0800 Subject: [PATCH 0186/1631] refine quad fromEuler/toEuler (#3512) --- cocos2d/core/renderer/render-engine.canvas.js | 42 ++++++++++++++++++- cocos2d/core/renderer/render-engine.jsb.js | 41 +++++++++++++++++- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js index 1de8f2b0638..f14152f4ccc 100644 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ b/cocos2d/core/renderer/render-engine.canvas.js @@ -5363,14 +5363,52 @@ quat.fromEuler = function (out, x, y, z) { var sz = Math.sin(z); var cz = Math.cos(z); - out.x = sx * cy * cz - cx * sy * sz; + out.x = sx * cy * cz + cx * sy * sz; out.y = cx * sy * cz + sx * cy * sz; out.z = cx * cy * sz - sx * sy * cz; - out.w = cx * cy * cz + sx * sy * sz; + out.w = cx * cy * cz - sx * sy * sz; return out; }; +/** + * Convert a quaternion back to euler angle (in degrees). + * + * @param {vec3} out - Euler angle stored as a vec3 + * @param {number} q - the quaternion to be converted + * @returns {vec3} out. + */ +quat.toEuler = function (out, q) { + var x = q.x, y = q.y, z = q.z, w = q.w; + var heading, attitude, bank; + var test = x * y + z * w; + if (test > 0.499) { // singularity at north pole + heading = 2 * Math.atan2(x,w); + attitude = Math.PI/2; + bank = 0; + } + if (test < -0.499) { // singularity at south pole + heading = -2 * Math.atan2(x,w); + attitude = - Math.PI/2; + bank = 0; + } + if(isNaN(heading)){ + var sqx = x*x; + var sqy = y*y; + var sqz = z*z; + heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // heading + attitude = Math.asin(2*test); // attitude + bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank + } + + out.y = toDegree(heading); + out.z = toDegree(attitude); + out.x = toDegree(bank); + + return out; +} + + /** * Returns a string representation of a quatenion * diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 25462c760e2..e7e16587e21 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -7184,14 +7184,51 @@ quat.fromEuler = function (out, x, y, z) { var sz = Math.sin(z); var cz = Math.cos(z); - out.x = sx * cy * cz - cx * sy * sz; + out.x = sx * cy * cz + cx * sy * sz; out.y = cx * sy * cz + sx * cy * sz; out.z = cx * cy * sz - sx * sy * cz; - out.w = cx * cy * cz + sx * sy * sz; + out.w = cx * cy * cz - sx * sy * sz; return out; }; +/** + * Convert a quaternion back to euler angle (in degrees). + * + * @param {vec3} out - Euler angle stored as a vec3 + * @param {number} q - the quaternion to be converted + * @returns {vec3} out. + */ +quat.toEuler = function (out, q) { + var x = q.x, y = q.y, z = q.z, w = q.w; + var heading, attitude, bank; + var test = x * y + z * w; + if (test > 0.499) { // singularity at north pole + heading = 2 * Math.atan2(x,w); + attitude = Math.PI/2; + bank = 0; + } + if (test < -0.499) { // singularity at south pole + heading = -2 * Math.atan2(x,w); + attitude = - Math.PI/2; + bank = 0; + } + if(isNaN(heading)){ + var sqx = x*x; + var sqy = y*y; + var sqz = z*z; + heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // heading + attitude = Math.asin(2*test); // attitude + bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank + } + + out.y = toDegree(heading); + out.z = toDegree(attitude); + out.x = toDegree(bank); + + return out; +} + /** * Returns a string representation of a quatenion * From 50b13beec4dcd8b1172793cf7e2c7aad30e4514f Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 16 Nov 2018 12:06:19 +0800 Subject: [PATCH 0187/1631] reset editBox bug fix before (#3517) --- cocos2d/core/platform/CCView.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 01547c16947..34bb999de13 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -348,15 +348,6 @@ cc.js.mixin(View.prototype, { cc.game.container.style['-webkit-transform-origin'] = '0px 0px 0px'; cc.game.container.style.transformOrigin = '0px 0px 0px'; this._isRotated = true; - - // Fix for issue: https://github.com/cocos-creator/fireball/issues/8365 - // Reference: https://www.douban.com/note/343402554/ - // For Chrome, z-index not working after container transform rotate 90deg. - // Because 'transform' style adds canvas (the top-element of container) to a new stack context. - // That causes the DOM Input was hidden under canvas. - // This should be done after container rotated, instead of in style-mobile.css. - cc.game.canvas.style['-webkit-transform'] = 'translateZ(0px)'; - cc.game.canvas.style.transform = 'translateZ(0px)'; } if (this._orientationChanging) { setTimeout(function () { From 0028478e44986b0e35d3677a6a8df054d1d60ab1 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 16 Nov 2018 14:02:21 +0800 Subject: [PATCH 0188/1631] dragonbones _animationIndex and _defaultArmatureIndex do not support animatable (#3523) --- extensions/dragonbones/ArmatureDisplay.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 35e7a2b6e6e..76208977c5b 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -206,6 +206,7 @@ let ArmatureDisplay = cc.Class({ type: DefaultArmaturesEnum, visible: true, editorOnly: true, + animatable: false, displayName: "Armature", tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.armature_name' }, @@ -239,6 +240,7 @@ let ArmatureDisplay = cc.Class({ type: DefaultAnimsEnum, visible: true, editorOnly: true, + animatable: false, displayName: 'Animation', tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.animation_name' }, From 42b46772bb11efcfc9cc11d54813d0bde2610a01 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 16 Nov 2018 15:15:26 +0800 Subject: [PATCH 0189/1631] fix audio resume failed when game back to foreground (#3524) --- cocos2d/audio/CCAudio.js | 4 ++-- cocos2d/core/components/CCAudioSource.js | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cocos2d/audio/CCAudio.js b/cocos2d/audio/CCAudio.js index 568120454c9..3e52db2402e 100644 --- a/cocos2d/audio/CCAudio.js +++ b/cocos2d/audio/CCAudio.js @@ -168,7 +168,7 @@ Audio.State = { }; proto.destroy = function () { - if (CC_WECHATGAME) { + if (CC_WECHATGAME || CC_QQPLAY) { this._element && this._element.destroy(); } this._element = null; @@ -264,7 +264,7 @@ Audio.State = { }; proto.getState = function () { - if (!CC_WECHATGAME) { + if (!CC_WECHATGAME && !CC_QQPLAY) { let elem = this._element; if (elem && Audio.State.PLAYING === this._state && elem.paused) { this._state = Audio.State.PAUSED; diff --git a/cocos2d/core/components/CCAudioSource.js b/cocos2d/core/components/CCAudioSource.js index 371c7aefec3..1337ac27918 100644 --- a/cocos2d/core/components/CCAudioSource.js +++ b/cocos2d/core/components/CCAudioSource.js @@ -208,10 +208,11 @@ var AudioSource = cc.Class({ }, _pausedCallback: function () { - var audio = this.audio; - if (audio.paused) return; - this.audio.pause(); - this._pausedFlag = true; + var state = this.audio.getState(); + if (state === cc.Audio.State.PLAYING) { + this.audio.pause(); + this._pausedFlag = true; + } }, _restoreCallback: function () { From b735e0fc52be5640cfdb2b502622fe859dc8c58b Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 16 Nov 2018 17:55:07 +0800 Subject: [PATCH 0190/1631] widget align only supports parent nodes not null (#3526) --- cocos2d/core/base-ui/CCWidgetManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/base-ui/CCWidgetManager.js b/cocos2d/core/base-ui/CCWidgetManager.js index 537b97dacc9..0a365294700 100644 --- a/cocos2d/core/base-ui/CCWidgetManager.js +++ b/cocos2d/core/base-ui/CCWidgetManager.js @@ -433,7 +433,7 @@ function updateAlignment (node) { } var widget = node._widget || node.getComponent(cc.Widget); // node._widget will be null when widget is disabled - if (widget) { + if (widget && parent) { align(node, widget); } } From 8fb89fa2d93e0ee463112023a8dc4070a42fbbb0 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Sun, 18 Nov 2018 21:29:42 +0800 Subject: [PATCH 0191/1631] add conversion between euler angles and quat for 2D (#3514) --- cocos2d/core/3d/polyfill-3d.js | 2 ++ cocos2d/core/CCNode.js | 30 ++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index e8c1e7c4b5d..ff4222439de 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -35,6 +35,7 @@ const ONE_DEGREE = Math.PI / 180; const POSITION_ON = 1 << 0; const SCALE_ON = 1 << 1; +const ERR_INVALID_NUMBER = CC_EDITOR && 'The %s is invalid'; function _updateLocalMatrix3d () { if (this._localMatDirty) { @@ -155,6 +156,7 @@ function _update3DFunction () { this._mulMat = _mulMat2d; } this._renderFlag |= RenderFlow.FLAG_TRANSFORM; + this._localMatDirty = DirtyFlag.ALL; } function _upgrade_1x_to_2x () { diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 819a99d0ff0..44d0aaaf015 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -721,8 +721,8 @@ let NodeDefines = { return this._eulerAngles.z; }, set (value) { - this._eulerAngles.z = value; - math.quat.fromEuler(this._quat, 0, 0, value); + math.vec3.set(this._eulerAngles, 0, 0, value); + this._fromEuler(); this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -1269,6 +1269,24 @@ let NodeDefines = { // INTERNAL + _toEuler () { + if (this.is3DNode) { + this._quat.toEuler(this._eulerAngles); + } + else { + let z = Math.asin(this._quat.z) / ONE_DEGREE * 2; + math.vec3.set(this._eulerAngles, 0, 0, z); + } + }, + _fromEuler () { + if (this.is3DNode) { + this._quat.fromEuler(this._eulerAngles); + } + else { + math.quat.fromEuler(this._quat, 0, 0, this._eulerAngles.z); + } + }, + _upgrade_1x_to_2x () { // Upgrade scaleX, scaleY from v1.x // TODO: remove in future version, 3.0 ? @@ -1300,7 +1318,7 @@ let NodeDefines = { this._rotationX = this._rotationY = undefined; } - this._quat.toEuler(this._eulerAngles); + this._toEuler(); // Upgrade from 2.0.0 preview 4 & earlier versions // TODO: Remove after final version @@ -2220,7 +2238,7 @@ let NodeDefines = { } if (CC_EDITOR) { - old.toEuler(this._eulerAngles); + this._toEuler(); } } } @@ -2461,7 +2479,7 @@ let NodeDefines = { else { math.quat.copy(this._quat, quat); } - this._quat.toEuler(this._eulerAngles); + this._toEuler(); this.setLocalDirty(LocalDirtyFlag.ROTATION); }, @@ -3132,7 +3150,7 @@ let NodeDefines = { this._localMatDirty = LocalDirtyFlag.ALL; this._worldMatDirty = true; - this._quat.toEuler(this._eulerAngles); + this._toEuler(); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._renderComponent) { From 5383d46a03d6e876bc29a2ba081c9576c98d45bf Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Sun, 18 Nov 2018 22:16:53 +0800 Subject: [PATCH 0192/1631] support 3d sprite&label (#3509) * support 3d sprite&label * no message * refine code * update render-engine * refine code * remove use2DPos * refine code * refine code --- cocos2d/core/3d/polyfill-3d.js | 3 + cocos2d/core/components/CCLabel.js | 5 + cocos2d/core/components/CCSprite.js | 4 + cocos2d/core/renderer/render-engine.canvas.js | 1 + cocos2d/core/renderer/render-engine.js | 19 +- cocos2d/core/renderer/render-engine.jsb.js | 35 +- .../webgl/assemblers/label/{ => 2d}/bmfont.js | 72 ++-- .../webgl/assemblers/label/{ => 2d}/ttf.js | 31 +- .../webgl/assemblers/label/3d/bmfont.js | 35 ++ .../renderer/webgl/assemblers/label/3d/ttf.js | 36 ++ .../renderer/webgl/assemblers/label/index.js | 13 +- .../webgl/assemblers/mask-assembler.js | 2 +- .../assemblers/sprite/{ => 2d}/bar-filled.js | 61 ++- .../webgl/assemblers/sprite/{ => 2d}/mesh.js | 60 +-- .../assemblers/sprite/2d/radial-filled.js | 339 ++++++++++++++++ .../assemblers/sprite/{ => 2d}/simple.js | 68 ++-- .../assemblers/sprite/{ => 2d}/sliced.js | 30 +- .../webgl/assemblers/sprite/{ => 2d}/tiled.js | 123 +++--- .../webgl/assemblers/sprite/3d/bar-filled.js | 67 ++++ .../webgl/assemblers/sprite/3d/mesh.js | 74 ++++ .../assemblers/sprite/3d/radial-filled.js | 47 +++ .../webgl/assemblers/sprite/3d/simple.js | 89 +++++ .../webgl/assemblers/sprite/3d/sliced.js | 100 +++++ .../webgl/assemblers/sprite/3d/tiled.js | 68 ++++ .../renderer/webgl/assemblers/sprite/index.js | 32 +- .../webgl/assemblers/sprite/radial-filled.js | 367 ------------------ .../core/renderer/webgl/assemblers/utils.js | 103 +++++ .../renderer/webgl/render-component-walker.js | 15 +- 28 files changed, 1224 insertions(+), 675 deletions(-) rename cocos2d/core/renderer/webgl/assemblers/label/{ => 2d}/bmfont.js (58%) rename cocos2d/core/renderer/webgl/assemblers/label/{ => 2d}/ttf.js (71%) create mode 100644 cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/bar-filled.js (87%) rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/mesh.js (82%) create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/simple.js (79%) rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/sliced.js (92%) rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/tiled.js (71%) create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/bar-filled.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/mesh.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/radial-filled.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/simple.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/sliced.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/tiled.js delete mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/utils.js diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index ff4222439de..c1de43a8ebc 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -155,6 +155,9 @@ function _update3DFunction () { this._calculWorldMatrix = _calculWorldMatrix2d; this._mulMat = _mulMat2d; } + if (this._renderComponent && this._renderComponent._on3DNodeChanged) { + this._renderComponent._on3DNodeChanged(); + } this._renderFlag |= RenderFlow.FLAG_TRANSFORM; this._localMatDirty = DirtyFlag.ALL; } diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index dc1e8c4ecce..5f3afe9bf90 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -503,6 +503,10 @@ let Label = cc.Class({ this.markForRender(!!this.string); }, + _on3DNodeChanged () { + this._updateAssembler(); + }, + _updateAssembler () { let assembler = Label._assembler.getAssembler(this); @@ -513,6 +517,7 @@ let Label = cc.Class({ if (!this._renderData) { this._renderData = this._assembler.createData(this); + this.markForUpdateRenderData(true); } }, diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 578549dd156..ef4ad542648 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -466,6 +466,10 @@ var Sprite = cc.Class({ this.markForUpdateRenderData(true); }, + _on3DNodeChanged () { + this._updateAssembler(); + }, + _updateAssembler: function () { let assembler = Sprite._assembler.getAssembler(this); diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js index 9979860ce52..75b5f40ba3e 100644 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ b/cocos2d/core/renderer/render-engine.canvas.js @@ -1300,6 +1300,7 @@ var _dataPool = new Pool(function () { return { x: 0.0, y: 0.0, + z: 0.0, u: 0.0, v: 0.0, color: 0 diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index ce0fde66ebf..6477d079f57 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -13773,13 +13773,12 @@ var templates = [ }, { name: 'sprite', - vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', + vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', defines: [ { name: 'useTexture', }, { name: 'useModel', }, { name: 'alphaTest', }, - { name: 'use2DPos', }, { name: 'useColor', } ], } ]; @@ -13808,6 +13807,7 @@ var _dataPool = new Pool(function () { return { x: 0.0, y: 0.0, + z: 0.0, u: 0.0, v: 0.0, color: 0 @@ -14214,7 +14214,6 @@ var SpriteMaterial = (function (Material$$1) { { name: 'useTexture', value: true }, { name: 'useModel', value: false }, { name: 'alphaTest', value: false }, - { name: 'use2DPos', value: true }, { name: 'useColor', value: true } ] ); @@ -14226,7 +14225,7 @@ var SpriteMaterial = (function (Material$$1) { SpriteMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); SpriteMaterial.prototype.constructor = SpriteMaterial; - var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },use2DPos: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; + var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; prototypeAccessors.effect.get = function () { return this._effect; @@ -14239,7 +14238,7 @@ var SpriteMaterial = (function (Material$$1) { prototypeAccessors.useTexture.set = function (val) { this._effect.define('useTexture', val); }; - + prototypeAccessors.useModel.get = function () { return this._effect.getDefine('useModel'); }; @@ -14248,14 +14247,6 @@ var SpriteMaterial = (function (Material$$1) { this._effect.define('useModel', val); }; - prototypeAccessors.use2DPos.get = function () { - return this._effect.getDefine('use2DPos'); - }; - - prototypeAccessors.use2DPos.set = function (val) { - this._effect.define('use2DPos', val); - }; - prototypeAccessors.useColor.get = function () { return this._effect.getDefine('useColor'); }; @@ -14295,7 +14286,6 @@ var SpriteMaterial = (function (Material$$1) { copy.texture = this.texture; copy.useTexture = this.useTexture; copy.useModel = this.useModel; - copy.use2DPos = this.use2DPos; copy.useColor = this.useColor; copy.updateHash(); return copy; @@ -14432,7 +14422,6 @@ var StencilMaterial = (function (Material$$1) { { name: 'useTexture', value: true }, { name: 'useModel', value: false }, { name: 'alphaTest', value: true }, - { name: 'use2DPos', value: true }, { name: 'useColor', value: true } ] ); diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 89665ed2a8f..9eb65257f68 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -1022,6 +1022,7 @@ _p$1.addModel = function(model) { _p$1.removeModel = function() {}; var chunks = { + 'skinning.vert': '\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}', }; var templates = [ @@ -1032,15 +1033,25 @@ var templates = [ defines: [ ], }, + { + name: 'mesh', + vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\n#ifdef useAttributeColor\n attribute vec4 a_color;\n varying vec4 v_color;\n#endif\n#ifdef useTexture\n attribute vec2 a_uv0;\n varying vec2 uv0;\n#endif\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useSkinning\n \nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef useSkinning\n mvp = mvp * skinMatrix();\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n #ifdef useAttributeColor\n v_color = a_color;\n #endif\n gl_Position = pos;\n}', + frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying vec2 uv0;\n#endif\n#ifdef useAttributeColor\n varying vec4 v_color;\n#endif\nuniform vec4 color;\nvoid main () {\n vec4 o = color;\n \n #ifdef useAttributeColor\n o *= v_color;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n gl_FragColor = o;\n}', + defines: [ + { name: 'useTexture', }, + { name: 'useModel', }, + { name: 'useSkinning', }, + { name: 'useJointsTexture', }, + { name: 'useAttributeColor', } ], + }, { name: 'sprite', - vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', + vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', defines: [ { name: 'useTexture', }, { name: 'useModel', }, { name: 'alphaTest', }, - { name: 'use2DPos', }, { name: 'useColor', } ], } ]; @@ -2321,6 +2332,7 @@ var _dataPool = new Pool(function () { return { x: 0.0, y: 0.0, + z: 0.0, u: 0.0, v: 0.0, color: 0 @@ -2731,7 +2743,6 @@ var SpriteMaterial = (function (Material$$1) { { name: 'useTexture', value: true }, { name: 'useModel', value: false }, { name: 'alphaTest', value: false }, - { name: 'use2DPos', value: true }, { name: 'useColor', value: true } ] ); @@ -2743,14 +2754,14 @@ var SpriteMaterial = (function (Material$$1) { SpriteMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); SpriteMaterial.prototype.constructor = SpriteMaterial; - var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },use2DPos: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; + var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; prototypeAccessors.effect.get = function () { return this._effect; }; prototypeAccessors.useTexture.get = function () { - this._effect.getDefine('useTexture'); + return this._effect.getDefine('useTexture'); }; prototypeAccessors.useTexture.set = function (val) { @@ -2758,23 +2769,15 @@ var SpriteMaterial = (function (Material$$1) { }; prototypeAccessors.useModel.get = function () { - this._effect.getDefine('useModel'); + return this._effect.getDefine('useModel'); }; prototypeAccessors.useModel.set = function (val) { this._effect.define('useModel', val); }; - prototypeAccessors.use2DPos.get = function () { - this._effect.getDefine('use2DPos'); - }; - - prototypeAccessors.use2DPos.set = function (val) { - this._effect.define('use2DPos', val); - }; - prototypeAccessors.useColor.get = function () { - this._effect.getDefine('useColor'); + return this._effect.getDefine('useColor'); }; prototypeAccessors.useColor.set = function (val) { @@ -2811,7 +2814,6 @@ var SpriteMaterial = (function (Material$$1) { copy.texture = this.texture; copy.useTexture = this.useTexture; copy.useModel = this.useModel; - copy.use2DPos = this.use2DPos; copy.useColor = this.useColor; copy.updateHash(); return copy; @@ -2947,7 +2949,6 @@ var StencilMaterial = (function (Material$$1) { { name: 'useTexture', value: true }, { name: 'useModel', value: false }, { name: 'alphaTest', value: true }, - { name: 'use2DPos', value: true }, { name: 'useColor', value: true } ] ); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js similarity index 58% rename from cocos2d/core/renderer/webgl/assemblers/label/bmfont.js rename to cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js index 11b6e1296a9..feb9b891253 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js @@ -23,8 +23,9 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('../../../../platform/js'); -const bmfontUtls = require('../../../utils/label/bmfont'); +const js = require('../../../../../platform/js'); +const bmfontUtls = require('../../../../utils/label/bmfont'); +const fillVertices = require('../../utils').fillVertices; module.exports = js.addon({ createData (comp) { @@ -32,38 +33,13 @@ module.exports = js.addon({ }, fillBuffers (comp, renderer) { - let node = comp.node, - renderData = comp._renderData, - data = renderData._data, - color = node._color._val; - - let matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; - - let vertexCount = renderData.vertexCount; - buffer.request(vertexCount, renderData.indiceCount); - - // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - uintbuf = buffer._uintVData; - - for (let i = 0; i < vertexCount; i++) { - let vert = data[i]; - vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; - vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; - vbuf[vertexOffset++] = vert.u; - vbuf[vertexOffset++] = vert.v; - uintbuf[vertexOffset++] = color; - } + let node = comp.node; + fillVertices(node, renderer._quadBuffer, comp._renderData, node._color._val); }, appendQuad (renderData, texture, rect, rotated, x, y, scale) { let dataOffset = renderData.dataLength; - + renderData.dataLength += 4; renderData.vertexCount = renderData.dataLength; renderData.indiceCount = renderData.dataLength / 2 * 3; @@ -84,12 +60,12 @@ module.exports = js.addon({ data[dataOffset].u = l; data[dataOffset].v = b; - data[dataOffset+1].u = r; - data[dataOffset+1].v = b; - data[dataOffset+2].u = l; - data[dataOffset+2].v = t; - data[dataOffset+3].u = r; - data[dataOffset+3].v = t; + data[dataOffset + 1].u = r; + data[dataOffset + 1].v = b; + data[dataOffset + 2].u = l; + data[dataOffset + 2].v = t; + data[dataOffset + 3].u = r; + data[dataOffset + 3].v = t; } else { l = (rect.x) / texw; r = (rect.x + rectHeight) / texw; @@ -98,21 +74,21 @@ module.exports = js.addon({ data[dataOffset].u = l; data[dataOffset].v = t; - data[dataOffset+1].u = l; - data[dataOffset+1].v = b; - data[dataOffset+2].u = r; - data[dataOffset+2].v = t; - data[dataOffset+3].u = r; - data[dataOffset+3].v = b; + data[dataOffset + 1].u = l; + data[dataOffset + 1].v = b; + data[dataOffset + 2].u = r; + data[dataOffset + 2].v = t; + data[dataOffset + 3].u = r; + data[dataOffset + 3].v = b; } data[dataOffset].x = x; data[dataOffset].y = y - rectHeight * scale; - data[dataOffset+1].x = x + rectWidth * scale; - data[dataOffset+1].y = y - rectHeight * scale; - data[dataOffset+2].x = x; - data[dataOffset+2].y = y; - data[dataOffset+3].x = x + rectWidth * scale; - data[dataOffset+3].y = y; + data[dataOffset + 1].x = x + rectWidth * scale; + data[dataOffset + 1].y = y - rectHeight * scale; + data[dataOffset + 2].x = x; + data[dataOffset + 2].y = y; + data[dataOffset + 3].x = x + rectWidth * scale; + data[dataOffset + 3].y = y; }, }, bmfontUtls); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js similarity index 71% rename from cocos2d/core/renderer/webgl/assemblers/label/ttf.js rename to cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js index 7fe92c669df..810d5b29fc1 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js @@ -23,8 +23,9 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('../../../../platform/js'); -const ttfUtls = require('../../../utils/label/ttf'); +const js = require('../../../../../platform/js'); +const ttfUtls = require('../../../../utils/label/ttf'); +const fillVertices = require('../../utils').fillVertices; const WHITE = cc.color(255, 255, 255, 255); @@ -49,31 +50,7 @@ module.exports = js.addon({ }, fillBuffers (comp, renderer) { - let data = comp._renderData._data, - node = comp.node, - color = WHITE._val, - matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; - - buffer.request(4, 6); - - // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - uintbuf = buffer._uintVData; - - // vertex - for (let i = 0; i < 4; i++) { - let vert = data[i]; - vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; - vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; - vbuf[vertexOffset++] = vert.u; - vbuf[vertexOffset++] = vert.v; - uintbuf[vertexOffset++] = color; - } + fillVertices(comp.node, renderer._quadBuffer, comp._renderData, WHITE._val); }, _updateVerts (comp) { diff --git a/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js new file mode 100644 index 00000000000..35264daf92b --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js @@ -0,0 +1,35 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/bmfont'); +const fillVertices3D = require('../../utils').fillVertices3D; + +module.exports = js.addon({ + fillBuffers (comp, renderer) { + let node = comp.node; + fillVertices3D(node, renderer._quadBuffer3D, comp._renderData, node._color._val); + }, +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js new file mode 100644 index 00000000000..5d7a2b07614 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js @@ -0,0 +1,36 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/ttf'); +const fillVertices3D = require('../../utils').fillVertices3D; + +const WHITE = cc.color(255, 255, 255, 255); + +module.exports = js.addon({ + fillBuffers (comp, renderer) { + fillVertices3D(comp.node, renderer._quadBuffer3D, comp._renderData, WHITE._val); + } +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/index.js b/cocos2d/core/renderer/webgl/assemblers/label/index.js index 7bac03a3f00..c4c47c55a03 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/index.js @@ -24,15 +24,20 @@ ****************************************************************************/ const Label = require('../../../../components/CCLabel'); -const ttfAssembler = require('./ttf'); -const bmfontAssembler = require('./bmfont'); + +const ttfAssembler = require('./2d/ttf'); +const bmfontAssembler = require('./2d/bmfont'); + +const ttfAssembler3D = require('./3d/ttf'); +const bmfontAssembler3D = require('./3d/bmfont'); var labelAssembler = { getAssembler (comp) { - let assembler = ttfAssembler; + let is3DNode = comp.node.is3DNode; + let assembler = is3DNode ? ttfAssembler3D : ttfAssembler; if (comp.font instanceof cc.BitmapFont) { - assembler = bmfontAssembler; + assembler = is3DNode ? bmfontAssembler3D : bmfontAssembler; } return assembler; diff --git a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js index 204cef1b00f..ab585fae55f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js @@ -26,7 +26,7 @@ const StencilManager = require('../stencil-manager'); const Mask = require('../../../components/CCMask'); const RenderFlow = require('../../render-flow'); -const spriteAssembler = require('./sprite/simple'); +const spriteAssembler = require('./sprite/2d/simple'); const graphicsAssembler = require('./graphics'); let _stencilMgr = StencilManager.sharedManager; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js similarity index 87% rename from cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js index 9c16d92cc98..c9cb27d09e1 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js @@ -23,16 +23,17 @@ THE SOFTWARE. ****************************************************************************/ -const Sprite = require('../../../../components/CCSprite'); +const Sprite = require('../../../../../components/CCSprite'); const FillType = Sprite.FillType; -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); +const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { useModel: false, updateRenderData (sprite) { let frame = sprite.spriteFrame; - + // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here if (frame) { @@ -70,7 +71,7 @@ module.exports = { fillRange = fillRange < 0.0 ? 0.0 : fillRange; fillRange = fillRange - fillStart; fillRange = fillRange < 0 ? 0 : fillRange; - + let fillEnd = fillStart + fillRange; fillEnd = fillEnd > 1 ? 1 : fillEnd; @@ -156,7 +157,7 @@ module.exports = { appx = node.anchorX * width, appy = node.anchorY * height; let l = -appx, b = -appy, - r = width-appx, t = height-appy; + r = width - appx, t = height - appy; let progressStart, progressEnd; switch (sprite._fillType) { @@ -198,19 +199,24 @@ module.exports = { renderData.dataLength = 8; renderData.vertexCount = 4; renderData.indiceCount = 6; + + let data = renderData._data; + for (let i = 0; i < data.length; i++) { + data[i].z = 0; + } return renderData; }, updateWorldVerts (sprite) { let node = sprite.node, data = sprite._renderData._data; - - let matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + + let matrix = node._worldMatrix; + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - + for (let i = 0; i < 4; i++) { - let local = data[i+4]; + let local = data[i + 4]; let world = data[i]; world.x = local.x * a + local.y * c + tx; world.y = local.x * b + local.y * d + ty; @@ -222,30 +228,21 @@ module.exports = { this.updateWorldVerts(sprite); } - let data = sprite._renderData._data, - node = sprite.node, - color = node._color._val, - matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; + // buffer + let buffer = renderer._meshBuffer, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; - buffer.request(4, 6); + let node = sprite.node; + fillVerticesWithoutCalc(node, buffer, sprite._renderData, node._color._val); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - uintbuf = buffer._uintVData; - - // vertex - for (let i = 0; i < 4; i++) { - let vert = data[i]; - vbuf[vertexOffset++] = vert.x; - vbuf[vertexOffset++] = vert.y; - vbuf[vertexOffset++] = vert.u; - vbuf[vertexOffset++] = vert.v; - uintbuf[vertexOffset++] = color; - } + let ibuf = buffer._iData; + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; } }; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js similarity index 82% rename from cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js index ada3e2f5381..4e35b95ddca 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js @@ -23,7 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); +const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { useModel: false, @@ -34,7 +35,7 @@ module.exports = { updateRenderData (sprite) { let frame = sprite.spriteFrame; - + // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here if (frame) { @@ -53,7 +54,7 @@ module.exports = { if (renderData.vertexCount !== vertices.x.length) { renderData.vertexCount = vertices.x.length; renderData.indiceCount = vertices.triangles.length; - + // 1 for world vertices, 2 for local vertices renderData.dataLength = renderData.vertexCount * 2; @@ -73,11 +74,6 @@ module.exports = { }, updateUVs (sprite) { - let material = sprite.getMaterial(); - let texture = material.effect.getProperty('texture'); - let texw = texture._width, - texh = texture._height; - let vertices = sprite.spriteFrame.vertices, u = vertices.nu, v = vertices.nv; @@ -112,28 +108,28 @@ module.exports = { offsetY = frame._offset.y, trimX = offsetX + (originalWidth - rectWidth) / 2, trimY = offsetY + (originalHeight - rectHeight) / 2; - - let scaleX = contentWidth / (sprite.trim ? rectWidth : originalWidth), + + let scaleX = contentWidth / (sprite.trim ? rectWidth : originalWidth), scaleY = contentHeight / (sprite.trim ? rectHeight : originalHeight); let renderData = sprite._renderData; let data = renderData._data; - + if (!sprite.trim) { for (let i = 0, l = x.length; i < l; i++) { - let vertice = data[i+l]; + let vertice = data[i + l]; vertice.x = (x[i]) * scaleX - appx; vertice.y = (originalHeight - y[i]) * scaleY - appy; } } else { for (let i = 0, l = x.length; i < l; i++) { - let vertice = data[i+l]; + let vertice = data[i + l]; vertice.x = (x[i] - trimX) * scaleX - appx; vertice.y = (originalHeight - y[i] - trimY) * scaleY - appy; } } - + renderData.vertDirty = false; }, @@ -141,12 +137,13 @@ module.exports = { let node = sprite.node, renderData = sprite._renderData, data = renderData._data; + let matrix = node._worldMatrix; + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - for (let i = 0, l = renderData.vertexCount; i < l; i++) { - let local = data[i+l]; + let local = data[i + l]; let world = data[i]; world.x = local.x * a + local.y * c + tx; world.y = local.x * b + local.y * d + ty; @@ -154,46 +151,27 @@ module.exports = { }, fillBuffers (sprite, renderer) { - let node = sprite.node, - color = node._color._val, - renderData = sprite._renderData, - data = renderData._data; - let vertices = sprite.spriteFrame.vertices; if (!vertices) { return; } - + // update world verts if (renderer.worldMatDirty) { this.updateWorldVerts(sprite); } // buffer - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2; - - let indiceOffset = buffer.indiceOffset, + let buffer = renderer._meshBuffer3D, + indiceOffset = buffer.indiceOffset, vertexId = buffer.vertexOffset; - buffer.request(renderData.vertexCount, renderData.indiceCount); + let node = sprite.node; + fillVerticesWithoutCalc(node, buffer, sprite._renderData, node._color._val); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - uintbuf = buffer._uintVData, - ibuf = buffer._iData; - - for (let i = 0, l = renderData.vertexCount; i < l; i++) { - let vertice = data[i]; - vbuf[vertexOffset++] = vertice.x; - vbuf[vertexOffset++] = vertice.y; - vbuf[vertexOffset++] = vertice.u; - vbuf[vertexOffset++] = vertice.v; - uintbuf[vertexOffset++] = color; - } - + let ibuf = buffer._iData; let triangles = vertices.triangles; - for (let i = 0, l = triangles.length; i < l; i++) { ibuf[indiceOffset++] = vertexId + triangles[i]; } diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js new file mode 100644 index 00000000000..88ed36b8fb1 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js @@ -0,0 +1,339 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); +const fillVertices = require('../../utils').fillVertices; + +const PI_2 = Math.PI * 2; + + +let _vertPos = [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)]; +let _vertices = [0, 0, 0, 0]; +let _uvs = [0, 0, 0, 0, 0, 0, 0, 0]; +let _intersectPoint_1 = [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)]; +let _intersectPoint_2 = [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)]; +let _center = cc.v2(0, 0); +let _triangles = []; + +function _calcInsectedPoints (left, right, bottom, top, center, angle, intersectPoints) { + //left bottom, right, top + let sinAngle = Math.sin(angle); + let cosAngle = Math.cos(angle); + let tanAngle, cotAngle; + if (Math.cos(angle) !== 0) { + tanAngle = sinAngle / cosAngle; + //calculate right and left + if ((left - center.x) * cosAngle > 0) { + let yleft = center.y + tanAngle * (left - center.x); + intersectPoints[0].x = left; + intersectPoints[0].y = yleft; + } + if ((right - center.x) * cosAngle > 0) { + let yright = center.y + tanAngle * (right - center.x); + + intersectPoints[2].x = right; + intersectPoints[2].y = yright; + } + + } + + if (Math.sin(angle) !== 0) { + cotAngle = cosAngle / sinAngle; + //calculate top and bottom + if ((top - center.y) * sinAngle > 0) { + let xtop = center.x + cotAngle * (top - center.y); + intersectPoints[3].x = xtop; + intersectPoints[3].y = top; + } + if ((bottom - center.y) * sinAngle > 0) { + let xbottom = center.x + cotAngle * (bottom - center.y); + intersectPoints[1].x = xbottom; + intersectPoints[1].y = bottom; + } + + } +} + +function _calculateVertices (sprite) { + let node = sprite.node, + width = node.width, height = node.height, + appx = node.anchorX * width, appy = node.anchorY * height; + + let l = -appx, b = -appy, + r = width - appx, t = height - appy; + + let vertices = _vertices; + vertices[0] = l; + vertices[1] = b; + vertices[2] = r; + vertices[3] = t; + + let fillCenter = sprite._fillCenter, + cx = _center.x = Math.min(Math.max(0, fillCenter.x), 1) * (r - l) + l, + cy = _center.y = Math.min(Math.max(0, fillCenter.y), 1) * (t - b) + b; + + _vertPos[0].x = _vertPos[3].x = l; + _vertPos[1].x = _vertPos[2].x = r; + _vertPos[0].y = _vertPos[1].y = b; + _vertPos[2].y = _vertPos[3].y = t; + + _triangles.length = 0; + if (cx !== vertices[0]) { + _triangles[0] = [3, 0]; + } + if (cx !== vertices[2]) { + _triangles[2] = [1, 2]; + } + if (cy !== vertices[1]) { + _triangles[1] = [0, 1]; + } + if (cy !== vertices[3]) { + _triangles[3] = [2, 3]; + } +} + +function _calculateUVs (spriteFrame) { + let atlasWidth = spriteFrame._texture.width; + let atlasHeight = spriteFrame._texture.height; + let textureRect = spriteFrame._rect; + + let u0, u1, v0, v1; + let uvs = _uvs; + + if (spriteFrame._rotated) { + u0 = (textureRect.x) / atlasWidth; + u1 = (textureRect.x + textureRect.height) / atlasWidth; + + v0 = (textureRect.y) / atlasHeight; + v1 = (textureRect.y + textureRect.width) / atlasHeight; + + uvs[0] = uvs[2] = u0; + uvs[4] = uvs[6] = u1; + uvs[3] = uvs[7] = v1; + uvs[1] = uvs[5] = v0; + } + else { + u0 = (textureRect.x) / atlasWidth; + u1 = (textureRect.x + textureRect.width) / atlasWidth; + + v0 = (textureRect.y) / atlasHeight; + v1 = (textureRect.y + textureRect.height) / atlasHeight; + + uvs[0] = uvs[4] = u0; + uvs[2] = uvs[6] = u1; + uvs[1] = uvs[3] = v1; + uvs[5] = uvs[7] = v0; + } +} + +function _getVertAngle (start, end) { + let placementX, placementY; + placementX = end.x - start.x; + placementY = end.y - start.y; + + if (placementX === 0 && placementY === 0) { + return undefined; + } else if (placementX === 0) { + if (placementY > 0) { + return Math.PI * 0.5; + } else { + return Math.PI * 1.5; + } + } else { + let angle = Math.atan(placementY / placementX); + if (placementX < 0) { + angle += Math.PI; + } + + return angle; + } +} + +function _generateTriangle (data, offset, vert0, vert1, vert2) { + let vertices = _vertices; + let v0x = vertices[0]; + let v0y = vertices[1]; + let v1x = vertices[2]; + let v1y = vertices[3]; + + data[offset].x = vert0.x; + data[offset].y = vert0.y; + data[offset + 1].x = vert1.x; + data[offset + 1].y = vert1.y; + data[offset + 2].x = vert2.x; + data[offset + 2].y = vert2.y; + + let progressX, progressY; + progressX = (vert0.x - v0x) / (v1x - v0x); + progressY = (vert0.y - v0y) / (v1y - v0y); + _generateUV(progressX, progressY, data, offset); + + progressX = (vert1.x - v0x) / (v1x - v0x); + progressY = (vert1.y - v0y) / (v1y - v0y); + _generateUV(progressX, progressY, data, offset + 1); + + progressX = (vert2.x - v0x) / (v1x - v0x); + progressY = (vert2.y - v0y) / (v1y - v0y); + _generateUV(progressX, progressY, data, offset + 2); +} + +function _generateUV (progressX, progressY, data, offset) { + let uvs = _uvs; + let px1 = uvs[0] + (uvs[2] - uvs[0]) * progressX; + let px2 = uvs[4] + (uvs[6] - uvs[4]) * progressX; + let py1 = uvs[1] + (uvs[3] - uvs[1]) * progressX; + let py2 = uvs[5] + (uvs[7] - uvs[5]) * progressX; + let uv = data[offset]; + uv.u = px1 + (px2 - px1) * progressY; + uv.v = py1 + (py2 - py1) * progressY; +} + +module.exports = { + useModel: false, + + createData (sprite) { + return sprite.requestRenderData(); + }, + + updateRenderData (sprite) { + let frame = sprite.spriteFrame; + + // TODO: Material API design and export from editor could affect the material activation process + // need to update the logic here + if (frame) { + if (!frame._original && dynamicAtlasManager) { + dynamicAtlasManager.insertSpriteFrame(frame); + } + if (sprite._material._texture !== frame._texture) { + sprite._activateMaterial(); + } + } + + let renderData = sprite._renderData; + if (renderData && frame) { + if (renderData.vertDirty || renderData.uvDirty) { + let data = renderData._data; + + let fillStart = sprite._fillStart; + let fillRange = sprite._fillRange; + if (fillRange < 0) { + fillStart += fillRange; + fillRange = -fillRange; + } + + //do round fill start [0,1), include 0, exclude 1 + while (fillStart >= 1.0) fillStart -= 1.0; + while (fillStart < 0.0) fillStart += 1.0; + + fillStart *= PI_2; + fillRange *= PI_2; + let fillEnd = fillStart + fillRange; + + //build vertices + _calculateVertices(sprite); + //build uvs + _calculateUVs(frame); + + _calcInsectedPoints(_vertices[0], _vertices[2], _vertices[1], _vertices[3], _center, fillStart, _intersectPoint_1); + _calcInsectedPoints(_vertices[0], _vertices[2], _vertices[1], _vertices[3], _center, fillStart + fillRange, _intersectPoint_2); + + let offset = 0; + for (let triangleIndex = 0; triangleIndex < 4; ++triangleIndex) { + let triangle = _triangles[triangleIndex]; + if (!triangle) { + continue; + } + //all in + if (fillRange >= PI_2) { + renderData.dataLength = offset + 3; + _generateTriangle(data, offset, _center, _vertPos[triangle[0]], _vertPos[triangle[1]]); + offset += 3; + continue; + } + //test against + let startAngle = _getVertAngle(_center, _vertPos[triangle[0]]); + let endAngle = _getVertAngle(_center, _vertPos[triangle[1]]); + if (endAngle < startAngle) endAngle += PI_2; + startAngle -= PI_2; + endAngle -= PI_2; + //testing + for (let testIndex = 0; testIndex < 3; ++testIndex) { + if (startAngle >= fillEnd) { + //all out + } else if (startAngle >= fillStart) { + renderData.dataLength = offset + 3; + if (endAngle >= fillEnd) { + //startAngle to fillEnd + _generateTriangle(data, offset, _center, _vertPos[triangle[0]], _intersectPoint_2[triangleIndex]); + } else { + //startAngle to endAngle + _generateTriangle(data, offset, _center, _vertPos[triangle[0]], _vertPos[triangle[1]]); + } + offset += 3; + } else { + //startAngle < fillStart + if (endAngle <= fillStart) { + //all out + } else if (endAngle <= fillEnd) { + renderData.dataLength = offset + 3; + //fillStart to endAngle + _generateTriangle(data, offset, _center, _intersectPoint_1[triangleIndex], _vertPos[triangle[1]]); + offset += 3; + } else { + renderData.dataLength = offset + 3; + //fillStart to fillEnd + _generateTriangle(data, offset, _center, _intersectPoint_1[triangleIndex], _intersectPoint_2[triangleIndex]); + offset += 3; + } + } + //add 2 * PI + startAngle += PI_2; + endAngle += PI_2; + } + } + + renderData.indiceCount = renderData.vertexCount = offset; + renderData.vertDirty = renderData.uvDirty = false; + } + } + }, + + fillBuffers (comp, renderer) { + let node = comp.node, + color = node._color._val, + buffer = renderer._meshBuffer, + renderData = comp._renderData; + + let indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + fillVertices(node, buffer, renderData, color); + + // buffer data may be realloc, need get reference after request. + let ibuf = buffer._iData; + for (let i = 0; i < renderData.dataLength; i++) { + ibuf[indiceOffset + i] = vertexId + i; + } + }, +}; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js similarity index 79% rename from cocos2d/core/renderer/webgl/assemblers/sprite/simple.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js index e4e50878b4c..3cd5ceaf787 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js @@ -23,14 +23,14 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { useModel: false, - + updateRenderData (sprite) { let frame = sprite._spriteFrame; - + // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here if (frame) { @@ -54,17 +54,15 @@ module.exports = { let data = sprite._renderData._data, node = sprite.node, color = node._color._val, - matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - + matrix = node._worldMatrix; + let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, indiceOffset = buffer.indiceOffset, vertexId = buffer.vertexOffset; buffer.request(4, 6); - + // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, uintbuf = buffer._uintVData, @@ -72,19 +70,21 @@ module.exports = { // get uv from sprite frame directly let uv = sprite._spriteFrame.uv; - vbuf[vertexOffset+2] = uv[0]; - vbuf[vertexOffset+3] = uv[1]; - vbuf[vertexOffset+7] = uv[2]; - vbuf[vertexOffset+8] = uv[3]; - vbuf[vertexOffset+12] = uv[4]; - vbuf[vertexOffset+13] = uv[5]; - vbuf[vertexOffset+17] = uv[6]; - vbuf[vertexOffset+18] = uv[7]; + vbuf[vertexOffset + 2] = uv[0]; + vbuf[vertexOffset + 3] = uv[1]; + vbuf[vertexOffset + 7] = uv[2]; + vbuf[vertexOffset + 8] = uv[3]; + vbuf[vertexOffset + 12] = uv[4]; + vbuf[vertexOffset + 13] = uv[5]; + vbuf[vertexOffset + 17] = uv[6]; + vbuf[vertexOffset + 18] = uv[7]; let data0 = data[0], data3 = data[3], vl = data0.x, vr = data3.x, vb = data0.y, vt = data3.y; + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + tx = matrix.m12, ty = matrix.m13; let al = a * vl, ar = a * vr, bl = b * vl, br = b * vr, cb = c * vb, ct = c * vt, @@ -92,28 +92,30 @@ module.exports = { // left bottom vbuf[vertexOffset] = al + cb + tx; - vbuf[vertexOffset+1] = bl + db + ty; + vbuf[vertexOffset + 1] = bl + db + ty; // right bottom - vbuf[vertexOffset+5] = ar + cb + tx; - vbuf[vertexOffset+6] = br + db + ty; + vbuf[vertexOffset + 5] = ar + cb + tx; + vbuf[vertexOffset + 6] = br + db + ty; // left top - vbuf[vertexOffset+10] = al + ct + tx; - vbuf[vertexOffset+11] = bl + dt + ty; + vbuf[vertexOffset + 10] = al + ct + tx; + vbuf[vertexOffset + 11] = bl + dt + ty; // right top - vbuf[vertexOffset+15] = ar + ct + tx; - vbuf[vertexOffset+16] = br + dt + ty; + vbuf[vertexOffset + 15] = ar + ct + tx; + vbuf[vertexOffset + 16] = br + dt + ty; + // color - uintbuf[vertexOffset+4] = color; - uintbuf[vertexOffset+9] = color; - uintbuf[vertexOffset+14] = color; - uintbuf[vertexOffset+19] = color; + uintbuf[vertexOffset + 4] = color; + uintbuf[vertexOffset + 9] = color; + uintbuf[vertexOffset + 14] = color; + uintbuf[vertexOffset + 19] = color; + // fill indice data ibuf[indiceOffset++] = vertexId; - ibuf[indiceOffset++] = vertexId+1; - ibuf[indiceOffset++] = vertexId+2; - ibuf[indiceOffset++] = vertexId+1; - ibuf[indiceOffset++] = vertexId+3; - ibuf[indiceOffset++] = vertexId+2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; }, createData (sprite) { @@ -152,7 +154,7 @@ module.exports = { r = cw + trimRight * scaleX - appx; t = ch + trimTop * scaleY - appy; } - + data[0].x = l; data[0].y = b; // data[1].x = r; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js similarity index 92% rename from cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js index 821aa6bcc25..dccc3a79062 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { useModel: false, @@ -41,7 +41,7 @@ module.exports = { updateRenderData (sprite, batchData) { let frame = sprite.spriteFrame; - + // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here if (frame) { @@ -62,20 +62,20 @@ module.exports = { } } }, - + updateVerts (sprite) { let renderData = sprite._renderData, data = renderData._data, node = sprite.node, width = node.width, height = node.height, appx = node.anchorX * width, appy = node.anchorY * height; - + let frame = sprite.spriteFrame; let leftWidth = frame.insetLeft; let rightWidth = frame.insetRight; let topHeight = frame.insetTop; let bottomHeight = frame.insetBottom; - + let sizableWidth = width - leftWidth - rightWidth; let sizableHeight = height - topHeight - bottomHeight; let xScale = width / (leftWidth + rightWidth); @@ -84,7 +84,7 @@ module.exports = { yScale = (isNaN(yScale) || yScale > 1) ? 1 : yScale; sizableWidth = sizableWidth < 0 ? 0 : sizableWidth; sizableHeight = sizableHeight < 0 ? 0 : sizableHeight; - + data[0].x = -appx; data[0].y = -appy; data[1].x = leftWidth * xScale - appx; @@ -114,7 +114,7 @@ module.exports = { vertexId = buffer.vertexOffset; let uvSliced = sprite.spriteFrame.uvSliced; - + buffer.request(vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. @@ -135,7 +135,7 @@ module.exports = { for (let r = 0; r < 3; ++r) { for (let c = 0; c < 3; ++c) { - let start = vertexId + r*4 + c; + let start = vertexId + r * 4 + c; ibuf[indiceOffset++] = start; ibuf[indiceOffset++] = start + 1; ibuf[indiceOffset++] = start + 4; @@ -149,18 +149,18 @@ module.exports = { updateWorldVerts (sprite) { let node = sprite.node, data = sprite._renderData._data; - - let matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + + let matrix = node._worldMatrix; + + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - for (let row = 0; row < 4; ++row) { let rowD = data[row]; for (let col = 0; col < 4; ++col) { let colD = data[col]; - let world = data[4 + row*4 + col]; - world.x = colD.x*a + rowD.y*c + tx; - world.y = colD.x*b + rowD.y*d + ty; + let world = data[4 + row * 4 + col]; + world.x = colD.x * a + rowD.y * c + tx; + world.y = colD.x * b + rowD.y * d + ty; } } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js similarity index 71% rename from cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js index 55d0cf7b49d..f38d7e11852 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js @@ -23,10 +23,14 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { useModel: false, + + vertexOffset: 5, + uvOffset: 2, + colorOffset: 4, createData (sprite) { return sprite.requestRenderData(); @@ -51,18 +55,14 @@ module.exports = { !(renderData.uvDirty || renderData.vertDirty)) return; - let texture = frame._texture; - let texw = texture.width, - texh = texture.height, - rect = frame._rect; - let node = sprite.node, contentWidth = Math.abs(node.width), contentHeight = Math.abs(node.height), appx = node.anchorX * contentWidth, appy = node.anchorY * contentHeight; - let rectWidth = rect.width, + let rect = frame._rect, + rectWidth = rect.width, rectHeight = rect.height, hRepeat = contentWidth / rectWidth, vRepeat = contentHeight / rectHeight, @@ -86,17 +86,48 @@ module.exports = { renderData.vertDirty = false; }, + fillVertices (vbuf, vertexOffset, matrix, row, col, data) { + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + tx = matrix.m12, ty = matrix.m13; + + let x, x1, y, y1; + for (let yindex = 0, ylength = row; yindex < ylength; ++yindex) { + y = data[yindex].y; + y1 = data[yindex+1].y; + for (let xindex = 0, xlength = col; xindex < xlength; ++xindex) { + x = data[xindex].x; + x1 = data[xindex+1].x; + + // Vertex + // lb + vbuf[vertexOffset] = x * a + y * c + tx; + vbuf[vertexOffset+1] = x * b + y * d + ty; + // rb + vbuf[vertexOffset+5] = x1 * a + y * c + tx; + vbuf[vertexOffset+6] = x1 * b + y * d + ty; + // lt + vbuf[vertexOffset+10] = x * a + y1 * c + tx; + vbuf[vertexOffset+11] = x * b + y1 * d + ty; + // rt + vbuf[vertexOffset+15] = x1 * a + y1 * c + tx; + vbuf[vertexOffset+16] = x1 * b + y1 * d + ty; + + vertexOffset += 20; + } + } + }, + fillBuffers (sprite, renderer) { let node = sprite.node, + is3DNode = node.is3DNode, color = node._color._val, renderData = sprite._renderData, data = renderData._data; // buffer - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2; - - let indiceOffset = buffer.indiceOffset, + let buffer = is3DNode ? renderer._meshBuffer3D : renderer._meshBuffer, + vertexOffset = buffer.byteOffset >> 2, + indiceOffset = buffer.indiceOffset, vertexId = buffer.vertexOffset; buffer.request(renderData.vertexCount, renderData.indiceCount); @@ -117,68 +148,54 @@ module.exports = { col = Math.ceil(hRepeat); let matrix = node._worldMatrix; - let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; + + this.fillVertices(vbuf, vertexOffset, matrix, row, col, data); - let x, x1, y, y1, coefu, coefv; + let offset = this.vertexOffset, uvOffset = this.uvOffset, colorOffset = this.colorOffset; + let offset1 = offset, offset2 = offset*2, offset3 = offset*3, offset4 = offset*4; + let coefu, coefv; for (let yindex = 0, ylength = row; yindex < ylength; ++yindex) { - y = data[yindex].y; - y1 = data[yindex+1].y; coefv = Math.min(1, vRepeat - yindex); for (let xindex = 0, xlength = col; xindex < xlength; ++xindex) { coefu = Math.min(1, hRepeat - xindex); - x = data[xindex].x; - x1 = data[xindex+1].x; - - // Vertex - // lb - vbuf[vertexOffset] = x * a + y * c + tx; - vbuf[vertexOffset+1] = x * b + y * d + ty; - // rb - vbuf[vertexOffset+5] = x1 * a + y * c + tx; - vbuf[vertexOffset+6] = x1 * b + y * d + ty; - // lt - vbuf[vertexOffset+10] = x * a + y1 * c + tx; - vbuf[vertexOffset+11] = x * b + y1 * d + ty; - // rt - vbuf[vertexOffset+15] = x1 * a + y1 * c + tx; - vbuf[vertexOffset+16] = x1 * b + y1 * d + ty; + let vertexOffsetU = vertexOffset + uvOffset; + let vertexOffsetV = vertexOffsetU + 1; // UV if (rotated) { // lb - vbuf[vertexOffset+2] = uv[0]; - vbuf[vertexOffset+3] = uv[1]; + vbuf[vertexOffsetU] = uv[0]; + vbuf[vertexOffsetV] = uv[1]; // rb - vbuf[vertexOffset+7] = uv[0]; - vbuf[vertexOffset+8] = uv[1] + (uv[7] - uv[1]) * coefu; + vbuf[vertexOffsetU+offset1] = uv[0]; + vbuf[vertexOffsetV+offset1] = uv[1] + (uv[7] - uv[1]) * coefu; // lt - vbuf[vertexOffset+12] = uv[0] + (uv[6] - uv[0]) * coefv; - vbuf[vertexOffset+13] = uv[1]; + vbuf[vertexOffsetU+offset2] = uv[0] + (uv[6] - uv[0]) * coefv; + vbuf[vertexOffsetV+offset2] = uv[1]; // rt - vbuf[vertexOffset+17] = vbuf[vertexOffset+12]; - vbuf[vertexOffset+18] = vbuf[vertexOffset+8]; + vbuf[vertexOffsetU+offset3] = vbuf[vertexOffsetU+offset2]; + vbuf[vertexOffsetV+offset3] = vbuf[vertexOffsetV+offset1]; } else { // lb - vbuf[vertexOffset+2] = uv[0]; - vbuf[vertexOffset+3] = uv[1]; + vbuf[vertexOffsetU] = uv[0]; + vbuf[vertexOffsetV] = uv[1]; // rb - vbuf[vertexOffset+7] = uv[0] + (uv[6] - uv[0]) * coefu; - vbuf[vertexOffset+8] = uv[1]; + vbuf[vertexOffsetU+offset1] = uv[0] + (uv[6] - uv[0]) * coefu; + vbuf[vertexOffsetV+offset1] = uv[1]; // lt - vbuf[vertexOffset+12] = uv[0]; - vbuf[vertexOffset+13] = uv[1] + (uv[7] - uv[1]) * coefv; + vbuf[vertexOffsetU+offset2] = uv[0]; + vbuf[vertexOffsetV+offset2] = uv[1] + (uv[7] - uv[1]) * coefv; // rt - vbuf[vertexOffset+17] = vbuf[vertexOffset+7]; - vbuf[vertexOffset+18] = vbuf[vertexOffset+13]; + vbuf[vertexOffsetU+offset3] = vbuf[vertexOffsetU+offset1]; + vbuf[vertexOffsetV+offset3] = vbuf[vertexOffsetV+offset2]; } // color - uintbuf[vertexOffset+4] = color; - uintbuf[vertexOffset+9] = color; - uintbuf[vertexOffset+14] = color; - uintbuf[vertexOffset+19] = color; - vertexOffset += 20; + uintbuf[vertexOffset+colorOffset] = color; + uintbuf[vertexOffset+colorOffset+offset1] = color; + uintbuf[vertexOffset+colorOffset+offset2] = color; + uintbuf[vertexOffset+colorOffset+offset3] = color; + vertexOffset += offset4; } } diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/bar-filled.js new file mode 100644 index 00000000000..a43ce15a631 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/bar-filled.js @@ -0,0 +1,67 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/bar-filled'); +const fillVerticesWithoutCalc3D = require('../../utils').fillVerticesWithoutCalc3D; + +const vec3 = cc.vmath.vec3; + +module.exports = js.addon({ + updateWorldVerts (sprite) { + let node = sprite.node, + data = sprite._renderData._data; + + let matrix = node._worldMatrix; + for (let i = 0; i < 4; i++) { + let local = data[i + 4]; + let world = data[i]; + vec3.transformMat4(world, local, matrix); + } + }, + + fillBuffers (sprite, renderer) { + if (renderer.worldMatDirty) { + this.updateWorldVerts(sprite); + } + + // buffer + let buffer = renderer._meshBuffer3D, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + let node = sprite.node; + fillVerticesWithoutCalc3D(node, buffer, sprite._renderData, node._color._val); + + // buffer data may be realloc, need get reference after request. + let ibuf = buffer._iData; + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; + } +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/mesh.js new file mode 100644 index 00000000000..e841de80532 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/mesh.js @@ -0,0 +1,74 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/mesh'); +const fillVerticesWithoutCalc3D = require('../../utils').fillVerticesWithoutCalc3D; + +const vec3 = cc.vmath.vec3; +let vec3_temp = vec3.create(); + +module.exports = js.addon({ + updateWorldVerts (sprite) { + let node = sprite.node, + renderData = sprite._renderData, + data = renderData._data; + + let matrix = node._worldMatrix; + for (let i = 0, l = renderData.vertexCount; i < l; i++) { + let local = data[i + l]; + let world = data[i]; + vec3.set(vec3_temp, local.x, local.y, 0); + vec3.transformMat4(world, vec3_temp, matrix); + } + }, + + fillBuffers (sprite, renderer) { + let vertices = sprite.spriteFrame.vertices; + if (!vertices) { + return; + } + + // update world verts + if (renderer.worldMatDirty) { + this.updateWorldVerts(sprite); + } + + // buffer + let buffer = renderer._meshBuffer3D, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + let node = sprite.node; + fillVerticesWithoutCalc3D(node, buffer, sprite._renderData, node._color._val); + + // buffer data may be realloc, need get reference after request. + let ibuf = buffer._iData; + let triangles = vertices.triangles; + for (let i = 0, l = triangles.length; i < l; i++) { + ibuf[indiceOffset++] = vertexId + triangles[i]; + } + }, +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/radial-filled.js new file mode 100644 index 00000000000..666b2bc2735 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/radial-filled.js @@ -0,0 +1,47 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/radial-filled'); +const fillVertices3D = require('../../utils').fillVertices3D; + +module.exports = js.addon({ + fillBuffers (comp, renderer) { + let node = comp.node, + color = node._color._val, + buffer = renderer._meshBuffer3D, + renderData = comp._renderData; + + let indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + fillVertices3D(node, buffer, renderData, color); + + // buffer data may be realloc, need get reference after request. + let ibuf = buffer._iData; + for (let i = 0; i < renderData.dataLength; i++) { + ibuf[indiceOffset + i] = vertexId + i; + } + }, +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/simple.js new file mode 100644 index 00000000000..46c7efd8b2d --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/simple.js @@ -0,0 +1,89 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/simple'); +const vec3 = cc.vmath.vec3; + +module.exports = js.addon({ + fillBuffers: (function() { + let vec3_temps = []; + for (let i = 0; i < 4; i++) { + vec3_temps.push(vec3.create()); + } + return function (sprite, renderer) { + let data = sprite._renderData._data, + node = sprite.node, + color = node._color._val, + matrix = node._worldMatrix; + + let buffer = renderer._meshBuffer3D, + vertexOffset = buffer.byteOffset >> 2, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + buffer.request(4, 6); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData, + ibuf = buffer._iData; + + let data0 = data[0], data3 = data[3]; + vec3.set(vec3_temps[0], data0.x, data0.y, 0); + vec3.set(vec3_temps[1], data3.x, data0.y, 0); + vec3.set(vec3_temps[2], data0.x, data3.y, 0); + vec3.set(vec3_temps[3], data3.x, data3.y, 0); + + // get uv from sprite frame directly + let uv = sprite._spriteFrame.uv; + for (let i = 0; i < 4; i++) { + // vertex + let vertex = vec3_temps[i]; + vec3.transformMat4(vertex, vertex, matrix); + + vbuf[vertexOffset++] = vertex.x; + vbuf[vertexOffset++] = vertex.y; + vbuf[vertexOffset++] = vertex.z; + + // uv + let uvOffset = i * 2; + vbuf[vertexOffset++] = uv[0 + uvOffset]; + vbuf[vertexOffset++] = uv[1 + uvOffset]; + + // color + uintbuf[vertexOffset++] = color; + } + + // fill indice data + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; + }; + })(), +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/sliced.js new file mode 100644 index 00000000000..33b56744d3b --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/sliced.js @@ -0,0 +1,100 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/sliced'); + +const vec3 = cc.vmath.vec3; +const vec3_temp = vec3.create(); + +module.exports = js.addon({ + fillBuffers (sprite, renderer) { + if (renderer.worldMatDirty) { + this.updateWorldVerts(sprite); + } + + let renderData = sprite._renderData, + node = sprite.node, + is3DNode = node.is3DNode, + color = node._color._val, + data = renderData._data; + + let buffer = is3DNode ? renderer._meshBuffer3D : renderer._meshBuffer, + vertexOffset = buffer.byteOffset >> 2, + vertexCount = renderData.vertexCount, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + let uvSliced = sprite.spriteFrame.uvSliced; + + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData, + ibuf = buffer._iData; + + for (let i = 4; i < 20; ++i) { + let vert = data[i]; + let uvs = uvSliced[i - 4]; + + vbuf[vertexOffset++] = vert.x; + vbuf[vertexOffset++] = vert.y; + vbuf[vertexOffset++] = vert.z; + vbuf[vertexOffset++] = uvs.u; + vbuf[vertexOffset++] = uvs.v; + uintbuf[vertexOffset++] = color; + } + + for (let r = 0; r < 3; ++r) { + for (let c = 0; c < 3; ++c) { + let start = vertexId + r * 4 + c; + ibuf[indiceOffset++] = start; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 4; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 5; + ibuf[indiceOffset++] = start + 4; + } + } + }, + + updateWorldVerts (sprite) { + let node = sprite.node, + data = sprite._renderData._data; + + let matrix = node._worldMatrix; + for (let row = 0; row < 4; ++row) { + let rowD = data[row]; + for (let col = 0; col < 4; ++col) { + let colD = data[col]; + let world = data[4 + row * 4 + col]; + + vec3.set(vec3_temp, colD.x, rowD.y, 0); + vec3.transformMat4(world, vec3_temp, matrix); + } + } + }, +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/tiled.js new file mode 100644 index 00000000000..4accfd7af8a --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/tiled.js @@ -0,0 +1,68 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/tiled'); +const vec3 = cc.vmath.vec3; + +module.exports = js.addon({ + vertexOffset: 6, + uvOffset: 3, + colorOffset: 5, + + fillVertices: (function () { + let vec3_temps = []; + for (let i = 0; i < 4; i++) { + vec3_temps.push(vec3.create()); + } + return function (vbuf, vertexOffset, matrix, row, col, data) { + let x, x1, y, y1; + for (let yindex = 0, ylength = row; yindex < ylength; ++yindex) { + y = data[yindex].y; + y1 = data[yindex+1].y; + for (let xindex = 0, xlength = col; xindex < xlength; ++xindex) { + x = data[xindex].x; + x1 = data[xindex+1].x; + + vec3.set(vec3_temps[0], x, y, 0); + vec3.set(vec3_temps[1], x1, y, 0); + vec3.set(vec3_temps[2], x, y1, 0); + vec3.set(vec3_temps[3], x1, y1, 0); + + for (let i = 0; i < 4; i ++) { + let vec3_temp = vec3_temps[i]; + vec3.transformMat4(vec3_temp, vec3_temp, matrix); + let offset = i * 6; + vbuf[vertexOffset + offset] = vec3_temp.x; + vbuf[vertexOffset + offset + 1] = vec3_temp.y; + vbuf[vertexOffset + offset + 2] = vec3_temp.z; + } + + vertexOffset += 24; + } + } + }; + })(), +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/index.js b/cocos2d/core/renderer/webgl/assemblers/sprite/index.js index ea4ddb592d3..367c6cf7452 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/index.js @@ -28,36 +28,44 @@ const Sprite = require('../../../../components/CCSprite'); const SpriteType = Sprite.Type; const FillType = Sprite.FillType; -const simpleRenderUtil = require('./simple'); -const slicedRenderUtil = require('./sliced'); -const tiledRenderUtil = require('./tiled'); -const radialFilledRenderUtil = require('./radial-filled'); -const barFilledRenderUtil = require('./bar-filled'); -const meshRenderUtil = require('./mesh'); +const simpleRenderUtil = require('./2d/simple'); +const slicedRenderUtil = require('./2d/sliced'); +const tiledRenderUtil = require('./2d/tiled'); +const radialFilledRenderUtil = require('./2d/radial-filled'); +const barFilledRenderUtil = require('./2d/bar-filled'); +const meshRenderUtil = require('./2d/mesh'); + +const simpleRenderUtil3D = require('./3d/simple'); +const slicedRenderUtil3D = require('./3d/sliced'); +const tiledRenderUtil3D = require('./3d/tiled'); +const radialFilledRenderUtil3D = require('./3d/radial-filled'); +const barFilledRenderUtil3D = require('./3d/bar-filled'); +const meshRenderUtil3D = require('./3d/mesh'); // Inline all type switch to avoid jit deoptimization during inlined function change let spriteAssembler = { getAssembler (sprite) { - let util = simpleRenderUtil; + let is3DNode = sprite.node.is3DNode; + let util = is3DNode ? simpleRenderUtil3D : simpleRenderUtil; switch (sprite.type) { case SpriteType.SLICED: - util = slicedRenderUtil; + util = is3DNode ? slicedRenderUtil3D : slicedRenderUtil; break; case SpriteType.TILED: - util = tiledRenderUtil; + util = is3DNode ? tiledRenderUtil3D : tiledRenderUtil; break; case SpriteType.FILLED: if (sprite._fillType === FillType.RADIAL) { - util = radialFilledRenderUtil; + util = is3DNode ? radialFilledRenderUtil3D : radialFilledRenderUtil; } else { - util = barFilledRenderUtil; + util = is3DNode ? barFilledRenderUtil3D : barFilledRenderUtil; } break; case SpriteType.MESH: - util = meshRenderUtil; + util = is3DNode ? meshRenderUtil3D : meshRenderUtil; break; } diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js deleted file mode 100644 index 302d203cb6e..00000000000 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ /dev/null @@ -1,367 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 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 dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - -const PI_2 = Math.PI * 2; - -module.exports = { - useModel: false, - - _vertPos: [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)], - _vertices: [0, 0, 0, 0], - _uvs: [0, 0, 0, 0, 0, 0, 0, 0], - _intersectPoint_1: [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)], - _intersectPoint_2: [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)], - _center: cc.v2(0, 0), - _triangles: [], - - createData (sprite) { - return sprite.requestRenderData(); - }, - - updateRenderData (sprite) { - let frame = sprite.spriteFrame; - - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } - - let renderData = sprite._renderData; - if (renderData && frame) { - if (renderData.vertDirty || renderData.uvDirty) { - let data = renderData._data; - - let fillStart = sprite._fillStart; - let fillRange = sprite._fillRange; - if (fillRange < 0) { - fillStart += fillRange; - fillRange = -fillRange; - } - - //do round fill start [0,1), include 0, exclude 1 - while (fillStart >= 1.0) fillStart -= 1.0; - while (fillStart < 0.0) fillStart += 1.0; - - fillStart *= PI_2; - fillRange *= PI_2; - let fillEnd = fillStart + fillRange; - - //build vertices - this._calculateVertices(sprite); - //build uvs - this._calculateUVs(frame); - - let center = this._center; - - let vertPos = this._vertPos, - vertices = this._vertices; - - let triangles = this._triangles; - - this._calcInsectedPoints(vertices[0], vertices[2], vertices[1], vertices[3], center, fillStart, this._intersectPoint_1); - this._calcInsectedPoints(vertices[0], vertices[2], vertices[1], vertices[3], center, fillStart + fillRange, this._intersectPoint_2); - - let offset = 0; - for (let triangleIndex = 0; triangleIndex < 4; ++triangleIndex) { - let triangle = triangles[triangleIndex]; - if (!triangle) { - continue; - } - //all in - if (fillRange >= PI_2) { - renderData.dataLength = offset + 3; - this._generateTriangle(data, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); - offset += 3; - continue; - } - //test against - let startAngle = this._getVertAngle(center, vertPos[triangle[0]]); - let endAngle = this._getVertAngle(center, vertPos[triangle[1]]); - if(endAngle < startAngle) endAngle += PI_2; - startAngle -= PI_2; - endAngle -= PI_2; - //testing - for(let testIndex = 0; testIndex < 3; ++testIndex) { - if(startAngle >= fillEnd) { - //all out - } else if (startAngle >= fillStart) { - renderData.dataLength = offset + 3; - if(endAngle >= fillEnd) { - //startAngle to fillEnd - this._generateTriangle(data, offset, center, vertPos[triangle[0]], this._intersectPoint_2[triangleIndex]); - } else { - //startAngle to endAngle - this._generateTriangle(data, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); - } - offset += 3; - } else { - //startAngle < fillStart - if(endAngle <= fillStart) { - //all out - } else if(endAngle <= fillEnd) { - renderData.dataLength = offset + 3; - //fillStart to endAngle - this._generateTriangle(data, offset, center, this._intersectPoint_1[triangleIndex], vertPos[triangle[1]]); - offset += 3; - } else { - renderData.dataLength = offset + 3; - //fillStart to fillEnd - this._generateTriangle(data, offset, center, this._intersectPoint_1[triangleIndex], this._intersectPoint_2[triangleIndex]); - offset += 3; - } - } - //add 2 * PI - startAngle += PI_2; - endAngle += PI_2; - } - } - - renderData.indiceCount = renderData.vertexCount = offset; - renderData.vertDirty = renderData.uvDirty = false; - } - } - }, - - _getVertAngle: function(start, end) { - let placementX, placementY; - placementX = end.x - start.x; - placementY = end.y - start.y; - - if(placementX === 0 && placementY === 0) { - return undefined; - } else if(placementX === 0) { - if(placementY > 0) { - return Math.PI * 0.5; - } else { - return Math.PI * 1.5; - } - } else { - let angle = Math.atan(placementY / placementX); - if(placementX < 0) { - angle += Math.PI; - } - - return angle; - } - }, - - _generateTriangle: function(data, offset, vert0, vert1, vert2) { - let vertices = this._vertices; - let v0x = vertices[0]; - let v0y = vertices[1]; - let v1x = vertices[2]; - let v1y = vertices[3]; - - data[offset].x = vert0.x; - data[offset].y = vert0.y; - data[offset+1].x = vert1.x; - data[offset+1].y = vert1.y; - data[offset+2].x = vert2.x; - data[offset+2].y = vert2.y; - - let progressX, progressY; - progressX = (vert0.x - v0x) / (v1x - v0x); - progressY = (vert0.y - v0y) / (v1y - v0y); - this._generateUV(progressX, progressY, data, offset); - - progressX = (vert1.x - v0x) / (v1x - v0x); - progressY = (vert1.y - v0y) / (v1y - v0y); - this._generateUV(progressX, progressY, data, offset + 1); - - progressX = (vert2.x - v0x) / (v1x - v0x); - progressY = (vert2.y - v0y) / (v1y - v0y); - this._generateUV(progressX, progressY, data, offset + 2); - }, - - _generateUV : function(progressX, progressY, data, offset) { - let uvs = this._uvs; - let px1 = uvs[0] + (uvs[2] - uvs[0]) * progressX; - let px2 = uvs[4] + (uvs[6] - uvs[4]) * progressX; - let py1 = uvs[1] + (uvs[3] - uvs[1]) * progressX; - let py2 = uvs[5] + (uvs[7] - uvs[5]) * progressX; - let uv = data[offset]; - uv.u = px1 + (px2 - px1) * progressY; - uv.v = py1 + (py2 - py1) * progressY; - }, - - _calcInsectedPoints: function(left, right, bottom, top, center, angle, intersectPoints) { - //left bottom, right, top - let sinAngle = Math.sin(angle); - let cosAngle = Math.cos(angle); - let tanAngle,cotAngle; - if(Math.cos(angle) !== 0) { - tanAngle = sinAngle / cosAngle; - //calculate right and left - if((left - center.x) * cosAngle > 0) { - let yleft = center.y + tanAngle * (left - center.x); - intersectPoints[0].x = left; - intersectPoints[0].y = yleft; - } - if((right - center.x) * cosAngle > 0) { - let yright = center.y + tanAngle * (right - center.x); - - intersectPoints[2].x = right; - intersectPoints[2].y = yright; - } - - } - - if(Math.sin(angle) !== 0) { - cotAngle = cosAngle / sinAngle; - //calculate top and bottom - if((top - center.y) * sinAngle > 0) { - let xtop = center.x + cotAngle * (top-center.y); - intersectPoints[3].x = xtop; - intersectPoints[3].y = top; - } - if((bottom - center.y) * sinAngle > 0) { - let xbottom = center.x + cotAngle * (bottom-center.y); - intersectPoints[1].x = xbottom; - intersectPoints[1].y = bottom; - } - - } - }, - - _calculateVertices : function (sprite) { - let node = sprite.node, - width = node.width, height = node.height, - appx = node.anchorX * width, appy = node.anchorY * height; - - let l = -appx, b = -appy, - r = width-appx, t = height-appy; - - let vertices = this._vertices; - vertices[0] = l; - vertices[1] = b; - vertices[2] = r; - vertices[3] = t; - - let center = this._center, - fillCenter = sprite._fillCenter, - cx = center.x = Math.min(Math.max(0, fillCenter.x), 1) * (r-l) + l, - cy = center.y = Math.min(Math.max(0, fillCenter.y), 1) * (t-b) + b; - - let vertPos = this._vertPos; - vertPos[0].x = vertPos[3].x = l; - vertPos[1].x = vertPos[2].x = r; - vertPos[0].y = vertPos[1].y = b; - vertPos[2].y = vertPos[3].y = t; - - let triangles = this._triangles; - triangles.length = 0; - if(cx !== vertices[0]) { - triangles[0] = [3, 0]; - } - if(cx !== vertices[2]) { - triangles[2] = [1, 2]; - } - if(cy !== vertices[1]) { - triangles[1] = [0, 1]; - } - if(cy !== vertices[3]) { - triangles[3] = [2, 3]; - } - }, - - _calculateUVs : function (spriteFrame) { - let atlasWidth = spriteFrame._texture.width; - let atlasHeight = spriteFrame._texture.height; - let textureRect = spriteFrame._rect; - - let u0, u1, v0, v1; - let uvs = this._uvs; - - if (spriteFrame._rotated) { - u0 = (textureRect.x) / atlasWidth; - u1 = (textureRect.x + textureRect.height) / atlasWidth; - - v0 = (textureRect.y) / atlasHeight; - v1 = (textureRect.y + textureRect.width) / atlasHeight; - - uvs[0] = uvs[2] = u0; - uvs[4] = uvs[6] = u1; - uvs[3] = uvs[7] = v1; - uvs[1] = uvs[5] = v0; - } - else { - u0 = (textureRect.x) / atlasWidth; - u1 = (textureRect.x + textureRect.width) / atlasWidth; - - v0 = (textureRect.y) / atlasHeight; - v1 = (textureRect.y + textureRect.height) / atlasHeight; - - uvs[0] = uvs[4] = u0; - uvs[2] = uvs[6] = u1; - uvs[1] = uvs[3] = v1; - uvs[5] = uvs[7] = v0; - } - }, - - fillBuffers (sprite, renderer) { - let renderData = sprite._renderData, - data = renderData._data, - node = sprite.node, - color = node._color._val; - - let matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - - // buffer - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, - vbuf = buffer._vData, - uintbuf = buffer._uintVData; - - let ibuf = buffer._iData, - indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; - - buffer.request(renderData.vertexCount, renderData.indiceCount); - - let count = data.length; - for (let i = 0; i < count; i++) { - let vert = data[i]; - vbuf[vertexOffset ++] = vert.x * a + vert.y * c + tx; - vbuf[vertexOffset ++] = vert.x * b + vert.y * d + ty; - vbuf[vertexOffset ++] = vert.u; - vbuf[vertexOffset ++] = vert.v; - uintbuf[vertexOffset ++] = color; - } - - for (let i = 0; i < count; i++) { - ibuf[indiceOffset+i] = vertexId+i; - } - }, -}; diff --git a/cocos2d/core/renderer/webgl/assemblers/utils.js b/cocos2d/core/renderer/webgl/assemblers/utils.js new file mode 100644 index 00000000000..e882620d102 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/utils.js @@ -0,0 +1,103 @@ + +const vec3 = cc.vmath.vec3; +let vec3_temp = vec3.create(); + +function fillVertices (node, buffer, renderData, color) { + let data = renderData._data, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount; + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; + + let matrix = node._worldMatrix; + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + tx = matrix.m12, ty = matrix.m13; + for (let i = 0; i < vertexCount; i++) { + let vert = data[i]; + vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; + vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } +} + +function fillVertices3D (node, buffer, renderData, color) { + let data = renderData._data, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount; + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; + + let matrix = node._worldMatrix; + + for (let i = 0; i < vertexCount; i++) { + let vert = data[i]; + vec3.set(vec3_temp, vert.x, vert.y, 0); + vec3.transformMat4(vec3_temp, vec3_temp, matrix); + vbuf[vertexOffset++] = vec3_temp.x; + vbuf[vertexOffset++] = vec3_temp.y; + vbuf[vertexOffset++] = vec3_temp.z; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } +} + +function fillVerticesWithoutCalc (node, buffer, renderData, color) { + let data = renderData._data, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount; + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; + + for (let i = 0; i < vertexCount; i++) { + let vert = data[i]; + vbuf[vertexOffset++] = vert.x; + vbuf[vertexOffset++] = vert.y; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } +} + +function fillVerticesWithoutCalc3D (node, buffer, renderData, color) { + let data = renderData._data, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount; + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; + + for (let i = 0; i < vertexCount; i++) { + let vert = data[i]; + vbuf[vertexOffset++] = vert.x; + vbuf[vertexOffset++] = vert.y; + vbuf[vertexOffset++] = vert.z; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } +} + +module.exports = { + fillVertices: fillVertices, + fillVertices3D: fillVertices3D, + fillVerticesWithoutCalc: fillVerticesWithoutCalc, + fillVerticesWithoutCalc3D: fillVerticesWithoutCalc3D +}; diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/render-component-walker.js index b4607819121..9bda2aa5ec4 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/render-component-walker.js @@ -23,9 +23,10 @@ THE SOFTWARE. ****************************************************************************/ -const macro = require('../../platform/CCMacro'); const renderEngine = require('../render-engine'); -const defaultVertexFormat = require('./vertex-format').vfmtPosUvColor; +const vertexFormat = require('./vertex-format'); +const defaultVertexFormat = vertexFormat.vfmtPosUvColor; +const vfmt3D = vertexFormat.vfmt3D; const StencilManager = require('./stencil-manager'); const dynamicAtlasManager = require('../utils/dynamic-atlas/manager'); const RenderFlow = require('../render-flow'); @@ -34,17 +35,9 @@ const MeshBuffer = require('./mesh-buffer'); let idGenerater = new (require('../../platform/id-generater'))('VertextFormat'); -const gfx = renderEngine.gfx; const RecyclePool = renderEngine.RecyclePool; const InputAssembler = renderEngine.InputAssembler; -const FLOATS_PER_VERT = defaultVertexFormat._bytes / 4; -const BYTE_PER_INDEX = 2; -const MAX_VERTEX = macro.BATCH_VERTEX_COUNT; -const MAX_VERTEX_BYTES = MAX_VERTEX * defaultVertexFormat._bytes; -const MAX_INDICE = MAX_VERTEX * BYTE_PER_INDEX; -const MAX_INDICE_BYTES = MAX_INDICE * 2; - let _buffers = {}; const empty_material = new renderEngine.Material(); @@ -70,6 +63,8 @@ var RenderComponentWalker = function (device, renderScene) { // buffers this._quadBuffer = this.getBuffer('quad', defaultVertexFormat); this._meshBuffer = this.getBuffer('mesh', defaultVertexFormat); + this._quadBuffer3D = this.getBuffer('quad', vfmt3D); + this._meshBuffer3D = this.getBuffer('mesh', vfmt3D); this._buffer = this._quadBuffer; this._batchedModels = []; From 5a2a53b8449c1cf23c8a8aeacefa35a0b27494db Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Sun, 18 Nov 2018 22:33:44 +0800 Subject: [PATCH 0193/1631] add an optionl parameter to indicate in which folder you want to load asset (#3485) --- cocos2d/core/load-pipeline/CCLoader.js | 68 ++++++++++++++----- .../load-pipeline/released-asset-checker.js | 2 +- cocos2d/core/platform/CCAssetLibrary.js | 29 +++++--- cocos2d/core/platform/url.js | 2 +- 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/cocos2d/core/load-pipeline/CCLoader.js b/cocos2d/core/load-pipeline/CCLoader.js index af36508414c..7caf9210003 100644 --- a/cocos2d/core/load-pipeline/CCLoader.js +++ b/cocos2d/core/load-pipeline/CCLoader.js @@ -36,7 +36,9 @@ var AutoReleaseUtils = require('./auto-release-utils'); // var pushToMap = require('../utils/misc').pushToMap; var ReleasedAssetChecker = CC_DEBUG && require('./released-asset-checker'); -var resources = new AssetTable(); +var assetTables = Object.create(null); +assetTables.assets = new AssetTable(); +assetTables.internal = new AssetTable(); function getXMLHttpRequest () { return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('MSXML2.XMLHTTP'); @@ -327,22 +329,26 @@ proto.flowInDeps = function (owner, urlList, callback) { return accepted; }; -proto._resources = resources; -proto._getResUuid = function (url, type, quiet) { - if (!url) { +proto._assetTables = assetTables; +proto._getResUuid = function (url, type, mount, quiet) { + mount = mount || 'assets'; + + var assetTable = assetTables[mount]; + if (!url || !assetTable) { return null; } + // Ignore parameter var index = url.indexOf('?'); if (index !== -1) url = url.substr(0, index); - var uuid = resources.getUuid(url, type); + var uuid = assetTable.getUuid(url, type); if ( !uuid ) { var extname = cc.path.extname(url); if (extname) { // strip extname url = url.slice(0, - extname.length); - uuid = resources.getUuid(url, type); + uuid = assetTable.getUuid(url, type); if (uuid && !quiet) { cc.warnID(4901, url, extname); } @@ -350,6 +356,7 @@ proto._getResUuid = function (url, type, quiet) { } return uuid; }; + // Find the asset's reference id in loader, asset could be asset object, asset uuid or asset url proto._getReferenceKey = function (assetOrUrlOrUuid) { var key; @@ -357,7 +364,7 @@ proto._getReferenceKey = function (assetOrUrlOrUuid) { key = assetOrUrlOrUuid._uuid || null; } else if (typeof assetOrUrlOrUuid === 'string') { - key = this._getResUuid(assetOrUrlOrUuid, null, true) || assetOrUrlOrUuid; + key = this._getResUuid(assetOrUrlOrUuid, null, null, true) || assetOrUrlOrUuid; } if (!key) { cc.warnID(4800, assetOrUrlOrUuid); @@ -456,13 +463,20 @@ proto._parseLoadResArgs = function (type, onProgress, onComplete) { * loadRes(url: string, completeCallback: (error: Error, resource: any) => void): void * loadRes(url: string): void */ -proto.loadRes = function (url, type, progressCallback, completeCallback) { +proto.loadRes = function (url, type, mount, progressCallback, completeCallback) { + if (arguments.length !== 5) { + completeCallback = progressCallback; + progressCallback = mount; + mount = 'assets'; + } + var args = this._parseLoadResArgs(type, progressCallback, completeCallback); type = args.type; progressCallback = args.onProgress; completeCallback = args.onComplete; + var self = this; - var uuid = self._getResUuid(url, type); + var uuid = self._getResUuid(url, type, mount); if (uuid) { this.load( { @@ -573,7 +587,13 @@ proto._loadResUuids = function (uuids, progressCallback, completeCallback, urls) * loadResArray(url: string[]): void * loadResArray(url: string[], type: typeof cc.Asset[]): void */ -proto.loadResArray = function (urls, type, progressCallback, completeCallback) { +proto.loadResArray = function (urls, type, mount, progressCallback, completeCallback) { + if (arguments.length !== 5) { + completeCallback = progressCallback; + progressCallback = mount; + mount = 'assets'; + } + var args = this._parseLoadResArgs(type, progressCallback, completeCallback); type = args.type; progressCallback = args.onProgress; @@ -584,7 +604,7 @@ proto.loadResArray = function (urls, type, progressCallback, completeCallback) { for (var i = 0; i < urls.length; i++) { var url = urls[i]; var assetType = isTypesArray ? type[i] : type; - var uuid = this._getResUuid(url, assetType); + var uuid = this._getResUuid(url, assetType, mount); if (uuid) { uuids.push(uuid); } @@ -647,14 +667,23 @@ proto.loadResArray = function (urls, type, progressCallback, completeCallback) { * loadResDir(url: string, completeCallback: (error: Error, resource: any[], urls: string[]) => void): void * loadResDir(url: string): void */ -proto.loadResDir = function (url, type, progressCallback, completeCallback) { +proto.loadResDir = function (url, type, mount, progressCallback, completeCallback) { + if (arguments.length !== 5) { + completeCallback = progressCallback; + progressCallback = mount; + mount = 'assets'; + } + + if (!assetTables[mount]) return; + var args = this._parseLoadResArgs(type, progressCallback, completeCallback); + type = args.type; progressCallback = args.onProgress; completeCallback = args.onComplete; var urls = []; - var uuids = resources.getUuidArray(url, type, urls); + var uuids = assetTables[mount].getUuidArray(url, type, urls); this._loadResUuids(uuids, progressCallback, function (errors, assetRes, urlRes) { // The spriteFrame url in spriteAtlas will be removed after build project // To show users the exact structure in asset panel, we need to return the spriteFrame assets in spriteAtlas @@ -689,7 +718,7 @@ proto.loadResDir = function (url, type, progressCallback, completeCallback) { proto.getRes = function (url, type) { var item = this._cache[url]; if (!item) { - var uuid = this._getResUuid(url, type, true); + var uuid = this._getResUuid(url, type, null, true); if (uuid) { var ref = this._getReferenceKey(uuid); item = this._cache[ref]; @@ -838,8 +867,8 @@ proto.releaseAsset = function (asset) { * @param {String} url * @param {Function} [type] - Only asset of type will be released if this argument is supplied. */ -proto.releaseRes = function (url, type) { - var uuid = this._getResUuid(url, type); +proto.releaseRes = function (url, type, mount) { + var uuid = this._getResUuid(url, type, mount); if (uuid) { this.release(uuid); } @@ -856,8 +885,11 @@ proto.releaseRes = function (url, type) { * @param {String} url * @param {Function} [type] - Only asset of type will be released if this argument is supplied. */ -proto.releaseResDir = function (url, type) { - var uuids = resources.getUuidArray(url, type); +proto.releaseResDir = function (url, type, mount) { + mount = mount || 'assets'; + if (!assetTables[mount]) return; + + var uuids = assetTables[mount].getUuidArray(url, type); for (var i = 0; i < uuids.length; i++) { var uuid = uuids[i]; this.release(uuid); diff --git a/cocos2d/core/load-pipeline/released-asset-checker.js b/cocos2d/core/load-pipeline/released-asset-checker.js index 195897084aa..48c122e7acc 100644 --- a/cocos2d/core/load-pipeline/released-asset-checker.js +++ b/cocos2d/core/load-pipeline/released-asset-checker.js @@ -48,7 +48,7 @@ function getItemDesc (item) { if (!tmpInfo) { tmpInfo = { path: "", type: null }; } - if (cc.loader._resources._getInfo_DEBUG(item.uuid, tmpInfo)) { + if (cc.loader._assetTables.assets._getInfo_DEBUG(item.uuid, tmpInfo)) { tmpInfo.path = 'resources/' + tmpInfo.path; return `"${tmpInfo.path}" (type: ${js.getClassName(tmpInfo.type)}, uuid: ${item.uuid})`; } diff --git a/cocos2d/core/platform/CCAssetLibrary.js b/cocos2d/core/platform/CCAssetLibrary.js index dcd816203a7..f5a1f8e6073 100644 --- a/cocos2d/core/platform/CCAssetLibrary.js +++ b/cocos2d/core/platform/CCAssetLibrary.js @@ -27,6 +27,7 @@ var Asset = require('../assets/CCAsset'); var callInNextTick = require('./utils').callInNextTick; var Loader = require('../load-pipeline/CCLoader'); +var AssetTable = require('../load-pipeline/asset-table'); var PackDownloader = require('../load-pipeline/pack-downloader'); var AutoReleaseUtils = require('../load-pipeline/auto-release-utils'); var decodeUuid = require('../utils/decode-uuid'); @@ -309,8 +310,11 @@ var AssetLibrary = { // init raw assets - var resources = Loader._resources; - resources.reset(); + var assetTables = Loader._assetTables; + for (var mount in assetTables) { + assetTables[mount].reset(); + } + var rawAssets = options.rawAssets; if (rawAssets) { for (var mountPoint in rawAssets) { @@ -327,16 +331,18 @@ var AssetLibrary = { // backward compatibility since 1.10 _uuidToRawAsset[uuid] = new RawAssetEntry(mountPoint + '/' + url, type); // init resources - if (mountPoint === 'assets') { - var ext = cc.path.extname(url); - if (ext) { - // trim base dir and extname - url = url.slice(0, - ext.length); - } - var isSubAsset = info[2] === 1; - // register - resources.add(url, uuid, type, !isSubAsset); + var ext = cc.path.extname(url); + if (ext) { + // trim base dir and extname + url = url.slice(0, - ext.length); } + + var isSubAsset = info[2] === 1; + if (!assetTables[mountPoint]) { + assetTables[mountPoint] = new AssetTable(); + } + + assetTables[mountPoint].add(url, uuid, type, !isSubAsset); } } } @@ -348,6 +354,7 @@ var AssetLibrary = { // init cc.url cc.url._init((options.mountPaths && options.mountPaths.assets) || _rawAssetsBase + 'assets'); } + }; // unload asset if it is destoryed diff --git a/cocos2d/core/platform/url.js b/cocos2d/core/platform/url.js index 8451781da4e..cec573ecdc5 100644 --- a/cocos2d/core/platform/url.js +++ b/cocos2d/core/platform/url.js @@ -73,7 +73,7 @@ cc.url = { } else { // Compatible with versions lower than 1.10 - var uuid = cc.loader._getResUuid(url.slice(10), cc.Asset, true); + var uuid = cc.loader._getResUuid(url.slice(10), cc.Asset, null, true); if (uuid) { return cc.AssetLibrary.getLibUrlNoExt(uuid, true) + cc.path.extname(url); } From e53ad00c71fec98bfdbf12f9613c18dfe13f3bbe Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 19 Nov 2018 11:43:33 +0800 Subject: [PATCH 0194/1631] improve toggle component (#3450) --- cocos2d/core/components/CCToggle.js | 128 +++++++++---------- cocos2d/core/components/CCToggleContainer.js | 28 +++- cocos2d/core/components/CCToggleGroup.js | 4 +- 3 files changed, 82 insertions(+), 78 deletions(-) diff --git a/cocos2d/core/components/CCToggle.js b/cocos2d/core/components/CCToggle.js index 7a34233182d..4a808b84ed5 100644 --- a/cocos2d/core/components/CCToggle.js +++ b/cocos2d/core/components/CCToggle.js @@ -31,7 +31,7 @@ * @class Toggle * @extends Button */ -var Toggle = cc.Class({ +let Toggle = cc.Class({ name: 'cc.Toggle', extends: require('./CCButton'), editor: CC_EDITOR && { @@ -47,12 +47,34 @@ var Toggle = cc.Class({ * !#zh 如果这个设置为 true,则 check mark 组件会处于 enabled 状态,否则处于 disabled 状态。 * @property {Boolean} isChecked */ + _N$isChecked: true, isChecked: { - default: true, - tooltip: CC_DEV && 'i18n:COMPONENT.toggle.isChecked', - notify: function () { + get: function () { + return this._N$isChecked; + }, + set: function (value) { + if (value === this._N$isChecked) { + return; + } + + var group = this.toggleGroup || this._toggleContainer; + if (group && group.enabled && this._N$isChecked) { + if (!group.allowSwitchOff) { + return; + } + + } + + this._N$isChecked = value; this._updateCheckMark(); - } + + if (group && group.enabled) { + group.updateToggles(this); + } + + this._emitToggleEvents(); + }, + tooltip: CC_DEV && 'i18n:COMPONENT.toggle.isChecked', }, /** @@ -120,6 +142,33 @@ var Toggle = cc.Class({ } }, + _hideCheckMark () { + this._N$isChecked = false; + this._updateCheckMark(); + }, + + toggle: function (event) { + this.isChecked = !this.isChecked; + }, + + /** + * !#en Make the toggle button checked. + * !#zh 使 toggle 按钮处于选中状态 + * @method check + */ + check: function () { + this.isChecked = true; + }, + + /** + * !#en Make the toggle button unchecked. + * !#zh 使 toggle 按钮处于未选中状态 + * @method uncheck + */ + uncheck: function () { + this.isChecked = false; + }, + _updateCheckMark: function () { if (this.checkMark) { this.checkMark.node.active = !!this.isChecked; @@ -147,85 +196,22 @@ var Toggle = cc.Class({ this.node.off('click', this.toggle, this); }, - toggle: function (event) { - var group = this.toggleGroup || this._toggleContainer; - - if (group && group.enabled && this.isChecked) { - if (!group.allowSwitchOff) { - return; - } - } - - this.isChecked = !this.isChecked; - - this._updateCheckMark(); - - if (group && group.enabled) { - group.updateToggles(this); - } - - this._emitToggleEvents(); - }, - _emitToggleEvents: function () { - if (CC_EDITOR) { return; } this.node.emit('toggle', this); if (this.checkEvents) { cc.Component.EventHandler.emitEvents(this.checkEvents, this); } - }, - - /** - * !#en Make the toggle button checked. - * !#zh 使 toggle 按钮处于选中状态 - * @method check - */ - check: function () { - var group = this.toggleGroup || this._toggleContainer; - - if (group && group.enabled && this.isChecked) { - if (!group.allowSwitchOff) { - return; - } - } - - this.isChecked = true; - - if (group && group.enabled) { - group.updateToggles(this); - } - - this._emitToggleEvents(); - }, - - /** - * !#en Make the toggle button unchecked. - * !#zh 使 toggle 按钮处于未选中状态 - * @method uncheck - */ - uncheck: function () { - var group = this.toggleGroup || this._toggleContainer; - - if (group && group.enabled && this.isChecked) { - if (!group.allowSwitchOff) { - return; - } - } - - this.isChecked = false; - - this._emitToggleEvents(); } + }); cc.Toggle = module.exports = Toggle; - -var js = require('../platform/js'); +const js = require('../platform/js'); js.get(Toggle.prototype, '_toggleContainer', function () { - var parent = this.node.parent; + let parent = this.node.parent; if (cc.Node.isNode(parent)) { return parent.getComponent(cc.ToggleContainer); } diff --git a/cocos2d/core/components/CCToggleContainer.js b/cocos2d/core/components/CCToggleContainer.js index ad400d0e108..f7fb2560aaf 100644 --- a/cocos2d/core/components/CCToggleContainer.js +++ b/cocos2d/core/components/CCToggleContainer.js @@ -55,21 +55,39 @@ var ToggleContainer = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.toggle_group.allowSwitchOff', default: false }, + + /** + * !#en If Toggle is clicked, it will trigger event's handler + * !#zh Toggle 按钮的点击事件列表。 + * @property {Component.EventHandler[]} checkEvents + */ + checkEvents: { + default: [], + type: cc.Component.EventHandler + }, }, updateToggles: function (toggle) { - this.toggleItems.forEach(function (item) { - if (toggle.isChecked && item !== toggle) { - item.isChecked = false; + if(!this.enabledInHierarchy) return; + + if (toggle.isChecked) { + this.toggleItems.forEach(function (item) { + if (item !== toggle && item.isChecked && item.enabled) { + item._hideCheckMark(); + } + }); + + if (this.checkEvents) { + cc.Component.EventHandler.emitEvents(this.checkEvents, toggle); } - }); + } }, _allowOnlyOneToggleChecked: function () { var isChecked = false; this.toggleItems.forEach(function (item) { if (isChecked) { - item.isChecked = false; + item._hideCheckMark(); } else if (item.isChecked) { isChecked = true; diff --git a/cocos2d/core/components/CCToggleGroup.js b/cocos2d/core/components/CCToggleGroup.js index 81ffa4397d8..2443e20862e 100644 --- a/cocos2d/core/components/CCToggleGroup.js +++ b/cocos2d/core/components/CCToggleGroup.js @@ -74,7 +74,7 @@ var ToggleGroup = cc.Class({ this._toggleItems.forEach(function (item){ if(toggle.isChecked) { if (item !== toggle && item.isChecked && item.enabled) { - item.isChecked = false; + item._hideCheckMark(); } } }); @@ -100,7 +100,7 @@ var ToggleGroup = cc.Class({ var isChecked = false; this._toggleItems.forEach(function (item) { if(isChecked && item.enabled) { - item.isChecked = false; + item._hideCheckMark(); } if (item.isChecked && item.enabled) { From 454eba43dea7034c48971616820d2025a5981757 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Mon, 19 Nov 2018 11:46:20 +0800 Subject: [PATCH 0195/1631] Advance the modification of the flag to avoid node attribute modification is invalid when opacity === 0. (#3528) --- cocos2d/core/renderer/render-flow.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 98cca2d1f8a..1ca195ce06e 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -118,10 +118,11 @@ _proto._children = function (node) { let children = node._children; for (let i = 0, l = children.length; i < l; i++) { let c = children[i]; + // Advance the modification of the flag to avoid node attribute modification is invalid when opacity === 0. + c._renderFlag |= worldTransformFlag | worldOpacityFlag; if (!c._activeInHierarchy || c._opacity === 0) continue; _cullingMask = c._cullingMask = c.groupIndex === 0 ? cullingMask : 1 << c.groupIndex; - c._renderFlag |= worldTransformFlag | worldOpacityFlag; - + // TODO: Maybe has better way to implement cascade opacity c._color.a = c._opacity * _walker.parentOpacity; flows[c._renderFlag]._func(c); From b9f60bce18f433b3568ccd329ac5342d48796631 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 19 Nov 2018 12:34:07 +0800 Subject: [PATCH 0196/1631] adapter wx.onShow params (#3515) --- cocos2d/core/CCGame.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index ce07b5986d2..a86fb22d42e 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -821,10 +821,11 @@ var game = { game.emit(game.EVENT_HIDE); } } - function onShown () { + // In order to adapt the most of platforms the onshow API. + function onShown (arg0, arg1, arg2, arg3, arg4) { if (hidden) { hidden = false; - game.emit(game.EVENT_SHOW); + game.emit(game.EVENT_SHOW, arg0, arg1, arg2, arg3, arg4); } } From e23918521cca481814715c303fb5f6e08af84627 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 19 Nov 2018 15:56:22 +0800 Subject: [PATCH 0197/1631] fix polyfill-3d scaleZ value err code (#3531) --- cocos2d/core/3d/polyfill-3d.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index c1de43a8ebc..b6cc00b8cd0 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -196,8 +196,8 @@ cc.js.getset(proto, 'is3DNode', function () { cc.js.getset(proto, 'scaleZ', function () { return this._scale.z; }, function (v) { - if (this._scale.z !== value) { - this._scale.z = value; + if (this._scale.z !== v) { + this._scale.z = v; this.setLocalDirty(DirtyFlag.SCALE); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; From 255ae255c5ddbded202c5298c222a2cafc7b11f0 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 19 Nov 2018 16:03:24 +0800 Subject: [PATCH 0198/1631] add click param to CCRichText (#3530) --- cocos2d/core/components/CCRichText.js | 9 ++++++++- cocos2d/core/utils/html-text-parser.js | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index 76fc68ef577..8f587a9cce8 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -373,10 +373,11 @@ let RichText = cc.Class({ for (let i = 0; i < this._labelSegments.length; ++i) { let labelSegment = this._labelSegments[i]; let clickHandler = labelSegment._clickHandler; + let clickParam = labelSegment._clickParam; if (clickHandler && this._containsTouchLocation(labelSegment, event.touch.getLocation())) { components.forEach(function (component) { if (component.enabledInHierarchy && component[clickHandler]) { - component[clickHandler](event); + component[clickHandler](event, clickParam); } }); event.stopPropagation(); @@ -626,6 +627,9 @@ let RichText = cc.Class({ if (richTextElement.style.event.click) { spriteNode._clickHandler = richTextElement.style.event.click; } + if (richTextElement.style.event.param) { + spriteNode._clickParam = richTextElement.style.event.param; + } } } else { @@ -842,6 +846,9 @@ let RichText = cc.Class({ if (textStyle.event.click) { labelNode._clickHandler = textStyle.event.click; } + if (textStyle.event.param) { + labelNode._clickParam = textStyle.event.param; + } } }, diff --git a/cocos2d/core/utils/html-text-parser.js b/cocos2d/core/utils/html-text-parser.js index b1e7fc7611d..7cc70ff07fc 100644 --- a/cocos2d/core/utils/html-text-parser.js +++ b/cocos2d/core/utils/html-text-parser.js @@ -25,7 +25,7 @@ ****************************************************************************/ var eventRegx = /^(click)(\s)*=/; -var imageAttrReg = /(\s)*src(\s)*=|(\s)*height(\s)*=|(\s)*width(\s)*=|(\s)*click(\s)*=/; +var imageAttrReg = /(\s)*src(\s)*=|(\s)*height(\s)*=|(\s)*width(\s)*=|(\s)*click(\s)*=|(\s)*param(\s)*=/; /** * A utils class for parsing HTML texts. The parsed results will be an object array. */ @@ -161,6 +161,11 @@ HtmlTextParser.prototype = { } else if (tagName === "click") { obj.event = this._processEventHandler(tagName + "=" + tagValue); } + + if (obj.event && tagName === 'param') { + obj.event.param = tagValue; + } + header = attribute.match(imageAttrReg); } @@ -178,7 +183,7 @@ HtmlTextParser.prototype = { attribute = header[0].substring("outline".length).trim(); var defaultOutlineObject = {color: "#ffffff", width: 1}; if (attribute) { - var outlineAttrReg = /(\s)*color(\s)*=|(\s)*width(\s)*=|(\s)*click(\s)*=/; + var outlineAttrReg = /(\s)*color(\s)*=|(\s)*width(\s)*=|(\s)*click(\s)*=|(\s)*param(\s)*=/; header = attribute.match(outlineAttrReg); var tagValue; while (header) { @@ -204,6 +209,11 @@ HtmlTextParser.prototype = { } else if (tagName === "width") { defaultOutlineObject.width = parseInt(tagValue); } + + if (obj.event && tagName === 'param') { + obj.event.param = tagValue; + } + header = attribute.match(outlineAttrReg); } } From 3eb90c77efc05a59f119070cb99c25c97a5e50f5 Mon Sep 17 00:00:00 2001 From: leda Date: Tue, 20 Nov 2018 09:54:33 +0800 Subject: [PATCH 0199/1631] restore webview/videoplayer support at creator 2.0.x (#3534) --- cocos2d/videoplayer/CCVideoPlayer.js | 3 ++- cocos2d/webview/CCWebView.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cocos2d/videoplayer/CCVideoPlayer.js b/cocos2d/videoplayer/CCVideoPlayer.js index 99ca1ad2370..f13a518bc8e 100644 --- a/cocos2d/videoplayer/CCVideoPlayer.js +++ b/cocos2d/videoplayer/CCVideoPlayer.js @@ -270,7 +270,8 @@ let VideoPlayer = cc.Class({ statics: { EventType: EventType, - ResourceType: ResourceType + ResourceType: ResourceType, + Impl: VideoPlayerImpl }, ctor () { diff --git a/cocos2d/webview/CCWebView.js b/cocos2d/webview/CCWebView.js index 19b6dedf0ce..a740a2e044a 100644 --- a/cocos2d/webview/CCWebView.js +++ b/cocos2d/webview/CCWebView.js @@ -107,6 +107,7 @@ let WebView = cc.Class({ statics: { EventType: EventType, + Impl: WebViewImpl }, From 23f900d6c85d2fb6a04c00374be809f998323b2a Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 20 Nov 2018 16:57:43 +0800 Subject: [PATCH 0200/1631] add a new prop to layout to controll the scale affect (#3529) --- cocos2d/core/components/CCLayout.js | 50 +++++++++++++++++++++-------- editor/i18n/en/localization.js | 3 +- editor/i18n/zh/localization.js | 3 +- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/cocos2d/core/components/CCLayout.js b/cocos2d/core/components/CCLayout.js index 435675eea94..2670dfd2eda 100644 --- a/cocos2d/core/components/CCLayout.js +++ b/cocos2d/core/components/CCLayout.js @@ -395,6 +395,23 @@ var Layout = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.layout.horizontal_direction', animatable: false }, + + /** + * !#en Adjust the layout if the children scaled. + * !#zh 子节点缩放比例是否影响布局。 + * @property affectedByScale + * @type {Boolean} + * @default false + */ + affectedByScale: { + default: false, + notify: function () { + // every time you switch this state, the layout will be calculated. + this._doLayoutDirty(); + }, + animatable: false, + tooltip: CC_DEV && 'i18n:COMPONENT.layout.affected_by_scale' + } }, statics: { @@ -435,6 +452,10 @@ var Layout = cc.Class({ this._layoutDirty = true; }, + _doScaleDirty: function () { + this._layoutDirty = this._layoutDirty || this.affectedByScale; + }, + _addEventListeners: function () { cc.director.on(cc.Director.EVENT_AFTER_UPDATE, this.updateLayout, this); this.node.on(NodeEvent.SIZE_CHANGED, this._resized, this); @@ -459,10 +480,10 @@ var Layout = cc.Class({ var children = this.node.children; for (var i = 0; i < children.length; ++i) { var child = children[i]; + child.on(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, @@ -471,29 +492,29 @@ var Layout = cc.Class({ var children = this.node.children; for (var i = 0; i < children.length; ++i) { var child = children[i]; + child.off(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, _childAdded: function (child) { + child.on(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); }, _childRemoved: function (child) { + child.off(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); @@ -541,8 +562,8 @@ var Layout = cc.Class({ for (var i = 0; i < children.length; ++i) { var child = children[i]; - let childScaleX = Math.abs(child.scaleX); - let childScaleY = Math.abs(child.scaleY); + let childScaleX = this._getUsedScaleValue(child.scaleX); + let childScaleY = this._getUsedScaleValue(child.scaleY); if (!child.activeInHierarchy) { continue; } @@ -639,7 +660,7 @@ var Layout = cc.Class({ var child = children[i]; if (child.activeInHierarchy) { activeChildCount++; - newHeight += child.height * Math.abs(child.scaleY); + newHeight += child.height * this._getUsedScaleValue(child.scaleY); } } @@ -687,8 +708,8 @@ var Layout = cc.Class({ for (var i = 0; i < children.length; ++i) { var child = children[i]; - let childScaleX = Math.abs(child.scaleX); - let childScaleY = Math.abs(child.scaleY); + let childScaleX = this._getUsedScaleValue(child.scaleX); + let childScaleY = this._getUsedScaleValue(child.scaleY); if (!child.activeInHierarchy) { continue; } @@ -829,7 +850,7 @@ var Layout = cc.Class({ } var fnPositionY = function (child, topOffset, row) { - return bottomBoundaryOfLayout + sign * (topOffset + child.anchorY * child.height * Math.abs(child.scaleY) + paddingY + row * this.spacingY); + return bottomBoundaryOfLayout + sign * (topOffset + child.anchorY * child.height * this._getUsedScaleValue(child.scaleY) + paddingY + row * this.spacingY); }.bind(this); @@ -870,7 +891,7 @@ var Layout = cc.Class({ } var fnPositionX = function (child, leftOffset, column) { - return leftBoundaryOfLayout + sign * (leftOffset + child.anchorX * child.width * Math.abs(child.scaleX) + paddingX + column * this.spacingX); + return leftBoundaryOfLayout + sign * (leftOffset + child.anchorX * child.width * this._getUsedScaleValue(child.scaleX) + paddingX + column * this.spacingX); }.bind(this); var newWidth = 0; @@ -918,7 +939,7 @@ var Layout = cc.Class({ var child = children[i]; if (child.activeInHierarchy) { activeChildCount++; - newWidth += child.width * Math.abs(child.scaleX); + newWidth += child.width * this._getUsedScaleValue(child.scaleX); } } newWidth += (activeChildCount - 1) * this.spacingX + this.paddingLeft + this.paddingRight; @@ -963,6 +984,10 @@ var Layout = cc.Class({ } }, + _getUsedScaleValue (value) { + return this.affectedByScale ? Math.abs(value) : 1; + }, + /** * !#en Perform the layout update * !#zh 立即执行更新布局 @@ -982,7 +1007,6 @@ var Layout = cc.Class({ this._layoutDirty = false; } } - }); /** diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 83440e218b4..3f0fcfb93ed 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -197,7 +197,8 @@ module.exports = { "vertical_direction": "Vertically align in the direction of the child Nodes: \n 1. TOP_TO_BOTTOM, \n 2. BOTTOM_TO_TOP", "horizontal_direction": "Horizontally align in the direction of the child Nodes: \n 1. LEFT_TO_RIGHT \n 2. RIGHT_TO_LEFT", "cell_size": "In Grid layout, the size of each child element.", - "start_axis": "In Grid layout, the arrangement direction of children elements." + "start_axis": "In Grid layout, the arrangement direction of children elements.", + "affected_by_scale": "Whether the scaling of the child node affects the layout." }, "particle": { "export_title": "Export custom particle data to plist file.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 87f41105add..16d684e42f3 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -201,7 +201,8 @@ module.exports = { 'vertical_direction': '垂直排列子节点的方向,包括:\n 1. TOP_TO_BOTTOM, 从上到下排列 \n 2. BOTTOM_TO_TOP, 从下到上排列', 'horizontal_direction': '水平排列子节点的方向,包括:\n 1. LEFT_TO_RIGHT, 从左到右排列 \n 2. RIGHT_TO_LEFT, 从右到左排列', 'cell_size': '网格布局中,规定每一个网格的大小', - 'start_axis': '网格布局中,子物体排版时的起始方向轴,支持水平和垂直两个方向。', + 'start_axis': '网格布局中,子物体排版时的起始方向轴,支持水平和垂直两个方向', + "affected_by_scale": "子节点的缩放是否影响布局" }, 'particle': { 'export_title': "将自定义的粒子数据导出成 plist 文件", From 1a3196185526b664e0ffc5791afde9eb36ead57f Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 20 Nov 2018 21:36:33 +0800 Subject: [PATCH 0201/1631] Adapte to native renderer version 1 --- cocos2d/core/CCNode.js | 5 ++++ cocos2d/core/camera/CCCamera.js | 8 ++++--- cocos2d/core/components/CCLabel.js | 4 ++++ cocos2d/core/components/CCRenderComponent.js | 8 +++---- .../renderer/canvas/renderers/label/bmfont.js | 4 ++-- cocos2d/core/renderer/index.js | 24 ++++++++++++------- cocos2d/core/renderer/render-engine.canvas.js | 2 +- cocos2d/core/renderer/render-engine.js | 2 +- cocos2d/core/renderer/render-engine.jsb.js | 18 ++++---------- cocos2d/core/renderer/utils/label/bmfont.js | 9 ++++--- cocos2d/core/renderer/utils/label/ttf.js | 5 ++-- .../renderer/webgl/assemblers/label/bmfont.js | 3 ++- cocos2d/core/utils/text-utils.js | 2 +- 13 files changed, 51 insertions(+), 43 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 6a1995ef449..6a421e1bf50 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1369,6 +1369,11 @@ let NodeDefines = { if (children.length > 0) { this._renderFlag |= RenderFlow.FLAG_CHILDREN; } + + if (CC_JSB) { + this._proxy.setName(this._name); + this._parent && this._proxy.updateParent(this._parent._proxy); + } }, // the same as _onBatchCreated but untouch prefab diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 2a33b0a3256..42f8a7f8327 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -412,7 +412,9 @@ let Camera = cc.Class({ camera.view = view; camera.dirty = true; - camera._cullingMask = camera.view._cullingMask = 1 << cc.Node.BuiltinGroupIndex.DEBUG; + let mask = 1 << cc.Node.BuiltinGroupIndex.DEBUG; + camera.setCullingMask(mask); + camera.view.cullingMask = mask; camera._sortDepth = cc.macro.MAX_ZINDEX; camera.setClearFlags(0); camera.setColor(0, 0, 0, 0); @@ -430,8 +432,8 @@ let Camera = cc.Class({ _updateCameraMask () { if (this._camera) { let mask = this._cullingMask & (~(1 << cc.Node.BuiltinGroupIndex.DEBUG)); - this._camera._cullingMask = mask; - this._camera.view._cullingMask = mask; + this._camera.setCullingMask(mask); + this._camera.view.cullingMask = mask; } }, diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index b64599d5982..4e25530ef16 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -504,6 +504,7 @@ let Label = cc.Class({ if (!this._renderData) { this._renderData = this._assembler.createData(this); + this._renderData.material = this._material; } if (CC_JSB) { @@ -567,6 +568,9 @@ let Label = cc.Class({ // For batch rendering, do not use uniform color. material.useColor = false; this._updateMaterial(material); + if (this._renderData) { + this._renderData.material = material; + } } this.markForUpdateRenderData(true); diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 115b00307d0..1678e7945dc 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -125,7 +125,7 @@ let RenderComponent = cc.Class({ if (CC_JSB) { this.node.on(cc.Node.EventType.COLOR_CHANGED, this._updateColor, this); - this._renderHandle.setEnable(true); + this._renderHandle.updateEnabled(true); } }, @@ -177,13 +177,13 @@ let RenderComponent = cc.Class({ if (enable && this._canRender()) { this.node._renderFlag |= RenderFlow.FLAG_RENDER; if (CC_JSB) { - this._renderHandle.setEnable(true); + this._renderHandle.updateEnabled(true); } } else if (!enable) { this.node._renderFlag &= ~RenderFlow.FLAG_RENDER; if (CC_JSB) { - this._renderHandle.setEnable(false); + this._renderHandle.updateEnabled(false); } } }, @@ -201,7 +201,7 @@ let RenderComponent = cc.Class({ this.node._renderFlag &= ~(RenderFlow.FLAG_RENDER | RenderFlow.FLAG_CUSTOM_IA_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_COLOR); if (CC_JSB) { - this._renderHandle.setEnable(false); + this._renderHandle.updateEnabled(false); } }, diff --git a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js index ecd320bc0fa..be5e4b15e18 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js +++ b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js @@ -25,14 +25,14 @@ const bmfontUtils = require('../../../utils/label/bmfont') const js = require('../../../../platform/js'); -const utils = require('../utils'); module.exports = js.addon({ createData (comp) { return comp.requestRenderData(); }, - appendQuad (renderData, texture, rect, rotated, x, y, scale) { + appendQuad (comp, texture, rect, rotated, x, y, scale) { + let renderData = comp._renderData; let dataOffset = renderData.dataLength; renderData.dataLength += 2; diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 0039990d0ce..8abb81ef568 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -94,28 +94,34 @@ cc.renderer = module.exports = { _cameraNode: null, _camera: null, _forward: null, + _flow: null, initWebGL (canvas, opts) { require('./webgl/assemblers'); const ModelBatcher = require('./webgl/model-batcher'); - this.Texture2D = renderEngine.Texture2D; this.canvas = canvas; if (CC_JSB && CC_NATIVERENDERER) { // native codes will create an instance of Device, so just use the global instance. this.device = window.device; + this.scene = new renderEngine.Scene(); + let builtins = _initBuiltins(this.device); + this._forward = new renderEngine.ForwardRenderer(this.device, builtins); + + this._flow = new renderer.RenderFlow(this.device, this.scene, this._forward); + this._handle = this._flow.getModelBatcher(); } else { this.device = new renderEngine.Device(canvas, opts); + this.scene = new renderEngine.Scene(); + + this._handle = new ModelBatcher(this.device, this.scene); + this._flow = cc.RenderFlow; + this._flow.init(this._handle); + let builtins = _initBuiltins(this.device); + this._forward = new renderEngine.ForwardRenderer(this.device, builtins); } - - this.scene = new renderEngine.Scene(); - - this._handle = new ModelBatcher(this.device, this.scene); - cc.RenderFlow.init(this._handle); - let builtins = _initBuiltins(this.device); - this._forward = new renderEngine.ForwardRenderer(this.device, builtins); }, initCanvas (canvas) { @@ -160,7 +166,7 @@ cc.renderer = module.exports = { this.device._stats.drawcalls = 0; if (ecScene) { // walk entity component scene to generate models - cc.RenderFlow.visit(ecScene); + this._flow.visit(CC_JSB ? ecScene._proxy : ecScene); // Render models in renderer scene this._forward.render(this.scene); this.drawCalls = this.device._stats.drawcalls; diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js index f14152f4ccc..f3c2d51af13 100644 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ b/cocos2d/core/renderer/render-engine.canvas.js @@ -1332,7 +1332,7 @@ var RenderData = (function (BaseRenderData$$1) { }; prototypeAccessors.dataLength.get = function () { - return this._data.length; + return this.vertices.length; }; prototypeAccessors.dataLength.set = function (length) { diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index b990dc511f0..d5b732f8924 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -13844,7 +13844,7 @@ var RenderData = (function (BaseRenderData$$1) { }; prototypeAccessors.dataLength.get = function () { - return this._data.length; + return this.vertices.length; }; prototypeAccessors.dataLength.set = function (length) { diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index e7e16587e21..6b211239e8e 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -611,6 +611,10 @@ var Effect = function Effect(techniques, properties, defines) { // TODO: check if params is valid for current technique??? }; +Effect.prototype.updateHash = function updateHash (hash) { + this._nativeObj.updateHash(hash); +}; + Effect.prototype.clear = function clear () { this._techniques.length = 0; this._properties = null; @@ -1181,18 +1185,6 @@ var _p$1 = renderer$4.ForwardRenderer.prototype; _p$1._ctor = function(device, builtin) { this.init(device, builtin.programTemplates, builtin.defaultTexture, window.innerWidth, window.innerHeight); }; -_p$1.render = function(scene) { - fillModelData(); - this.renderNative(scene, modelsData); - - models.length = 0; -}; -_p$1.renderCamera = function(camera, scene) { - fillModelData(); - this.renderCameraNative(camera, scene, modelsData); - - models.length = 0; -}; // Scene _p$1 = renderer$4.Scene.prototype; @@ -2545,7 +2537,7 @@ var RenderData = (function (BaseRenderData$$1) { }; prototypeAccessors.dataLength.get = function () { - return this._data.length; + return this.vertices.length; }; prototypeAccessors.dataLength.set = function (length) { diff --git a/cocos2d/core/renderer/utils/label/bmfont.js b/cocos2d/core/renderer/utils/label/bmfont.js index 1851862331b..0a414376715 100644 --- a/cocos2d/core/renderer/utils/label/bmfont.js +++ b/cocos2d/core/renderer/utils/label/bmfont.js @@ -23,12 +23,11 @@ THE SOFTWARE. ****************************************************************************/ +let textUtils = require('../../../utils/text-utils'); const macro = require('../../../platform/CCMacro'); - const Label = require('../../../components/CCLabel'); const Overflow = Label.Overflow; -const textUtils = require('../../../utils/text-utils'); let FontLetterDefinition = function() { this._u = 0; @@ -132,7 +131,7 @@ let _labelWidth = 0; let _labelHeight = 0; let _maxLineWidth = 0; -module.exports = { +textUtils.bmfont = module.exports = { updateRenderData (comp) { if (!comp._vertsDirty) return; if (_comp === comp) return; @@ -668,14 +667,14 @@ module.exports = { } let letterPositionX = letterInfo._positionX + _linesOffsetX[letterInfo._lineIndex]; - this.appendQuad(renderData, texture, _tmpRect, isRotated, letterPositionX - appx, py - appy, _bmfontScale); + this.appendQuad(_comp, texture, _tmpRect, isRotated, letterPositionX - appx, py - appy, _bmfontScale); } } return ret; }, - appendQuad (renderData, texture, rect, rotated, x, y, scale) { + appendQuad (comp, texture, rect, rotated, x, y, scale) { }, _computeAlignmentOffset: function() { diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 2ff7a26642a..be64397b4e0 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -23,9 +23,8 @@ THE SOFTWARE. ****************************************************************************/ +let textUtils = require('../../../utils/text-utils'); const macro = require('../../../platform/CCMacro'); -const textUtils = require('../../../utils/text-utils'); - const Component = require('../../../components/CCComponent'); const Label = require('../../../components/CCLabel'); const LabelOutline = require('../../../components/CCLabelOutline'); @@ -90,7 +89,7 @@ let _canvasPool = { }; -module.exports = { +textUtils.ttf = module.exports = { _getAssemblerData () { if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { diff --git a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js index 74e042ed3fb..31253f08e04 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js @@ -61,7 +61,8 @@ module.exports = js.addon({ } }, - appendQuad (renderData, texture, rect, rotated, x, y, scale) { + appendQuad (comp, texture, rect, rotated, x, y, scale) { + let renderData = comp._renderData; let dataOffset = renderData.dataLength; renderData.dataLength += 4; diff --git a/cocos2d/core/utils/text-utils.js b/cocos2d/core/utils/text-utils.js index 0ea9cd7c90b..c45b8501f66 100644 --- a/cocos2d/core/utils/text-utils.js +++ b/cocos2d/core/utils/text-utils.js @@ -151,4 +151,4 @@ var textUtils = { }, }; -module.exports = textUtils; +cc.textUtils = module.exports = textUtils; From 025695d245fa0c402b86fd3019a0bbdc3e293e63 Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 21 Nov 2018 12:02:20 +0800 Subject: [PATCH 0202/1631] update param value format (#3540) --- cocos2d/core/utils/html-text-parser.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/utils/html-text-parser.js b/cocos2d/core/utils/html-text-parser.js index 7cc70ff07fc..479a78c14e3 100644 --- a/cocos2d/core/utils/html-text-parser.js +++ b/cocos2d/core/utils/html-text-parser.js @@ -163,7 +163,7 @@ HtmlTextParser.prototype = { } if (obj.event && tagName === 'param') { - obj.event.param = tagValue; + obj.event.param = tagValue.replace(/^\"|\"$/g, ''); } header = attribute.match(imageAttrReg); @@ -211,7 +211,7 @@ HtmlTextParser.prototype = { } if (obj.event && tagName === 'param') { - obj.event.param = tagValue; + obj.event.param = tagValue.replace(/^\"|\"$/g, ''); } header = attribute.match(outlineAttrReg); @@ -242,7 +242,6 @@ HtmlTextParser.prototype = { obj.event = eventObj; } - return obj; }, From 8e1d7cf0758a2c9c340db02c2249a0781d0ed1e3 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 21 Nov 2018 17:51:35 +0800 Subject: [PATCH 0203/1631] Use shared buffer for node matrix --- cocos2d/core/CCNode.js | 6 ------ cocos2d/core/renderer/index.js | 8 ++++---- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 6a421e1bf50..e6e43ff0ec8 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -2681,17 +2681,11 @@ let NodeDefines = { }, setLocalDirty (flag) { - if (CC_JSB) { - this._proxy.setMatrixDirty(); - } this._localMatDirty = this._localMatDirty | flag; this._worldMatDirty = true; }, setWorldDirty () { - if (CC_JSB) { - this._proxy.setMatrixDirty(); - } this._worldMatDirty = true; }, diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 8abb81ef568..754f4b465f2 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -108,9 +108,9 @@ cc.renderer = module.exports = { this.scene = new renderEngine.Scene(); let builtins = _initBuiltins(this.device); this._forward = new renderEngine.ForwardRenderer(this.device, builtins); - - this._flow = new renderer.RenderFlow(this.device, this.scene, this._forward); - this._handle = this._flow.getModelBatcher(); + let nativeFlow = new renderer.RenderFlow(this.device, this.scene, this._forward); + this._flow = cc.RenderFlow; + this._flow.init(nativeFlow); } else { this.device = new renderEngine.Device(canvas, opts); @@ -166,7 +166,7 @@ cc.renderer = module.exports = { this.device._stats.drawcalls = 0; if (ecScene) { // walk entity component scene to generate models - this._flow.visit(CC_JSB ? ecScene._proxy : ecScene); + this._flow.visit(ecScene); // Render models in renderer scene this._forward.render(this.scene); this.drawCalls = this.device._stats.drawcalls; From 534aa576da6fe7b6786ed89210d100b0cc4aa657 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 22 Nov 2018 16:07:01 +0800 Subject: [PATCH 0204/1631] Update to shared vertices and indices --- cocos2d/core/components/CCRenderComponent.js | 4 ---- cocos2d/core/renderer/utils/label/bmfont.js | 7 ++++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 1678e7945dc..c3a93af77e8 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -149,9 +149,6 @@ let RenderComponent = cc.Class({ setVertsDirty () { this._vertsDirty = true; - if (CC_JSB) { - this._renderHandle.setVertsDirty(); - } }, _onNodeSizeDirty () { @@ -239,7 +236,6 @@ let RenderComponent = cc.Class({ _updateMaterial (material) { this._material = material; - this._updateBlendFunc(); material.updateHash(); }, diff --git a/cocos2d/core/renderer/utils/label/bmfont.js b/cocos2d/core/renderer/utils/label/bmfont.js index 0a414376715..8048faa0a7c 100644 --- a/cocos2d/core/renderer/utils/label/bmfont.js +++ b/cocos2d/core/renderer/utils/label/bmfont.js @@ -138,6 +138,7 @@ textUtils.bmfont = module.exports = { _comp = comp; + this._reserveQuads(comp, comp.string.toString().length); this._updateProperties(); this._updateContent(); @@ -151,6 +152,8 @@ textUtils.bmfont = module.exports = { this._resetProperties(); }, + _reserveQuads () {}, + _updateFontScale () { _bmfontScale = _fontSize / _originFontSize; }, @@ -595,7 +598,9 @@ textUtils.bmfont = module.exports = { let node = _comp.node; let renderData = _comp._renderData; - renderData.dataLength = renderData.vertexCount = renderData.indiceCount = 0; + if (renderData) { + renderData.dataLength = renderData.vertexCount = renderData.indiceCount = 0; + } let contentSize = _contentSize, appx = node._anchorPoint.x * contentSize.width, From 4ceb6e087afc7c44828e173540d6a421954992b5 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 22 Nov 2018 16:36:37 +0800 Subject: [PATCH 0205/1631] notify quads update finish for bmfont assembler --- cocos2d/core/renderer/utils/label/bmfont.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cocos2d/core/renderer/utils/label/bmfont.js b/cocos2d/core/renderer/utils/label/bmfont.js index 8048faa0a7c..9218edef133 100644 --- a/cocos2d/core/renderer/utils/label/bmfont.js +++ b/cocos2d/core/renderer/utils/label/bmfont.js @@ -675,6 +675,7 @@ textUtils.bmfont = module.exports = { this.appendQuad(_comp, texture, _tmpRect, isRotated, letterPositionX - appx, py - appy, _bmfontScale); } } + this._quadsUpdated(_comp); return ret; }, @@ -682,6 +683,8 @@ textUtils.bmfont = module.exports = { appendQuad (comp, texture, rect, rotated, x, y, scale) { }, + _quadsUpdated (comp) {}, + _computeAlignmentOffset: function() { _linesOffsetX.length = 0; From 37f4f06419a7b6a68283a4d1e46ff937bdccb941 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 22 Nov 2018 17:17:19 +0800 Subject: [PATCH 0206/1631] CCClass: allow array type working togather with getter (#3545) --- cocos2d/core/platform/preprocess-class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/preprocess-class.js b/cocos2d/core/platform/preprocess-class.js index 16caa3039eb..a8ada68f7f4 100644 --- a/cocos2d/core/platform/preprocess-class.js +++ b/cocos2d/core/platform/preprocess-class.js @@ -159,7 +159,7 @@ function checkUrl (val, className, propName, url) { function parseType (val, type, className, propName) { if (Array.isArray(type)) { - if (CC_EDITOR) { + if (CC_EDITOR && 'default' in val) { var isArray = require('./CCClass').isArray; // require lazily to avoid circular require() calls if (!isArray(val.default)) { cc.warnID(5507, className, propName); From ed709cba417f03504dbd2d755161488f2b95e9cc Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 23 Nov 2018 09:26:07 +0800 Subject: [PATCH 0207/1631] fix when the particle system can't play (#3547) --- cocos2d/particle/CCParticleSystem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index f2ead2eba80..440d2167e50 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -929,7 +929,7 @@ var ParticleSystem = cc.Class({ if (!self._custom) { self._initWithDictionary(content); } - if (!self.spriteFrame) { + if (!self.spriteFrame || !self._renderSpriteFrame) { if (file.spriteFrame) { self.spriteFrame = file.spriteFrame; } From 4f15936d990fabca94724fffa0a3a1763d9742f0 Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 23 Nov 2018 15:00:17 +0800 Subject: [PATCH 0208/1631] Adapt to the JS engine. --- cocos2d/core/CCNode.js | 8 ++++---- cocos2d/core/components/CCLabel.js | 2 +- cocos2d/core/components/CCRenderComponent.js | 12 ++++++------ cocos2d/core/components/CCSprite.js | 2 +- cocos2d/core/renderer/render-engine.js | 2 +- predefine.js | 1 + 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index e6e43ff0ec8..843ff210009 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1170,7 +1170,7 @@ let NodeDefines = { this._eulerAngles = cc.v3(); // Proxy - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._proxy = new renderer.NodeProxy(); this._proxy.bind(this); } @@ -1246,7 +1246,7 @@ let NodeDefines = { } } - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._proxy.unbind(); } }, @@ -1288,7 +1288,7 @@ let NodeDefines = { } // Node proxy - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._parent && this._proxy.updateParent(this._parent._proxy); } }, @@ -1370,7 +1370,7 @@ let NodeDefines = { this._renderFlag |= RenderFlow.FLAG_CHILDREN; } - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._proxy.setName(this._name); this._parent && this._proxy.updateParent(this._parent._proxy); } diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 4e25530ef16..74ca329b367 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -507,7 +507,7 @@ let Label = cc.Class({ this._renderData.material = this._material; } - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._renderHandle.setUseModel(!!assembler.useModel); } }, diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index c3a93af77e8..00b620a390d 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -106,7 +106,7 @@ let RenderComponent = cc.Class({ this._postAssembler = this.constructor._postAssembler; // Render handle for native system - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._renderHandle = new renderer.RenderHandle(); this._renderHandle.bind(this); } @@ -123,7 +123,7 @@ let RenderComponent = cc.Class({ this.node._renderFlag |= RenderFlow.FLAG_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_COLOR; - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this.node.on(cc.Node.EventType.COLOR_CHANGED, this._updateColor, this); this._renderHandle.updateEnabled(true); } @@ -133,7 +133,7 @@ let RenderComponent = cc.Class({ this.node._renderComponent = null; this.node.off(cc.Node.EventType.SIZE_CHANGED, this._onNodeSizeDirty, this); this.node.off(cc.Node.EventType.ANCHOR_CHANGED, this._onNodeSizeDirty, this); - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this.node.off(cc.Node.EventType.COLOR_CHANGED, this._updateColor, this); } this.disableRender(); @@ -173,13 +173,13 @@ let RenderComponent = cc.Class({ markForRender (enable) { if (enable && this._canRender()) { this.node._renderFlag |= RenderFlow.FLAG_RENDER; - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._renderHandle.updateEnabled(true); } } else if (!enable) { this.node._renderFlag &= ~RenderFlow.FLAG_RENDER; - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._renderHandle.updateEnabled(false); } } @@ -197,7 +197,7 @@ let RenderComponent = cc.Class({ disableRender () { this.node._renderFlag &= ~(RenderFlow.FLAG_RENDER | RenderFlow.FLAG_CUSTOM_IA_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_COLOR); - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._renderHandle.updateEnabled(false); } }, diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 6b1dd137c94..dc29be937d6 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -472,7 +472,7 @@ var Sprite = cc.Class({ this.markForUpdateRenderData(true); } - if (CC_JSB) { + if (CC_JSB && CC_NATIVERENDERER) { this._renderHandle.setUseModel(!!assembler.useModel); } }, diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index d5b732f8924..787f768a375 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -11142,7 +11142,7 @@ prototypeAccessors$5.cullingMask.get = function () { return this._cullingMask; }; -prototypeAccessors$5.cullingMask.set = function (mask) { +Camera.prototype.setCullingMask = function setCullingMask (mask) { this._cullingMask = mask; }; diff --git a/predefine.js b/predefine.js index 35cd7b8d497..aaaf3faf32a 100644 --- a/predefine.js +++ b/predefine.js @@ -142,6 +142,7 @@ if (CC_BUILD) { _global.CC_DEV = CC_DEV; _global.CC_DEBUG = CC_DEBUG; _global.CC_JSB = CC_JSB; + _global.CC_NATIVERENDERER = CC_NATIVERENDERER; _global.CC_WECHATGAME_SUB = CC_WECHATGAMESUB; _global.CC_WECHATGAME = CC_WECHATGAME; _global.CC_QQPLAY = CC_QQPLAY; From 172eaef235d23d6828e3a6ad0be317c7eca662ef Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 23 Nov 2018 15:32:16 +0800 Subject: [PATCH 0209/1631] Restore cullingmask change. --- cocos2d/core/renderer/render-engine.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 787f768a375..ecf633275b5 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -11142,6 +11142,10 @@ prototypeAccessors$5.cullingMask.get = function () { return this._cullingMask; }; +prototypeAccessors$5.cullingMask.set = function (mask) { + this._cullingMask = mask; +}; + Camera.prototype.setCullingMask = function setCullingMask (mask) { this._cullingMask = mask; }; From f43430de0d9a832eeb6694cd13daa41a77c43c45 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Sat, 24 Nov 2018 11:17:54 +0800 Subject: [PATCH 0210/1631] Do render inside RenderFlow --- cocos2d/core/renderer/index.js | 9 ++++----- cocos2d/core/renderer/render-flow.js | 9 ++++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 754f4b465f2..3afab4e3db3 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -116,11 +116,11 @@ cc.renderer = module.exports = { this.device = new renderEngine.Device(canvas, opts); this.scene = new renderEngine.Scene(); - this._handle = new ModelBatcher(this.device, this.scene); - this._flow = cc.RenderFlow; - this._flow.init(this._handle); let builtins = _initBuiltins(this.device); this._forward = new renderEngine.ForwardRenderer(this.device, builtins); + this._handle = new ModelBatcher(this.device, this.scene); + this._flow = cc.RenderFlow; + this._flow.init(this._handle, this._forward); } }, @@ -166,9 +166,8 @@ cc.renderer = module.exports = { this.device._stats.drawcalls = 0; if (ecScene) { // walk entity component scene to generate models - this._flow.visit(ecScene); + this._flow.render(ecScene); // Render models in renderer scene - this._forward.render(this.scene); this.drawCalls = this.device._stats.drawcalls; } }, diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 8ff5db09788..a9d47f21e37 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -12,7 +12,7 @@ const POST_UPDATE_RENDER_DATA = 1 << 8; const POST_RENDER = 1 << 9; const FINAL = 1 << 10; -let _batcher; +let _batcher, _forward; let _cullingMask = 0; // @@ -197,7 +197,7 @@ function init (node) { RenderFlow.flows = flows; RenderFlow.createFlow = createFlow; -RenderFlow.visit = function (scene) { +RenderFlow.render = function (scene) { _batcher.reset(); _batcher.walking = true; @@ -217,10 +217,13 @@ RenderFlow.visit = function (scene) { } _batcher.terminate(); + + _forward.render(_batcher._renderScene); }; -RenderFlow.init = function (batcher) { +RenderFlow.init = function (batcher, forwardRenderer) { _batcher = batcher; + _forward = forwardRenderer; flows[0] = EMPTY_FLOW; for (let i = 1; i < FINAL; i++) { From 5a81a3bdaa4b5843ebf658f9f30dd883da745aee Mon Sep 17 00:00:00 2001 From: pandamicro Date: Sat, 24 Nov 2018 11:18:16 +0800 Subject: [PATCH 0211/1631] Use device drawcall APIs --- cocos2d/core/renderer/index.js | 5 ++--- cocos2d/core/renderer/render-engine.js | 10 +++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 3afab4e3db3..3088adba78c 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -163,12 +163,11 @@ cc.renderer = module.exports = { }, render (ecScene) { - this.device._stats.drawcalls = 0; + this.device.resetDrawCalls(); if (ecScene) { // walk entity component scene to generate models this._flow.render(ecScene); - // Render models in renderer scene - this.drawCalls = this.device._stats.drawcalls; + this.drawCalls = this.device.getDrawCalls(); } }, diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index ecf633275b5..b82ffb71c9c 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -10168,6 +10168,14 @@ Device.prototype.setPrimitiveType = function setPrimitiveType (type) { this._next.primitiveType = type; }; +Device.prototype.resetDrawCalls = function resetDrawCalls () { + this._stats.drawcalls = 0; +}; + +Device.prototype.getDrawCalls = function getDrawCalls () { + return this._stats.drawcalls; +}; + /** * @method draw * @param {Number} base @@ -10263,7 +10271,7 @@ Device.prototype.draw = function draw (base, count) { // } // update stats - this._stats.drawcalls += 1; + this._stats.drawcalls ++; // reset states cur.set(next); From dca7ec15ebea400599659693f271e9037431407e Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 26 Nov 2018 11:45:34 +0800 Subject: [PATCH 0212/1631] fix particle rendering texture for reset bug (#3553) --- cocos2d/particle/CCParticleSystem.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 440d2167e50..8efb29b4c8b 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -231,7 +231,7 @@ var properties = { } this._renderSpriteFrame = value; - if (value._uuid) { + if (!value || value._uuid) { this._spriteFrame = value; } @@ -259,7 +259,9 @@ var properties = { return this._texture; }, set: function (value) { - cc.warnID(6017); + if (value) { + cc.warnID(6017); + } }, type: cc.Texture2D, tooltip: CC_DEV && 'i18n:COMPONENT.particle_system.texture', @@ -805,6 +807,9 @@ var ParticleSystem = cc.Class({ this._applyFile(); } } + else if (this._custom && this.spriteFrame && !this._renderSpriteFrame) { + this._applySpriteFrame(this.spriteFrame); + } // auto play if (!CC_EDITOR || cc.engine.isPlaying) { if (this.playOnLoad) { From 915ccf4e6e273f9003c14560ab1e48f9fa090132 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Mon, 26 Nov 2018 11:46:36 +0800 Subject: [PATCH 0213/1631] doc: improve api (#3548) * doc: improve api * use macro instead platform to eliminate runtime branch --- cocos2d/core/CCGame.js | 10 ++++------ cocos2d/core/load-pipeline/CCLoader.js | 6 ++++-- cocos2d/core/platform/CCInputManager.js | 8 ++++---- cocos2d/core/platform/CCView.js | 2 +- cocos2d/videoplayer/video-player-impl.js | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 4dcaaabdfb5..94d077cdc2a 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -694,11 +694,9 @@ var game = { let el = this.config.id, width, height, - localCanvas, localContainer, - isWeChatGame = cc.sys.platform === cc.sys.WECHAT_GAME, - isQQPlay = cc.sys.platform === cc.sys.QQ_PLAY; + localCanvas, localContainer; - if (isWeChatGame || CC_JSB) { + if (CC_WECHATGAME || CC_JSB) { this.container = localContainer = document.createElement("DIV"); this.frame = localContainer.parentNode === document.body ? document.documentElement : localContainer.parentNode; if (cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { @@ -712,7 +710,7 @@ var game = { } this.canvas = localCanvas; } - else if (isQQPlay) { + else if (CC_QQPLAY) { this.container = cc.container = document.createElement("DIV"); this.frame = document.documentElement; this.canvas = localCanvas = canvas; @@ -768,7 +766,7 @@ var game = { 'antialias': cc.macro.ENABLE_WEBGL_ANTIALIAS, 'alpha': cc.macro.ENABLE_TRANSPARENT_CANVAS }; - if (isWeChatGame || isQQPlay) { + if (CC_WECHATGAME || CC_QQPLAY) { opts['preserveDrawingBuffer'] = true; } renderer.initWebGL(localCanvas, opts); diff --git a/cocos2d/core/load-pipeline/CCLoader.js b/cocos2d/core/load-pipeline/CCLoader.js index af36508414c..85dbf6bcf21 100644 --- a/cocos2d/core/load-pipeline/CCLoader.js +++ b/cocos2d/core/load-pipeline/CCLoader.js @@ -713,13 +713,15 @@ proto.getResCount = function () { }; /** - * !#en Get all resource dependencies of the requested asset in an array, including itself. + * !#en + * Get all resource dependencies of the loaded asset in an array, including itself. * The owner parameter accept the following types: 1. The asset itself; 2. The resource url; 3. The asset's uuid.
* The returned array stores the dependencies with their uuids, after retrieve dependencies, * you can release them, access dependent assets by passing the uuid to {{#crossLink "loader/getRes:method"}}{{/crossLink}}, or other stuffs you want.
* For release all dependencies of an asset, please refer to {{#crossLink "loader/release:method"}}{{/crossLink}} * Here is some examples: - * !#zh 获取一个指定资源的所有依赖资源,包含它自身,并保存在数组中返回。owner 参数接收以下几种类型:1. 资源 asset 对象;2. 资源目录下的 url;3. 资源的 uuid。
+ * !#zh + * 获取某个已经加载好的资源的所有依赖资源,包含它自身,并保存在数组中返回。owner 参数接收以下几种类型:1. 资源 asset 对象;2. 资源目录下的 url;3. 资源的 uuid。
* 返回的数组将仅保存依赖资源的 uuid,获取这些 uuid 后,你可以从 loader 释放这些资源;通过 {{#crossLink "loader/getRes:method"}}{{/crossLink}} 获取某个资源或者进行其他你需要的操作。
* 想要释放一个资源及其依赖资源,可以参考 {{#crossLink "loader/release:method"}}{{/crossLink}}。下面是一些示例代码: * diff --git a/cocos2d/core/platform/CCInputManager.js b/cocos2d/core/platform/CCInputManager.js index c01fc498ca0..106d68dae5a 100644 --- a/cocos2d/core/platform/CCInputManager.js +++ b/cocos2d/core/platform/CCInputManager.js @@ -223,7 +223,7 @@ let inputManager = { * @return {Object} */ getHTMLElementPosition (element) { - if (sys.platform === sys.WECHAT_GAME) { + if (CC_WECHATGAME) { return { left: 0, top: 0, @@ -354,7 +354,7 @@ let inputManager = { if (event.pageX != null) //not avalable in <= IE8 return {x: event.pageX, y: event.pageY}; - if (sys.platform === sys.WECHAT_GAME) { + if (CC_WECHATGAME) { pos.left = 0; pos.top = 0; } @@ -417,7 +417,7 @@ let inputManager = { let supportMouse = ('mouse' in sys.capabilities); let supportTouches = ('touches' in sys.capabilities); - if (sys.platform === sys.WECHAT_GAME) { + if (CC_WECHATGAME) { prohibition = false; supportTouches = true; supportMouse = false; @@ -527,7 +527,7 @@ let inputManager = { let _touchEventsMap = { "touchstart": function (touchesToHandle) { selfPointer.handleTouchesBegin(touchesToHandle); - if (sys.platform !== sys.WECHAT_GAME) { + if (!CC_WECHATGAME) { element.focus(); } }, diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 34bb999de13..7fe3aab84cd 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -1060,7 +1060,7 @@ cc.ContainerStrategy = cc.Class({ _setupContainer: function (view, w, h) { var locCanvas = cc.game.canvas, locContainer = cc.game.container; - if (cc.sys.platform !== cc.sys.WECHAT_GAME) { + if (!CC_WECHATGAME) { if (cc.sys.os === cc.sys.OS_ANDROID) { document.body.style.width = (view._isRotated ? h : w) + 'px'; document.body.style.height = (view._isRotated ? w : h) + 'px'; diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 76e093387ed..85cb66ebd34 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -546,7 +546,7 @@ VideoPlayerImpl._polyfill = { * so it is best to provide mp4 and webm or ogv file */ let dom = document.createElement("video"); -if (sys.platform !== sys.WECHAT_GAME) { +if (!CC_WECHATGAME) { if (dom.canPlayType("video/ogg")) { VideoPlayerImpl._polyfill.canPlayType.push(".ogg"); VideoPlayerImpl._polyfill.canPlayType.push(".ogv"); From a3eaab3349aefec94ddc1ea4c8379a03a5334968 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Mon, 26 Nov 2018 22:16:46 +0800 Subject: [PATCH 0214/1631] Avoid Spine/db effect retrieving issue --- cocos2d/core/components/CCRenderComponent.js | 8 ++++++-- cocos2d/core/renderer/render-engine.js | 13 +++++++++++++ cocos2d/core/renderer/render-engine.jsb.js | 11 +++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 00b620a390d..a5ec5728013 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -107,11 +107,15 @@ let RenderComponent = cc.Class({ // Render handle for native system if (CC_JSB && CC_NATIVERENDERER) { - this._renderHandle = new renderer.RenderHandle(); - this._renderHandle.bind(this); + this.initNativeHandle(); } }, + initNativeHandle () { + this._renderHandle = new renderer.RenderHandle(); + this._renderHandle.bind(this); + }, + onEnable () { if (this.node._renderComponent) { this.node._renderComponent.enabled = false; diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index b82ffb71c9c..4349d750751 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -13797,6 +13797,17 @@ var templates = [ { name: 'alphaTest', }, { name: 'use2DPos', }, { name: 'useColor', } ], + }, + { + name: 'skeleton', + vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', + frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', + defines: [ + { name: 'useTexture', }, + { name: 'useModel', }, + { name: 'alphaTest', }, + { name: 'use2DPos', }, + { name: 'useColor', } ], } ]; var shaders = { @@ -14299,6 +14310,8 @@ var SpriteMaterial = (function (Material$$1) { return SpriteMaterial; }(Material)); + + // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. var GraySpriteMaterial = (function (Material$$1) { diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 6b211239e8e..47294502d2a 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -1226,6 +1226,17 @@ var templates = [ { name: 'alphaTest', }, { name: 'use2DPos', }, { name: 'useColor', } ], + }, + { + name: 'skeleton', + vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', + frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', + defines: [ + { name: 'useTexture', }, + { name: 'useModel', }, + { name: 'alphaTest', }, + { name: 'use2DPos', }, + { name: 'useColor', } ], } ]; var shaders = { From 354b92a7e70260e1f64011de8058c1748debaa1e Mon Sep 17 00:00:00 2001 From: pandamicro Date: Mon, 26 Nov 2018 23:08:36 +0800 Subject: [PATCH 0215/1631] Update render engine --- cocos2d/core/renderer/render-engine.js | 14 +- cocos2d/core/renderer/render-engine.jsb.js | 1311 ++------------------ 2 files changed, 82 insertions(+), 1243 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 4349d750751..2d0ad6a5526 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -2,7 +2,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - render-engine v1.2.1 + render-engine v1.2.2 http://www.cocos.com Permission is hereby granted, free of charge, to any person obtaining a copy @@ -10168,10 +10168,16 @@ Device.prototype.setPrimitiveType = function setPrimitiveType (type) { this._next.primitiveType = type; }; +/** + * @method resetDrawCalls + */ Device.prototype.resetDrawCalls = function resetDrawCalls () { this._stats.drawcalls = 0; }; - + +/** + * @method getDrawCalls + */ Device.prototype.getDrawCalls = function getDrawCalls () { return this._stats.drawcalls; }; @@ -10271,7 +10277,7 @@ Device.prototype.draw = function draw (base, count) { // } // update stats - this._stats.drawcalls ++; + this._stats.drawcalls++; // reset states cur.set(next); @@ -14310,8 +14316,6 @@ var SpriteMaterial = (function (Material$$1) { return SpriteMaterial; }(Material)); - - // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. var GraySpriteMaterial = (function (Material$$1) { diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 47294502d2a..aa85f0a9d11 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -2,7 +2,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - render-engine v1.2.1 + render-engine v1.2.2 http://www.cocos.com Permission is hereby granted, free of charge, to any person obtaining a copy @@ -28,1171 +28,6 @@ 'use strict'; -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gl = window.__gl; - -var _filterGL = [ - [ gl.GL_NEAREST, gl.GL_NEAREST_MIPMAP_NEAREST, gl.GL_NEAREST_MIPMAP_LINEAR ], - [ gl.GL_LINEAR, gl.GL_LINEAR_MIPMAP_NEAREST, gl.GL_LINEAR_MIPMAP_LINEAR ] ]; - -var _textureFmtGL = [ - // TEXTURE_FMT_RGB_DXT1: 0 - { format: gl.RGB, internalFormat: gl.COMPRESSED_RGB_S3TC_DXT1_EXT, pixelType: 0, bpp: 3 }, - - // TEXTURE_FMT_RGBA_DXT1: 1 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_S3TC_DXT1_EXT, pixelType: 0, bpp: 4 }, - - // TEXTURE_FMT_RGBA_DXT3: 2 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_S3TC_DXT3_EXT, pixelType: 0, bpp: 8 }, - - // TEXTURE_FMT_RGBA_DXT5: 3 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_S3TC_DXT5_EXT, pixelType: 0, bpp: 8 }, - - // TEXTURE_FMT_RGB_ETC1: 4 - { format: gl.RGB, internalFormat: gl.COMPRESSED_RGB_ETC1_WEBGL, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5 - { format: gl.RGB, internalFormat: gl.COMPRESSED_RGB_PVRTC_2BPPV1_IMG, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, pixelType: 0, bpp:0 }, - - // TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7 - { format: gl.RGB, internalFormat: gl.COMPRESSED_RGB_PVRTC_4BPPV1_IMG, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, pixelType: null }, - - // TEXTURE_FMT_A8: 9 - { format: gl.ALPHA, internalFormat: gl.ALPHA, pixelType: gl.UNSIGNED_BYTE, bpp: 8 }, - - // TEXTURE_FMT_L8: 10 - { format: gl.LUMINANCE, internalFormat: gl.LUMINANCE, pixelType: gl.UNSIGNED_BYTE, bpp: 8 }, - - // TEXTURE_FMT_L8_A8: 11 - { format: gl.LUMINANCE_ALPHA, internalFormat: gl.LUMINANCE_ALPHA, pixelType: gl.UNSIGNED_BYTE, bpp: 16 }, - - // TEXTURE_FMT_R5_G6_B5: 12 - { format: gl.RGB, internalFormat: gl.RGB, pixelType: gl.UNSIGNED_SHORT_5_6_5, bpp: 16 }, - - // TEXTURE_FMT_R5_G5_B5_A1: 13 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.UNSIGNED_SHORT_5_5_5_1, bpp: 16 }, - - // TEXTURE_FMT_R4_G4_B4_A4: 14 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.UNSIGNED_SHORT_4_4_4_4, bpp: 16 }, - - // TEXTURE_FMT_RGB8: 15 - { format: gl.RGB, internalFormat: gl.RGB, pixelType: gl.UNSIGNED_BYTE, bpp: 24 }, - - // TEXTURE_FMT_RGBA8: 16 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.UNSIGNED_BYTE, bpp: 32 }, - - // TEXTURE_FMT_RGB16F: 17 - { format: gl.RGB, internalFormat: gl.RGB, pixelType: gl.HALF_FLOAT_OES, bpp: 0 }, - - // TEXTURE_FMT_RGBA16F: 18 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.HALF_FLOAT_OES, bpp: 0 }, - - // TEXTURE_FMT_RGB32F: 19 - { format: gl.RGB, internalFormat: gl.RGB, pixelType: gl.FLOAT, bpp: 96 }, - - // TEXTURE_FMT_RGBA32F: 20 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.FLOAT, bpp: 128 }, - - // TEXTURE_FMT_R32F: 21 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_111110F: 22 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_SRGB: 23 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_SRGBA: 24 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_D16: 25 - // TODO: fix it on android - { format: gl.DEPTH_COMPONENT, internalFormat: gl.DEPTH_COMPONENT16, pixelType: gl.UNSIGNED_SHORT }, - - // TEXTURE_FMT_D24: 26 - // { format: gl.DEPTH_COMPONENT, internalFormat: gl.DEPTH_COMPONENT24, pixelType: gl.FLOAT }, - - // TEXTURE_FMT_D24S8: 27 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 } ]; - -/** - * enums - */ -var enums = { - // buffer usage - USAGE_STATIC: 35044, // gl.STATIC_DRAW - USAGE_DYNAMIC: 35048, // gl.DYNAMIC_DRAW - USAGE_STREAM: 35040, // gl.STREAM_DRAW - - // index buffer format - INDEX_FMT_UINT8: 5121, // gl.UNSIGNED_BYTE - INDEX_FMT_UINT16: 5123, // gl.UNSIGNED_SHORT - INDEX_FMT_UINT32: 5125, // gl.UNSIGNED_INT (OES_element_index_uint) - - // vertex attribute semantic - ATTR_POSITION: 'a_position', - ATTR_NORMAL: 'a_normal', - ATTR_TANGENT: 'a_tangent', - ATTR_BITANGENT: 'a_bitangent', - ATTR_WEIGHTS: 'a_weights', - ATTR_JOINTS: 'a_joints', - ATTR_COLOR: 'a_color', - ATTR_COLOR0: 'a_color0', - ATTR_COLOR1: 'a_color1', - ATTR_UV: 'a_uv', - ATTR_UV0: 'a_uv0', - ATTR_UV1: 'a_uv1', - ATTR_UV2: 'a_uv2', - ATTR_UV3: 'a_uv3', - ATTR_UV4: 'a_uv4', - ATTR_UV5: 'a_uv5', - ATTR_UV6: 'a_uv6', - ATTR_UV7: 'a_uv7', - - // vertex attribute type - ATTR_TYPE_INT8: 5120, // gl.BYTE - ATTR_TYPE_UINT8: 5121, // gl.UNSIGNED_BYTE - ATTR_TYPE_INT16: 5122, // gl.SHORT - ATTR_TYPE_UINT16: 5123, // gl.UNSIGNED_SHORT - ATTR_TYPE_INT32: 5124, // gl.INT - ATTR_TYPE_UINT32: 5125, // gl.UNSIGNED_INT - ATTR_TYPE_FLOAT32: 5126, // gl.FLOAT - - // texture filter - FILTER_NEAREST: 0, - FILTER_LINEAR: 1, - - // texture wrap mode - WRAP_REPEAT: 10497, // gl.REPEAT - WRAP_CLAMP: 33071, // gl.CLAMP_TO_EDGE - WRAP_MIRROR: 33648, // gl.MIRRORED_REPEAT - - // texture format - // compress formats - TEXTURE_FMT_RGB_DXT1: 0, - TEXTURE_FMT_RGBA_DXT1: 1, - TEXTURE_FMT_RGBA_DXT3: 2, - TEXTURE_FMT_RGBA_DXT5: 3, - TEXTURE_FMT_RGB_ETC1: 4, - TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5, - TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6, - TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7, - TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8, - - // normal formats - TEXTURE_FMT_A8: 9, - TEXTURE_FMT_L8: 10, - TEXTURE_FMT_L8_A8: 11, - TEXTURE_FMT_R5_G6_B5: 12, - TEXTURE_FMT_R5_G5_B5_A1: 13, - TEXTURE_FMT_R4_G4_B4_A4: 14, - TEXTURE_FMT_RGB8: 15, - TEXTURE_FMT_RGBA8: 16, - TEXTURE_FMT_RGB16F: 17, - TEXTURE_FMT_RGBA16F: 18, - TEXTURE_FMT_RGB32F: 19, - TEXTURE_FMT_RGBA32F: 20, - TEXTURE_FMT_R32F: 21, - TEXTURE_FMT_111110F: 22, - TEXTURE_FMT_SRGB: 23, - TEXTURE_FMT_SRGBA: 24, - - // depth formats - TEXTURE_FMT_D16: 25, - TEXTURE_FMT_D24: 26, - TEXTURE_FMT_D24S8: 27, - - // depth and stencil function - DS_FUNC_NEVER: 512, // gl.NEVER - DS_FUNC_LESS: 513, // gl.LESS - DS_FUNC_EQUAL: 514, // gl.EQUAL - DS_FUNC_LEQUAL: 515, // gl.LEQUAL - DS_FUNC_GREATER: 516, // gl.GREATER - DS_FUNC_NOTEQUAL: 517, // gl.NOTEQUAL - DS_FUNC_GEQUAL: 518, // gl.GEQUAL - DS_FUNC_ALWAYS: 519, // gl.ALWAYS - - // render-buffer format - RB_FMT_RGBA4: 32854, // gl.RGBA4 - RB_FMT_RGB5_A1: 32855, // gl.RGB5_A1 - RB_FMT_RGB565: 36194, // gl.RGB565 - RB_FMT_D16: 33189, // gl.DEPTH_COMPONENT16 - RB_FMT_S8: 36168, // gl.STENCIL_INDEX8 - RB_FMT_D24S8: 34041, // gl.DEPTH_STENCIL - - // blend-equation - BLEND_FUNC_ADD: 32774, // gl.FUNC_ADD - BLEND_FUNC_SUBTRACT: 32778, // gl.FUNC_SUBTRACT - BLEND_FUNC_REVERSE_SUBTRACT: 32779, // gl.FUNC_REVERSE_SUBTRACT - - // blend - BLEND_ZERO: 0, // gl.ZERO - BLEND_ONE: 1, // gl.ONE - BLEND_SRC_COLOR: 768, // gl.SRC_COLOR - BLEND_ONE_MINUS_SRC_COLOR: 769, // gl.ONE_MINUS_SRC_COLOR - BLEND_DST_COLOR: 774, // gl.DST_COLOR - BLEND_ONE_MINUS_DST_COLOR: 775, // gl.ONE_MINUS_DST_COLOR - BLEND_SRC_ALPHA: 770, // gl.SRC_ALPHA - BLEND_ONE_MINUS_SRC_ALPHA: 771, // gl.ONE_MINUS_SRC_ALPHA - BLEND_DST_ALPHA: 772, // gl.DST_ALPHA - BLEND_ONE_MINUS_DST_ALPHA: 773, // gl.ONE_MINUS_DST_ALPHA - BLEND_CONSTANT_COLOR: 32769, // gl.CONSTANT_COLOR - BLEND_ONE_MINUS_CONSTANT_COLOR: 32770, // gl.ONE_MINUS_CONSTANT_COLOR - BLEND_CONSTANT_ALPHA: 32771, // gl.CONSTANT_ALPHA - BLEND_ONE_MINUS_CONSTANT_ALPHA: 32772, // gl.ONE_MINUS_CONSTANT_ALPHA - BLEND_SRC_ALPHA_SATURATE: 776, // gl.SRC_ALPHA_SATURATE - - // stencil operation - STENCIL_OP_KEEP: 7680, // gl.KEEP - STENCIL_OP_ZERO: 0, // gl.ZERO - STENCIL_OP_REPLACE: 7681, // gl.REPLACE - STENCIL_OP_INCR: 7682, // gl.INCR - STENCIL_OP_INCR_WRAP: 34055, // gl.INCR_WRAP - STENCIL_OP_DECR: 7683, // gl.DECR - STENCIL_OP_DECR_WRAP: 34056, // gl.DECR_WRAP - STENCIL_OP_INVERT: 5386, // gl.INVERT - - // cull - CULL_NONE: 0, - CULL_FRONT: 1028, - CULL_BACK: 1029, - CULL_FRONT_AND_BACK: 1032, - - // primitive type - PT_POINTS: 0, // gl.POINTS - PT_LINES: 1, // gl.LINES - PT_LINE_LOOP: 2, // gl.LINE_LOOP - PT_LINE_STRIP: 3, // gl.LINE_STRIP - PT_TRIANGLES: 4, // gl.TRIANGLES - PT_TRIANGLE_STRIP: 5, // gl.TRIANGLE_STRIP - PT_TRIANGLE_FAN: 6, // gl.TRIANGLE_FAN -}; - -/** - * @method attrTypeBytes - * @param {ATTR_TYPE_*} attrType - */ -function attrTypeBytes(attrType) { - if (attrType === enums.ATTR_TYPE_INT8) { - return 1; - } else if (attrType === enums.ATTR_TYPE_UINT8) { - return 1; - } else if (attrType === enums.ATTR_TYPE_INT16) { - return 2; - } else if (attrType === enums.ATTR_TYPE_UINT16) { - return 2; - } else if (attrType === enums.ATTR_TYPE_INT32) { - return 4; - } else if (attrType === enums.ATTR_TYPE_UINT32) { - return 4; - } else if (attrType === enums.ATTR_TYPE_FLOAT32) { - return 4; - } - - console.warn(("Unknown ATTR_TYPE: " + attrType)); - return 0; -} - -/** - * @method glTextureFmt - * @param {TEXTURE_FMT_*} fmt - */ -function glTextureFmt(fmt) { - var result = _textureFmtGL[fmt]; - if (result === undefined) { - console.warn(("Unknown TEXTURE_FMT: " + fmt)); - return _textureFmtGL[enums.TEXTURE_FMT_RGBA8]; - } - - return result; -} - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gfx = window.gfx; - -// ==================== -// exports -// ==================== - -var VertexFormat = function VertexFormat(infos) { - var this$1 = this; - - this._attr2el = {}; - this._elements = []; - this._bytes = 0; - - var offset = 0; - for (var i = 0, len = infos.length; i < len; ++i) { - var info = infos[i]; - var el = { - name: info.name, - offset: offset, - stride: 0, - stream: -1, - type: info.type, - num: info.num, - normalize: (info.normalize === undefined) ? false : info.normalize, - bytes: info.num * attrTypeBytes(info.type), - }; - // log('info.num is:' + info.num + ' attrTypeBytes(info.type) is:' + attrTypeBytes(info.type)); - - this$1._attr2el[el.name] = el; - this$1._elements.push(el); - - this$1._bytes += el.bytes; - offset += el.bytes; - } - - for (var i$1 = 0, len$1 = this._elements.length; i$1 < len$1; ++i$1) { - var el$1 = this$1._elements[i$1]; - el$1.stride = this$1._bytes; - } - - this._nativeObj = new gfx.VertexFormatNative(this._elements); -}; - -/** - * @method element - * @param {string} attrName - */ -VertexFormat.prototype.element = function element (attrName) { - return this._attr2el[attrName]; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gl$1 = window.__gl; -var gfx$1 = window.gfx; - -var _tmpGetSetDesc = { - get: undefined, - set: undefined, - enumerable: true, - configurable: true -}; - -window.device = gfx$1.Device.getInstance(); -window.device._gl = window.__gl; - -//FIXME: -window.device._stats = { vb: 0 }; -window.device._caps = { - maxVextexTextures: 16, - maxFragUniforms: 1024, - maxTextureUints: 8, - maxVertexAttributes: 16, - maxDrawBuffers: 8, - maxColorAttatchments: 8 -}; - -device.setBlendColor32 = device.setBlendColor; - -var _p = gfx$1.Program.prototype; -_p._ctor = function(device, options) { - this.init(device, options.vert, options.frag); -}; - -_p = gfx$1.VertexBuffer.prototype; -_p._ctor = function(device, format, usage, data, numVertices) { - this.init(device, format._nativeObj, usage, data, numVertices); - this._nativePtr = this.self(); -}; -_tmpGetSetDesc.get = _p.getCount; -_tmpGetSetDesc.set = undefined; -Object.defineProperty(_p, "count", _tmpGetSetDesc); - -_p = gfx$1.IndexBuffer.prototype; -_p._ctor = function(device, format, usage, data, numIndices) { - this.init(device, format, usage, data, numIndices); - this._nativePtr = this.self(); -}; -_tmpGetSetDesc.get = _p.getCount; -_tmpGetSetDesc.set = undefined; -Object.defineProperty(_p, "count", _tmpGetSetDesc); - -gfx$1.VertexFormat = VertexFormat; -Object.assign(gfx$1, enums); - -function convertImages(images) { - if (images) { - for (var i = 0, len = images.length; i < len; ++i) { - var image = images[i]; - if (image !== null) { - if (image instanceof window.HTMLCanvasElement) { - if (image._data) { - images[i] = image._data._data; - } - else { - images[i] = null; - } - } - else if (image instanceof window.HTMLImageElement) { - images[i] = image._data; - } - } - } - } -} - -function convertOptions(options) { - if (options.images && options.images[0] instanceof HTMLImageElement) { - var image = options.images[0]; - options.glInternalFormat = image._glInternalFormat; - options.glFormat = image._glFormat; - options.glType = image._glType; - options.bpp = image._bpp; - options.compressed = image._compressed; - options.premultiplyAlpha = image._premultiplyAlpha; - } - else if (options.images && options.images[0] instanceof HTMLCanvasElement) { - options.glInternalFormat = gl$1.RGBA; - options.glFormat = gl$1.RGBA; - options.glType = gl$1.UNSIGNED_BYTE; - options.bpp = 32; - options.compressed = false; - } - else { - var gltf = glTextureFmt(options.format); - options.glInternalFormat = gltf.internalFormat; - options.glFormat = gltf.format; - options.glType = gltf.pixelType; - options.bpp = gltf.bpp; - options.compressed = options.glFormat >= enums.TEXTURE_FMT_RGB_DXT1 && - options.glFormat <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1; - } - - convertImages(options.images); -} - -_p = gfx$1.Texture2D.prototype; -_p._ctor = function(device, options) { - convertOptions(options); - this.init(device, options); -}; -_p.destroy = function() { -}; -_p.update = function(options) { - convertOptions(options); - this.updateNative(options); -}; -_p.updateSubImage = function(option) { - var images = [option.image]; - convertImages(images); - var data = new Uint32Array(8 + - (images[0].length + 3) / 4); - - data[0] = option.x; - data[1] = option.y; - data[2] = option.width; - data[3] = option.height; - data[4] = option.level; - data[5] = option.flipY; - data[6] = false; - data[7] = images[0].length; - var imageData = new Uint8Array(data.buffer); - imageData.set(images[0], 32); - - this.updateSubImageNative(data); -}; -_tmpGetSetDesc.get = _p.getWidth; -_tmpGetSetDesc.set = undefined; -Object.defineProperty(_p, "_width", _tmpGetSetDesc); -_tmpGetSetDesc.get = _p.getHeight; -Object.defineProperty(_p, "_height", _tmpGetSetDesc); - -_p = gfx$1.FrameBuffer.prototype; -_p._ctor = function(device, width, height, options) { - this.init(device, width, height, options); -}; - -gfx$1.RB_FMT_D16 = 0x81A5; // GL_DEPTH_COMPONENT16 hack for JSB - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gfx$3 = window.gfx; - -var InputAssembler = function InputAssembler(vb, ib, pt) { - if ( pt === void 0 ) pt = gfx$3.PT_TRIANGLES; - - this._vertexBuffer = vb; - this._indexBuffer = ib; - this._primitiveType = pt; - this._start = 0; - this._count = -1; - - // TODO: instancing data - // this._stream = 0; -}; - -InputAssembler.prototype.getPrimitiveCount = function getPrimitiveCount () { - if (this._count !== -1) { - return this._count; - } - - if (this._indexBuffer) { - return this._indexBuffer.count; - } - - return this._vertexBuffer.count; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var renderer = window.renderer; -var _stageOffset = 0; -var _name2stageID = {}; - -var config = { - addStage: function (name) { - // already added - if (_name2stageID[name] !== undefined) { - return; - } - - var stageID = 1 << _stageOffset; - _name2stageID[name] = stageID; - - _stageOffset += 1; - - renderer.addStage(name); - }, - - stageID: function (name) { - var id = _name2stageID[name]; - if (id === undefined) { - return -1; - } - return id; - }, - - stageIDs: function (nameList) { - var key = 0; - for (var i = 0; i < nameList.length; ++i) { - var id = _name2stageID[nameList[i]]; - if (id !== undefined) { - key |= id; - } - } - return key; - } -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var renderer$1 = window.renderer; - -var Effect = function Effect(techniques, properties, defines) { - if ( properties === void 0 ) properties = {}; - if ( defines === void 0 ) defines = []; - - this._techniques = techniques; - this._properties = properties; - this._defines = defines; - - var techniqueObjs = []; - var techniqueObj; - for (var i = 0, len = techniques.length; i < len; ++i) { - techniqueObj = techniques[i]._nativeObj; - techniqueObjs.push(techniqueObj); - } - - this._nativeObj = new renderer$1.EffectNative(); - this._nativeObj.init(techniqueObjs, properties, defines); - this._nativePtr = this._nativeObj.self(); - - // TODO: check if params is valid for current technique??? -}; - -Effect.prototype.updateHash = function updateHash (hash) { - this._nativeObj.updateHash(hash); -}; - -Effect.prototype.clear = function clear () { - this._techniques.length = 0; - this._properties = null; - this._defines.length = 0; -}; - -Effect.prototype.getTechnique = function getTechnique (stage) { - var this$1 = this; - - var stageID = config.stageID(stage); - for (var i = 0; i < this._techniques.length; ++i) { - var tech = this$1._techniques[i]; - if (tech.stageIDs & stageID) { - return tech; - } - } - - return null; -}; - -Effect.prototype.getProperty = function getProperty (name) { - return this._properties[name]; -}; - -Effect.prototype.setProperty = function setProperty (name, value) { - // TODO: check if params is valid for current technique??? - this._properties[name] = value; - this._nativeObj.setProperty(name, value); -}; - -Effect.prototype.getDefine = function getDefine (name) { - var this$1 = this; - - for (var i = 0; i < this._defines.length; ++i) { - var def = this$1._defines[i]; - if ( def.name === name ) { - return def.value; - } - } - - console.warn(("Failed to get define " + name + ", define not found.")); - return null; -}; - -Effect.prototype.define = function define (name, value) { - var this$1 = this; - - for (var i = 0; i < this._defines.length; ++i) { - var def = this$1._defines[i]; - if ( def.name === name ) { - def.value = value; - this$1._nativeObj.setDefineValue(name, value); - return; - } - } - - console.warn(("Failed to set define " + name + ", define not found.")); -}; - -Effect.prototype.extractDefines = function extractDefines (out) { - var this$1 = this; - if ( out === void 0 ) out = {}; - - for (var i = 0; i < this._defines.length; ++i) { - var def = this$1._defines[i]; - out[def.name] = def.value; - } - - return out; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var renderer$2 = window.renderer; -var _genID = 0; - -var Technique = function Technique(stages, parameters, passes, layer) { - if ( layer === void 0 ) layer = 0; - - this._id = _genID++; - this._stageIDs = config.stageIDs(stages); - this.stageIDs = this._stageIDs; - this._parameters = parameters; // {name, type, size, val} - this._passes = passes; - this.passes = this._passes; - this._layer = layer; - this._stages = stages; - // TODO: this._version = 'webgl' or 'webgl2' // ???? - - var passesNative = []; - for (var i = 0, len = passes.length; i < len; ++i) { - passesNative.push(passes[i]._native); - } - this._nativeObj = new renderer$2.TechniqueNative(stages, parameters, passesNative, layer); - -}; - -Technique.prototype.copy = function copy (technique) { - var this$1 = this; - - this._id = technique._id; - this._stageIDs = technique._stageIDs; - - this._parameters = []; - for (var i = 0; i < technique._parameters.length; ++i) { - var parameter = technique._parameters[i]; - this$1._parameters.push({name: parameter.name, type: parameter.type}); - } - - for (var i$1 = 0; i$1 < technique._passes.length; ++i$1) { - var pass = this$1._passes[i$1]; - if (!pass) { - pass = new renderer$2.Pass(); - this$1._passes.push(pass); - } - pass.copy(technique._passes[i$1]); - } - this._passes.length = technique._passes.length; - this._layer = technique._layer; -}; - -Technique.prototype.setStages = function setStages (stages) { - this._stageIDs = config.stageIDs(stages); - this._stages = stages; - - this._nativeObj.setStages(stages); -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gfx$4 = window.gfx; -var renderer$3 = window.renderer; - -var Pass = function Pass(name) { - this._programName = name; - - // cullmode - this._cullMode = gfx$4.CULL_BACK; - - // blending - this._blend = false; - this._blendEq = gfx$4.BLEND_FUNC_ADD; - this._blendAlphaEq = gfx$4.BLEND_FUNC_ADD; - this._blendSrc = gfx$4.BLEND_ONE; - this._blendDst = gfx$4.BLEND_ZERO; - this._blendSrcAlpha = gfx$4.BLEND_ONE; - this._blendDstAlpha = gfx$4.BLEND_ZERO; - this._blendColor = 0xffffffff; - - // depth - this._depthTest = false; - this._depthWrite = false; - this._depthFunc = gfx$4.DS_FUNC_LESS; - - // stencil - this._stencilTest = false; - // front - this._stencilFuncFront = gfx$4.DS_FUNC_ALWAYS; - this._stencilRefFront = 0; - this._stencilMaskFront = 0xff; - this._stencilFailOpFront = gfx$4.STENCIL_OP_KEEP; - this._stencilZFailOpFront = gfx$4.STENCIL_OP_KEEP; - this._stencilZPassOpFront = gfx$4.STENCIL_OP_KEEP; - this._stencilWriteMaskFront = 0xff; - // back - this._stencilFuncBack = gfx$4.DS_FUNC_ALWAYS; - this._stencilRefBack = 0; - this._stencilMaskBack = 0xff; - this._stencilFailOpBack = gfx$4.STENCIL_OP_KEEP; - this._stencilZFailOpBack = gfx$4.STENCIL_OP_KEEP; - this._stencilZPassOpBack = gfx$4.STENCIL_OP_KEEP; - this._stencilWriteMaskBack = 0xff; - - var binary = new Uint32Array(25); - binary[0] = this._cullMode; - binary[1] = this._blendEq; - binary[2] = this._blendSrc; - binary[3] = this._blendDst; - binary[4] = this._blendAlphaEq; - binary[5] = this._blendSrcAlpha; - binary[6] = this._blendDstAlpha; - binary[7] = this._blendColor; - binary[8] = this._depthTest; - binary[9] = this._depthWrite; - binary[10] = this._depthFunc; - binary[11] = this._stencilFuncFront; - binary[12] = this._stencilRefFront; - binary[13] = this._stencilMaskFront; - binary[14] = this._stencilFailOpFront; - binary[15] = this._stencilZFailOpFront; - binary[16] = this._stencilZPassOpFront; - binary[17] = this._stencilWriteMaskFront; - binary[18] = this._stencilFuncBack; - binary[19] = this._stencilRefBack; - binary[20] = this._stencilMaskBack; - binary[21] = this._stencilFailOpBack; - binary[22] = this._stencilZFailOpBack; - binary[23] = this._stencilZPassOpBack; - binary[24] = this._stencilWriteMaskBack; - this._native = new renderer$3.PassNative(); - this._native.init(this._programName, binary); -}; - -Pass.prototype.copy = function copy (pass) { - this._programName = pass._programName; - // cullmode - this._cullMode = pass._cullMode; - // blending - this._blend = pass._blend; - this._blendEq = pass._blendEq; - this._blendAlphaEq = pass._blendAlphaEq; - this._blendSrc = pass._blendSrc; - this._blendDst = pass._blendDst; - this._blendSrcAlpha = pass._blendSrcAlpha; - this._blendDstAlpha = pass._blendDstAlpha; - this._blendColor = pass._blendColor; - // depth - this._depthTest = pass._depthTest; - this._depthWrite = pass._depthWrite; - this._depthFunc = pass._depthFunc; - this._stencilTest = pass._stencilTest; - // front - this._stencilFuncFront = pass._stencilFuncFront; - this._stencilRefFront = pass._stencilRefFront; - this._stencilMaskFront = pass._stencilMaskFront; - this._stencilFailOpFront = pass._stencilFailOpFront; - this._stencilZFailOpFront = pass._stencilZFailOpFront; - this._stencilZPassOpFront = pass._stencilZPassOpFront; - this._stencilWriteMaskFront = pass._stencilWriteMaskFront; - // back - this._stencilFuncBack = pass._stencilFuncBack; - this._stencilRefBack = pass._stencilRefBack; - this._stencilMaskBack = pass._stencilMaskBack; - this._stencilFailOpBack = pass._stencilFailOpBack; - this._stencilZFailOpBack = pass._stencilZFailOpBack; - this._stencilZPassOpBack = pass._stencilZPassOpBack; - this._stencilWriteMaskBack = pass._stencilWriteMaskBack; -}; - -Pass.prototype.setCullMode = function setCullMode (cullMode) { - this._cullMode = cullMode; - - this._native.setCullMode(cullMode); -}; - -Pass.prototype.disableStecilTest = function disableStecilTest () { - this._stencilTest = false; - - this._native.disableStecilTest(); -}; - -Pass.prototype.setBlend = function setBlend ( - blendEq, - blendSrc, - blendDst, - blendAlphaEq, - blendSrcAlpha, - blendDstAlpha, - blendColor -) { - if ( blendEq === void 0 ) blendEq = gfx$4.BLEND_FUNC_ADD; - if ( blendSrc === void 0 ) blendSrc = gfx$4.BLEND_ONE; - if ( blendDst === void 0 ) blendDst = gfx$4.BLEND_ZERO; - if ( blendAlphaEq === void 0 ) blendAlphaEq = gfx$4.BLEND_FUNC_ADD; - if ( blendSrcAlpha === void 0 ) blendSrcAlpha = gfx$4.BLEND_ONE; - if ( blendDstAlpha === void 0 ) blendDstAlpha = gfx$4.BLEND_ZERO; - if ( blendColor === void 0 ) blendColor = 0xffffffff; - - this._blend = true; - this._blendEq = blendEq; - this._blendSrc = blendSrc; - this._blendDst = blendDst; - this._blendAlphaEq = blendAlphaEq; - this._blendSrcAlpha = blendSrcAlpha; - this._blendDstAlpha = blendDstAlpha; - this._blendColor = blendColor; - - this._native.setBlend(blendEq, - blendSrc, - blendDst, - blendAlphaEq, - blendSrcAlpha, - blendDstAlpha, - blendColor); -}; - -Pass.prototype.setDepth = function setDepth ( - depthTest, - depthWrite, - depthFunc -) { - if ( depthTest === void 0 ) depthTest = false; - if ( depthWrite === void 0 ) depthWrite = false; - if ( depthFunc === void 0 ) depthFunc = gfx$4.DS_FUNC_LESS; - - this._depthTest = depthTest; - this._depthWrite = depthWrite; - this._depthFunc = depthFunc; - - this._native.setDepth(depthTest, depthWrite, depthFunc); -}; - -Pass.prototype.setStencilFront = function setStencilFront ( - stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask -) { - if ( stencilFunc === void 0 ) stencilFunc = gfx$4.DS_FUNC_ALWAYS; - if ( stencilRef === void 0 ) stencilRef = 0; - if ( stencilMask === void 0 ) stencilMask = 0xff; - if ( stencilFailOp === void 0 ) stencilFailOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilZFailOp === void 0 ) stencilZFailOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilZPassOp === void 0 ) stencilZPassOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilWriteMask === void 0 ) stencilWriteMask = 0xff; - - this._stencilTest = true; - this._stencilFuncFront = stencilFunc; - this._stencilRefFront = stencilRef; - this._stencilMaskFront = stencilMask; - this._stencilFailOpFront = stencilFailOp; - this._stencilZFailOpFront = stencilZFailOp; - this._stencilZPassOpFront = stencilZPassOp; - this._stencilWriteMaskFront = stencilWriteMask; - - this._native.setStencilFront(stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask); -}; - -Pass.prototype.setStencilBack = function setStencilBack ( - stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask -) { - if ( stencilFunc === void 0 ) stencilFunc = gfx$4.DS_FUNC_ALWAYS; - if ( stencilRef === void 0 ) stencilRef = 0; - if ( stencilMask === void 0 ) stencilMask = 0xff; - if ( stencilFailOp === void 0 ) stencilFailOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilZFailOp === void 0 ) stencilZFailOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilZPassOp === void 0 ) stencilZPassOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilWriteMask === void 0 ) stencilWriteMask = 0xff; - - this._stencilTest = true; - this._stencilFuncBack = stencilFunc; - this._stencilRefBack = stencilRef; - this._stencilMaskBack = stencilMask; - this._stencilFailOpBack = stencilFailOp; - this._stencilZFailOpBack = stencilZFailOp; - this._stencilZPassOpBack = stencilZPassOp; - this._stencilWriteMaskBack = stencilWriteMask; - - this._native.setStencilBack(stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask); -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Model = function Model() { - this._poolID = -1; - this._node = null; - this._inputAssemblers = []; - this._effects = []; - this._defines = []; - this._dynamicIA = false; - this._viewID = -1; - - // TODO: we calculate aabb based on vertices - // this._aabb -}; - -var prototypeAccessors = { inputAssemblerCount: { configurable: true },dynamicIA: { configurable: true },drawItemCount: { configurable: true } }; - -prototypeAccessors.inputAssemblerCount.get = function () { - return this._inputAssemblers.length; -}; - -prototypeAccessors.dynamicIA.get = function () { - return this._dynamicIA; -}; - -prototypeAccessors.drawItemCount.get = function () { - return this._dynamicIA ? 1 : this._inputAssemblers.length; -}; - -Model.prototype.setNode = function setNode (node) { - this._node = node; -}; - -Model.prototype.setDynamicIA = function setDynamicIA (enabled) { - this._dynamicIA = enabled; -}; - -Model.prototype.addInputAssembler = function addInputAssembler (ia) { - if (this._inputAssemblers.indexOf(ia) !== -1) { - return; - } - this._inputAssemblers.push(ia); -}; - -Model.prototype.clearInputAssemblers = function clearInputAssemblers () { - this._inputAssemblers.length = 0; -}; - -Model.prototype.addEffect = function addEffect (effect) { - if (this._effects.indexOf(effect) !== -1) { - return; - } - this._effects.push(effect); - - // - // let defs = Object.create(null); - // effect.extractDefines(defs); - // this._defines.push(defs); -}; - -Model.prototype.clearEffects = function clearEffects () { - this._effects.length = 0; - this._defines.length = 0; -}; - -Model.prototype.extractDrawItem = function extractDrawItem (out, index) { - if (this._dynamicIA) { - out.model = this; - out.node = this._node; - out.ia = null; - out.effect = this._effects[0]; - out.defines = out.effect.extractDefines(this._defines[0]); - - return; - } - - if (index >= this._inputAssemblers.length ) { - out.model = null; - out.node = null; - out.ia = null; - out.effect = null; - out.defines = null; - - return; - } - - out.model = this; - out.node = this._node; - out.ia = this._inputAssemblers[index]; - - var effect, defines; - if (index < this._effects.length) { - effect = this._effects[index]; - defines = this._defines[index]; - } else { - effect = this._effects[this._effects.length-1]; - defines = this._defines[this._effects.length-1]; - } - out.effect = effect; - out.defines = effect.extractDefines(defines); -}; - -Object.defineProperties( Model.prototype, prototypeAccessors ); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var renderer$4 = window.renderer; - -// projection -renderer$4.PROJ_PERSPECTIVE = 0; -renderer$4.PROJ_ORTHO = 1; - -// lights -renderer$4.LIGHT_DIRECTIONAL = 0; -renderer$4.LIGHT_POINT = 1; -renderer$4.LIGHT_SPOT = 2; - -// shadows -renderer$4.SHADOW_NONE = 0; -renderer$4.SHADOW_HARD = 1; -renderer$4.SHADOW_SOFT = 2; - -// parameter type -renderer$4.PARAM_INT = 0; -renderer$4.PARAM_INT2 = 1; -renderer$4.PARAM_INT3 = 2; -renderer$4.PARAM_INT4 = 3; -renderer$4.PARAM_FLOAT = 4; -renderer$4.PARAM_FLOAT2 = 5; -renderer$4.PARAM_FLOAT3 = 6; -renderer$4.PARAM_FLOAT4 = 7; -renderer$4.PARAM_COLOR3 = 8; -renderer$4.PARAM_COLOR4 = 9; -renderer$4.PARAM_MAT2 = 10; -renderer$4.PARAM_MAT3 = 11; -renderer$4.PARAM_MAT4 = 12; -renderer$4.PARAM_TEXTURE_2D = 13; -renderer$4.PARAM_TEXTURE_CUBE = 14; - -// clear flags -renderer$4.CLEAR_COLOR = 1; -renderer$4.CLEAR_DEPTH = 2; -renderer$4.CLEAR_STENCIL = 4; -renderer$4.InputAssembler = InputAssembler; -renderer$4.config = config; -renderer$4.Effect = Effect; -renderer$4.Technique = Technique; -renderer$4.Pass = Pass; -renderer$4.Model = Model; - -var models = []; -var sizeOfModel = 13; -var lengthOfCachedModels = 500; -// length + 500 modles(8 for each model) -var modelsData = new Float64Array(1 + lengthOfCachedModels*sizeOfModel); -var modelsData32 = new Float32Array(modelsData.buffer); -var fillModelData = function() { - if (models.length > lengthOfCachedModels) { - modelsData = new Floa64Array(1 + models.length*sizeOfModel); - lengthOfCachedModels = models.length; - modelsData32 = new Float32Array(modelsData.buffer); - } - - modelsData[0] = models.length; - var index64 = 1; - var index32 = 2; - var model; - var worldMatrix; - var ia; - for (var i = 0, len = models.length; i < len; ++i) { - model = models[i]; - - ia = model._inputAssemblers[0]; - - // 3 elements of 64 bits data - modelsData[index64++] = model._effects[0]._nativePtr; - modelsData[index64++] = ia._vertexBuffer._nativePtr; - modelsData[index64++] = ia._indexBuffer._nativePtr; - - index32 += 6; - modelsData32[index32++] = model._dynamicIA; - modelsData32[index32++] = model._viewID; - worldMatrix = model._node.getWorldRTInAB(); - modelsData32.set(worldMatrix, index32); - index32 += 16; - - modelsData32[index32++] = ia._start; - modelsData32[index32++] = ia._count; - - index64 += 10; - } -}; - -// ForwardRenderer adapter -var _p$1 = renderer$4.ForwardRenderer.prototype; -_p$1._ctor = function(device, builtin) { - this.init(device, builtin.programTemplates, builtin.defaultTexture, window.innerWidth, window.innerHeight); -}; - -// Scene -_p$1 = renderer$4.Scene.prototype; -_p$1.addModel = function(model) { - models.push(model); -}; -_p$1.removeModel = function() {}; - var chunks = { 'skinning.vert': '\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}', }; @@ -2218,7 +1053,7 @@ var FixedArray = function FixedArray(size) { this._data = new Array(size); }; -var prototypeAccessors$1 = { length: { configurable: true },data: { configurable: true } }; +var prototypeAccessors = { length: { configurable: true },data: { configurable: true } }; FixedArray.prototype._resize = function _resize (size) { var this$1 = this; @@ -2230,11 +1065,11 @@ FixedArray.prototype._resize = function _resize (size) { } }; -prototypeAccessors$1.length.get = function () { +prototypeAccessors.length.get = function () { return this._count; }; -prototypeAccessors$1.data.get = function () { +prototypeAccessors.data.get = function () { return this._data; }; @@ -2294,7 +1129,7 @@ FixedArray.prototype.sort = function sort$1 (cmp) { return sort(this._data, 0, this._count, cmp); }; -Object.defineProperties( FixedArray.prototype, prototypeAccessors$1 ); +Object.defineProperties( FixedArray.prototype, prototypeAccessors ); var Pool = function Pool(fn, size) { var this$1 = this; @@ -2355,17 +1190,17 @@ var LinkedArray = function LinkedArray(fn, size) { this._pool = new Pool(fn, size); }; -var prototypeAccessors$2 = { head: { configurable: true },tail: { configurable: true },length: { configurable: true } }; +var prototypeAccessors$1 = { head: { configurable: true },tail: { configurable: true },length: { configurable: true } }; -prototypeAccessors$2.head.get = function () { +prototypeAccessors$1.head.get = function () { return this._head; }; -prototypeAccessors$2.tail.get = function () { +prototypeAccessors$1.tail.get = function () { return this._tail; }; -prototypeAccessors$2.length.get = function () { +prototypeAccessors$1.length.get = function () { return this._count; }; @@ -2427,7 +1262,7 @@ LinkedArray.prototype.forEach = function forEach (fn, binder) { } }; -Object.defineProperties( LinkedArray.prototype, prototypeAccessors$2 ); +Object.defineProperties( LinkedArray.prototype, prototypeAccessors$1 ); var RecyclePool = function RecyclePool(fn, size) { var this$1 = this; @@ -2441,13 +1276,13 @@ var RecyclePool = function RecyclePool(fn, size) { } }; -var prototypeAccessors$3 = { length: { configurable: true },data: { configurable: true } }; +var prototypeAccessors$2 = { length: { configurable: true },data: { configurable: true } }; -prototypeAccessors$3.length.get = function () { +prototypeAccessors$2.length.get = function () { return this._count; }; -prototypeAccessors$3.data.get = function () { +prototypeAccessors$2.data.get = function () { return this._data; }; @@ -2489,7 +1324,7 @@ RecyclePool.prototype.sort = function sort$1 (cmp) { return sort(this._data, 0, this._count, cmp); }; -Object.defineProperties( RecyclePool.prototype, prototypeAccessors$3 ); +Object.defineProperties( RecyclePool.prototype, prototypeAccessors$2 ); var _bufferPools = Array(8); for (var i = 0; i < 8; ++i) { @@ -2721,7 +1556,7 @@ function murmurhash2_32_gc(str, seed) { return h >>> 0; } -var renderer$6 = window.renderer; +var renderer = window.renderer; // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. @@ -2794,33 +1629,33 @@ function computeHash(material) { continue; } switch(param.type) { - case renderer$6.PARAM_INT: - case renderer$6.PARAM_FLOAT: + case renderer.PARAM_INT: + case renderer.PARAM_FLOAT: hashData += prop + ';'; break; - case renderer$6.PARAM_INT2: - case renderer$6.PARAM_FLOAT2: + case renderer.PARAM_INT2: + case renderer.PARAM_FLOAT2: hashData += prop.x + ',' + prop.y + ';'; break; - case renderer$6.PARAM_INT4: - case renderer$6.PARAM_FLOAT4: + case renderer.PARAM_INT4: + case renderer.PARAM_FLOAT4: hashData += prop.x + ',' + prop.y + ',' + prop.z + ',' + prop.w + ';'; break; - case renderer$6.PARAM_COLOR4: + case renderer.PARAM_COLOR4: hashData += prop.r + ',' + prop.g + ',' + prop.b + ',' + prop.a + ';'; break; - case renderer$6.PARAM_MAT2: + case renderer.PARAM_MAT2: hashData += prop.m00 + ',' + prop.m01 + ',' + prop.m02 + ',' + prop.m03 + ';'; break; - case renderer$6.PARAM_TEXTURE_2D: - case renderer$6.PARAM_TEXTURE_CUBE: + case renderer.PARAM_TEXTURE_2D: + case renderer.PARAM_TEXTURE_CUBE: hashData += material._texIds[propKey] + ';'; break; - case renderer$6.PARAM_INT3: - case renderer$6.PARAM_FLOAT3: - case renderer$6.PARAM_COLOR3: - case renderer$6.PARAM_MAT3: - case renderer$6.PARAM_MAT4: + case renderer.PARAM_INT3: + case renderer.PARAM_FLOAT3: + case renderer.PARAM_COLOR3: + case renderer.PARAM_MAT3: + case renderer.PARAM_MAT4: hashData += JSON.stringify(prop) + ';'; break; default: @@ -2857,9 +1692,6 @@ var Material = (function (Asset$$1) { Material.prototype.updateHash = function updateHash (value) { this._hash = value || computeHash(this); - if (CC_JSB && this._effect) { - this._effect.updateHash(this._hash); - } }; Object.defineProperties( Material.prototype, prototypeAccessors ); @@ -2867,7 +1699,7 @@ var Material = (function (Asset$$1) { return Material; }(Asset)); -var gfx$5 = window.gfx; +var gfx = window.gfx; // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. @@ -2875,28 +1707,28 @@ var SpriteMaterial = (function (Material$$1) { function SpriteMaterial() { Material$$1.call(this, false); - var pass = new renderer$6.Pass('sprite'); + var pass = new renderer.Pass('sprite'); pass.setDepth(false, false); - pass.setCullMode(gfx$5.CULL_NONE); + pass.setCullMode(gfx.CULL_NONE); pass.setBlend( - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA, - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA, + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer$6.Technique( + var mainTech = new renderer.Technique( ['transparent'], [ - { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer$6.PARAM_COLOR4 } ], + { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, + { name: 'color', type: renderer.PARAM_COLOR4 } ], [ pass ] ); this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer$6.Effect( + this._effect = new renderer.Effect( [ mainTech ], { @@ -3004,28 +1836,28 @@ var GraySpriteMaterial = (function (Material$$1) { function GraySpriteMaterial() { Material$$1.call(this, false); - var pass = new renderer$6.Pass('gray_sprite'); + var pass = new renderer.Pass('gray_sprite'); pass.setDepth(false, false); - pass.setCullMode(gfx$5.CULL_NONE); + pass.setCullMode(gfx.CULL_NONE); pass.setBlend( - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA, - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA, + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer$6.Technique( + var mainTech = new renderer.Technique( ['transparent'], [ - { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer$6.PARAM_COLOR4 } ], + { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, + { name: 'color', type: renderer.PARAM_COLOR4 } ], [ pass ] ); this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer$6.Effect( + this._effect = new renderer.Effect( [ mainTech ], { @@ -3093,28 +1925,28 @@ var StencilMaterial = (function (Material$$1) { function StencilMaterial() { Material$$1.call(this, false); - this._pass = new renderer$6.Pass('sprite'); + this._pass = new renderer.Pass('sprite'); this._pass.setDepth(false, false); - this._pass.setCullMode(gfx$5.CULL_NONE); + this._pass.setCullMode(gfx.CULL_NONE); this._pass.setBlend( - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA, - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA, + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA ); - var mainTech = new renderer$6.Technique( + var mainTech = new renderer.Technique( ['transparent'], [ - { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, - { name: 'alphaThreshold', type: renderer$6.PARAM_FLOAT }, - { name: 'color', type: renderer$6.PARAM_COLOR4 } ], + { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, + { name: 'alphaThreshold', type: renderer.PARAM_FLOAT }, + { name: 'color', type: renderer.PARAM_COLOR4 } ], [ this._pass ] ); - this._effect = new renderer$6.Effect( + this._effect = new renderer.Effect( [ mainTech ], { @@ -10644,28 +9476,31 @@ var canvas = { Texture2D: Texture2D }; +var gfx$1 = window.gfx; +var renderer$1 = window.renderer; + // intenral // deps // Add stage to renderer -renderer$4.config.addStage('transparent'); +renderer$1.config.addStage('transparent'); var renderEngine = { // core classes Device: gfx$1.Device, - ForwardRenderer: renderer$4.ForwardRenderer, + ForwardRenderer: renderer$1.ForwardRenderer, Texture2D: gfx$1.Texture2D, // Canvas render support canvas: canvas, // render scene - Scene: renderer$4.Scene, - Camera: renderer$4.Camera, - View: renderer$4.View, - Model: renderer$4.Model, + Scene: renderer$1.Scene, + Camera: renderer$1.Camera, + View: renderer$1.View, + Model: renderer$1.Model, RenderData: RenderData, IARenderData: IARenderData, - InputAssembler: renderer$4.InputAssembler, + InputAssembler: renderer$1.InputAssembler, // assets Asset: Asset, @@ -10686,7 +9521,7 @@ var renderEngine = { // modules math: math, - renderer: renderer$4, + renderer: renderer$1, gfx: gfx$1, }; From 2090ae884e74d286531f22ec810e8f79669e6beb Mon Sep 17 00:00:00 2001 From: pandamicro Date: Mon, 26 Nov 2018 23:22:19 +0800 Subject: [PATCH 0216/1631] Fix Material updateHash adaptation --- cocos2d/core/renderer/render-engine.jsb.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index aa85f0a9d11..35fa7d6b03a 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -1692,6 +1692,9 @@ var Material = (function (Asset$$1) { Material.prototype.updateHash = function updateHash (value) { this._hash = value || computeHash(this); + if (CC_JSB && this._effect) { + this._effect.updateHash(this._hash); + } }; Object.defineProperties( Material.prototype, prototypeAccessors ); From 5e46df53bb71c516e4a534dd2519b3ce49b284fd Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 27 Nov 2018 10:38:00 +0800 Subject: [PATCH 0217/1631] fixed read property from animation clip (#3542) * fixed read property from animation clip * should not set gltf animation name to skeleton animation clip * fixed test * fixed test --- cocos2d/animation/animation-animator.js | 8 ++++---- cocos2d/core/3d/CCModel.js | 7 ------- test/qunit/lib/polyfill-for-phantom.js | 3 +++ 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/cocos2d/animation/animation-animator.js b/cocos2d/animation/animation-animator.js index 2780e546b34..77ebe24d837 100644 --- a/cocos2d/animation/animation-animator.js +++ b/cocos2d/animation/animation-animator.js @@ -226,10 +226,10 @@ function initClipData (root, state) { var curves = state.curves; curves.length = 0; - state.duration = clip.duration; - state.speed = clip.speed; - state.wrapMode = clip.wrapMode; - state.frameRate = clip.sample; + state.duration = Number.parseFloat(clip.duration); + state.speed = Number.parseFloat(clip.speed); + state.wrapMode = Number.parseInt(clip.wrapMode); + state.frameRate = Number.parseFloat(clip.sample); if ((state.wrapMode & WrapModeMask.Loop) === WrapModeMask.Loop) { state.repeatCount = Infinity; diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index 0b827277d33..69f08710857 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -268,12 +268,8 @@ let Model = cc.Class({ this._initNodes(); let gltf = this._gltf; - let bin = this._bin; - - let accessors = gltf.accessors; let gltfAnimation = gltf.animations[clip._animationID]; - clip.name = gltfAnimation.name; clip.wrapMode = cc.WrapMode.Loop; let duration = 0; @@ -281,7 +277,6 @@ let Model = cc.Class({ let paths = curveData.paths = {}; let nodes = gltf.nodes; - let rootNode = nodes[0]; let samplers = gltfAnimation.samplers; let channels = gltfAnimation.channels; @@ -292,8 +287,6 @@ let Model = cc.Class({ let inputArray = this._createArray(gltf, sampler.input); let outputArray = this._createArray(gltf, sampler.output); - let interpolation = sampler.interpolation; - let target = gltfChannel.target; let node = nodes[target.node]; diff --git a/test/qunit/lib/polyfill-for-phantom.js b/test/qunit/lib/polyfill-for-phantom.js index 9752b43255e..2238a9a4ee3 100644 --- a/test/qunit/lib/polyfill-for-phantom.js +++ b/test/qunit/lib/polyfill-for-phantom.js @@ -158,3 +158,6 @@ if (!Object.getOwnPropertySymbols) { return []; }; } + +Number.parseFloat = Number.parseFloat || parseFloat; +Number.parseInt = Number.parseInt || parseInt; From d7530216750ff563944f9d4f1c90c5f13c8388f4 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 27 Nov 2018 12:41:54 +0800 Subject: [PATCH 0218/1631] fix outline enable and disable is invaild bug (#3564) --- cocos2d/core/components/CCLabelOutline.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCLabelOutline.js b/cocos2d/core/components/CCLabelOutline.js index 95f94971a34..993721bcebe 100644 --- a/cocos2d/core/components/CCLabelOutline.js +++ b/cocos2d/core/components/CCLabelOutline.js @@ -87,10 +87,18 @@ let LabelOutline = cc.Class({ } }, + onEnable () { + this._updateRenderData() + }, + + onDisable () { + this._updateRenderData() + }, + _updateRenderData () { let label = this.node.getComponent(cc.Label); if (label) { - label._updateRenderData(true); + label._updateRenderData(); } } From 99b98d12c663dc0f697ff5161f5484c1c9644601 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 27 Nov 2018 13:40:25 +0800 Subject: [PATCH 0219/1631] improve rotateTo/rotateBy (#3563) * improve rotateTo/rotateBy * improve rotateTo/rotateBy --- cocos2d/actions/CCActionInterval.js | 182 ++++++++++++++++------------ 1 file changed, 102 insertions(+), 80 deletions(-) diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index ee5fdda61cc..c69e28843c1 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -876,8 +876,9 @@ cc.Spawn._actionOneTwo = function (action1, action2) { * @class RotateTo * @extends ActionInterval * @param {Number} duration duration in seconds - * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees. - * @param {Number} [deltaAngleY] deltaAngleY in degrees. + * @param {Number|Vec3} dstAngleX dstAngleX in degrees. + * @param {Number} [dstAngleY] dstAngleY in degrees. + * @param {Number} [dstAngleZ] dstAngleZ in degrees. * @example * var rotateTo = new cc.RotateTo(2, 61.0); */ @@ -885,12 +886,18 @@ cc.RotateTo = cc.Class({ name: 'cc.RotateTo', extends: cc.ActionInterval, - ctor:function (duration, dstAngleX, dstAngleY) { - this._angle = cc.v3(); - this._startAngle = cc.v3(); - this._dstAngle = cc.v3(); - this._need3D = false; - dstAngleX !== undefined && this.initWithDuration(duration, dstAngleX, dstAngleY); + ctor:function (duration, dstAngleX, dstAngleY, dstAngleZ) { + // for 3d + this._startQuat = cc.quat(); + this._dstQuat = cc.quat(); + + // for 2d + this._startAngle = 0; + this._dstAngle = 0; + this._angle = 0; + + this._is3D = true; + dstAngleX !== undefined && this.initWithDuration(duration, dstAngleX, dstAngleY, dstAngleZ); }, /* @@ -898,26 +905,32 @@ cc.RotateTo = cc.Class({ * @param {Number} duration * @param {Number|Vec3} dstAngleX * @param {Number} dstAngleY + * @param {Number} dstAngleZ * @return {Boolean} */ - initWithDuration:function (duration, dstAngleX, dstAngleY) { + initWithDuration:function (duration, dstAngleX, dstAngleY, dstAngleZ) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - let dstAngle = this._dstAngle; - if (dstAngleX instanceof cc.Vec3) { - dstAngle.set(dstAngleX); - if (dstAngleX.x || dstAngleX.y) { - this._need3D = true; - } - } - else if (dstAngleY !== undefined) { - dstAngle.x = dstAngleX; - dstAngle.y = dstAngleY; - dstAngle.z = 0; - this._need3D = true; + if (typeof dstAngleX === 'number' && dstAngleY === undefined) { + this._dstAngle = dstAngleX; + this._is3D = false; } else { - dstAngle.x = dstAngle.y = 0; - dstAngle.z = dstAngleX; + let dstQuat = this._dstQuat; + if (dstAngleX instanceof cc.Quat) { + dstQuat.set(dstAngleX); + } + else { + if (dstAngleX instanceof cc.Vec3) { + dstAngleY = dstAngleX.y; + dstAngleZ = dstAngleX.z; + dstAngleX = dstAngleX.x; + } + else { + dstAngleY = dstAngleY || 0; + dstAngleZ = dstAngleZ || 0; + } + cc.vmath.quat.fromEuler(dstQuat, dstAngleX, dstAngleY, dstAngleZ); + } } return true; } @@ -927,31 +940,29 @@ cc.RotateTo = cc.Class({ clone:function () { var action = new cc.RotateTo(); this._cloneDecoration(action); - action.initWithDuration(this._duration, this._dstAngle); + if (this._is3D) { + action.initWithDuration(this._duration, this._dstQuat); + } + else { + action.initWithDuration(this._duration, this._dstAngle); + } return action; }, - _formatAngle (angle) { - if (angle > 180) angle -= 360; - if (angle < -180) angle += 360; - return angle; - }, - startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - this._startAngle.set(target.eulerAngles); - - let angle = this._angle; - cc.vmath.vec3.sub(angle, this._dstAngle, this._startAngle); - - angle.x = this._formatAngle(angle.x); - angle.y = this._formatAngle(angle.y); - angle.z = this._formatAngle(angle.z); - - if (this._need3D) { + if (this._is3D) { + this._startQuat.set(target.quat); target.is3DNode = true; } + else { + this._startAngle = target.angle % 360; + let angle = this._dstAngle - this._startAngle; + if (angle > 180) angle -= 360; + if (angle < -180) angle += 360; + this._angle = angle; + } }, reverse:function () { @@ -961,17 +972,12 @@ cc.RotateTo = cc.Class({ update:function (dt) { dt = this._computeEaseTime(dt); if (this.target) { - let angle = this._angle; - let startAngle = this._startAngle; - let rotationZ = -(startAngle.z + angle.z * dt); - if (this._need3D) { - let rotationX = startAngle.x + angle.x * dt; - let rotationY = startAngle.y + angle.y * dt; - quat.fromEuler(_quat_tmp, rotationX, rotationY, rotationZ); + if (this._is3D) { + cc.vmath.quat.slerp(_quat_tmp, this._startQuat, this._dstQuat, dt); this.target.setRotation(_quat_tmp); } else { - this.target.angle = rotationZ; + this.target.angle = this._startAngle + this._angle * dt; } } } @@ -984,15 +990,16 @@ cc.RotateTo = cc.Class({ * !#zh 旋转到目标角度,通过逐帧修改它的 rotation 属性,旋转方向将由最短的角度决定。 * @method rotateTo * @param {Number} duration duration in seconds - * @param {Number} deltaAngleX deltaAngleX in degrees. - * @param {Number} [deltaAngleY] deltaAngleY in degrees. + * @param {Number} dstAngleX dstAngleX in degrees. + * @param {Number} [dstAngleY] dstAngleY in degrees. + * @param {Number} [dstAngleZ] dstAngleZ in degrees. * @return {ActionInterval} * @example * // example * var rotateTo = cc.rotateTo(2, 61.0); */ -cc.rotateTo = function (duration, deltaAngleX, deltaAngleY) { - return new cc.RotateTo(duration, deltaAngleX, deltaAngleY); +cc.rotateTo = function (duration, dstAngleX, dstAngleY, dstAngleZ) { + return new cc.RotateTo(duration, dstAngleX, dstAngleY, dstAngleZ); }; @@ -1004,6 +1011,7 @@ cc.rotateTo = function (duration, deltaAngleX, deltaAngleY) { * @param {Number} duration duration in seconds * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees * @param {Number} [deltaAngleY] deltaAngleY in degrees + * @param {Number} [deltaAngleZ] deltaAngleZ in degrees * @example * var actionBy = new cc.RotateBy(2, 360); */ @@ -1011,11 +1019,16 @@ cc.RotateBy = cc.Class({ name: 'cc.RotateBy', extends: cc.ActionInterval, - ctor: function (duration, deltaAngleX, deltaAngleY) { + ctor: function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { this._angle = cc.v3(); - this._startAngle = cc.v3(); - this._need3D = false; - deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY); + // for 3d + this._quat = cc.quat(); + // for 2d + this._startAngle = 0; + + this._lastDt = 0; + this._is3D = true; + deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY, deltaAngleZ); }, /* @@ -1023,26 +1036,26 @@ cc.RotateBy = cc.Class({ * @param {Number} duration duration in seconds * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees * @param {Number} [deltaAngleY=] deltaAngleY in degrees + * @param {Number} [deltaAngleZ=] deltaAngleZ in degrees * @return {Boolean} */ - initWithDuration:function (duration, deltaAngleX, deltaAngleY) { + initWithDuration:function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { if (deltaAngleX instanceof cc.Vec3) { - this._angle.set(deltaAngleX); - if (deltaAngleX.x || deltaAngleX.y) { - this._need3D = true; - } + deltaAngleY = deltaAngleX.y; + deltaAngleZ = deltaAngleX.z; + deltaAngleX = deltaAngleX.x; } - else if (deltaAngleY !== undefined) { - this._angle.x = deltaAngleX; - this._angle.y = deltaAngleY; - this._angle.z = 0; - this._need3D = true; + else if (deltaAngleY === undefined) { + deltaAngleZ = deltaAngleX; + deltaAngleX = deltaAngleY = 0; + this._is3D = false; } else { - this._angle.x = this._angle.y = 0; - this._angle.z = deltaAngleX; + deltaAngleY = deltaAngleY || 0; + deltaAngleZ = deltaAngleZ || 0; } + cc.vmath.vec3.set(this._angle, deltaAngleX, deltaAngleY, deltaAngleZ); return true; } return false; @@ -1052,32 +1065,40 @@ cc.RotateBy = cc.Class({ var action = new cc.RotateBy(); this._cloneDecoration(action); action.initWithDuration(this._duration, this._angle); + action._is3D = this._is3D; return action; }, startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - this._startAngle.set(target.eulerAngles); - if (this._need3D) { + if (this._is3D) { target.is3DNode = true; + this._quat.set(target.quat); } + else { + this._startAngle = target.angle; + } + this._lastDt = 0; }, update:function (dt) { dt = this._computeEaseTime(dt); if (this.target) { let angle = this._angle; - let startAngle = this._startAngle; - let rotationZ = -(startAngle.z + angle.z * dt); - if (this._need3D) { - let rotationX = startAngle.x + angle.x * dt; - let rotationY = startAngle.y + angle.y * dt; - quat.fromEuler(_quat_tmp, rotationX, rotationY, rotationZ); - this.target.setRotation(_quat_tmp); + let dstQuat = this._quat; + let delta = dt - this._lastDt; + let angleX = angle.x, angleY = angle.y, angleZ = angle.z; + if (this._is3D) { + if (angleX) cc.vmath.quat.rotateX(dstQuat, dstQuat, angleX * cc.macro.RAD * delta); + if (angleY) cc.vmath.quat.rotateY(dstQuat, dstQuat, angleY * cc.macro.RAD * delta); + if (angleZ) cc.vmath.quat.rotateZ(dstQuat, dstQuat, angleZ * cc.macro.RAD * delta); + this.target.setRotation(dstQuat); } else { - this.target.angle = rotationZ; + this.target.angle = this._startAngle + angleZ * dt; } + + this._lastDt = dt; } }, @@ -1102,13 +1123,14 @@ cc.RotateBy = cc.Class({ * @param {Number} duration duration in seconds * @param {Number} deltaAngleX deltaAngleX in degrees * @param {Number} [deltaAngleY] deltaAngleY in degrees + * @param {Number} [deltaAngleZ] deltaAngleZ in degrees * @return {ActionInterval} * @example * // example * var actionBy = cc.rotateBy(2, 360); */ -cc.rotateBy = function (duration, deltaAngleX, deltaAngleY) { - return new cc.RotateBy(duration, deltaAngleX, deltaAngleY); +cc.rotateBy = function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { + return new cc.RotateBy(duration, deltaAngleX, deltaAngleY, deltaAngleZ); }; From 9815dde7de968d610e12bc2a2e3a504c2d43c73e Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 27 Nov 2018 15:15:16 +0800 Subject: [PATCH 0220/1631] improve rotateTo/rotateBy (#3565) * improve rotateTo/rotateBy * improve rotateTo/rotateBy * improve rotateTo/rotateBy * improve rotateTo/rotateBy * improve rotateTo/rotateBy --- cocos2d/actions/CCActionInterval.js | 177 +++++------------------ cocos2d/core/3d/actions.js | 215 ++++++++++++++++++++++++++++ cocos2d/core/3d/index.js | 1 + 3 files changed, 251 insertions(+), 142 deletions(-) create mode 100644 cocos2d/core/3d/actions.js diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index c69e28843c1..e904b3b2cb8 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -25,10 +25,6 @@ THE SOFTWARE. ****************************************************************************/ -const quat = cc.vmath.quat; -let _quat_tmp = cc.quat(); -let _vec3_tmp = cc.v3(); - /** * @module cc @@ -871,14 +867,12 @@ cc.Spawn._actionOneTwo = function (action1, action2) { /* - * Rotates a Node object to a certain angle by modifying its rotation property.
+ * Rotates a Node object to a certain angle by modifying its angle property.
* The direction will be decided by the shortest angle. * @class RotateTo * @extends ActionInterval * @param {Number} duration duration in seconds - * @param {Number|Vec3} dstAngleX dstAngleX in degrees. - * @param {Number} [dstAngleY] dstAngleY in degrees. - * @param {Number} [dstAngleZ] dstAngleZ in degrees. + * @param {Number} dstAngle dstAngle in degrees. * @example * var rotateTo = new cc.RotateTo(2, 61.0); */ @@ -886,52 +880,22 @@ cc.RotateTo = cc.Class({ name: 'cc.RotateTo', extends: cc.ActionInterval, - ctor:function (duration, dstAngleX, dstAngleY, dstAngleZ) { - // for 3d - this._startQuat = cc.quat(); - this._dstQuat = cc.quat(); - - // for 2d + ctor:function (duration, dstAngle) { this._startAngle = 0; this._dstAngle = 0; this._angle = 0; - - this._is3D = true; - dstAngleX !== undefined && this.initWithDuration(duration, dstAngleX, dstAngleY, dstAngleZ); + dstAngle !== undefined && this.initWithDuration(duration, dstAngle); }, /* * Initializes the action. * @param {Number} duration - * @param {Number|Vec3} dstAngleX - * @param {Number} dstAngleY - * @param {Number} dstAngleZ + * @param {Number} dstAngle * @return {Boolean} */ - initWithDuration:function (duration, dstAngleX, dstAngleY, dstAngleZ) { + initWithDuration:function (duration, dstAngle) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - if (typeof dstAngleX === 'number' && dstAngleY === undefined) { - this._dstAngle = dstAngleX; - this._is3D = false; - } - else { - let dstQuat = this._dstQuat; - if (dstAngleX instanceof cc.Quat) { - dstQuat.set(dstAngleX); - } - else { - if (dstAngleX instanceof cc.Vec3) { - dstAngleY = dstAngleX.y; - dstAngleZ = dstAngleX.z; - dstAngleX = dstAngleX.x; - } - else { - dstAngleY = dstAngleY || 0; - dstAngleZ = dstAngleZ || 0; - } - cc.vmath.quat.fromEuler(dstQuat, dstAngleX, dstAngleY, dstAngleZ); - } - } + this._dstAngle = dstAngle; return true; } return false; @@ -940,29 +904,18 @@ cc.RotateTo = cc.Class({ clone:function () { var action = new cc.RotateTo(); this._cloneDecoration(action); - if (this._is3D) { - action.initWithDuration(this._duration, this._dstQuat); - } - else { - action.initWithDuration(this._duration, this._dstAngle); - } + action.initWithDuration(this._duration, this._dstAngle); return action; }, startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - if (this._is3D) { - this._startQuat.set(target.quat); - target.is3DNode = true; - } - else { - this._startAngle = target.angle % 360; - let angle = this._dstAngle - this._startAngle; - if (angle > 180) angle -= 360; - if (angle < -180) angle += 360; - this._angle = angle; - } + this._startAngle = target.angle % 360; + let angle = this._dstAngle - this._startAngle; + if (angle > 180) angle -= 360; + if (angle < -180) angle += 360; + this._angle = angle; }, reverse:function () { @@ -972,46 +925,36 @@ cc.RotateTo = cc.Class({ update:function (dt) { dt = this._computeEaseTime(dt); if (this.target) { - if (this._is3D) { - cc.vmath.quat.slerp(_quat_tmp, this._startQuat, this._dstQuat, dt); - this.target.setRotation(_quat_tmp); - } - else { - this.target.angle = this._startAngle + this._angle * dt; - } + this.target.angle = this._startAngle + this._angle * dt; } } }); /** * !#en - * Rotates a Node object to a certain angle by modifying its rotation property.
+ * Rotates a Node object to a certain angle by modifying its angle property.
* The direction will be decided by the shortest angle. - * !#zh 旋转到目标角度,通过逐帧修改它的 rotation 属性,旋转方向将由最短的角度决定。 + * !#zh 旋转到目标角度,通过逐帧修改它的 angle 属性,旋转方向将由最短的角度决定。 * @method rotateTo * @param {Number} duration duration in seconds - * @param {Number} dstAngleX dstAngleX in degrees. - * @param {Number} [dstAngleY] dstAngleY in degrees. - * @param {Number} [dstAngleZ] dstAngleZ in degrees. + * @param {Number} dstAngle dstAngle in degrees. * @return {ActionInterval} * @example * // example * var rotateTo = cc.rotateTo(2, 61.0); */ -cc.rotateTo = function (duration, dstAngleX, dstAngleY, dstAngleZ) { - return new cc.RotateTo(duration, dstAngleX, dstAngleY, dstAngleZ); +cc.rotateTo = function (duration, dstAngle) { + return new cc.RotateTo(duration, dstAngle); }; /* - * Rotates a Node object clockwise a number of degrees by modifying its rotation property. + * Rotates a Node object clockwise a number of degrees by modifying its angle property. * Relative to its properties to modify. * @class RotateBy * @extends ActionInterval * @param {Number} duration duration in seconds - * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees - * @param {Number} [deltaAngleY] deltaAngleY in degrees - * @param {Number} [deltaAngleZ] deltaAngleZ in degrees + * @param {Number} deltaAngle deltaAngle in degrees * @example * var actionBy = new cc.RotateBy(2, 360); */ @@ -1019,43 +962,21 @@ cc.RotateBy = cc.Class({ name: 'cc.RotateBy', extends: cc.ActionInterval, - ctor: function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { - this._angle = cc.v3(); - // for 3d - this._quat = cc.quat(); - // for 2d + ctor: function (duration, deltaAngle) { + this._deltaAngle = cc.v3(); this._startAngle = 0; - - this._lastDt = 0; - this._is3D = true; - deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY, deltaAngleZ); + deltaAngle !== undefined && this.initWithDuration(duration, deltaAngle); }, /* * Initializes the action. * @param {Number} duration duration in seconds - * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees - * @param {Number} [deltaAngleY=] deltaAngleY in degrees - * @param {Number} [deltaAngleZ=] deltaAngleZ in degrees + * @param {Number} deltaAngle deltaAngle in degrees * @return {Boolean} */ - initWithDuration:function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { + initWithDuration:function (duration, deltaAngle) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - if (deltaAngleX instanceof cc.Vec3) { - deltaAngleY = deltaAngleX.y; - deltaAngleZ = deltaAngleX.z; - deltaAngleX = deltaAngleX.x; - } - else if (deltaAngleY === undefined) { - deltaAngleZ = deltaAngleX; - deltaAngleX = deltaAngleY = 0; - this._is3D = false; - } - else { - deltaAngleY = deltaAngleY || 0; - deltaAngleZ = deltaAngleZ || 0; - } - cc.vmath.vec3.set(this._angle, deltaAngleX, deltaAngleY, deltaAngleZ); + this._deltaAngle = deltaAngle; return true; } return false; @@ -1064,50 +985,24 @@ cc.RotateBy = cc.Class({ clone:function () { var action = new cc.RotateBy(); this._cloneDecoration(action); - action.initWithDuration(this._duration, this._angle); - action._is3D = this._is3D; + action.initWithDuration(this._duration, this._deltaAngle); return action; }, startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - if (this._is3D) { - target.is3DNode = true; - this._quat.set(target.quat); - } - else { - this._startAngle = target.angle; - } - this._lastDt = 0; + this._startAngle = target.angle; }, update:function (dt) { dt = this._computeEaseTime(dt); if (this.target) { - let angle = this._angle; - let dstQuat = this._quat; - let delta = dt - this._lastDt; - let angleX = angle.x, angleY = angle.y, angleZ = angle.z; - if (this._is3D) { - if (angleX) cc.vmath.quat.rotateX(dstQuat, dstQuat, angleX * cc.macro.RAD * delta); - if (angleY) cc.vmath.quat.rotateY(dstQuat, dstQuat, angleY * cc.macro.RAD * delta); - if (angleZ) cc.vmath.quat.rotateZ(dstQuat, dstQuat, angleZ * cc.macro.RAD * delta); - this.target.setRotation(dstQuat); - } - else { - this.target.angle = this._startAngle + angleZ * dt; - } - - this._lastDt = dt; + this.target.angle = this._startAngle + this._deltaAngle * dt; } }, reverse:function () { - let angle = this._angle; - _vec3_tmp.x = -angle.x; - _vec3_tmp.y = -angle.y; - _vec3_tmp.z = -angle.z; - var action = new cc.RotateBy(this._duration, _vec3_tmp); + var action = new cc.RotateBy(this._duration, -this._deltaAngle); this._cloneDecoration(action); this._reverseEaseList(action); return action; @@ -1116,21 +1011,19 @@ cc.RotateBy = cc.Class({ /** * !#en - * Rotates a Node object clockwise a number of degrees by modifying its rotation property. + * Rotates a Node object clockwise a number of degrees by modifying its angle property. * Relative to its properties to modify. * !#zh 旋转指定的角度。 * @method rotateBy * @param {Number} duration duration in seconds - * @param {Number} deltaAngleX deltaAngleX in degrees - * @param {Number} [deltaAngleY] deltaAngleY in degrees - * @param {Number} [deltaAngleZ] deltaAngleZ in degrees + * @param {Number} deltaAngle deltaAngle in degrees * @return {ActionInterval} * @example * // example * var actionBy = cc.rotateBy(2, 360); */ -cc.rotateBy = function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { - return new cc.RotateBy(duration, deltaAngleX, deltaAngleY, deltaAngleZ); +cc.rotateBy = function (duration, deltaAngle) { + return new cc.RotateBy(duration, deltaAngle); }; diff --git a/cocos2d/core/3d/actions.js b/cocos2d/core/3d/actions.js new file mode 100644 index 00000000000..687aa5daa83 --- /dev/null +++ b/cocos2d/core/3d/actions.js @@ -0,0 +1,215 @@ + +const quat = cc.vmath.quat; +let _quat_tmp = cc.quat(); +let _vec3_tmp = cc.v3(); + +/* + * Rotates a Node object to a certain angle by modifying its quaternion property.
+ * The direction will be decided by the shortest angle. + * @class Rotate3DTo + * @extends ActionInterval + * @param {Number} duration duration in seconds + * @param {Number|Vec3} dstAngleX dstAngleX in degrees. + * @param {Number} [dstAngleY] dstAngleY in degrees. + * @param {Number} [dstAngleZ] dstAngleZ in degrees. + * @example + * var rotate3DTo = new cc.Rotate3DTo(2, cc.v3(0, 180, 0)); + */ +cc.Rotate3DTo = cc.Class({ + name: 'cc.Rotate3DTo', + extends: cc.ActionInterval, + + ctor:function (duration, dstAngleX, dstAngleY, dstAngleZ) { + this._startQuat = cc.quat(); + this._dstQuat = cc.quat(); + + dstAngleX !== undefined && this.initWithDuration(duration, dstAngleX, dstAngleY, dstAngleZ); + }, + + /* + * Initializes the action. + * @param {Number} duration + * @param {Number|Vec3|Quat} dstAngleX + * @param {Number} dstAngleY + * @param {Number} dstAngleZ + * @return {Boolean} + */ + initWithDuration:function (duration, dstAngleX, dstAngleY, dstAngleZ) { + if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { + let dstQuat = this._dstQuat; + if (dstAngleX instanceof cc.Quat) { + dstQuat.set(dstAngleX); + } + else { + if (dstAngleX instanceof cc.Vec3) { + dstAngleY = dstAngleX.y; + dstAngleZ = dstAngleX.z; + dstAngleX = dstAngleX.x; + } + else { + dstAngleY = dstAngleY || 0; + dstAngleZ = dstAngleZ || 0; + } + cc.vmath.quat.fromEuler(dstQuat, dstAngleX, dstAngleY, dstAngleZ); + } + return true; + } + return false; + }, + + clone:function () { + var action = new cc.Rotate3DTo(); + this._cloneDecoration(action); + action.initWithDuration(this._duration, this._dstQuat); + return action; + }, + + startWithTarget:function (target) { + cc.ActionInterval.prototype.startWithTarget.call(this, target); + this._startQuat.set(target.quat); + }, + + reverse:function () { + cc.logID(1016); + }, + + update:function (dt) { + dt = this._computeEaseTime(dt); + if (this.target) { + quat.slerp(_quat_tmp, this._startQuat, this._dstQuat, dt); + this.target.setRotation(_quat_tmp); + } + } +}); + +/** + * !#en + * Rotates a Node object to a certain angle by modifying its quternion property.
+ * The direction will be decided by the shortest angle. + * !#zh 旋转到目标角度,通过逐帧修改它的 quternion 属性,旋转方向将由最短的角度决定。 + * @method rotate3DTo + * @param {Number} duration duration in seconds + * @param {Number|Vec3|Quat} dstAngleX dstAngleX in degrees. + * @param {Number} [dstAngleY] dstAngleY in degrees. + * @param {Number} [dstAngleZ] dstAngleZ in degrees. + * @return {ActionInterval} + * @example + * // example + * var rotate3DTo = cc.rotate3DTo(2, cc.v3(0, 180, 0)); + */ +cc.rotate3DTo = function (duration, dstAngleX, dstAngleY, dstAngleZ) { + return new cc.Rotate3DTo(duration, dstAngleX, dstAngleY, dstAngleZ); +}; + + +/* + * Rotates a Node object counter clockwise a number of degrees by modifying its quaternion property. + * Relative to its properties to modify. + * @class Rotate3DBy + * @extends ActionInterval + * @param {Number} duration duration in seconds + * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees + * @param {Number} [deltaAngleY] deltaAngleY in degrees + * @param {Number} [deltaAngleZ] deltaAngleZ in degrees + * @example + * var actionBy = new cc.Rotate3DBy(2, cc.v3(0, 360, 0)); + */ +cc.Rotate3DBy = cc.Class({ + name: 'cc.Rotate3DBy', + extends: cc.ActionInterval, + + ctor: function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { + this._angle = cc.v3(); + this._quat = cc.quat(); + this._lastDt = 0; + deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY, deltaAngleZ); + }, + + /* + * Initializes the action. + * @param {Number} duration duration in seconds + * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees + * @param {Number} [deltaAngleY=] deltaAngleY in degrees + * @param {Number} [deltaAngleZ=] deltaAngleZ in degrees + * @return {Boolean} + */ + initWithDuration:function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { + if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { + if (deltaAngleX instanceof cc.Vec3) { + deltaAngleY = deltaAngleX.y; + deltaAngleZ = deltaAngleX.z; + deltaAngleX = deltaAngleX.x; + } + else { + deltaAngleY = deltaAngleY || 0; + deltaAngleZ = deltaAngleZ || 0; + } + cc.vmath.vec3.set(this._angle, deltaAngleX, deltaAngleY, deltaAngleZ); + return true; + } + return false; + }, + + clone:function () { + var action = new cc.Rotate3DBy(); + this._cloneDecoration(action); + action.initWithDuration(this._duration, this._angle); + return action; + }, + + startWithTarget:function (target) { + cc.ActionInterval.prototype.startWithTarget.call(this, target); + this._quat.set(target.quat); + this._lastDt = 0; + }, + + update: (function(){ + let RAD = Math.PI / 180; + return function (dt) { + dt = this._computeEaseTime(dt); + if (this.target) { + let angle = this._angle; + let dstQuat = this._quat; + let delta = dt - this._lastDt; + let angleX = angle.x, angleY = angle.y, angleZ = angle.z; + if (angleX) quat.rotateX(dstQuat, dstQuat, angleX * RAD * delta); + if (angleY) quat.rotateY(dstQuat, dstQuat, angleY * RAD * delta); + if (angleZ) quat.rotateZ(dstQuat, dstQuat, angleZ * RAD * delta); + this.target.setRotation(dstQuat); + + this._lastDt = dt; + } + } + })(), + + reverse:function () { + let angle = this._angle; + _vec3_tmp.x = -angle.x; + _vec3_tmp.y = -angle.y; + _vec3_tmp.z = -angle.z; + var action = new cc.Rotate3DBy(this._duration, _vec3_tmp); + this._cloneDecoration(action); + this._reverseEaseList(action); + return action; + } +}); + +/** + * !#en + * Rotates a Node object counter clockwise a number of degrees by modifying its quaternion property. + * Relative to its properties to modify. + * !#zh 旋转指定的 3D 角度。 + * @method rotate3DBy + * @param {Number} duration duration in seconds + * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees + * @param {Number} [deltaAngleY] deltaAngleY in degrees + * @param {Number} [deltaAngleZ] deltaAngleZ in degrees + * @return {ActionInterval} + * @example + * // example + * var actionBy = cc.rotate3DBy(2, cc.v3(0, 360, 0)); + */ +cc.rotate3DBy = function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { + return new cc.Rotate3DBy(duration, deltaAngleX, deltaAngleY, deltaAngleZ); +}; + diff --git a/cocos2d/core/3d/index.js b/cocos2d/core/3d/index.js index c85054a8262..97cd062485f 100644 --- a/cocos2d/core/3d/index.js +++ b/cocos2d/core/3d/index.js @@ -8,6 +8,7 @@ require('./CCModel'); require('./CCSkeleton'); require('./CCSkeletonAnimationClip'); require('./CCModelMeshResource'); +require('./actions'); if (!CC_EDITOR || !Editor.isMainProcess) { require('./CCSkeletonAnimation'); From 95a7f734958c0640c4b7d2bbccff1423ba086d42 Mon Sep 17 00:00:00 2001 From: mac <1053210246@qq.com> Date: Tue, 27 Nov 2018 16:09:37 +0800 Subject: [PATCH 0221/1631] fix when js call _onBatchRestored has not update native parent bug --- cocos2d/core/CCNode.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 843ff210009..26f72236f48 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1398,6 +1398,11 @@ let NodeDefines = { if (children.length > 0) { this._renderFlag |= RenderFlow.FLAG_CHILDREN; } + + if (CC_JSB && CC_NATIVERENDERER) { + this._proxy.setName(this._name); + this._parent && this._proxy.updateParent(this._parent._proxy); + } }, // EVENT TARGET From 6718919999d8efcde42d2ea4045b3ac82d4baa5e Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 27 Nov 2018 16:21:37 +0800 Subject: [PATCH 0222/1631] RichText support node color settings (#3560) * RichText support node color settings * refine code * refine code * remove cascade color --- cocos2d/core/CCNode.js | 27 ++++++++++++++++++++++++++- cocos2d/core/components/CCRichText.js | 10 +++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index b61a3155699..18a05e52b7e 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -60,7 +60,7 @@ const SCALE_ON = 1 << 1; const ROTATION_ON = 1 << 2; const SIZE_ON = 1 << 3; const ANCHOR_ON = 1 << 4; - +const COLOR_ON = 1 << 5; let BuiltinGroupIndex = cc.Enum({ DEBUG: 31 @@ -250,6 +250,16 @@ var EventType = cc.Enum({ * @static */ ANCHOR_CHANGED: 'anchor-changed', + /** + * !#en The event type for color change events. + * Performance note, this event will be triggered every time corresponding properties being changed, + * if the event callback have heavy logic it may have great performance impact, try to avoid such scenario. + * !#zh 当节点颜色改变时触发的事件。 + * 性能警告:这个事件会在每次对应的属性被修改时触发,如果事件回调损耗较高,有可能对性能有很大的负面影响,请尽量避免这种情况。 + * @property {String} COLOR_CHANGED + * @static + */ + COLOR_CHANGED: 'color-changed', /** * !#en The event type for new child added events. * !#zh 当新的子节点被添加时触发的事件。 @@ -941,6 +951,10 @@ var Node = cc.Class({ if (this._renderComponent) { this._renderFlag |= RenderFlow.FLAG_COLOR; } + + if (this._eventMask & COLOR_ON) { + this.emit(EventType.COLOR_CHANGED, value); + } } }, }, @@ -1436,6 +1450,7 @@ var Node = cc.Class({ * node.on(cc.Node.EventType.TOUCH_END, callback, this); * node.on(cc.Node.EventType.TOUCH_CANCEL, callback, this); * node.on(cc.Node.EventType.ANCHOR_CHANGED, callback); + * node.on(cc.Node.EventType.COLOR_CHANGED, callback); */ on (type, callback, target, useCapture) { let forDispatch = this._checknSetupSysEvent(type); @@ -1459,6 +1474,10 @@ var Node = cc.Class({ case EventType.ANCHOR_CHANGED: this._eventMask |= ANCHOR_ON; break; + case EventType.COLOR_CHANGED: + this._eventMask |= COLOR_ON; + break; + } if (!this._bubblingListeners) { this._bubblingListeners = new EventTarget(); @@ -1600,6 +1619,9 @@ var Node = cc.Class({ case EventType.ANCHOR_CHANGED: this._eventMask &= ~ANCHOR_ON; break; + case EventType.COLOR_CHANGED: + this._eventMask &= ~COLOR_ON; + break; } } } @@ -1658,6 +1680,9 @@ var Node = cc.Class({ if ((this._eventMask & ANCHOR_ON) && !listeners.hasEventListener(EventType.ANCHOR_CHANGED)) { this._eventMask &= ~ANCHOR_ON; } + if ((this._eventMask & COLOR_ON) && !listeners.hasEventListener(EventType.COLOR_CHANGED)) { + this._eventMask &= ~COLOR_ON; + } } if (this._capturingListeners) { this._capturingListeners.targetOff(target); diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index 8f587a9cce8..1a3b7d76860 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -107,7 +107,6 @@ pool.get = function (string, fontAsset, fontSize) { labelComponent._enableBold(false); labelComponent._enableItalics(false); labelComponent._enableUnderline(false); - return labelNode; }; @@ -304,12 +303,21 @@ let RichText = cc.Class({ this._onTTFLoaded(); }, + _onColorChanged (parentColor) { + let children = this.node.children; + children.forEach(function (childNode) { + childNode.color = parentColor; + }); + }, + _addEventListeners () { this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); + this.node.on(cc.Node.EventType.COLOR_CHANGED, this._onColorChanged, this); }, _removeEventListeners () { this.node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); + this.node.off(cc.Node.EventType.COLOR_CHANGED, this._onColorChanged, this); }, _updateLabelSegmentTextAttributes () { From 7e64aaf035c308c2caaac7ceaad368faa3b99409 Mon Sep 17 00:00:00 2001 From: caryliu Date: Tue, 27 Nov 2018 17:34:33 +0800 Subject: [PATCH 0223/1631] revert temp changes of spine --- cocos2d/core/renderer/render-engine.js | 13 +------------ cocos2d/core/renderer/render-engine.jsb.js | 13 +------------ 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 2d0ad6a5526..13a6a24adb2 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -13803,18 +13803,7 @@ var templates = [ { name: 'alphaTest', }, { name: 'use2DPos', }, { name: 'useColor', } ], - }, - { - name: 'skeleton', - vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', - frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', - defines: [ - { name: 'useTexture', }, - { name: 'useModel', }, - { name: 'alphaTest', }, - { name: 'use2DPos', }, - { name: 'useColor', } ], - } ]; + }]; var shaders = { chunks: chunks, diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 35fa7d6b03a..10a33c224e0 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -61,18 +61,7 @@ var templates = [ { name: 'alphaTest', }, { name: 'use2DPos', }, { name: 'useColor', } ], - }, - { - name: 'skeleton', - vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', - frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', - defines: [ - { name: 'useTexture', }, - { name: 'useModel', }, - { name: 'alphaTest', }, - { name: 'use2DPos', }, - { name: 'useColor', } ], - } ]; + }]; var shaders = { chunks: chunks, From 11cb52009ea3ff3dacc046b158d7bf3dbf1a5c05 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 27 Nov 2018 22:48:30 +0800 Subject: [PATCH 0224/1631] fixed bar-filled (#3566) --- .../webgl/assemblers/sprite/2d/bar-filled.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js index c9cb27d09e1..e2162b18569 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js @@ -123,22 +123,22 @@ module.exports = { switch (sprite._fillType) { case FillType.HORIZONTAL: data[0].u = quadUV0 + (quadUV2 - quadUV0) * fillStart; - data[0].v = quadUV1; + data[0].v = quadUV1 + (quadUV3 - quadUV1) * fillStart; data[1].u = quadUV0 + (quadUV2 - quadUV0) * fillEnd; - data[1].v = quadUV3; + data[1].v = quadUV1 + (quadUV3 - quadUV1) * fillEnd; data[2].u = quadUV4 + (quadUV6 - quadUV4) * fillStart; - data[2].v = quadUV5; + data[2].v = quadUV5 + (quadUV7 - quadUV5) * fillStart; data[3].u = quadUV4 + (quadUV6 - quadUV4) * fillEnd; - data[3].v = quadUV7; + data[3].v = quadUV5 + (quadUV7 - quadUV5) * fillEnd; break; case FillType.VERTICAL: - data[0].u = quadUV0; + data[0].u = quadUV0 + (quadUV4 - quadUV0) * fillStart; data[0].v = quadUV1 + (quadUV5 - quadUV1) * fillStart; - data[1].u = quadUV2; + data[1].u = quadUV2 + (quadUV6 - quadUV2) * fillStart; data[1].v = quadUV3 + (quadUV7 - quadUV3) * fillStart; - data[2].u = quadUV4; + data[2].u = quadUV0 + (quadUV4 - quadUV0) * fillEnd; data[2].v = quadUV1 + (quadUV5 - quadUV1) * fillEnd; - data[3].u = quadUV6; + data[3].u = quadUV2 + (quadUV6 - quadUV2) * fillEnd; data[3].v = quadUV3 + (quadUV7 - quadUV3) * fillEnd; break; default: From a67bfe6753b9d3031fe19a00f8dcf4aeaa43cbc7 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Tue, 27 Nov 2018 22:49:36 +0800 Subject: [PATCH 0225/1631] optimize children (#3552) --- cocos2d/core/renderer/render-flow.js | 10 ++++++---- cocos2d/core/value-types/color.js | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 1ca195ce06e..01f1646775d 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -110,23 +110,25 @@ _proto._children = function (node) { let cullingMask = _cullingMask; let parentOpacity = _walker.parentOpacity; - _walker.parentOpacity *= (node._opacity / 255); + let opacity = (_walker.parentOpacity *= (node._opacity / 255)); let worldTransformFlag = _walker.worldMatDirty ? WORLD_TRANSFORM : 0; let worldOpacityFlag = _walker.parentOpacityDirty ? COLOR : 0; + let worldDirtyFlag = worldTransformFlag | worldOpacityFlag; let children = node._children; for (let i = 0, l = children.length; i < l; i++) { let c = children[i]; // Advance the modification of the flag to avoid node attribute modification is invalid when opacity === 0. - c._renderFlag |= worldTransformFlag | worldOpacityFlag; + c._renderFlag |= worldDirtyFlag; if (!c._activeInHierarchy || c._opacity === 0) continue; _cullingMask = c._cullingMask = c.groupIndex === 0 ? cullingMask : 1 << c.groupIndex; // TODO: Maybe has better way to implement cascade opacity - c._color.a = c._opacity * _walker.parentOpacity; + let colorVal = c._color._val; + c._color._fastSetA(c._opacity * opacity); flows[c._renderFlag]._func(c); - c._color.a = 255; + c._color._val = colorVal; } _walker.parentOpacity = parentOpacity; diff --git a/cocos2d/core/value-types/color.js b/cocos2d/core/value-types/color.js index f521c7654da..2b25ff83efd 100644 --- a/cocos2d/core/value-types/color.js +++ b/cocos2d/core/value-types/color.js @@ -340,6 +340,10 @@ var Color = (function () { return this; }; + proto._fastSetA = function (alpha) { + this._val = ((this._val & 0x00ffffff) | ((alpha << 24) >>> 0)) >>> 0; + }; + js.getset(proto, 'r', proto.getR, proto.setR, true); js.getset(proto, 'g', proto.getG, proto.setG, true); js.getset(proto, 'b', proto.getB, proto.setB, true); From 702c2c6c0e42631294dfa88c20bbb5bcdc13761a Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 28 Nov 2018 10:44:18 +0800 Subject: [PATCH 0226/1631] fix outline enable and disable invaild / rm label updateRenderData CC_EDITOR (#3567) --- cocos2d/core/components/CCLabel.js | 6 +++--- cocos2d/core/components/CCLabelOutline.js | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 6a2ee91f3c6..93a77b5f1c1 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -527,7 +527,7 @@ let Label = cc.Class({ self._texture = spriteFrame._texture; self._activateMaterial(force); - if (CC_EDITOR || force) { + if (force) { this._assembler && this._assembler.updateRenderData(this); } }; @@ -557,7 +557,7 @@ let Label = cc.Class({ this._texture = this._ttfTexture; this._activateMaterial(force); - if (CC_EDITOR || force) { + if (force) { this._assembler && this._assembler.updateRenderData(this); } } @@ -612,7 +612,7 @@ let Label = cc.Class({ this.markForUpdateRenderData(true); } - if (CC_EDITOR || force) { + if (force) { this._updateAssembler(); this._applyFontTexture(force); } diff --git a/cocos2d/core/components/CCLabelOutline.js b/cocos2d/core/components/CCLabelOutline.js index 95f94971a34..d846be4b955 100644 --- a/cocos2d/core/components/CCLabelOutline.js +++ b/cocos2d/core/components/CCLabelOutline.js @@ -87,10 +87,18 @@ let LabelOutline = cc.Class({ } }, + onEnable () { + this._updateRenderData(); + }, + + onDisable () { + this._updateRenderData(); + }, + _updateRenderData () { let label = this.node.getComponent(cc.Label); if (label) { - label._updateRenderData(true); + label._updateRenderData(); } } From ea830ec403cb994698a60200e90577f8008d523b Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 28 Nov 2018 13:06:46 +0800 Subject: [PATCH 0227/1631] add system font to richtext (#3570) --- cocos2d/core/components/CCRichText.js | 64 ++++++++++++++++++++++++--- editor/i18n/en/localization.js | 2 + editor/i18n/zh/localization.js | 2 + 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index 1a3b7d76860..d6113103123 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -73,7 +73,7 @@ let pool = new js.Pool(function (node) { return true; }, 20); -pool.get = function (string, fontAsset, fontSize) { +pool.get = function (string, richtext) { let labelNode = this._get(); if (!labelNode) { labelNode = new cc.PrivateNode(RichTextChildName); @@ -91,16 +91,16 @@ pool.get = function (string, fontAsset, fontSize) { if (typeof string !== 'string') { string = '' + string; } - let isAsset = fontAsset instanceof cc.Font; + let isAsset = richtext.fontAsset instanceof cc.Font; if (isAsset) { - labelComponent.font = fontAsset; + labelComponent.font = richtext.fontAsset; } else { - labelComponent.fontFamily = "Arial"; + labelComponent.fontFamily = richtext.fontFamily; } labelComponent.string = string; labelComponent.horizontalAlign = HorizontalAlign.LEFT; labelComponent.verticalAlign = VerticalAlign.TOP; - labelComponent.fontSize = fontSize || 40; + labelComponent.fontSize = richtext.fontSize || 40; labelComponent.overflow = 0; labelComponent.enableWrapText = true; labelComponent.lineHeight = 40; @@ -137,6 +137,7 @@ let RichText = cc.Class({ editor: CC_EDITOR && { menu: 'i18n:MAIN_MENU.component.renderers/RichText', help: 'i18n:COMPONENT.help_url.richtext', + inspector: 'packages://inspector/inspectors/comps/richtext.js', executeInEditMode: true }, @@ -189,6 +190,26 @@ let RichText = cc.Class({ } }, + /** + * !#en Custom System font of RichText + * !#zh 富文本定制系统字体 + * @property {String} fontFamily + */ + _fontFamily: "Arial", + fontFamily: { + tooltip: CC_DEV && 'i18n:COMPONENT.richtext.font_family', + get () { + return this._fontFamily; + }, + set (value) { + if (this._fontFamily === value) return; + this._fontFamily = value; + this._layoutDirty = true; + this._updateRichTextStatus(); + }, + animatable: false + }, + /** * !#en Custom TTF font of RichText * !#zh 富文本定制字体 @@ -203,12 +224,38 @@ let RichText = cc.Class({ this._layoutDirty = true; if (this.font) { + this.useSystemFont = false; this._onTTFLoaded(); } + else { + this.useSystemFont = true; + } this._updateRichTextStatus(); } }, + /** + * !#en Whether use system font name or not. + * !#zh 是否使用系统字体。 + * @property {Boolean} isSystemFontUsed + */ + _isSystemFontUsed: true, + useSystemFont: { + get () { + return this._isSystemFontUsed; + }, + set (value) { + if (!value && !this.font || (this._isSystemFontUsed === value)) { + return; + } + this._isSystemFontUsed = value; + this._layoutDirty = true; + this._updateRichTextStatus(); + }, + animatable: false, + tooltip: CC_DEV && 'i18n:COMPONENT.richtext.system_font', + }, + /** * !#en The maximize width of the RichText * !#zh 富文本的最大宽度 @@ -327,7 +374,7 @@ let RichText = cc.Class({ }, _createFontLabel (string) { - return pool.get(string, this.font, this.fontSize); + return pool.get(string, this); }, _onTTFLoaded () { @@ -807,6 +854,11 @@ let RichText = cc.Class({ } let index = labelNode._styleIndex; + + if (this._isSystemFontUsed) { + labelComponent.fontFamily = this._fontFamily; + } + labelComponent.useSystemFont = this._isSystemFontUsed; labelComponent.lineHeight = this.lineHeight; labelComponent.horizontalAlign = HorizontalAlign.LEFT; labelComponent.verticalAlign = VerticalAlign.CENTER; diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index b8650f64d6f..41acc1e97fe 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -240,6 +240,8 @@ module.exports = { "horizontal_align": "Horizontal alignment", "font_size": "Font size, in points", "font": "Custom TTF font of RichText", + "font_family": "Custom System font of RichText", + "system_font": "Whether to use the system default font", "line_height": "Line height, in points", "max_width": "The maximize width of RichText, pass 0 means not limit the maximize width.", "image_atlas": "The image atlas for the img tag. For each src value in the img tag, there should be a valid spriteFrame in the image atlas.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 7bc3d4825ed..b20c9cc166c 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -244,6 +244,8 @@ module.exports = { "horizontal_align": "水平对齐方式", "font_size": "字体大小, 单位是 point", "font": "富文本定制字体", + "font_family": "富文本定制系统字体", + 'system_font': "是否使用系统默认字体", "line_height": "字体行高, 单位是 point", "max_width": "富文本的最大宽度, 传 0 的话意味着必须手动换行.", "image_atlas": "对于 img 标签里面的 src 属性名称,都需要在 imageAtlas 里面找到一个有效的 spriteFrame,否则 img tag 会判定为无效。", From 58efb6360cbd2711d446736af2d6b1eef782fb8f Mon Sep 17 00:00:00 2001 From: benloong Date: Wed, 28 Nov 2018 13:58:04 +0800 Subject: [PATCH 0228/1631] set playOnFocus decorate default value to true (#3568) `@playOnFocus` decorate not set `Component._playOnFocus` to true as desired `@playOnFocus(true)` works correct, but creator.d.ts type info does not match. So i think this decorate should has a default `true` value. --- cocos2d/core/platform/CCClassDecorator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCClassDecorator.js b/cocos2d/core/platform/CCClassDecorator.js index f0d6773af28..62798281179 100644 --- a/cocos2d/core/platform/CCClassDecorator.js +++ b/cocos2d/core/platform/CCClassDecorator.js @@ -587,7 +587,7 @@ var disallowMultiple = (CC_DEV ? createEditorDecorator : createDummyDecorator)(c * playOnFocus(): Function * playOnFocus(_class: Function): void */ -var playOnFocus = (CC_DEV ? createEditorDecorator : createDummyDecorator)(checkCtorArgument, 'playOnFocus'); +var playOnFocus = (CC_DEV ? createEditorDecorator : createDummyDecorator)(checkCtorArgument, 'playOnFocus', true); /** * !#en From 84a014d41d43a2b3d481c05324a36408e6c54b7e Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Thu, 29 Nov 2018 18:18:35 +0800 Subject: [PATCH 0229/1631] Fix rendering residue for transparent images on Chrome69. (#3357) (#3573) * Fix rendering residue for transparent images on Chrome69. * Disable dynamicAtlasManager to fix rendering residue for transparent images on Chrome69. --- cocos2d/core/CCGame.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 94d077cdc2a..3f622a14bf2 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -776,6 +776,10 @@ var game = { if (!cc.macro.CLEANUP_IMAGE_CACHE && dynamicAtlasManager) { dynamicAtlasManager.enabled = true; } + // Disable dynamicAtlasManager to fix rendering residue for transparent images on Chrome69. + if (cc.sys.browserType == cc.sys.BROWSER_TYPE_CHROME && parseFloat(cc.sys.browserVersion) >= 69.0) { + dynamicAtlasManager.enabled = false; + } } if (!this._renderContext) { this.renderType = this.RENDER_TYPE_CANVAS; From 87c6aa6aca35af60a646a8a7c1709ed386aead8b Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 30 Nov 2018 09:32:47 +0800 Subject: [PATCH 0230/1631] upgrade del to 3.0 (#3572) --- gulpfile.js | 22 +++++++++++----------- package.json | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index dbd088bde9b..dbb628a1b81 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -97,15 +97,15 @@ gulp.task('build-jsb', ['build-jsb-preview', 'build-jsb-dev', 'build-jsb-min']); // test // ///////// -gulp.task('clean-test', ['clean-test-cases'], function (done) { - Del([ +gulp.task('clean-test', ['clean-test-cases'], function () { + return Del([ './bin/cocos2d-js-extends-for-test.js', './bin/cocos2d-js-for-test.js', - ], done); + ]); }); -gulp.task('clean-test-cases', function (done) { - Del('./bin/test/**/*', done); +gulp.task('clean-test-cases', function () { + return Del('./bin/test/**/*'); }); gulp.task('build-test-cases', ['clean-test-cases'], function (done) { @@ -145,13 +145,13 @@ gulp.task('test-no-build', function (done) { // global // //////////// -gulp.task('clean-cache', function (done) { - Del(['./bin/.cache/*', '!./bin/.cache/dev/**'], done); +gulp.task('clean-cache', function () { + return Del(['./bin/.cache/*', '!./bin/.cache/dev/**']); }); // fast build, only for develop -gulp.task('build-dev', ['clean-cache', 'build-html5-preview', 'build-jsb-preview'], function (done) { - Del(['./bin/cocos2d-jsb-min.js', './bin/cocos2d-jsb.js'], done); +gulp.task('build-dev', ['clean-cache', 'build-html5-preview', 'build-jsb-preview'], function () { + return Del(['./bin/cocos2d-jsb-min.js', './bin/cocos2d-jsb.js']); }); // only build preview for html5 since it will built by editor @@ -160,8 +160,8 @@ gulp.task('build', ['clean-cache', 'build-html5-preview', 'build-jsb']); // default task gulp.task('default', ['build']); -gulp.task('clean', function (done) { - Del('./bin/**/*', done); +gulp.task('clean', function () { + return Del('./bin/**/*'); }); //////////// diff --git a/package.json b/package.json index 765eb8b4e6d..a0e8966c879 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "babelify": "7.3.0", "browserify": "13.0.0", "chalk": "1.1.0", - "del": "1.2.0", + "del": "3.0.0", "event-stream": "3.3.2", "fire-fs": "0.2.1", "gulp": "^3.9.1", From eee77f890b3cc97e7e79843469e9f60b8fc8fad9 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 30 Nov 2018 15:48:00 +0800 Subject: [PATCH 0231/1631] fixed texture image check in wechat game platform (#3576) --- cocos2d/core/renderer/render-engine.js | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 6477d079f57..b6bc910fdb5 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -8086,6 +8086,8 @@ function _createShader(gl, type, src) { return shader; } +const ArrayBufferView = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array)).constructor; + var Texture = function Texture(device) { this._device = device; @@ -8284,11 +8286,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { + if (!(img instanceof ArrayBufferView)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8347,11 +8345,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { + if (!(img instanceof ArrayBufferView)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8640,11 +8634,7 @@ var TextureCube = (function (Texture$$1) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { + if (!(img instanceof ArrayBufferView)) { gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); } else { if (this._compressed) { @@ -8691,11 +8681,7 @@ var TextureCube = (function (Texture$$1) { } else { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { + if (!(img instanceof ArrayBufferView)) { gl.texImage2D( gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, From 218af3bc53b6b174667caa7b2d399c63d1b85481 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 30 Nov 2018 16:45:54 +0800 Subject: [PATCH 0232/1631] refine buffer view check (#3578) --- cocos2d/core/renderer/render-engine.js | 10 ++++------ index.js | 1 + polyfill/array-buffer.js | 6 ++++++ 3 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 polyfill/array-buffer.js diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index b6bc910fdb5..16a874dd636 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -8086,8 +8086,6 @@ function _createShader(gl, type, src) { return shader; } -const ArrayBufferView = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array)).constructor; - var Texture = function Texture(device) { this._device = device; @@ -8286,7 +8284,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if (!(img instanceof ArrayBufferView)) { + if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8345,7 +8343,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if (!(img instanceof ArrayBufferView)) { + if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8634,7 +8632,7 @@ var TextureCube = (function (Texture$$1) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if (!(img instanceof ArrayBufferView)) { + if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); } else { if (this._compressed) { @@ -8681,7 +8679,7 @@ var TextureCube = (function (Texture$$1) { } else { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if (!(img instanceof ArrayBufferView)) { + if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { gl.texImage2D( gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, diff --git a/index.js b/index.js index ba16a62b359..4af245b191a 100644 --- a/index.js +++ b/index.js @@ -49,6 +49,7 @@ require('./polyfill/string'); require('./polyfill/misc'); require('./polyfill/array'); require('./polyfill/object'); +require('./polyfill/array-buffer'); if (!(CC_EDITOR && Editor.isMainProcess)) { require('./polyfill/typescript'); } diff --git a/polyfill/array-buffer.js b/polyfill/array-buffer.js new file mode 100644 index 00000000000..8ea63dd7642 --- /dev/null +++ b/polyfill/array-buffer.js @@ -0,0 +1,6 @@ +if (!ArrayBuffer.isView) { + const ArrayBufferView = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array)).constructor; + ArrayBuffer.isView = function (view) { + return view instanceof ArrayBufferView; + }; +} \ No newline at end of file From 3220b3a1451fe3366d52143a8ee0aa5c28429aae Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 3 Dec 2018 11:27:38 +0800 Subject: [PATCH 0233/1631] fixed bar-filled (#3581) --- .../webgl/assemblers/sprite/bar-filled.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index a24131a5d4e..5f35a71b822 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -122,22 +122,22 @@ module.exports = { switch (sprite._fillType) { case FillType.HORIZONTAL: data[0].u = quadUV0 + (quadUV2 - quadUV0) * fillStart; - data[0].v = quadUV1; + data[0].v = quadUV1 + (quadUV3 - quadUV1) * fillStart; data[1].u = quadUV0 + (quadUV2 - quadUV0) * fillEnd; - data[1].v = quadUV3; + data[1].v = quadUV1 + (quadUV3 - quadUV1) * fillEnd; data[2].u = quadUV4 + (quadUV6 - quadUV4) * fillStart; - data[2].v = quadUV5; + data[2].v = quadUV5 + (quadUV7 - quadUV5) * fillStart; data[3].u = quadUV4 + (quadUV6 - quadUV4) * fillEnd; - data[3].v = quadUV7; + data[3].v = quadUV5 + (quadUV7 - quadUV5) * fillEnd; break; case FillType.VERTICAL: - data[0].u = quadUV0; + data[0].u = quadUV0 + (quadUV4 - quadUV0) * fillStart; data[0].v = quadUV1 + (quadUV5 - quadUV1) * fillStart; - data[1].u = quadUV2; + data[1].u = quadUV2 + (quadUV6 - quadUV2) * fillStart; data[1].v = quadUV3 + (quadUV7 - quadUV3) * fillStart; - data[2].u = quadUV4; + data[2].u = quadUV0 + (quadUV4 - quadUV0) * fillEnd; data[2].v = quadUV1 + (quadUV5 - quadUV1) * fillEnd; - data[3].u = quadUV6; + data[3].u = quadUV2 + (quadUV6 - quadUV2) * fillEnd; data[3].v = quadUV3 + (quadUV7 - quadUV3) * fillEnd; break; default: From 198399e28acbc6f28ac309110eb7de86369ac415 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 3 Dec 2018 15:36:39 +0800 Subject: [PATCH 0234/1631] Fix failed to update particle system _renderSpriteFrame (#3577) --- cocos2d/particle/CCParticleSystem.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 8efb29b4c8b..db8950a9a7c 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -156,12 +156,9 @@ var properties = { } if (this._custom !== value) { this._custom = value; - if (!value) { - this._applyFile(); - } + this._applyFile(); if (CC_EDITOR) { cc.engine.repaintInEditMode(); - // self.preview = self.preview; } } }, @@ -190,7 +187,6 @@ var properties = { this._applyFile(); if (CC_EDITOR) { cc.engine.repaintInEditMode(); - //self.preview = self.preview; } } else { @@ -934,7 +930,8 @@ var ParticleSystem = cc.Class({ if (!self._custom) { self._initWithDictionary(content); } - if (!self.spriteFrame || !self._renderSpriteFrame) { + + if (!self._spriteFrame) { if (file.spriteFrame) { self.spriteFrame = file.spriteFrame; } @@ -942,6 +939,9 @@ var ParticleSystem = cc.Class({ self._initTextureWithDictionary(content); } } + else if (!self._renderSpriteFrame && self._spriteFrame) { + self._applySpriteFrame(self.spriteFrame); + } }); } }, From 6be47893e73294db1ae9763d1fb87bd3039e1d99 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 3 Dec 2018 15:42:34 +0800 Subject: [PATCH 0235/1631] add stopAnimation/startAnimation to game pasue/resume (#3584) --- cocos2d/core/CCGame.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 3f622a14bf2..475f84f30e3 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -286,6 +286,8 @@ var game = { if (cc.audioEngine) { cc.audioEngine._break(); } + // Pause animation + cc.director.stopAnimation(); // Pause main loop if (this._intervalId) window.cancelAnimFrame(this._intervalId); @@ -305,6 +307,8 @@ var game = { if (cc.audioEngine) { cc.audioEngine._restore(); } + // Resume animation + cc.director.startAnimation(); // Resume main loop this._runMainLoop(); }, From 0adce117f0d630d766e5990230b5eaaf08843a41 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 3 Dec 2018 16:48:19 +0800 Subject: [PATCH 0236/1631] add platform differ on baiduGame, vivoGame and oppoGame (#3582) --- .../core/load-pipeline/audio-downloader.js | 3 +- cocos2d/core/platform/CCSys.js | 75 ++++++++++++++++++- cocos2d/core/platform/CCView.js | 19 ++++- cocos2d/videoplayer/video-player-impl.js | 3 +- 4 files changed, 90 insertions(+), 10 deletions(-) diff --git a/cocos2d/core/load-pipeline/audio-downloader.js b/cocos2d/core/load-pipeline/audio-downloader.js index 006c53fe5ac..7732e314d77 100644 --- a/cocos2d/core/load-pipeline/audio-downloader.js +++ b/cocos2d/core/load-pipeline/audio-downloader.js @@ -35,7 +35,8 @@ function loadDomAudio (item, callback) { var dom = document.createElement('audio'); dom.src = item.url; - if (CC_WECHATGAME) { + const isBaiduGame = (cc.sys.platform === cc.sys.BAIDU_GAME); + if (CC_WECHATGAME || isBaiduGame) { callback(null, dom); return; } diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 6f8d03fa426..36c9e46c548 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -24,6 +24,14 @@ THE SOFTWARE. ****************************************************************************/ +let settingPlatform; + if (!CC_EDITOR) { + settingPlatform = window._CCSettings ? _CCSettings.platform: undefined; + } +const isBaiduGame = (settingPlatform === 'baidugame'); +const isVivoGame = (settingPlatform === 'vivogame'); +const isOppoGame = (settingPlatform === 'oppogame'); + function initSys () { /** * System variables @@ -353,6 +361,24 @@ function initSys () { * @default 106 */ sys.FB_PLAYABLE_ADS = 106; + /** + * @property {Number} BAIDU_GAME + * @readOnly + * @default 107 + */ + sys.BAIDU_GAME = 107; + /** + * @property {Number} VIVO_GAME + * @readOnly + * @default 108 + */ + sys.VIVO_GAME = 108; + /** + * @property {Number} OPPO_GAME + * @readOnly + * @default 109 + */ + sys.OPPO_GAME = 109; /** * BROWSER_TYPE_WECHAT * @property {String} BROWSER_TYPE_WECHAT @@ -374,6 +400,20 @@ function initSys () { * @default "wechatgamesub" */ sys.BROWSER_TYPE_WECHAT_GAME_SUB = "wechatgamesub"; + /** + * BROWSER_TYPE_BAIDU_GAME + * @property {String} BROWSER_TYPE_BAIDU_GAME + * @readOnly + * @default "baidugame" + */ + sys.BROWSER_TYPE_BAIDU_GAME = "baidugame"; + /** + * BROWSER_TYPE_BAIDU_GAME_SUB + * @property {String} BROWSER_TYPE_BAIDU_GAME_SUB + * @readOnly + * @default "baidugamesub" + */ + sys.BROWSER_TYPE_BAIDU_GAME_SUB = "baidugamesub"; /** * BROWSER_TYPE_QQ_PLAY * @property {String} BROWSER_TYPE_QQ_PLAY @@ -533,8 +573,8 @@ function initSys () { * Is web browser ? * @property {Boolean} isBrowser */ - sys.isBrowser = typeof window === 'object' && typeof document === 'object' && !CC_WECHATGAME && !CC_QQPLAY && !CC_JSB; - + sys.isBrowser = typeof window === 'object' && typeof document === 'object' && !CC_WECHATGAME && !CC_QQPLAY && !CC_JSB && !isBaiduGame; + if (CC_EDITOR && Editor.isMainProcess) { sys.isMobile = false; sys.platform = sys.EDITOR_CORE; @@ -553,13 +593,25 @@ function initSys () { sys.__audioSupport = {}; } else if (CC_JSB) { - var platform = sys.platform = __getPlatform(); + let platform; + if (isVivoGame) { + platform = sys.VIVO_GAME; + } + else if (isOppoGame) { + platform = sys.OPPO_GAME; + } + else { + platform = __getPlatform(); + } + sys.platform = platform; sys.isMobile = (platform === sys.ANDROID || platform === sys.IPAD || platform === sys.IPHONE || platform === sys.WP8 || platform === sys.TIZEN || - platform === sys.BLACKBERRY); + platform === sys.BLACKBERRY || + platform === sys.VIVO_GAME || + platform === sys.OPPO_GAME); sys.os = __getOS(); sys.language = __getCurrentLanguage(); @@ -704,6 +756,21 @@ function initSys () { format: ['.mp3'] }; } + else if (isBaiduGame) { + let env = device.getSystemInfo(); + sys.platform = env.platform; + sys.browserType = env.browserType; + sys.isMobile = env.isMobile; + sys.language = env.language; + sys.os = env.os; + sys.osVersion = env.osVersion; + sys.osMainVersion = env.osMainVersion; + sys.browserVersion = env.browserVersion; + sys.windowPixelResolution = env.windowPixelResolution; + sys.localStorage = env.localStorage; + sys.capabilities = env.capabilities; + sys.__audioSupport = env.audioSupport; + } else { // browser or runtime var win = window, nav = win.navigator, doc = document, docEle = doc.documentElement; diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 7fe3aab84cd..9d792f9c7be 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -30,9 +30,11 @@ const js = require('../platform/js'); const renderer = require('../renderer'); require('../platform/CCClass'); +const isBaiduGame = (cc.sys.platform === cc.sys.BAIDU_GAME); + var __BrowserGetter = { init: function(){ - if (!CC_WECHATGAME && !CC_QQPLAY) { + if (!CC_WECHATGAME && !CC_QQPLAY && !isBaiduGame) { this.html = document.getElementsByTagName("html")[0]; } }, @@ -57,6 +59,15 @@ var __BrowserGetter = { if (cc.sys.os === cc.sys.OS_IOS) // All browsers are WebView __BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_SAFARI; +if (isBaiduGame) { + if (cc.sys.browserType === cc.sys.BROWSER_TYPE_BAIDU_GAME_SUB) { + __BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_BAIDU_GAME_SUB; + } + else { + __BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_BAIDU_GAME; + } +} + if (CC_WECHATGAME) { if (cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { __BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB; @@ -401,7 +412,7 @@ cc.js.mixin(View.prototype, { }, _adjustViewportMeta: function () { - if (this._isAdjustViewport && !CC_JSB && !CC_WECHATGAME && !CC_QQPLAY) { + if (this._isAdjustViewport && !CC_JSB && !CC_WECHATGAME && !CC_QQPLAY && !isBaiduGame) { this._setViewportMeta(__BrowserGetter.meta, false); this._isAdjustViewport = false; } @@ -802,7 +813,7 @@ cc.js.mixin(View.prototype, { * @param {ResolutionPolicy|Number} resolutionPolicy The resolution policy desired */ setRealPixelResolution: function (width, height, resolutionPolicy) { - if (!CC_JSB && !CC_WECHATGAME && !CC_QQPLAY) { + if (!CC_JSB && !CC_WECHATGAME && !CC_QQPLAY && !isBaiduGame) { // Set viewport's width this._setViewportMeta({"width": width}, true); @@ -1060,7 +1071,7 @@ cc.ContainerStrategy = cc.Class({ _setupContainer: function (view, w, h) { var locCanvas = cc.game.canvas, locContainer = cc.game.container; - if (!CC_WECHATGAME) { + if (!CC_WECHATGAME && !isBaiduGame) { if (cc.sys.os === cc.sys.OS_ANDROID) { document.body.style.width = (view._isRotated ? h : w) + 'px'; document.body.style.height = (view._isRotated ? w : h) + 'px'; diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 85cb66ebd34..85393f9d2cf 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -545,8 +545,9 @@ VideoPlayerImpl._polyfill = { * But native does not support this encode, * so it is best to provide mp4 and webm or ogv file */ +const isBaiduGame = (cc.sys.platform === cc.sys.BAIDU_GAME); let dom = document.createElement("video"); -if (!CC_WECHATGAME) { +if (!CC_WECHATGAME && !isBaiduGame) { if (dom.canPlayType("video/ogg")) { VideoPlayerImpl._polyfill.canPlayType.push(".ogg"); VideoPlayerImpl._polyfill.canPlayType.push(".ogv"); From e000e74c1c718fe0b9b467f714943448f1b55b24 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 3 Dec 2018 18:31:45 +0800 Subject: [PATCH 0237/1631] update alignWithScree in Canvas for fireball/issues/8281 (#3186) (#3585) --- cocos2d/core/components/CCCanvas.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/cocos2d/core/components/CCCanvas.js b/cocos2d/core/components/CCCanvas.js index 8ab27b973ba..c1f09de84e3 100644 --- a/cocos2d/core/components/CCCanvas.js +++ b/cocos2d/core/components/CCCanvas.js @@ -76,6 +76,7 @@ var Canvas = cc.Class({ this._designResolution.width = value.width; this._designResolution.height = value.height; this.applySettings(); + this.alignWithScreen(); }, tooltip: CC_DEV && 'i18n:COMPONENT.canvas.design_resolution' }, @@ -97,6 +98,7 @@ var Canvas = cc.Class({ if (this._fitHeight !== value) { this._fitHeight = value; this.applySettings(); + this.alignWithScreen(); } }, tooltip: CC_DEV && 'i18n:COMPONENT.canvas.fit_height' @@ -116,6 +118,7 @@ var Canvas = cc.Class({ if (this._fitWidth !== value) { this._fitWidth = value; this.applySettings(); + this.alignWithScreen(); } }, tooltip: CC_DEV && 'i18n:COMPONENT.canvas.fit_width' @@ -123,7 +126,7 @@ var Canvas = cc.Class({ }, ctor: function () { - this._thisOnResized = this.onResized.bind(this); + this._thisOnResized = this.alignWithScreen.bind(this); }, __preload: function () { @@ -138,8 +141,6 @@ var Canvas = cc.Class({ } Canvas.instance = this; - cc.director.on(cc.Director.EVENT_AFTER_UPDATE, this.alignWithScreen, this); - if (CC_EDITOR) { cc.engine.on('design-resolution-changed', this._thisOnResized); } @@ -153,7 +154,7 @@ var Canvas = cc.Class({ } this.applySettings(); - this.onResized(); + this.alignWithScreen(); // Camera could be removed in canvas render mode let cameraNode = cc.find('Main Camera', this.node); @@ -165,7 +166,7 @@ var Canvas = cc.Class({ let camera = cameraNode.getComponent(Camera); if (!camera) { camera = cameraNode.addComponent(Camera); - + let ClearFlags = Camera.ClearFlags; camera.clearFlags = ClearFlags.COLOR | ClearFlags.DEPTH | ClearFlags.STENCIL; camera.depth = -1; @@ -174,8 +175,6 @@ var Canvas = cc.Class({ }, onDestroy: function () { - cc.director.off(cc.Director.EVENT_AFTER_UPDATE, this.alignWithScreen, this); - if (CC_EDITOR) { cc.engine.off('design-resolution-changed', this._thisOnResized); } @@ -218,11 +217,6 @@ var Canvas = cc.Class({ this.node.height = nodeSize.height; }, - onResized: function () { - // TODO - size dirty - this.alignWithScreen(); - }, - applySettings: function () { var ResolutionPolicy = cc.ResolutionPolicy; var policy; From 767e56d1407149651377ddb32cdd896c327477ff Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Mon, 3 Dec 2018 19:59:41 +0800 Subject: [PATCH 0238/1631] V2.0 skeleton optimize (#3537) * export vfmt for jsb adapter * fix some bug drabonebones 2.0 * remove useless code * Export StencilManager to jsb adapter * Support dragonbones bin load * remove dragonbones and spine lib file when compile jsb * rename materials to materialCache * add blank line * Add premultipliedAlpha property in dragonbones * Remove unuse child node which is created by old code. * Change copyright time --- cocos2d/core/CCGame.js | 12 +- cocos2d/core/assets/CCBufferAsset.js | 52 +++ cocos2d/core/assets/index.js | 1 + cocos2d/core/load-pipeline/downloader.js | 1 + cocos2d/core/load-pipeline/loader.js | 1 + .../core/renderer/webgl/stencil-manager.js | 2 +- cocos2d/core/renderer/webgl/vertex-format.js | 4 + extensions/dragonbones/ArmatureDisplay.js | 142 +++----- extensions/dragonbones/CCArmatureDisplay.js | 117 ++++++ extensions/dragonbones/CCFactory.js | 100 +++-- extensions/dragonbones/CCSlot.js | 162 +++++---- extensions/dragonbones/DragonBonesAsset.js | 89 +++-- extensions/dragonbones/canvas-assembler.js | 78 ---- extensions/dragonbones/index.js | 207 +++++------ extensions/dragonbones/webgl-assembler.js | 343 +++++++++++++----- extensions/spine/Skeleton.js | 6 +- extensions/spine/index.js | 129 ++++--- extensions/spine/spine-assembler.js | 18 +- gulp/tasks/engine.js | 6 + 19 files changed, 886 insertions(+), 584 deletions(-) create mode 100644 cocos2d/core/assets/CCBufferAsset.js create mode 100644 extensions/dragonbones/CCArmatureDisplay.js delete mode 100644 extensions/dragonbones/canvas-assembler.js diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 475f84f30e3..e43fd181fb7 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -61,7 +61,7 @@ var game = { EVENT_HIDE: "game_on_hide", /** - * Event triggered when game back to foreground + * !#en Event triggered when game back to foreground * Please note that this event is not 100% guaranteed to be fired on Web platform, * on native platforms, it corresponds to enter foreground event. * !#zh 游戏进入前台运行时触发的事件。 @@ -73,6 +73,15 @@ var game = { */ EVENT_SHOW: "game_on_show", + /** + * !#en Event triggered when game restart + * !#zh 调用restart后,触发事件。 + * @property EVENT_RESTART + * @constant + * @type {String} + */ + EVENT_RESTART: "game_on_restart", + /** * Event triggered after game inited, at this point all engine objects and game scripts are loaded * @property EVENT_GAME_INITED @@ -347,6 +356,7 @@ var game = { cc.director.reset(); game.onStart(); + game.emit(game.EVENT_RESTART); }); }, diff --git a/cocos2d/core/assets/CCBufferAsset.js b/cocos2d/core/assets/CCBufferAsset.js new file mode 100644 index 00000000000..c9d1e915d21 --- /dev/null +++ b/cocos2d/core/assets/CCBufferAsset.js @@ -0,0 +1,52 @@ +/**************************************************************************** + Copyright (c) 2013-2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://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. + ****************************************************************************/ + +/** + * @class BufferAsset + * @extends Asset + */ +var BufferAsset = cc.Class({ + name: 'cc.BufferAsset', + extends: cc.Asset, + + ctor () { + this._buffer = null; + }, + + properties: { + _nativeAsset: { + get () { + return this._buffer; + }, + set (bin) { + this._buffer = bin.buffer || bin; + }, + override: true + }, + } +}); + +cc.BufferAsset = module.exports = BufferAsset; diff --git a/cocos2d/core/assets/index.js b/cocos2d/core/assets/index.js index 95bd670b52b..69832482a70 100644 --- a/cocos2d/core/assets/index.js +++ b/cocos2d/core/assets/index.js @@ -40,3 +40,4 @@ require('./CCBitmapFont'); require('./CCLabelAtlas'); require('./CCTextAsset'); require('./CCJsonAsset'); +require('./CCBufferAsset'); diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index 681ca642e29..aca582ea22f 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -179,6 +179,7 @@ var defaultMap = { // Binary 'binary' : downloadBinary, + 'dbbin' : downloadBinary, 'default' : downloadText }; diff --git a/cocos2d/core/load-pipeline/loader.js b/cocos2d/core/load-pipeline/loader.js index b40e59f9c9b..1d45a3227ee 100644 --- a/cocos2d/core/load-pipeline/loader.js +++ b/cocos2d/core/load-pipeline/loader.js @@ -142,6 +142,7 @@ var defaultMap = { // binary 'binary' : loadBinary, + 'dbbin' : loadBinary, // Font 'font' : fontLoader.loadFont, diff --git a/cocos2d/core/renderer/webgl/stencil-manager.js b/cocos2d/core/renderer/webgl/stencil-manager.js index 284e65da551..d97cdb30e90 100644 --- a/cocos2d/core/renderer/webgl/stencil-manager.js +++ b/cocos2d/core/renderer/webgl/stencil-manager.js @@ -172,4 +172,4 @@ StencilManager.prototype = { StencilManager.sharedManager = new StencilManager(); StencilManager.Stage = Stage; -module.exports = StencilManager; \ No newline at end of file +module.exports = cc.StencilManager = StencilManager; diff --git a/cocos2d/core/renderer/webgl/vertex-format.js b/cocos2d/core/renderer/webgl/vertex-format.js index 94351122408..4d0169467f7 100644 --- a/cocos2d/core/renderer/webgl/vertex-format.js +++ b/cocos2d/core/renderer/webgl/vertex-format.js @@ -32,6 +32,7 @@ var vfmt3D = new gfx.VertexFormat([ { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true }, ]); vfmt3D.name = 'vfmt3D'; +gfx.VertexFormat.XYZ_UV_Color = vfmt3D; var vfmtPosUvColor = new gfx.VertexFormat([ { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, @@ -39,18 +40,21 @@ var vfmtPosUvColor = new gfx.VertexFormat([ { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true }, ]); vfmtPosUvColor.name = 'vfmtPosUvColor'; +gfx.VertexFormat.XY_UV_Color = vfmtPosUvColor; var vfmtPosUv = new gfx.VertexFormat([ { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 } ]); vfmtPosUv.name = 'vfmtPosUv'; +gfx.VertexFormat.XY_UV = vfmtPosUv; var vfmtPosColor = new gfx.VertexFormat([ { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true }, ]); vfmtPosColor.name = 'vfmtPosColor'; +gfx.VertexFormat.XY_Color = vfmtPosColor; module.exports = { vfmt3D, diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 76208977c5b..00f9b4b41b0 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -120,7 +120,6 @@ let ArmatureDisplay = cc.Class({ // parse the atlas asset data this._parseDragonAtlasAsset(); this._buildArmature(); - this._activateMaterial(); }, tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.dragon_bones_atlas_asset' }, @@ -240,7 +239,6 @@ let ArmatureDisplay = cc.Class({ type: DefaultAnimsEnum, visible: true, editorOnly: true, - animatable: false, displayName: 'Animation', tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.animation_name' }, @@ -254,7 +252,9 @@ let ArmatureDisplay = cc.Class({ timeScale: { default: 1, notify () { - this._armature.animation.timeScale = this.timeScale; + if (this._armature) { + this._armature.animation.timeScale = this.timeScale; + } }, tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.time_scale' }, @@ -276,6 +276,20 @@ let ArmatureDisplay = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.play_times' }, + /** + * !#en Indicates whether to enable premultiplied alpha. + * You should disable this option when image's transparent area appears to have opaque pixels, + * or enable this option when image's half transparent area appears to be darken. + * !#zh 是否启用贴图预乘。 + * 当图片的透明区域出现色块时需要关闭该选项,当图片的半透明区域颜色变黑时需要启用该选项。 + * @property {Boolean} premultipliedAlpha + * @default false + */ + premultipliedAlpha: { + default: false, + tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.premultipliedAlpha' + }, + /** * !#en Indicates whether open debug bones. * !#zh 是否显示 bone 的 debug 信息。 @@ -292,10 +306,37 @@ let ArmatureDisplay = cc.Class({ }, ctor () { + this._renderDatas = []; + this._material = new SpriteMaterial; + // Property _materialCache Use to cache material,since dragonBones may use multiple texture, + // it will clone from the '_material' property,if the dragonbones only have one texture, + // it will just use the _material,won't clone it. + // So if invoke getMaterial,it only return _material,if you want to change all materialCache, + // you can change materialCache directly. + this._materialCache = {}; this._inited = false; this._factory = dragonBones.CCFactory.getInstance(); }, + onLoad () { + // Adapt to old code,remove unuse child which is created by old code. + // This logic can be remove after 2.2 or later. + var children = this.node.children; + for (var i = 0, n = children.length; i < n; i++) { + var child = children[i]; + var pos = child._name && child._name.search('CHILD_ARMATURE-'); + if (pos === 0) { + child.destroy(); + } + } + }, + + // override + _updateMaterial (material) { + this._super(material); + this._materialCache = {}; + }, + __preload () { this._init(); }, @@ -307,7 +348,6 @@ let ArmatureDisplay = cc.Class({ this._parseDragonAsset(); this._parseDragonAtlasAsset(); this._refresh(); - this._activateMaterial(); }, onEnable () { @@ -331,6 +371,7 @@ let ArmatureDisplay = cc.Class({ this._armature.dispose(); this._armature = null; } + this._renderDatas.length = 0; }, _initDebugDraw () { @@ -352,31 +393,16 @@ let ArmatureDisplay = cc.Class({ } }, - _activateMaterial () { - let texture = this.dragonAtlasAsset && this.dragonAtlasAsset.texture; - - - // Get material - let material = this._material || new SpriteMaterial(); - material.useColor = false; - - if (texture) { - material.texture = texture; - this.markForUpdateRenderData(true); - this.markForRender(true); - } - else { - this.disableRender(); - } - - this._updateMaterial(material); - }, - _buildArmature () { if (!this.dragonAsset || !this.dragonAtlasAsset || !this.armatureName) return; - let factory = dragonBones.CCFactory.getInstance(); - this._armature = factory.buildArmatureDisplay(this.armatureName, this.dragonAsset._dragonBonesData.name, this); + var displayProxy = this._factory.buildArmatureDisplay(this.armatureName, this.dragonAsset._dragonBonesData.name, this); + if (!displayProxy) return; + + this._displayProxy = displayProxy; + this._displayProxy._ccNode = this.node; + + this._armature = this._displayProxy._armature; this._armature.animation.timeScale = this.timeScale; if (this.animationName) { @@ -507,7 +533,9 @@ let ArmatureDisplay = cc.Class({ * @param {Object} [target] - The target (this object) to invoke the callback, can be null */ addEventListener (eventType, listener, target) { - this.addDBEventListener(eventType, listener, target); + if (this._displayProxy) { + this._displayProxy.addDBEventListener(eventType, listener, target); + } }, /** @@ -521,7 +549,9 @@ let ArmatureDisplay = cc.Class({ * @param {Object} [target] */ removeEventListener (eventType, listener, target) { - this.removeDBEventListener(eventType, listener, target); + if (this._displayProxy) { + this._displayProxy.removeDBEventListener(eventType, listener, target); + } }, /** @@ -535,7 +565,7 @@ let ArmatureDisplay = cc.Class({ * @return {dragonBones.ArmatureDisplay} */ buildArmature (armatureName, node) { - return dragonBones.CCFactory.getInstance().createArmatureNode(this, armatureName, node); + return this._factory.createArmatureNode(this, armatureName, node); }, /** @@ -549,60 +579,6 @@ let ArmatureDisplay = cc.Class({ armature () { return this._armature; }, - - //////////////////////////////////// - // dragonbones api - dbInit (armature) { - this._armature = armature; - }, - - dbClear () { - this._armature = null; - }, - - dbUpdate () { - if (!CC_DEBUG) return; - this._initDebugDraw(); - - let debugDraw = this._debugDraw; - if (!debugDraw) return; - - debugDraw.clear(); - let bones = this._armature.getBones(); - for (let i = 0, l = bones.length; i < l; i++) { - let bone = bones[i]; - let boneLength = Math.max(bone.boneData.length, 5); - let startX = bone.globalTransformMatrix.tx; - let startY = -bone.globalTransformMatrix.ty; - let endX = startX + bone.globalTransformMatrix.a * boneLength; - let endY = startY - bone.globalTransformMatrix.b * boneLength; - - debugDraw.moveTo(startX, startY); - debugDraw.lineTo(endX, endY); - debugDraw.stroke(); - } - }, - - advanceTimeBySelf (on) { - this.shouldAdvanced = !!on; - }, - - hasDBEventListener (type) { - return this.hasEventListener(type); - }, - - addDBEventListener (type, listener, target) { - this.on(type, listener, target); - }, - - removeDBEventListener (type, listener, target) { - this.off(type, listener, target); - }, - - dispatchDBEvent (type, eventObject) { - this.emit(type, eventObject); - }, - //////////////////////////////////// }); module.exports = dragonBones.ArmatureDisplay = ArmatureDisplay; diff --git a/extensions/dragonbones/CCArmatureDisplay.js b/extensions/dragonbones/CCArmatureDisplay.js new file mode 100644 index 00000000000..c1377b5b1de --- /dev/null +++ b/extensions/dragonbones/CCArmatureDisplay.js @@ -0,0 +1,117 @@ +/**************************************************************************** + Copyright (c) 2018 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. + ****************************************************************************/ +let EventTarget = require('../../cocos2d/core/event/event-target'); + +dragonBones.CCArmatureDisplay = cc.Class({ + name: 'dragonBones.CCArmatureDisplay', + mixins: [EventTarget], + + properties: { + // adapt old api + node: { + get () { + return this; + } + } + }, + + getRootDisplay () { + var parentSlot = this._armature._parent; + if (!parentSlot) { + return this; + } + + var slot; + while (parentSlot) + { + slot = parentSlot; + parentSlot = parentSlot._armature._parent; + } + return slot._armature.getDisplay(); + }, + + convertToRootSpace (pos) { + var slot = this._armature._parent; + if (!slot) + { + return pos; + } + slot.updateWorldMatrix(); + + let worldMatrix = slot._worldMatrix; + let newPos = cc.v2(0,0); + newPos.x = pos.x * worldMatrix.m00 + pos.y * worldMatrix.m04 + worldMatrix.m12; + newPos.y = pos.x * worldMatrix.m01 + pos.y * worldMatrix.m05 + worldMatrix.m13; + return newPos; + }, + + convertToWorldSpace (point) { + var newPos = this.convertToRootSpace(point); + var ccNode = this.getRootNode(); + var finalPos = ccNode.convertToWorldSpace(newPos); + return finalPos; + }, + + getRootNode () { + var rootDisplay = this.getRootDisplay(); + return rootDisplay && rootDisplay._ccNode; + }, + + //////////////////////////////////// + // dragonbones api + dbInit (armature) { + this._armature = armature; + }, + + dbClear () { + this._armature = null; + }, + + dbUpdate () { + + }, + + advanceTimeBySelf (on) { + this.shouldAdvanced = !!on; + }, + + hasDBEventListener (type) { + return this.hasEventListener(type); + }, + + addDBEventListener (type, listener, target) { + this.on(type, listener, target); + }, + + removeDBEventListener (type, listener, target) { + this.off(type, listener, target); + }, + + dispatchDBEvent (type, eventObject) { + this.emit(type, eventObject); + } + //////////////////////////////////// + +}); diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index b02da97d985..919cf7701c5 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -23,12 +23,27 @@ THE SOFTWARE. ****************************************************************************/ -let BaseObject = dragonBones.BaseObject; +let BaseObject = dragonBones.BaseObject, + BaseFactory = dragonBones.BaseFactory; +/** + * @module dragonBones +*/ + +/** + * @class CCFactory + * @extends BaseFactory +*/ var CCFactory = dragonBones.CCFactory = cc.Class({ name: 'dragonBones.CCFactory', - extends: dragonBones.BaseFactory, - + extends: BaseFactory, + /** + * @method getInstance + * @return {CCFactory} + * @static + * @example + * let factory = dragonBones.CCFactory.getInstance(); + */ statics: { _factory: null, getInstance () { @@ -42,21 +57,51 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ ctor () { this._dragonBones = new dragonBones.DragonBones(); - if (!CC_EDITOR && cc.director._scheduler) { - cc.director._scheduler.enableForTarget(this); - cc.director._scheduler.scheduleUpdate(this, cc.Scheduler.PRIORITY_SYSTEM, false); + if (!CC_JSB && !CC_EDITOR && cc.director._scheduler) { + cc.game.on(cc.game.EVENT_RESTART, this.initUpdate, this); + this.initUpdate(); } }, + initUpdate (dt) { + cc.director._scheduler.enableForTarget(this); + cc.director._scheduler.scheduleUpdate(this, cc.Scheduler.PRIORITY_SYSTEM, false); + }, + update (dt) { this._dragonBones.advanceTime(dt); }, - buildArmatureDisplay (armatureName, dragonBonesName, comp) { - this._display = comp; - let armature = this.buildArmature(armatureName, dragonBonesName, comp); - this._display = null; - return armature; + parseDragonBonesDataOnly (rawData, name, scale) { + if (name === undefined) { name = null; } + if (scale === undefined) { scale = 1.0; } + var dataParser = rawData instanceof ArrayBuffer ? BaseFactory._binaryParser : this._dataParser; + var dragonBonesData = dataParser.parseDragonBonesData(rawData, scale); + return dragonBonesData; + }, + + handleTextureAtlasData (isBinary, name, scale) { + if (name === undefined) { name = null; } + if (scale === undefined) { scale = 1.0; } + + var dataParser = isBinary ? BaseFactory._binaryParser : this._dataParser; + + while (true) { + var textureAtlasData = this._buildTextureAtlasData(null, null); + if (dataParser.parseTextureAtlasData(null, textureAtlasData, scale)) { + this.addTextureAtlasData(textureAtlasData, name); + } + else { + textureAtlasData.returnToPool(); + break; + } + } + }, + + // Build new aramture with a new display. + buildArmatureDisplay (armatureName, dragonBonesName) { + let armature = this.buildArmature(armatureName, dragonBonesName); + return armature && armature._display; }, parseTextureAtlasData (jsonString, texture) { @@ -64,6 +109,9 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ return this._super(atlasJsonObj, texture); }, + // Build sub armature from an exist armature component. + // It will share dragonAsset and dragonAtlasAsset. + // But node can not share,or will cause render error. createArmatureNode (comp, armatureName, node) { node = node || new cc.Node(); let display = node.getComponent(dragonBones.ArmatureDisplay); @@ -80,23 +128,7 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ return display; }, - - _buildChildArmature (dataPackage, slot, displayData) { - let temp = this._display; - - let name = 'CHILD_ARMATURE-' + displayData.path; - let node = this._display.node.getChildByName(name); - if (!node) { - node = new cc.Node(); - } - let display = this.createArmatureNode(temp, displayData.path, node); - node.name = name; - - this._display = temp; - return display._armature; - }, - _buildTextureAtlasData (textureAtlasData, textureAtlas) { if (textureAtlasData) { textureAtlasData.renderTexture = textureAtlas; @@ -141,8 +173,10 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ // fixed dragonbones sort issue // armature._sortSlots = this._sortSlots; + var display = new dragonBones.CCArmatureDisplay(); + armature.init(dataPackage.armature, - this._display, this._display, this._dragonBones + display, display, this._dragonBones ); return armature; @@ -150,17 +184,9 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ _buildSlot (dataPackage, slotData, displays) { let slot = BaseObject.borrowObject(dragonBones.CCSlot); - let displayList = []; - slot.name = slotData.name; - slot.reset(); - - // let display = new cc.Node(); - // display.name = slot.name; - let display = slot; slot.init(slotData, displays, display, display); - return slot; } -}); \ No newline at end of file +}); diff --git a/extensions/dragonbones/CCSlot.js b/extensions/dragonbones/CCSlot.js index ce59f5116be..fdb34c74397 100644 --- a/extensions/dragonbones/CCSlot.js +++ b/extensions/dragonbones/CCSlot.js @@ -33,19 +33,23 @@ dragonBones.CCSlot = cc.Class({ extends: dragonBones.Slot, ctor () { - this._vertices = []; this._localVertices = []; this._indices = []; this._matrix = math.mat4.create(); + this._worldMatrix = math.mat4.create(); + this._worldMatrixDirty = true; this._visible = false; this._color = cc.color(); }, - reset () { - this._vertices.length = 0; + _onClear () { + this._super(); this._localVertices.length = 0; this._indices.length = 0; math.mat4.identity(this._matrix); + math.mat4.identity(this._worldMatrix); + this._worldMatrixDirty = true; + this._color = cc.color(); this._visible = false; }, @@ -55,72 +59,40 @@ dragonBones.CCSlot = cc.Class({ } }, + // just for adapt to dragonbones api,no need to do any thing _onUpdateDisplay () { - if (this._childArmature) { - this._childArmature.display._isChildArmature = true; - } }, + // just for adapt to dragonbones api,no need to do any thing _initDisplay (value) { }, _addDisplay () { this._visible = true; - - if (!CC_EDITOR) { - this._rawDisplay.parent = this._armature.display.node; - } }, + // just for adapt to dragonbones api,no need to do any thing _replaceDisplay (value) { - if (value instanceof dragonBones.ArmatureDisplay) { - value.node.parent = null; - } - - if (this._display instanceof dragonBones.ArmatureDisplay) { - this._display.node.parent = this._armature.display.node; - } }, _removeDisplay () { this._visible = false; - - if (!CC_EDITOR) { - this._rawDisplay.parent = null; - } }, + // just for adapt to dragonbones api,no need to do any thing _disposeDisplay (object) { - }, + // just for adapt to dragonbones api,no need to do any thing _updateVisible () { }, - _updateZOrder: function() { + // just for adapt to dragonbones api,no need to do any thing + _updateZOrder () { }, _updateBlendMode () { - // TODO: new implementation needed - return; - if (this._renderDisplay instanceof cc.Scale9Sprite) { - switch (this._blendMode) { - case 0: // BlendMode Normal - break; - case 1: // BlendMode Add - let texture = this._renderDisplay._spriteFrame.getTexture(); - if (texture && texture.hasPremultipliedAlpha()) { - this._renderDisplay.setBlendFunc(BlendFactor.ONE, BlendFactor.ONE); - } - else { - this._renderDisplay.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE); - } - break; - default: - break; - } - } - else if (this._childArmature) { + if (this._childArmature) { let childSlots = this._childArmature.getSlots(); for (let i = 0, l = childSlots.length; i < l; i++) { let slot = childSlots[i]; @@ -138,14 +110,16 @@ dragonBones.CCSlot = cc.Class({ c.a = this._colorTransform.alphaMultiplier * 255; }, + //return dragonBones.CCTexture2D + getTexture () { + return this._textureData && this._textureData.spriteFrame && this._textureData.spriteFrame.getTexture(); + }, + _updateFrame () { - this._vertices.length = 0; this._indices.length = 0; - let vertices = this._vertices, - indices = this._indices, + let indices = this._indices, localVertices = this._localVertices; - vertices.length = 0; indices.length = 0; localVertices.length = 0; @@ -153,7 +127,7 @@ dragonBones.CCSlot = cc.Class({ // update the frame if (!this._display || this._displayIndex < 0 || !currentTextureData) return; - let currentDisplayData = this._displayIndex < this.rawDisplayDatas.length ? this.rawDisplayDatas[this._displayIndex] : null;; + let currentDisplayData = this._displayIndex < this.rawDisplayDatas.length ? this.rawDisplayDatas[this._displayIndex] : null; let textureAtlas = this._armature._replacedTexture || currentTextureData.parent.renderTexture; if (textureAtlas && (!currentTextureData.spriteFrame || currentTextureData.spriteFrame.getTexture() !== textureAtlas)) { @@ -188,14 +162,13 @@ dragonBones.CCSlot = cc.Class({ const uvOffset = vertexOffset + vertexCount * 2; for (let i = 0, l = vertexCount; i < l; i++) { - let x = floatArray[vertexOffset + i*2]; - let y = -floatArray[vertexOffset + i*2 + 1]; + let x = floatArray[vertexOffset + i*2] * scale; + let y = -floatArray[vertexOffset + i*2 + 1] * scale; let u = (region.x + floatArray[uvOffset + i*2] * region.width) / textureAtlasWidth; let v = (region.y + floatArray[uvOffset + i*2 + 1] * region.height) / textureAtlasHeight; - vertices.push({ x, y, u, v}); - localVertices.push({ x, y}); + localVertices.push({ x, y, u, v}); } for (let i = 0; i < triangleCount * 3; ++i) { @@ -229,7 +202,6 @@ dragonBones.CCSlot = cc.Class({ this._pivotY -= region.height * scale; for (let i = 0; i < 4; i++) { - vertices.push({}); localVertices.push({}); } @@ -237,15 +209,15 @@ dragonBones.CCSlot = cc.Class({ let b = (region.y + region.height) / textureAtlasHeight; let r = (region.x + region.width) / textureAtlasWidth; let t = region.y / textureAtlasHeight; - vertices[0].u = l; vertices[0].v = b; - vertices[1].u = r; vertices[1].v = b; - vertices[2].u = l; vertices[2].v = t; - vertices[3].u = r; vertices[3].v = t; + localVertices[0].u = l; localVertices[0].v = b; + localVertices[1].u = r; localVertices[1].v = b; + localVertices[2].u = l; localVertices[2].v = t; + localVertices[3].u = r; localVertices[3].v = t; - localVertices[0].x = localVertices[2].x = vertices[0].x = vertices[2].x = 0; - localVertices[1].x = localVertices[3].x = vertices[1].x = vertices[3].x = region.width; - localVertices[0].y = localVertices[1].y = vertices[0].y = vertices[1].y = 0; - localVertices[2].y = localVertices[3].y = vertices[2].y = vertices[3].y = region.height; + localVertices[0].x = localVertices[2].x = 0; + localVertices[1].x = localVertices[3].x = region.width; + localVertices[0].y = localVertices[1].y = 0; + localVertices[2].y = localVertices[3].y = region.height; indices[0] = 0; indices[1] = 1; @@ -258,7 +230,7 @@ dragonBones.CCSlot = cc.Class({ } }, - _updateMesh : function() { + _updateMesh () { const scale = this._armature._armatureData.scale; const meshData = this._meshData; const hasDeform = this._deformVertices.length > 0 && meshData.inheritDeform; @@ -337,7 +309,6 @@ dragonBones.CCSlot = cc.Class({ } } - this._updateVertices(); }, _updateTransform () { @@ -349,28 +320,59 @@ dragonBones.CCSlot = cc.Class({ t.m12 = this.globalTransformMatrix.tx - (this.globalTransformMatrix.a * this._pivotX + this.globalTransformMatrix.c * this._pivotY); t.m13 = -(this.globalTransformMatrix.ty - (this.globalTransformMatrix.b * this._pivotX + this.globalTransformMatrix.d * this._pivotY)); - if (this._display instanceof dragonBones.ArmatureDisplay) { - let node = this._display.node; - math.mat4.copy(node._matrix, t); - node._localMatDirty = false; - node.setWorldDirty(); + this._worldMatrixDirty = true; + }, + + updateWorldMatrix () { + if (!this._armature) return; + + var parentSlot = this._armature._parent; + if (parentSlot) { + parentSlot.updateWorldMatrix(); } - this._updateVertices(); + if (this._worldMatrixDirty) { + this.calculWorldMatrix(); + var childArmature = this.childArmature; + if (!childArmature) return; + var slots = childArmature.getSlots(); + for (var i = 0,n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot) { + slot._worldMatrixDirty = true; + } + } + } }, - _updateVertices () { - let t = this._matrix; - let a = t.m00, b = t.m01, c = t.m04, d = t.m05, tx = t.m12, ty = t.m13; - - let vertices = this._vertices; - let localVertices = this._localVertices; - for (let i = 0, l = vertices.length; i < l; i++) { - let x = localVertices[i].x; - let y = localVertices[i].y; + _mulMat (out, a, b) { + let aa=a.m00, ab=a.m01, ac=a.m04, ad=a.m05, atx=a.m12, aty=a.m13; + let ba=b.m00, bb=b.m01, bc=b.m04, bd=b.m05, btx=b.m12, bty=b.m13; + if (ab !== 0 || ac !== 0) { + out.m00 = ba * aa + bb * ac; + out.m01 = ba * ab + bb * ad; + out.m04 = bc * aa + bd * ac; + out.m05 = bc * ab + bd * ad; + out.m12 = aa * btx + ac * bty + atx; + out.m13 = ab * btx + ad * bty + aty; + } + else { + out.m00 = ba * aa; + out.m01 = bb * ad; + out.m04 = bc * aa; + out.m05 = bd * ad; + out.m12 = aa * btx + atx; + out.m13 = ad * bty + aty; + } + }, - vertices[i].x = a * x + c * y + tx; - vertices[i].y = b * x + d * y + ty; + calculWorldMatrix () { + var parent = this._armature._parent; + if (parent) { + this._mulMat(this._worldMatrix ,parent._worldMatrix, this._matrix); + } else { + math.mat4.copy(this._worldMatrix, this._matrix); } + this._worldMatrixDirty = false; } }); diff --git a/extensions/dragonbones/DragonBonesAsset.js b/extensions/dragonbones/DragonBonesAsset.js index c98ee7e410e..fb3d3c0737a 100644 --- a/extensions/dragonbones/DragonBonesAsset.js +++ b/extensions/dragonbones/DragonBonesAsset.js @@ -58,7 +58,18 @@ var DragonBonesAsset = cc.Class({ this._dragonBonesJson = value; this.reset(); } - } + }, + + _nativeAsset: { + get () { + return this._buffer; + }, + set (bin) { + this._buffer = bin.buffer || bin; + this.reset(); + }, + override: true + }, }, statics: { @@ -80,48 +91,56 @@ var DragonBonesAsset = cc.Class({ } }, - init: function (factory) { + init (factory) { if (CC_EDITOR) { - factory = factory || new dragonBones.CCFactory(); + this._factory = factory || new dragonBones.CCFactory(); + } else { + this._factory = factory; } + if (this._dragonBonesData) { - let sameNamedDragonBonesData = factory.getDragonBonesData(this._dragonBonesData.name); - if (sameNamedDragonBonesData) { - // already added asset, see #2002 - for (let i = 0; i < this._dragonBonesData.armatureNames.length; i++) { - let armatureName = this._dragonBonesData.armatureNames[i]; - if (!sameNamedDragonBonesData.armatures[armatureName]) { - // merge with new armature - sameNamedDragonBonesData.addArmature(this._dragonBonesData.armatures[armatureName]); - } - } - this._dragonBonesData = sameNamedDragonBonesData; - } - else { - factory.addDragonBonesData(this._dragonBonesData); + let hasSame = this.checkSameNameData(this._dragonBonesData); + if (!hasSame) { + this._factory.addDragonBonesData(this._dragonBonesData); } } else { - let _dragonBonesJson = JSON.parse(this.dragonBonesJson); - let sameNamedDragonBonesData = factory.getDragonBonesData(_dragonBonesJson.name); - if (sameNamedDragonBonesData) { - // already added asset, see #2002 - let dragonBonesData; - for (let i = 0; i < _dragonBonesJson.armature.length; i++) { - let armatureName = _dragonBonesJson.armature[i].name; - if (!sameNamedDragonBonesData.armatures[armatureName]) { - // add new armature - if (!dragonBonesData) { - dragonBonesData = factory._dataParser.parseDragonBonesData(_dragonBonesJson); - } - sameNamedDragonBonesData.addArmature(dragonBonesData.armatures[armatureName]); - } - } - this._dragonBonesData = sameNamedDragonBonesData; + if (this.dragonBonesJson) { + this.initWithRawData(JSON.parse(this.dragonBonesJson), false); + } else { + this.initWithRawData(this._nativeAsset, true); } - else { - this._dragonBonesData = factory.parseDragonBonesData(_dragonBonesJson); + } + }, + + checkSameNameData (dragonBonesData) { + let sameNamedDragonBonesData = this._factory.getDragonBonesData(dragonBonesData.name); + if (sameNamedDragonBonesData) { + // already added asset, see #2002 + let armatureNames = dragonBonesData.armatureNames; + for (let i = 0; i < armatureNames.length; i++) { + let armatureName = armatureNames[i]; + if (!sameNamedDragonBonesData.armatures[armatureName]) { + sameNamedDragonBonesData.addArmature(dragonBonesData.armatures[armatureName]); + } } + this._dragonBonesData = sameNamedDragonBonesData; + return true; + } + return false; + }, + + initWithRawData (rawData, isBinary) { + if (!rawData) { + return; + } + + let dragonBonesData = this._factory.parseDragonBonesDataOnly(rawData); + let hasSame = this.checkSameNameData(dragonBonesData); + if (!hasSame) { + this._dragonBonesData = dragonBonesData; + this._factory.handleTextureAtlasData(isBinary); + this._factory.addDragonBonesData(dragonBonesData); } }, diff --git a/extensions/dragonbones/canvas-assembler.js b/extensions/dragonbones/canvas-assembler.js deleted file mode 100644 index e73c1d71aec..00000000000 --- a/extensions/dragonbones/canvas-assembler.js +++ /dev/null @@ -1,78 +0,0 @@ -const Armature = require('./ArmatureDisplay'); -const renderEngine = require('../../cocos2d/core/renderer/render-engine'); -const math = renderEngine.math; - -const utils = require('../../cocos2d/core/renderer/canvas/renderers/utils'); - -let _color = cc.color(); - -let _matrix = math.mat4.create(); -let _matrix2 = math.mat4.create(); - -let armatureAssembler = { - draw (ctx, comp) { - let armature = comp._armature; - if (!armature || comp._isChildArmature) return 0; - - ctx.save(); - - let node = comp.node; - let matrix = node._worldMatrix; - - let texture = comp.dragonAtlasAsset.texture; - this.drawArmature(ctx, armature, texture, matrix); - - ctx.restore(); - - return 1; - }, - - drawArmature (ctx, armature, texture, matrix) { - let slots = armature._slots; - - for (let i = 0, l = slots.length; i < l; i++) { - let slot = slots[i]; - if (!slot._visible || !slot._displayData) continue; - - if (slot.childArmature) { - math.mat4.mul(_matrix, matrix, slot._matrix); - this.drawArmature(ctx, slot.childArmature, texture, _matrix); - continue; - } - - let localVertices = slot._localVertices; - - if (localVertices.length !== 4) { - continue; - } - - ctx.save(); - - math.mat4.mul(_matrix2, matrix, slot._matrix); - - let m = _matrix2; - ctx.transform(m.m00, -m.m01, -m.m04, m.m05, m.m12, -m.m13); - - let vertices = slot._vertices; - let sx = vertices[0].u * texture.width; - let sy = vertices[3].v * texture.height; - let sw = vertices[3].u * texture.width - sx; - let sh = vertices[0].v * texture.height - sy; - - let x = localVertices[0].x; - let y = localVertices[0].y; - let w = localVertices[3].x - x; - let h = localVertices[3].y - y; - y = -y-h; - - _color._val = slot._color; - let image = utils.getFrameCache(texture, _color, sx, sy, sw, sh); - - ctx.drawImage(image, x, y, w, h); - - ctx.restore(); - } - } -}; - -module.exports = Armature._assembler = armatureAssembler; diff --git a/extensions/dragonbones/index.js b/extensions/dragonbones/index.js index cc405aff6e6..baa5d051de1 100644 --- a/extensions/dragonbones/index.js +++ b/extensions/dragonbones/index.js @@ -40,107 +40,110 @@ */ var _global = typeof window === 'undefined' ? global : window; -_global.dragonBones = require('./lib/dragonBones'); - -dragonBones.DisplayType = { - Image : 0, - Armature : 1, - Mesh : 2 -}; - -dragonBones.ArmatureType = { - Armature : 0, - MovieClip : 1, - Stage : 2 -}; - -dragonBones.ExtensionType = { - FFD : 0, - AdjustColor : 10, - BevelFilter : 11, - BlurFilter : 12, - DropShadowFilter : 13, - GlowFilter : 14, - GradientBevelFilter : 15, - GradientGlowFilter : 16 -}; - -dragonBones.EventType = { - Frame : 0, - Sound : 1 -}; - -dragonBones.ActionType = { - Play : 0, - Stop : 1, - GotoAndPlay : 2, - GotoAndStop : 3, - FadeIn : 4, - FadeOut : 5 -}; - -dragonBones.AnimationFadeOutMode = { - None : 0, - SameLayer : 1, - SameGroup : 2, - SameLayerAndGroup : 3, - All : 4 -}; - -dragonBones.BinaryOffset = { - WeigthBoneCount: 0, - WeigthFloatOffset: 1, - WeigthBoneIndices: 2, - - MeshVertexCount: 0, - MeshTriangleCount: 1, - MeshFloatOffset: 2, - MeshWeightOffset: 3, - MeshVertexIndices: 4, - - TimelineScale: 0, - TimelineOffset: 1, - TimelineKeyFrameCount: 2, - TimelineFrameValueCount: 3, - TimelineFrameValueOffset: 4, - TimelineFrameOffset: 5, - - FramePosition: 0, - FrameTweenType: 1, - FrameTweenEasingOrCurveSampleCount: 2, - FrameCurveSamples: 3, - - DeformMeshOffset: 0, - DeformCount: 1, - DeformValueCount: 2, - DeformValueOffset: 3, - DeformFloatOffset: 4 -}; - -dragonBones.BoneType = { - Bone: 0, - Surface: 1 -}; - -if (!CC_EDITOR || !Editor.isMainProcess) { - require('./CCFactory'); - require('./CCSlot'); - require('./CCTextureData'); - - // require the component for dragonbones - require('./DragonBonesAsset'); - require('./DragonBonesAtlasAsset'); - require('./ArmatureDisplay'); - - cc.game.once(cc.game.EVENT_ENGINE_INITED, function () { - if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { - require('./canvas-assembler'); - } - else { - require('./webgl-assembler'); +if (!CC_JSB) { + _global.dragonBones = require('./lib/dragonBones'); +} + +if (_global.dragonBones !== undefined) { + + dragonBones.DisplayType = { + Image : 0, + Armature : 1, + Mesh : 2 + }; + + dragonBones.ArmatureType = { + Armature : 0, + MovieClip : 1, + Stage : 2 + }; + + dragonBones.ExtensionType = { + FFD : 0, + AdjustColor : 10, + BevelFilter : 11, + BlurFilter : 12, + DropShadowFilter : 13, + GlowFilter : 14, + GradientBevelFilter : 15, + GradientGlowFilter : 16 + }; + + dragonBones.EventType = { + Frame : 0, + Sound : 1 + }; + + dragonBones.ActionType = { + Play : 0, + Stop : 1, + GotoAndPlay : 2, + GotoAndStop : 3, + FadeIn : 4, + FadeOut : 5 + }; + + dragonBones.AnimationFadeOutMode = { + None : 0, + SameLayer : 1, + SameGroup : 2, + SameLayerAndGroup : 3, + All : 4 + }; + + dragonBones.BinaryOffset = { + WeigthBoneCount: 0, + WeigthFloatOffset: 1, + WeigthBoneIndices: 2, + + MeshVertexCount: 0, + MeshTriangleCount: 1, + MeshFloatOffset: 2, + MeshWeightOffset: 3, + MeshVertexIndices: 4, + + TimelineScale: 0, + TimelineOffset: 1, + TimelineKeyFrameCount: 2, + TimelineFrameValueCount: 3, + TimelineFrameValueOffset: 4, + TimelineFrameOffset: 5, + + FramePosition: 0, + FrameTweenType: 1, + FrameTweenEasingOrCurveSampleCount: 2, + FrameCurveSamples: 3, + + DeformMeshOffset: 0, + DeformCount: 1, + DeformValueCount: 2, + DeformValueOffset: 3, + DeformFloatOffset: 4 + }; + + dragonBones.BoneType = { + Bone: 0, + Surface: 1 + }; + + if (!CC_EDITOR || !Editor.isMainProcess) { + + if (!CC_JSB) { + require('./CCFactory'); + require('./CCSlot'); + require('./CCTextureData'); + require('./CCArmatureDisplay'); } - }); -} else { - require('./DragonBonesAsset'); - require('./DragonBonesAtlasAsset'); + + // require the component for dragonbones + require('./DragonBonesAsset'); + require('./DragonBonesAtlasAsset'); + require('./ArmatureDisplay'); + + require('./webgl-assembler'); + } else { + require('./DragonBonesAsset'); + require('./DragonBonesAtlasAsset'); + } + } diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index f07a0a0fce7..c352845dc91 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -23,156 +23,305 @@ THE SOFTWARE. ****************************************************************************/ +const StencilManager = require('../../cocos2d/core/renderer/webgl/stencil-manager').sharedManager; const Armature = require('./ArmatureDisplay'); - const renderEngine = require('../../cocos2d/core/renderer/render-engine'); -const math = renderEngine.math; - -const js = require('../../cocos2d/core/platform/js'); - const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); +const gfx = renderEngine.gfx; +const SpriteMaterial = renderEngine.SpriteMaterial; const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; -let _matrix = math.mat4.create(); -let _v3 = cc.v3(); +let _boneColor = cc.color(255, 0, 0, 255); +let _slotColor = cc.color(0, 0, 255, 255); + +const STENCIL_SEP = '@'; + +function _updateKeyWithStencilRef (key, stencilRef) { + return key.replace(/@\d+$/, STENCIL_SEP + stencilRef); +} + +function _getSlotMaterial (comp, slot, premultiAlpha) { + premultiAlpha = premultiAlpha || false; + let tex = slot.getTexture(); + if(!tex)return null; + let src, dst; + + switch (slot._blendMode) { + case 1://additive + src = premultiAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; + dst = cc.macro.ONE; + break; + case 10://multiply + src = cc.macro.DST_COLOR; + dst = cc.macro.ONE_MINUS_SRC_ALPHA; + break; + case 12://screen + src = cc.macro.ONE; + dst = cc.macro.ONE_MINUS_SRC_COLOR; + break; + case 0://normal + default: + src = premultiAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; + dst = cc.macro.ONE_MINUS_SRC_ALPHA; + break; + } + + let key = tex.url + src + dst + STENCIL_SEP + '0'; + comp._material = comp._material || new SpriteMaterial(); + let baseMaterial = comp._material; + let materialCache = comp._materialCache; + let material = materialCache[key]; + if (!material) { + + var baseKey = baseMaterial._hash; + if (!materialCache[baseKey]) { + material = baseMaterial; + } else { + material = baseMaterial.clone(); + } -let _vbuf, _uintbuf, - _vertexId, _ibuf, - _vertexOffset, _indiceOffset, - _a, _b, _c, _d, _tx, _ty, + material.useModel = true; + // update texture + material.texture = tex; + material.useColor = false; + + // update blend function + let pass = material._mainTech.passes[0]; + pass.setBlend( + gfx.BLEND_FUNC_ADD, + src, dst, + gfx.BLEND_FUNC_ADD, + src, dst + ); + materialCache[key] = material; + material.updateHash(key); + } + else if (material.texture !== tex) { + material.texture = tex; + material.updateHash(key); + } + return material; +} + +let _vertexOffset, _indiceOffset, _nodeR, _nodeG, _nodeB, _nodeA, - _renderData, - _worldMatrix; + _material, _currMaterial, + _dataId, _datas, _data, _newData; let armatureAssembler = { + useModel: true, + updateRenderData (comp) { + let armature = comp._armature; - if (!armature || comp._isChildArmature) { + if (!armature) { return; } - - let renderData = comp._renderData; - if (!renderData) { - renderData = comp._renderData = comp.requestRenderData(); - } - - let size = comp.node._contentSize; - let anchor = comp.node._anchorPoint; - renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y); - renderData.material = comp.getMaterial(); - - renderData.vertexCount = 0; - renderData.indiceCount = 0; - - this.calcBufferCount(renderData, armature); - }, - - calcBufferCount (renderData, armature) { - let slots = armature._slots; - for (let i = 0, l = slots.length; i < l; i++) { - let slot = slots[i]; - if (!slot._visible || !slot._displayData) continue; - if (slot.childArmature) { - this.calcBufferCount(renderData, slot.childArmature); - continue; - } - renderData.vertexCount += slot._vertices.length; - renderData.indiceCount += slot._indices.length; + _dataId = 0; + _datas = comp._renderDatas; + _data = _datas[_dataId]; + _newData = false; + if (!_data) { + _data = _datas[_dataId] = comp.requestRenderData(); } - }, - - fillBuffers (comp, renderer) { - let armature = comp._armature; - if (!armature || comp._isChildArmature) return; - - let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), - renderData = comp._renderData; - - _vertexOffset = buffer.byteOffset >> 2; - _indiceOffset = buffer.indiceOffset; - _vertexId = buffer.vertexOffset; - - buffer.request(renderData.vertexCount, renderData.indiceCount); - - // buffer data may be realloc, need get reference after request. - _vbuf = buffer._vData; - _uintbuf = buffer._uintVData; - _ibuf = buffer._iData; + _data.dataLength = 0; + _material = null; + _currMaterial = null; + _vertexOffset = 0; + _indiceOffset = 0; let node = comp.node; - let nodeColor = node.color; _nodeR = nodeColor.r / 255; _nodeG = nodeColor.g / 255; _nodeB = nodeColor.b / 255; _nodeA = nodeColor.a / 255; - _worldMatrix = node._worldMatrix; - _a = _worldMatrix.m00; _b = _worldMatrix.m01; _c = _worldMatrix.m04; _d = _worldMatrix.m05; - _tx = _worldMatrix.m12; _ty = _worldMatrix.m13; - - this.fillIndexBufferWithArmature(armature); - this.fillVertexBufferWithArmature(armature); - - comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; - - _worldMatrix = _ibuf = _vbuf = _uintbuf = null; + this.traverseArmature(comp,armature); }, - fillVertexBufferWithArmature (armature) { + traverseArmature (comp,armature) { let slots = armature._slots; + let premultipliedAlpha = comp.premultipliedAlpha; for (let i = 0, l = slots.length; i < l; i++) { let slot = slots[i]; if (!slot._visible || !slot._displayData) continue; + slot.updateWorldMatrix(); + + // If slot has childArmature,then the slot has no + // vertices and indice info.It only has sub slots + // transform info,so multiply the slot's transform + // with parent transform and give the sub slots. if (slot.childArmature) { - math.mat4.mul(_matrix, _worldMatrix, slot._matrix); - _a = _matrix.m00; _b = _matrix.m01; _c = _matrix.m04; _d = _matrix.m05; - _tx = _matrix.m12; _ty = _matrix.m13; - this.fillVertexBufferWithArmature(slot.childArmature); - _a = _worldMatrix.m00; _b = _worldMatrix.m01; _c = _worldMatrix.m04; _d = _worldMatrix.m05; - _tx = _worldMatrix.m12; _ty = _worldMatrix.m13; + this.traverseArmature(comp, slot.childArmature); continue; } - let vertices = slot._vertices; + _material = _getSlotMaterial(comp, slot, premultipliedAlpha); + if (!_material) { + continue; + } + + // Check break + if (_currMaterial !== _material) { + if (_currMaterial) { + _newData = true; + _data.material = _currMaterial; + } + else { + // Init data material + _data.material = _material; + } + _currMaterial = _material; + } + + // Request new render data and new vertex content + if (_newData) { + // set old data vertex indice + _data.vertexCount = _vertexOffset; + _data.indiceCount = _indiceOffset; + // gen new data + _dataId++; + _data = _datas[_dataId]; + if (!_data) { + _data = _datas[_dataId] = comp.requestRenderData(); + } + _data.material = _currMaterial; + _data.dataLength = 0; + + // reset offset + _vertexOffset = 0; + _indiceOffset = 0; + } + + let indices = slot._indices; + let indiceBuffer = _data._indices; + for (let j = 0, il = indices.length; j < il; j++) { + indiceBuffer[_indiceOffset++] = _vertexOffset + indices[j]; + } + + let vertices = slot._localVertices; let slotColor = slot._color; + let worldMatrix = slot._worldMatrix; let cr = slotColor.r * _nodeR; let cg = slotColor.g * _nodeG; let cb = slotColor.b * _nodeB; let ca = slotColor.a * _nodeA; let color = ((ca<<24) >>> 0) + (cb<<16) + (cg<<8) + cr; + let vertexBuffer = _data._data; + _data.dataLength += vertices.length; for (let j = 0, vl = vertices.length; j < vl; j++) { let vertex = vertices[j]; - _vbuf[_vertexOffset++] = vertex.x * _a + vertex.y * _c + _tx; - _vbuf[_vertexOffset++] = vertex.x * _b + vertex.y * _d + _ty; - _vbuf[_vertexOffset++] = vertex.u; - _vbuf[_vertexOffset++] = vertex.v; - _uintbuf[_vertexOffset++] = color; + let content = vertexBuffer[_vertexOffset++]; + content.x = vertex.x * worldMatrix.m00 + vertex.y * worldMatrix.m04 + worldMatrix.m12; + content.y = vertex.x * worldMatrix.m01 + vertex.y * worldMatrix.m05 + worldMatrix.m13; + content.u = vertex.u; + content.v = vertex.v; + content.color = color; } } + + _data.vertexCount = _vertexOffset; + _data.indiceCount = _indiceOffset; + + // Check for last data valid or not + if (_vertexOffset > 0 && _indiceOffset > 0) { + _datas.length = _dataId + 1; + } + else { + _datas.length = _dataId; + } }, - fillIndexBufferWithArmature (armature) { - let slots = armature._slots; - for (let i = 0, l = slots.length; i < l; i++) { - let slot = slots[i]; - if (!slot._visible || !slot._displayData) continue; + fillBuffers (comp, renderer) { - if (slot.childArmature) { - this.fillIndexBufferWithArmature(slot.childArmature); - continue; + let armature = comp._armature; + if (!armature) return; + + let renderDatas = comp._renderDatas; + let materialCache = comp._materialCache; + + for (let index = 0, length = renderDatas.length; index < length; index++) { + let data = renderDatas[index]; + + let key = data.material._hash; + let newKey = _updateKeyWithStencilRef(key, StencilManager.getStencilRef()); + if (key !== newKey) { + data.material = materialCache[newKey] || data.material.clone(); + data.material.updateHash(newKey); + if (!materialCache[newKey]) { + materialCache[newKey] = data.material; + } } - let indices = slot._indices; - for (let j = 0, il = indices.length; j < il; j++) { - _ibuf[_indiceOffset++] = _vertexId + indices[j]; + if (data.material !== renderer.material) { + renderer._flush(); + renderer.node = comp.node; + renderer.material = data.material; + } + + let vertexs = data._data; + let indices = data._indices; + + let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), + vertexOffset = buffer.byteOffset >> 2, + vertexCount = data.vertexCount; + + let indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + buffer.request(vertexCount, data.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + ibuf = buffer._iData, + uintbuf = buffer._uintVData; + + // fill vertex buffer + let vert; + for (let i = 0, l = data.dataLength; i < l; i++) { + vert = vertexs[i]; + vbuf[vertexOffset++] = vert.x; + vbuf[vertexOffset++] = vert.y; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = vert.color; + } + + // index buffer + for (let i = 0, l = indices.length; i < l; i ++) { + ibuf[indiceOffset++] = vertexId + indices[i]; } + } + + if (comp.debugBones && comp._debugDraw) { + + var graphics = comp._debugDraw; + graphics.clear(); + + graphics.lineWidth = 5; + graphics.strokeColor = _boneColor; + graphics.fillColor = _slotColor; // Root bone color is same as slot color. - _vertexId += slot._vertices.length; + let bones = armature.getBones(); + for (let i = 0, l = bones.length; i < l; i++) { + let bone = bones[i]; + let boneLength = Math.max(bone.boneData.length, 5); + let startX = bone.globalTransformMatrix.tx; + let startY = -bone.globalTransformMatrix.ty; + let endX = startX + bone.globalTransformMatrix.a * boneLength; + let endY = startY - bone.globalTransformMatrix.b * boneLength; + + graphics.moveTo(startX, startY); + graphics.lineTo(endX, endY); + graphics.stroke(); + } } + + comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; } }; diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 218db733d18..57b9c74ce63 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -324,7 +324,7 @@ sp.Skeleton = cc.Class({ this._listener = null; this._boundingBox = cc.rect(); this._material = new SpriteMaterial(); - this._materials = {}; + this._materialCache = {}; this._renderDatas = []; this._debugRenderer = null; }, @@ -332,7 +332,7 @@ sp.Skeleton = cc.Class({ // override _updateMaterial (material) { this._super(material); - this._materials = {}; + this._materialCache = {}; }, /** @@ -406,7 +406,7 @@ sp.Skeleton = cc.Class({ if (!this._material) { this._boundingBox = cc.rect(); this._material = new SpriteMaterial(); - this._materials = {}; + this._materialCache = {}; this._renderDatas = []; } }, diff --git a/extensions/spine/index.js b/extensions/spine/index.js index b5936ddcef2..0d7cf499b9d 100644 --- a/extensions/spine/index.js +++ b/extensions/spine/index.js @@ -42,71 +42,84 @@ */ var _global = typeof window === 'undefined' ? global : window; -_global.sp = {}; +var _isUseSpine = true; -// The attachment type of spine. It contains three type: REGION(0), BOUNDING_BOX(1), MESH(2) and SKINNED_MESH. -sp.ATTACHMENT_TYPE = { - REGION: 0, - BOUNDING_BOX: 1, - MESH: 2, - SKINNED_MESH:3 -}; +if (CC_JSB && _global.spine === undefined) { + _isUseSpine = false; +} + +if (_isUseSpine) { + _global.sp = {}; + + // The attachment type of spine. It contains three type: REGION(0), BOUNDING_BOX(1), MESH(2) and SKINNED_MESH. + sp.ATTACHMENT_TYPE = { + REGION: 0, + BOUNDING_BOX: 1, + MESH: 2, + SKINNED_MESH:3 + }; -/** - * !#en The event type of spine skeleton animation. - * !#zh 骨骼动画事件类型。 - * @enum AnimationEventType - */ -sp.AnimationEventType = cc.Enum({ - /** - * !#en The play spine skeleton animation start type. - * !#zh 开始播放骨骼动画。 - * @property {Number} START - */ - START: 0, - /** - * !#en Another entry has replaced this entry as the current entry. This entry may continue being applied for mixing. - * !#zh 当前的 entry 被其他的 entry 替换。当使用 mixing 时,当前的 entry 会继续运行。 - */ - INTERRUPT: 1, - /** - * !#en The play spine skeleton animation finish type. - * !#zh 播放骨骼动画结束。 - * @property {Number} END - */ - END: 2, - /** - * !#en The entry will be disposed. - * !#zh entry 将被销毁。 - */ - DISPOSE: 3, /** - * !#en The play spine skeleton animation complete type. - * !#zh 播放骨骼动画完成。 - * @property {Number} COMPLETE + * !#en The event type of spine skeleton animation. + * !#zh 骨骼动画事件类型。 + * @enum AnimationEventType */ - COMPLETE: 4, + sp.AnimationEventType = cc.Enum({ + /** + * !#en The play spine skeleton animation start type. + * !#zh 开始播放骨骼动画。 + * @property {Number} START + */ + START: 0, + /** + * !#en Another entry has replaced this entry as the current entry. This entry may continue being applied for mixing. + * !#zh 当前的 entry 被其他的 entry 替换。当使用 mixing 时,当前的 entry 会继续运行。 + */ + INTERRUPT: 1, + /** + * !#en The play spine skeleton animation finish type. + * !#zh 播放骨骼动画结束。 + * @property {Number} END + */ + END: 2, + /** + * !#en The entry will be disposed. + * !#zh entry 将被销毁。 + */ + DISPOSE: 3, + /** + * !#en The play spine skeleton animation complete type. + * !#zh 播放骨骼动画完成。 + * @property {Number} COMPLETE + */ + COMPLETE: 4, + /** + * !#en The spine skeleton animation event type. + * !#zh 骨骼动画事件。 + * @property {Number} EVENT + */ + EVENT: 5 + }); + /** - * !#en The spine skeleton animation event type. - * !#zh 骨骼动画事件。 - * @property {Number} EVENT + * @module sp */ - EVENT: 5 -}); + if (!CC_EDITOR || !Editor.isMainProcess) { + + if (CC_JSB) { + sp.spine = _global.spine; + } else { + sp.spine = require('./lib/spine'); + } -/** - * @module sp - */ -if (!CC_EDITOR || !Editor.isMainProcess) { - - sp.spine = require('./lib/spine'); - require('./skeleton-texture'); - require('./skeleton-data'); - require('./Skeleton'); - require('./spine-assembler'); -} -else { - require('./skeleton-data'); + require('./skeleton-texture'); + require('./skeleton-data'); + require('./Skeleton'); + require('./spine-assembler'); + } + else { + require('./skeleton-data'); + } } /** diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 470ac676fcb..ac1bb9f563d 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -73,12 +73,12 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { let key = tex.url + src + dst + STENCIL_SEP + '0'; comp._material = comp._material || new SpriteMaterial(); let baseMaterial = comp._material; - let materials = comp._materials; - let material = materials[key]; + let materialCache = comp._materialCache; + let material = materialCache[key]; if (!material) { var baseKey = baseMaterial._hash; - if (!materials[baseKey]) { + if (!materialCache[baseKey]) { material = baseMaterial; } else { material = baseMaterial.clone(); @@ -97,7 +97,7 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { gfx.BLEND_FUNC_ADD, src, dst ); - materials[key] = material; + materialCache[key] = material; material.updateHash(key); } else if (material.texture !== tex) { @@ -177,7 +177,7 @@ var spineAssembler = { let material = null, currMaterial = null; let vertexCount = 0, vertexOffset = 0; let indiceCount = 0, indiceOffset = 0; - let materials = comp._materials; + let materialCache = comp._materialCache; for (let i = 0, n = locSkeleton.drawOrder.length; i < n; i++) { slot = locSkeleton.drawOrder[i]; if (!slot.attachment) @@ -310,7 +310,7 @@ var spineAssembler = { fillBuffers (comp, renderer) { let renderDatas = comp._renderDatas; - let materials = comp._materials; + let materialCache = comp._materialCache; for (let index = 0, length = renderDatas.length; index < length; index++) { let data = renderDatas[index]; @@ -319,10 +319,10 @@ var spineAssembler = { let key = data.material._hash; let newKey = _updateKeyWithStencilRef(key, StencilManager.getStencilRef()); if (key !== newKey) { - data.material = materials[newKey] || data.material.clone(); + data.material = materialCache[newKey] || data.material.clone(); data.material.updateHash(newKey); - if (!materials[newKey]) { - materials[newKey] = data.material; + if (!materialCache[newKey]) { + materialCache[newKey] = data.material; } } diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index d7449919ceb..ad72b7e7649 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -40,6 +40,12 @@ const Optimizejs = require('gulp-optimize-js'); var jsbSkipModules = [ // modules need to skip in jsb + '../../extensions/spine/lib/spine.js', + '../../extensions/dragonbones/lib/dragonBones.js', + '../../extensions/dragonbones/CCArmatureDisplay.js', + '../../extensions/dragonbones/CCFactory.js', + '../../extensions/dragonbones/CCSlot.js', + '../../extensions/dragonbones/CCTextureData.js' ]; var jsbAliasify = { replacements: { From a6fd13f49225db7c09ea3362d92a07106062effe Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 4 Dec 2018 10:31:42 +0800 Subject: [PATCH 0239/1631] improve video player and webview (#3463) (#3587) * improve video player and webview * refine code * refine code --- cocos2d/core/platform/CCView.js | 4 +--- cocos2d/videoplayer/video-player-impl.js | 14 ++++++++++++-- cocos2d/webview/webview-impl.js | 5 +++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 9d792f9c7be..37b23b2fe1d 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -1127,9 +1127,7 @@ cc.ContentStrategy = cc.Class({ Math.abs(containerW - contentW) < 2 && (contentW = containerW); Math.abs(containerH - contentH) < 2 && (contentH = containerH); - var viewport = cc.rect(Math.round((containerW - contentW) / 2), - Math.round((containerH - contentH) / 2), - contentW, contentH); + var viewport = cc.rect((containerW - contentW) / 2, (containerH - contentH) / 2, contentW, contentH); // Translate the content if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS){ diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 85393f9d2cf..d828c3228f9 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -167,6 +167,7 @@ let VideoPlayerImpl = cc.Class({ let orientation = cc.winSize.width > cc.winSize.height ? "landscape" : "portrait"; video.setAttribute("x5-playsinline", ""); video.setAttribute("x5-video-player-type", "h5"); + video.setAttribute("x5-video-player-fullscreen", "false"); video.setAttribute("x5-video-orientation", orientation); this._video = video; @@ -278,7 +279,7 @@ let VideoPlayerImpl = cc.Class({ video.pause(); }, - _resume: function () { + resume: function () { this.play(); }, @@ -356,6 +357,9 @@ let VideoPlayerImpl = cc.Class({ }, setKeepAspectRatioEnabled: function () { + if (CC_EDITOR) { + return; + } cc.logID(7700); }, @@ -368,8 +372,8 @@ let VideoPlayerImpl = cc.Class({ if (!video) { return; } + this._fullScreenEnabled = enable; if (sys.os === sys.OS_IOS && sys.isBrowser) { - this._fullScreenEnabled = enable; if (this._loadedmeta) { triggerFullScene(video, enable); } @@ -381,6 +385,7 @@ let VideoPlayerImpl = cc.Class({ else { cc.screen.exitFullScreen(video); } + video.setAttribute("x5-video-player-fullscreen", enable ? "true" : "false"); } }, @@ -483,6 +488,11 @@ let VideoPlayerImpl = cc.Class({ let appx = (w * _mat4_temp.m00) * node._anchorPoint.x; let appy = (h * _mat4_temp.m05) * node._anchorPoint.y; + + let viewport = cc.view._viewportRect; + offsetX += viewport.x / dpr; + offsetY += viewport.y / dpr; + let tx = _mat4_temp.m12 * scaleX - appx + offsetX, ty = _mat4_temp.m13 * scaleY - appy + offsetY; let matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")"; diff --git a/cocos2d/webview/webview-impl.js b/cocos2d/webview/webview-impl.js index 8516caecf09..c323534460b 100644 --- a/cocos2d/webview/webview-impl.js +++ b/cocos2d/webview/webview-impl.js @@ -370,6 +370,11 @@ let WebViewImpl = cc.Class({ let h = this._div.clientHeight * scaleY; let appx = (w * _mat4_temp.m00) * node._anchorPoint.x; let appy = (h * _mat4_temp.m05) * node._anchorPoint.y; + + let viewport = cc.view._viewportRect; + offsetX += viewport.x / dpr; + offsetY += viewport.y / dpr; + let tx = _mat4_temp.m12 * scaleX - appx + offsetX, ty = _mat4_temp.m13 * scaleY - appy + offsetY; let matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")"; From cada315da7c4c35ea70722deab208da2b20ebcc7 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 4 Dec 2018 13:49:33 +0800 Subject: [PATCH 0240/1631] add material system (#3543) * add shaders and effects * add material and effect * add npm modules * apply to new material system * fixed sharedMaterials displayName * update effect&material format * update shader * add asset.onLoad * sync material & effect * support load builtin assets * add shader asset * merge shader and effect asset * remove unused code * refine build-shader * add missing require * change ShaderAsset to EffectAsset * fixed radial-filled * refine code * should use env presets * refine code * refine code * fixed test * refine compute material hash * refine code * move builtin assets logic to AssetLibrary * refine call asset.onLoad --- cocos2d/core/3d/CCSkinnedMeshRenderer.js | 26 +- cocos2d/core/CCGame.js | 14 +- cocos2d/core/assets/CCAsset.js | 4 +- cocos2d/core/assets/CCEffectAsset.js | 20 ++ cocos2d/core/assets/CCMaterial.js | 181 ++++++++++ cocos2d/core/assets/index.js | 4 +- cocos2d/core/assets/utils/compute-hash.js | 111 ++++++ cocos2d/core/assets/utils/murmurhash2_gc.js | 50 +++ cocos2d/core/components/CCLabel.js | 14 +- cocos2d/core/components/CCMask.js | 34 +- cocos2d/core/components/CCMotionStreak.js | 12 +- cocos2d/core/components/CCRenderComponent.js | 95 +++-- cocos2d/core/components/CCSprite.js | 59 +-- cocos2d/core/graphics/graphics.js | 12 +- cocos2d/core/load-pipeline/uuid-loader.js | 2 + cocos2d/core/mesh/CCMeshRenderer.js | 42 +-- cocos2d/core/mesh/mesh-renderer.js | 11 +- cocos2d/core/platform/CCAssetLibrary.js | 38 ++ cocos2d/core/platform/utils.js | 2 +- cocos2d/core/renderer/index.js | 4 +- cocos2d/core/renderer/render-engine.js | 94 ++--- .../webgl/assemblers/graphics/index.js | 12 +- .../webgl/assemblers/mask-assembler.js | 10 +- .../webgl/assemblers/motion-streak.js | 2 +- .../webgl/assemblers/sprite/2d/bar-filled.js | 85 ++--- .../webgl/assemblers/sprite/2d/mesh.js | 54 ++- .../assemblers/sprite/2d/radial-filled.js | 162 ++++----- .../webgl/assemblers/sprite/2d/simple.js | 21 +- .../webgl/assemblers/sprite/2d/sliced.js | 27 +- .../webgl/assemblers/sprite/2d/tiled.js | 15 +- .../renderer/webgl/assemblers/sprite/utils.js | 18 + cocos2d/core/renderer/webgl/model-batcher.js | 7 +- .../core/renderer/webgl/stencil-manager.js | 1 - cocos2d/core/value-types/index.js | 17 +- cocos2d/particle/CCParticleSystem.js | 18 +- cocos2d/particle/particle-system-assembler.js | 2 +- cocos2d/renderer/build/build-mapping.js | 49 +++ cocos2d/renderer/build/build-shader.js | 104 ++++++ cocos2d/renderer/build/shdc-lib.js | 305 ++++++++++++++++ cocos2d/renderer/chunks/index.js | 3 + cocos2d/renderer/chunks/skinning.inc | 43 +++ cocos2d/renderer/effect.js | 278 +++++++++++++++ cocos2d/renderer/mappings/enums.js | 50 +++ cocos2d/renderer/mappings/gfx/enums.js | 336 ++++++++++++++++++ cocos2d/renderer/mappings/index.js | 276 ++++++++++++++ cocos2d/renderer/mappings/index.js.map | 1 + cocos2d/renderer/mappings/offline-mappings.js | 73 ++++ cocos2d/tilemap/CCTiledLayer.js | 14 +- cocos2d/tilemap/tmx-layer-assembler.js | 2 +- extensions/dragonbones/ArmatureDisplay.js | 15 +- extensions/dragonbones/webgl-assembler.js | 2 +- extensions/spine/Skeleton.js | 6 +- extensions/spine/spine-assembler.js | 25 +- gulp/util/create-bundler.js | 31 +- package.json | 7 +- 55 files changed, 2420 insertions(+), 480 deletions(-) create mode 100644 cocos2d/core/assets/CCEffectAsset.js create mode 100644 cocos2d/core/assets/CCMaterial.js create mode 100644 cocos2d/core/assets/utils/compute-hash.js create mode 100644 cocos2d/core/assets/utils/murmurhash2_gc.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/utils.js create mode 100644 cocos2d/renderer/build/build-mapping.js create mode 100644 cocos2d/renderer/build/build-shader.js create mode 100644 cocos2d/renderer/build/shdc-lib.js create mode 100644 cocos2d/renderer/chunks/index.js create mode 100644 cocos2d/renderer/chunks/skinning.inc create mode 100644 cocos2d/renderer/effect.js create mode 100644 cocos2d/renderer/mappings/enums.js create mode 100644 cocos2d/renderer/mappings/gfx/enums.js create mode 100644 cocos2d/renderer/mappings/index.js create mode 100644 cocos2d/renderer/mappings/index.js.map create mode 100644 cocos2d/renderer/mappings/offline-mappings.js diff --git a/cocos2d/core/3d/CCSkinnedMeshRenderer.js b/cocos2d/core/3d/CCSkinnedMeshRenderer.js index bcc8715e08e..7755806f8fa 100644 --- a/cocos2d/core/3d/CCSkinnedMeshRenderer.js +++ b/cocos2d/core/3d/CCSkinnedMeshRenderer.js @@ -59,7 +59,7 @@ let SkinnedMeshRenderer = cc.Class({ this._skeleton = val; this._initJoints(); this._initJointsTexture(); - this.activeMaterials(true); + this._activateMaterial(true); }, type: Skeleton }, @@ -76,27 +76,23 @@ let SkinnedMeshRenderer = cc.Class({ } }, - _createMaterial () { - let material = new renderEngine.MeshMaterial(); - material.color = cc.Color.WHITE; - material._mainTech._passes[0].setDepth(true, true); - material.useModel = false; - material.useSkinning = true; + _activateSubMaterial (material) { + material.setProperty('color', cc.Color.WHITE); + material.define('useSkinning', true); + material.define('useTexture', true); if (this._jointsTexture) { - material.useJointsTexture = true; - material.jointsTexture = this._jointsTexture; - material.jointsTextureSize = this._jointsTexture.width; + material.define('useJointsTexture', true); + material.setProperty('jointsTexture', this._jointsTexture); + material.setProperty('jointsTextureSize', this._jointsTexture.width); } else { - material.useJointsTexture = false; - material.jointMatrices = this._jointsTextureData; + material.define('useJointsTexture', false); + material.setProperty('jointMatrices', this._jointsTextureData); } - - return material; }, - activeMaterials (force) { + _activateMaterial (force) { if (!this._jointsTextureData) { this.disableRender(); return; diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index a86fb22d42e..e2e6d35a5ec 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -375,15 +375,17 @@ var game = { // Init engine this._initEngine(); - // Log engine version - console.log('Cocos Creator v' + cc.ENGINE_VERSION); + cc.AssetLibrary._loadBuiltins(() => { + // Log engine version + console.log('Cocos Creator v' + cc.ENGINE_VERSION); - this._setAnimFrame(); - this._runMainLoop(); + this._setAnimFrame(); + this._runMainLoop(); - this.emit(this.EVENT_GAME_INITED); + this.emit(this.EVENT_GAME_INITED); - if (cb) cb(); + if (cb) cb(); + }); }, eventTargetOn: EventTarget.prototype.on, diff --git a/cocos2d/core/assets/CCAsset.js b/cocos2d/core/assets/CCAsset.js index 12887a87a70..fa8c2e92e11 100644 --- a/cocos2d/core/assets/CCAsset.js +++ b/cocos2d/core/assets/CCAsset.js @@ -119,8 +119,8 @@ cc.Asset = cc.Class({ * @private */ _nativeAsset: { - get () {}, - set (obj) {} + get () { }, + set (obj) { } }, }, diff --git a/cocos2d/core/assets/CCEffectAsset.js b/cocos2d/core/assets/CCEffectAsset.js new file mode 100644 index 00000000000..e6f513d8ef4 --- /dev/null +++ b/cocos2d/core/assets/CCEffectAsset.js @@ -0,0 +1,20 @@ +const Asset = require('./CCAsset'); + +let EffectAsset = cc.Class({ + name: 'cc.EffectAsset', + extends: Asset, + + properties: { + shaders: Object, + effect: Object + }, + + onLoad () { + let lib = cc.renderer._forward._programLib; + for (let i = 0; i < this.shaders.length; i++) { + lib.define(this.shaders[i]); + } + } +}); + +module.exports = cc.EffectAsset = EffectAsset; diff --git a/cocos2d/core/assets/CCMaterial.js b/cocos2d/core/assets/CCMaterial.js new file mode 100644 index 00000000000..1c338aceb26 --- /dev/null +++ b/cocos2d/core/assets/CCMaterial.js @@ -0,0 +1,181 @@ +/**************************************************************************** + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://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. + ****************************************************************************/ +// @ts-check + +const Asset = require('./CCAsset'); +const Texture = require('./CCTexture2D'); +const EffectAsset = require('./CCEffectAsset'); + +import computeHash from './utils/compute-hash'; +import Effect from '../../renderer/effect'; + +let Material = cc.Class({ + name: 'cc.Material', + extends: Asset, + + ctor () { + this._effect = null; + }, + + properties: { + _effectAsset: { + type: EffectAsset, + default: null, + }, + _defines: { + default: {}, + type: Object + }, + _props: { + default: {}, + type: Object + }, + + effectName: CC_EDITOR ? { + get () { + return this._effectAsset.name; + }, + set (val) { + let effectAsset = cc.AssetLibrary.getBuiltin('effect', val); + if (!effectAsset) { + Editor.warn(`no effect named '${val}' found`); + return; + } + this.effectAsset = effectAsset; + } + } : undefined, + + effectAsset: { + get () { + return this._effectAsset; + }, + set (asset) { + this._effectAsset = asset; + if (!asset) { + cc.error('Can not set an empty effect asset.'); + return; + } + this._effect = Effect.parseEffect(asset.effect); + } + }, + + effect: { + get () { + return this._effect; + } + } + }, + + statics: { + getInstantiatedBuiltinMaterial(name) { + let builtinMaterial = cc.AssetLibrary.getBuiltin('material', 'builtin-' + name); + return Material.getInstantiatedMaterial(builtinMaterial, this); + }, + getInstantiatedMaterial(mat, renderComponent) { + if (mat._owner === renderComponent) { + return mat; + } + else { + let instance = new Material(); + instance.copy(mat); + instance._native = mat._native + ' (Instance)'; + instance._owner = renderComponent; + return instance; + } + } + }, + + /** + * + * @param {Material} mat + */ + copy(mat) { + this.effectAsset = mat.effectAsset; + + for (let name in mat._defines) { + this.define(name, mat._defines[name]); + } + + for (let name in mat._props) { + this.setProperty(name, mat._props[name]); + } + }, + + /** + * + * @param {string} name + * @param {*} val + */ + setProperty(name, val) { + this._props[name] = val; + + if (this._effect) { + if (val instanceof Texture) { + this._effect.setProperty(name, val._texture); + } + else { + this._effect.setProperty(name, val); + } + } + }, + + getProperty(name) { + return this._props[name]; + }, + + /** + * + * @param {string} name + * @param {*} val + */ + define(name, val) { + this._defines[name] = val; + if (this._effect) { + this._effect.define(name, val); + } + }, + + getDefine(name) { + return this._defines[name]; + }, + + updateHash (val) { + this._hash = val || computeHash(this); + }, + + onLoad () { + this.effectAsset = this._effectAsset; + if (!this._effect) return; + + for (let def in this._defines) { + this._effect.define(def, this._defines[def]); + } + for (let prop in this._props) { + this._effect.setProperty(prop, this._props[prop]); + } + }, +}); + +module.exports = cc.Material = Material; diff --git a/cocos2d/core/assets/index.js b/cocos2d/core/assets/index.js index a6496175013..5c855b1a8d7 100644 --- a/cocos2d/core/assets/index.js +++ b/cocos2d/core/assets/index.js @@ -40,4 +40,6 @@ require('./CCBitmapFont'); require('./CCLabelAtlas'); require('./CCTextAsset'); require('./CCJsonAsset'); -require('./CCBufferAsset'); \ No newline at end of file +require('./CCBufferAsset'); +require('./CCEffectAsset'); +require('./CCMaterial'); diff --git a/cocos2d/core/assets/utils/compute-hash.js b/cocos2d/core/assets/utils/compute-hash.js new file mode 100644 index 00000000000..a39bc6cfeb4 --- /dev/null +++ b/cocos2d/core/assets/utils/compute-hash.js @@ -0,0 +1,111 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import murmurhash2 from './murmurhash2_gc'; +import enums from '../../../renderer/mappings/enums'; + +// function genHashCode (str) { +// var hash = 0; +// if (str.length == 0) { +// return hash; +// } +// for (var i = 0; i < str.length; i++) { +// var char = str.charCodeAt(i); +// hash = ((hash<<5)-hash)+char; +// hash = hash & hash; // Convert to 32bit integer +// } +// return hash; +// } + +function serializeDefines (defines) { + let str = ''; + for (let i = 0; i < defines.length; i++) { + str += defines[i].name + defines[i].value; + } + return str; +} + +function serializePass (pass) { + let str = pass._programName + pass._cullMode; + if (pass._blend) { + str += pass._blendEq + pass._blendAlphaEq + pass._blendSrc + pass._blendDst + + pass._blendSrcAlpha + pass._blendDstAlpha + pass._blendColor; + } + if (pass._depthTest) { + str += pass._depthWrite + pass._depthFunc; + } + if (pass._stencilTest) { + str += pass._stencilFuncFront + pass._stencilRefFront + pass._stencilMaskFront + + pass._stencilFailOpFront + pass._stencilZFailOpFront + pass._stencilZPassOpFront + + pass._stencilWriteMaskFront + + pass._stencilFuncBack + pass._stencilRefBack + pass._stencilMaskBack + + pass._stencilFailOpBack + pass._stencilZFailOpBack + pass._stencilZPassOpBack + + pass._stencilWriteMaskBack; + } + return str; +} + +export default function computeHash(material) { + let effect = material._effect; + let hashData = ''; + if (effect) { + let i, j, techData, param, prop, propKey; + + // effect._defines + hashData += serializeDefines(effect._defines); + // effect._techniques + for (i = 0; i < effect._techniques.length; i++) { + techData = effect._techniques[i]; + // technique.stageIDs + hashData += techData.stageIDs; + // technique._layer + // hashData += + techData._layer + "_"; + // technique.passes + for (j = 0; j < techData.passes.length; j++) { + hashData += serializePass(techData.passes[j]); + } + } + + for (let name in effect._properties) { + let param = effect._properties[name]; + let prop = param.value; + + if (!prop) { + continue; + } + switch(param.type) { + case enums.PARAM_INT: + case enums.PARAM_FLOAT: + hashData += prop + ';'; + break; + case enums.PARAM_INT2: + case enums.PARAM_FLOAT2: + hashData += prop.x + ',' + prop.y + ';'; + break; + case enums.PARAM_INT4: + case enums.PARAM_FLOAT4: + hashData += prop.x + ',' + prop.y + ',' + prop.z + ',' + prop.w + ';'; + break; + case enums.PARAM_COLOR4: + hashData += prop.r + ',' + prop.g + ',' + prop.b + ',' + prop.a + ';'; + break; + case enums.PARAM_MAT2: + hashData += prop.m00 + ',' + prop.m01 + ',' + prop.m02 + ',' + prop.m03 + ';'; + break; + case enums.PARAM_TEXTURE_2D: + case enums.PARAM_TEXTURE_CUBE: + hashData += prop._id + ';'; + break; + case enums.PARAM_INT3: + case enums.PARAM_FLOAT3: + case enums.PARAM_COLOR3: + case enums.PARAM_MAT3: + case enums.PARAM_MAT4: + hashData += JSON.stringify(prop) + ';'; + break; + default: + break; + } + } + } + return hashData ? murmurhash2(hashData, 666) : hashData; +}; \ No newline at end of file diff --git a/cocos2d/core/assets/utils/murmurhash2_gc.js b/cocos2d/core/assets/utils/murmurhash2_gc.js new file mode 100644 index 00000000000..605ac359e59 --- /dev/null +++ b/cocos2d/core/assets/utils/murmurhash2_gc.js @@ -0,0 +1,50 @@ +/** + * JS Implementation of MurmurHash2 + * + * @author Gary Court + * @see http://github.com/garycourt/murmurhash-js + * @author Austin Appleby + * @see http://sites.google.com/site/murmurhash/ + * + * @param {string} str ASCII only + * @param {number} seed Positive integer only + * @return {number} 32-bit positive integer hash + */ + +export default function murmurhash2_32_gc(str, seed) { + var + l = str.length, + h = seed ^ l, + i = 0, + k; + + while (l >= 4) { + k = + ((str.charCodeAt(i) & 0xff)) | + ((str.charCodeAt(++i) & 0xff) << 8) | + ((str.charCodeAt(++i) & 0xff) << 16) | + ((str.charCodeAt(++i) & 0xff) << 24); + + k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); + k ^= k >>> 24; + k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); + + h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k; + + l -= 4; + ++i; + } + + switch (l) { + case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16; + case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8; + case 1: h ^= (str.charCodeAt(i) & 0xff); + h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); + } + + h ^= h >>> 13; + h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); + h ^= h >>> 15; + + return h >>> 0; +} \ No newline at end of file diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 6b83a37eca8..1acc37d5382 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -26,9 +26,8 @@ const macro = require('../platform/CCMacro'); const RenderComponent = require('./CCRenderComponent'); -const renderEngine = require('../renderer/render-engine'); const RenderFlow = require('../renderer/render-flow'); -const SpriteMaterial = renderEngine.SpriteMaterial; +const Material = require('../assets/CCMaterial'); /** * !#en Enum for text alignment. @@ -568,7 +567,7 @@ let Label = cc.Class({ }, _activateMaterial (force) { - let material = this._material; + let material = this.sharedMaterials[0]; if (material && !force) { return; } @@ -580,7 +579,8 @@ let Label = cc.Class({ // WebGL else { if (!material) { - material = new SpriteMaterial(); + material = Material.getInstantiatedBuiltinMaterial('sprite', this); + material.define('useTexture', true); } // Setup blend function for premultiplied ttf label texture if (this._texture === this._ttfTexture) { @@ -589,10 +589,8 @@ let Label = cc.Class({ else { this._srcBlendFactor = cc.macro.BlendFactor.SRC_ALPHA; } - material.texture = this._texture; - // For batch rendering, do not use uniform color. - material.useColor = false; - this._updateMaterial(material); + material.setProperty('texture', this._texture); + this.setMaterial(0, material); } this.markForUpdateRenderData(true); diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index b8fcf9ecf58..1cd0fc08edd 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -27,7 +27,7 @@ const misc = require('../utils/misc'); const renderEngine = require('../renderer/render-engine'); const math = renderEngine.math; -const StencilMaterial = renderEngine.StencilMaterial; +const Material = require('../assets/CCMaterial'); const RenderComponent = require('./CCRenderComponent'); const RenderFlow = require('../renderer/render-flow'); const Graphics = require('../graphics/graphics'); @@ -194,9 +194,10 @@ let Mask = cc.Class({ cc.warnID(4201); return; } - if (this._material) { - this._material.alphaThreshold = this.alphaThreshold; - this._material.updateHash(); + let material = this.sharedMaterials[0]; + if (material) { + material.alphaThreshold = this.alphaThreshold; + material.updateHash(); } } }, @@ -355,24 +356,29 @@ let Mask = cc.Class({ // WebGL if (cc.game.renderType !== cc.game.RENDER_TYPE_CANVAS) { // Init material - if (!this._material) { - this._material = new StencilMaterial(); + let material = this.sharedMaterials[0]; + if (!material) { + material = Material.getInstantiatedBuiltinMaterial('sprite', this); + material.define('alphaTest', true); } // Reset material if (this._type === MaskType.IMAGE_STENCIL) { let texture = this.spriteFrame.getTexture(); - this._material.useModel = false; - this._material.useTexture = true; - this._material.useColor = true; - this._material.texture = texture; - this._material.alphaThreshold = this.alphaThreshold; + material.define('useModel', false); + material.define('useTexture', true); + material.define('useColor', true); + + material.setProperty('texture', texture); + material.setProperty('alphaThreshold', this.alphaThreshold); } else { - this._material.useModel = true; - this._material.useTexture = false; - this._material.useColor = false; + material.define('useModel', true); + material.define('useTexture', false); + material.define('useColor', false); } + + this.setMaterial(0, material); } this.markForRender(true); diff --git a/cocos2d/core/components/CCMotionStreak.js b/cocos2d/core/components/CCMotionStreak.js index e097fbb2c2d..32bed00bf89 100644 --- a/cocos2d/core/components/CCMotionStreak.js +++ b/cocos2d/core/components/CCMotionStreak.js @@ -25,7 +25,7 @@ ****************************************************************************/ const RenderComponent = require('../components/CCRenderComponent'); -const SpriteMaterial = require('../renderer/render-engine').SpriteMaterial; +const Material = require('../assets/CCMaterial'); const textureUtil = require('../utils/texture-util'); /** @@ -240,15 +240,15 @@ var MotionStreak = cc.Class({ }, _activateMaterial () { - let material = this._material; + let material = this.sharedMaterials[0]; if (!material) { - material = this._material = new SpriteMaterial(); - material.useColor = false; + material = Material.getInstantiatedBuiltinMaterial('sprite', this); + material.define('useTexture', true); } if (this._texture && this._texture.loaded) { - material.texture = this._texture; - this._updateMaterial(material); + material.setProperty('texture', this._texture); + this.setMaterial(0, material); this.markForRender(true); this.markForUpdateRenderData(true); } diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 5f054168258..c4e976fb9ef 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -29,6 +29,7 @@ const RenderFlow = require('../renderer/render-flow'); const BlendFactor = require('../platform/CCMacro').BlendFactor; const RenderData = renderEngine.RenderData; const gfx = renderEngine.gfx; +const Material = require('../assets/CCMaterial'); /** * !#en @@ -95,10 +96,26 @@ let RenderComponent = cc.Class({ type: BlendFactor, tooltip: CC_DEV && 'i18n:COMPONENT.sprite.dst_blend_factor' }, + + _materials: { + default: [], + type: Material, + }, + + sharedMaterials: { + get () { + return this._materials; + }, + set (val) { + this._materials = val; + this._activateMaterial(true); + }, + type: [Material], + displayName: 'Materials' + } }, ctor () { - this._material = null; this._renderData = null; this.__allocedDatas = []; this._vertexFormat = null; @@ -125,7 +142,7 @@ let RenderComponent = cc.Class({ RenderData.free(this.__allocedDatas[i]); } this.__allocedDatas.length = 0; - this._material = null; + this._materials.length = 0; this._renderData = null; }, @@ -180,47 +197,73 @@ let RenderComponent = cc.Class({ }, _updateColor () { - let material = this._material; - if (material) { + let materials = this._materials; + for (let i = 0; i < materials.length; i++) { + let material = materials[i]; // For batch rendering, update the color only when useColor is set to true. - if (material.useColor) { - material.color = this.node.color; + if (material.getDefine('useColor')) { + material.setProperty('color', this.node.color); material.updateHash(); } - - // reset flag when set color to material successfully - this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; } + // reset flag when set color to material successfully + this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; }, - getMaterial () { - return this._material; + getMaterials () { + return this._materials; }, + getMaterial (index) { + if (index < 0 || index >= this._materials.length) { + return null; + } - _updateMaterial (material) { - this._material = material; + let material = this._materials[index]; + if (!material) return null; + + let instantiated = Material.getInstantiatedMaterial(material, this); + if (instantiated !== material) { + this.setMaterial(index, instantiated); + } - this._updateBlendFunc(); - material.updateHash(); + return this._materials[index]; }, - + setMaterial (index, material) { + this._materials[index] = material; + if (material) { + this._updateMaterialBlendFunc(true, material); + } + this.markForUpdateRenderData(true); + }, + _updateBlendFunc: function (updateHash) { - if (!this._material) { - return; + let materials = this._materials; + for (let i = 0; i < materials.length; i++) { + let material = materials[i]; + this._updateMaterialBlendFunc(updateHash, material); } + }, - var pass = this._material._mainTech.passes[0]; - pass.setBlend( - gfx.BLEND_FUNC_ADD, - this._srcBlendFactor, this._dstBlendFactor, - gfx.BLEND_FUNC_ADD, - this._srcBlendFactor, this._dstBlendFactor - ); + _updateMaterialBlendFunc (updateHash, material) { + let passes = material._effect.getTechnique('transparent').passes; + for (let j = 0; j < passes.length; j++) { + let pass = passes[j]; + pass.setBlend( + true, + gfx.BLEND_FUNC_ADD, + this._srcBlendFactor, this._dstBlendFactor, + gfx.BLEND_FUNC_ADD, + this._srcBlendFactor, this._dstBlendFactor + ); + } if (updateHash) { - this._material.updateHash(); + material.updateHash(); } }, + + _activateMaterial (force) { + } }); RenderComponent._assembler = null; RenderComponent._postAssembler = null; diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index ef4ad542648..27a5aaf7404 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -28,9 +28,8 @@ const misc = require('../utils/misc'); const NodeEvent = require('../CCNode').EventType; const RenderComponent = require('./CCRenderComponent'); const RenderFlow = require('../renderer/render-flow'); -const renderEngine = require('../renderer/render-engine'); -const SpriteMaterial = renderEngine.SpriteMaterial; -const GraySpriteMaterial = renderEngine.GraySpriteMaterial; + +const Material = require('../assets/CCMaterial'); /** * !#en Enum for sprite type. @@ -157,7 +156,6 @@ var Sprite = cc.Class({ extends: RenderComponent, ctor () { - this._assembler = null; this._graySpriteMaterial = null; this._spriteMaterial = null; }, @@ -480,7 +478,7 @@ var Sprite = cc.Class({ if (!this._renderData) { this._renderData = this._assembler.createData(this); - this._renderData.material = this._material; + this._renderData.material = this.sharedMaterials[0]; this.markForUpdateRenderData(true); } }, @@ -490,39 +488,47 @@ var Sprite = cc.Class({ // WebGL if (cc.game.renderType !== cc.game.RENDER_TYPE_CANVAS) { - // Get material - let material; + this.markForUpdateRenderData(true); + this.markForRender(true); + + let material = this.sharedMaterials[0]; + // if material is not internal material, then need do nothing + if (material && material!== this._graySpriteMaterial && material !== this._spriteMaterial) { + return; + } + if (this._state === State.GRAY) { - if (!this._graySpriteMaterial) { - this._graySpriteMaterial = new GraySpriteMaterial(); - } material = this._graySpriteMaterial; + if (!material) { + material = this._graySpriteMaterial = Material.getInstantiatedBuiltinMaterial('gray-sprite', this); + } + + this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; } else { - if (!this._spriteMaterial) { - this._spriteMaterial = new SpriteMaterial(); - } material = this._spriteMaterial; + if (!material) { + material = this._spriteMaterial = Material.getInstantiatedBuiltinMaterial('sprite', this); + material.define('useColor', true); + material.define('useTexture', true); + } + this.node._renderFlag |= RenderFlow.FLAG_COLOR; } - // For batch rendering, do not use uniform color. - material.useColor = false; + // Set texture if (spriteFrame && spriteFrame.textureLoaded()) { let texture = spriteFrame.getTexture(); - if (material.texture !== texture) { - material.texture = texture; - this._updateMaterial(material); + if (material.getProperty('texture') !== texture) { + material.setProperty('texture', texture); + this.setMaterial(0, material); } - else if (material !== this._material) { - this._updateMaterial(material); + else if (material !== this.sharedMaterials[0]) { + this.setMaterial(0, material); } + if (this._renderData) { this._renderData.material = material; } - - this.node._renderFlag |= RenderFlow.FLAG_COLOR; - this.markForUpdateRenderData(true); - this.markForRender(true); } else { this.disableRender(); @@ -551,7 +557,7 @@ var Sprite = cc.Class({ if (!this._enabled) return false; } else { - if (!this._enabled || !this._material || !this.node._activeInHierarchy) return false; + if (!this._enabled || !this.sharedMaterials[0] || !this.node._activeInHierarchy) return false; } let spriteFrame = this._spriteFrame; @@ -604,7 +610,8 @@ var Sprite = cc.Class({ } var spriteFrame = this._spriteFrame; - if (!spriteFrame || (this._material && this._material._texture) !== (spriteFrame && spriteFrame._texture)) { + let material = this.sharedMaterials[0]; + if (!spriteFrame || (material && material._texture) !== (spriteFrame && spriteFrame._texture)) { // disable render flow until texture is loaded this.markForRender(false); } diff --git a/cocos2d/core/graphics/graphics.js b/cocos2d/core/graphics/graphics.js index ef596a8e14c..92bc0190715 100644 --- a/cocos2d/core/graphics/graphics.js +++ b/cocos2d/core/graphics/graphics.js @@ -25,7 +25,7 @@ ****************************************************************************/ const RenderComponent = require('../components/CCRenderComponent'); -const SpriteMaterial = require('../renderer/render-engine').SpriteMaterial; +const Material = require('../assets/CCMaterial'); const Types = require('./types'); const LineCap = Types.LineCap; @@ -195,15 +195,13 @@ let Graphics = cc.Class({ this.node._renderFlag &= ~cc.RenderFlow.FLAG_RENDER; this.node._renderFlag |= cc.RenderFlow.FLAG_CUSTOM_IA_RENDER; - if (this._material) { + if (this.sharedMaterials[0]) { return; } - let material = new SpriteMaterial(); - material.useColor = false; - material.useTexture = false; - material.useModel = true; - this._updateMaterial(material); + let material = Material.getInstantiatedBuiltinMaterial('sprite', this); + material.define('useModel', true); + this.setMaterial(0, material); }, /** diff --git a/cocos2d/core/load-pipeline/uuid-loader.js b/cocos2d/core/load-pipeline/uuid-loader.js index df7b7f2186c..2d52d9c9dc7 100644 --- a/cocos2d/core/load-pipeline/uuid-loader.js +++ b/cocos2d/core/load-pipeline/uuid-loader.js @@ -177,6 +177,7 @@ function loadDepends (pipeline, item, asset, depends, callback) { callback(null, asset); } else { + if (!errors && asset.onLoad) asset.onLoad(); callback(errors, asset); } }); @@ -285,6 +286,7 @@ function loadUuid (item, callback) { cc.deserialize.Details.pool.put(tdInfo); if (depends.length === 0) { + if (asset.onLoad) asset.onLoad(); return callback(null, asset); } loadDepends(this.pipeline, item, asset, depends, callback); diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index aaab02f4da3..5f2a1b111c6 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -29,6 +29,7 @@ const renderEngine = require('../renderer/render-engine'); const gfx = renderEngine.gfx; const RenderFlow = require('../renderer/render-flow'); const aabb = require('../3d/geom-utils/aabb'); +const Material = require('../assets/CCMaterial'); let MeshRenderer = cc.Class({ name: 'cc.MeshRenderer', @@ -51,7 +52,7 @@ let MeshRenderer = cc.Class({ set (v) { if (this._mesh === v) return; this._mesh = v; - this.activeMaterials(true); + this._activateMaterial(true); this.markForUpdateRenderData(true); this.node._renderFlag |= RenderFlow.FLAG_TRANSFORM; }, @@ -72,27 +73,24 @@ let MeshRenderer = cc.Class({ onEnable () { this._super(); - this.activeMaterials(); + this._activateMaterial(); }, - _createMaterial (subMesh) { - let material = new renderEngine.MeshMaterial(); - material.color = this.node.color; - material._mainTech._passes[0].setDepth(true, true); - material.useModel = true; + _activateSubMaterial (material, subMesh) { + material.define('useTexture', true); + material.define('useModel', true); + material.setProperty('color', this.node.color); if (subMesh._vertexBuffer._format._attr2el[gfx.ATTR_COLOR]) { - material.useAttributeColor = true; + material.define('useAttributeColor', true); } - - return material; }, _updateColor () { let materials = this._materials; for (let i = 0; i < materials.length; i++) { let material = materials[i]; - material.color = this.node.color; + material.setProperty('color', this.node.color); material.updateHash(); } @@ -101,10 +99,9 @@ let MeshRenderer = cc.Class({ _reset () { this._materials.length = 0; - this._material = null; }, - activeMaterials (force) { + _activateMaterial (force) { let mesh = this._mesh; // TODO: should init mesh when mesh loaded, need asset load event support if (mesh) { @@ -116,10 +113,6 @@ let MeshRenderer = cc.Class({ return; } - if (this._material && !force) { - return; - } - if (aabb) { this._boundingBox = aabb.fromPoints(aabb.create(), mesh._minPos, mesh._maxPos); } @@ -127,11 +120,18 @@ let MeshRenderer = cc.Class({ this._reset(); let subMeshes = mesh._subMeshes; - for (let i = 0; i < subMeshes.length; i++) { - let material = this._createMaterial(subMeshes[i]); - this._materials.push(material); + let materials = this.sharedMaterials; + + if (!materials[0]) { + materials[0] = Material.getInstantiatedBuiltinMaterial('mesh', this); + } + + for (let i = 0; i < materials.length; i++) { + let subMesh = subMeshes[i]; + if (!subMesh) continue; + let material = materials[i]; + this._activateSubMaterial(material, subMesh); } - this._material = this._materials[0]; this.markForUpdateRenderData(true); this.markForRender(true); diff --git a/cocos2d/core/mesh/mesh-renderer.js b/cocos2d/core/mesh/mesh-renderer.js index f451b05dc2c..45cc9dce76f 100644 --- a/cocos2d/core/mesh/mesh-renderer.js +++ b/cocos2d/core/mesh/mesh-renderer.js @@ -41,7 +41,7 @@ let meshRendererAssembler = { let submeshes = comp.mesh._subMeshes; for (let i = 0; i < submeshes.length; i++) { let data = new IARenderData(); - data.material = comp._materials[i]; + data.material = comp.sharedMaterials[i] || comp.sharedMaterials[0]; data.ia = submeshes[i]; renderDatas.push(data); } @@ -72,7 +72,7 @@ let meshRendererAssembler = { ibData.length ); - data.ia = new renderEngine.InputAssembler(ia._vertexBuffer, ib, gfx.PT_LINES); + data.ia = new InputAssembler(ia._vertexBuffer, ib, gfx.PT_LINES); return data; }, @@ -99,20 +99,19 @@ let meshRendererAssembler = { let tmpMaterial = renderer.material; let tmpNode = renderer.node; - renderer.node = comp._material.useModel ? comp.node : renderer._dummyNode; + renderer.node = comp instanceof cc.SkinnedMeshRenderer ? renderer._dummyNode : comp.node; comp.mesh._uploadData(); let textures = comp.textures; - let materials = comp._materials; for (let i = 0; i < renderDatas.length; i++) { let renderData = renderDatas[i]; let material = renderData.material; if (textures[i]) { - material.texture = textures[i]; + material.setProperty('texture', textures[i]); } else { - material.useTexture = false; + material.define('useTexture', false); } renderer.material = material; diff --git a/cocos2d/core/platform/CCAssetLibrary.js b/cocos2d/core/platform/CCAssetLibrary.js index f5a1f8e6073..b96b02ec949 100644 --- a/cocos2d/core/platform/CCAssetLibrary.js +++ b/cocos2d/core/platform/CCAssetLibrary.js @@ -385,4 +385,42 @@ AssetLibrary._uuidToAsset = {}; // } //}; + +let _builtins = { + effect: {}, + material: {} +}; + +function loadBuiltins (name, type, cb) { + let dirname = name + 's'; + let builtin = _builtins[name] = {}; + cc.loader.loadResDir(dirname, type, 'internal', () => { }, (err, assets) => { + if (err) { + cc.error(err); + } + else { + for (let i = 0; i < assets.length; i++) { + builtin[`${assets[i].name}`] = assets[i]; + } + } + + cb(); + }); +} + +AssetLibrary._loadBuiltins = function (cb) { + loadBuiltins('effect', cc.EffectAsset, () => { + loadBuiltins('material', cc.Material, cb); + }); +}; + +AssetLibrary.getBuiltin = function (type, name) { + return _builtins[type][name]; +}; + +AssetLibrary.getBuiltins = function (type) { + if (!type) return _builtins; + return _builtins[type]; +}; + module.exports = cc.AssetLibrary = AssetLibrary; diff --git a/cocos2d/core/platform/utils.js b/cocos2d/core/platform/utils.js index 752821e8b13..bc42e4e2179 100644 --- a/cocos2d/core/platform/utils.js +++ b/cocos2d/core/platform/utils.js @@ -108,7 +108,7 @@ if (CC_DEV) { if (CC_TEST) { // editor mocks using in unit tests if (typeof Editor === 'undefined') { - Editor = { + window.Editor = { UuidUtils: { NonUuidMark: '.', uuid: function () { diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 9568e45218a..6d71accf9ef 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -39,8 +39,8 @@ function _initBuiltins(device) { return { defaultTexture: defaultTexture, - programTemplates: renderEngine.shaders.templates, - programChunks: renderEngine.shaders.chunks, + programTemplates: {}, + programChunks: {}, }; } diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index ca919bb3621..29d9926c6a5 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -7266,10 +7266,11 @@ color4.str = function (a) { * @returns {array} */ color4.array = function (out, a) { - out[0] = a.r; - out[1] = a.g; - out[2] = a.b; - out[3] = a.a; + let scale = a instanceof cc.Color ? 1 / 255 : 1; + out[0] = a.r * scale; + out[1] = a.g * scale; + out[2] = a.b * scale; + out[3] = a.a * scale; return out; }; @@ -8086,6 +8087,7 @@ function _createShader(gl, type, src) { return shader; } +var _textureInstanceId = 0; var Texture = function Texture(device) { this._device = device; @@ -8105,6 +8107,8 @@ var Texture = function Texture(device) { this._format = enums$1.TEXTURE_FMT_RGBA8; this._target = -1; + + this._id = _textureInstanceId++; }; /** @@ -10399,6 +10403,7 @@ Pass.prototype.setCullMode = function setCullMode (cullMode) { }; Pass.prototype.setBlend = function setBlend ( + enabled, blendEq, blendSrc, blendDst, @@ -10407,6 +10412,7 @@ Pass.prototype.setBlend = function setBlend ( blendDstAlpha, blendColor ) { + if ( enabled === void 0 ) enabled = false; if ( blendEq === void 0 ) blendEq = gfx.BLEND_FUNC_ADD; if ( blendSrc === void 0 ) blendSrc = gfx.BLEND_ONE; if ( blendDst === void 0 ) blendDst = gfx.BLEND_ZERO; @@ -10415,7 +10421,7 @@ Pass.prototype.setBlend = function setBlend ( if ( blendDstAlpha === void 0 ) blendDstAlpha = gfx.BLEND_ZERO; if ( blendColor === void 0 ) blendColor = 0xffffffff; - this._blend = true; + this._blend = enabled; this._blendEq = blendEq; this._blendSrc = blendSrc; this._blendDst = blendDst; @@ -10539,12 +10545,12 @@ var config = { var _genID$1 = 0; -var Technique = function Technique(stages, parameters, passes, layer) { +var Technique = function Technique(stages, passes, layer) { if ( layer === void 0 ) layer = 0; this._id = _genID$1++; this._stageIDs = config.stageIDs(stages); - this._parameters = parameters; // {name, type, size, val} + // this._parameters = parameters; // {name, type, size, val} this._passes = passes; this._layer = layer; // TODO: this._version = 'webgl' or 'webgl2' // ???? @@ -10556,11 +10562,11 @@ Technique.prototype.copy = function (technique) { this._id = technique._id; this._stageIDs = technique._stageIDs; - this._parameters = []; - for (let i = 0; i < technique._parameters.length; ++i) { - let parameter = technique._parameters[i]; - this._parameters.push({name: parameter.name, type: parameter.type}); - } + // this._parameters = []; + // for (let i = 0; i < technique._parameters.length; ++i) { + // let parameter = technique._parameters[i]; + // this._parameters.push({name: parameter.name, type: parameter.type}); + // } for (let i = 0; i < technique._passes.length; ++i) { let pass = this._passes[i]; @@ -12944,7 +12950,7 @@ var ProgramLib = function ProgramLib(device, templates, chunks) { this._templates = {}; for (var i = 0; i < templates.length; ++i) { var tmpl = templates[i]; - this$1.define(tmpl.name, tmpl.vert, tmpl.frag, tmpl.defines); + this$1.define(tmpl); } // register chunks @@ -12965,54 +12971,56 @@ var ProgramLib = function ProgramLib(device, templates, chunks) { * { name: 'lightCount', min: 1, max: 4 } * ]); */ -ProgramLib.prototype.define = function define (name, vert, frag, defines) { +ProgramLib.prototype.define = function define (prog) { + let name = prog.name, vert = prog.vert, frag = prog.frag, defines = prog.defines; if (this._templates[name]) { - console.warn(("Failed to define shader " + name + ": already exists.")); + console.warn(`Failed to define shader ${name}: already exists.`); return; } - var id = ++_shdID; + let id = ++_shdID; // calculate option mask offset - var offset = 0; - var loop = function ( i ) { - var def = defines[i]; - def._offset = offset; - - var cnt = 1; + let offset = 0; + for (let i = 0; i < defines.length; ++i) { + let def = defines[i]; + let cnt = 1; - if (def.min !== undefined && def.max !== undefined) { - cnt = Math.ceil((def.max - def.min) * 0.5); + if (def.type === 'number') { + let range = def.range || []; + def.min = range[0] || 0; + def.max = range[1] || 4; + cnt = Math.ceil(Math.log2(def.max - def.min)); def._map = function (value) { - return (value - this._min) << def._offset; + return (value - this.min) << this._offset; }.bind(def); - } else { + } else { // boolean def._map = function (value) { if (value) { - return 1 << def._offset; + return 1 << this._offset; } return 0; }.bind(def); } offset += cnt; - def._offset = offset; - }; - - for (var i = 0; i < defines.length; ++i) loop( i ); + } vert = this._precision + vert; frag = this._precision + frag; // store it this._templates[name] = { - id: id, - name: name, - vert: vert, - frag: frag, - defines: defines + id, + name, + vert, + frag, + defines, + attributes: prog.attributes, + uniforms: prog.uniforms, + extensions: prog.extensions }; }; @@ -13036,6 +13044,10 @@ ProgramLib.prototype.getKey = function getKey (name, defines) { return key << 8 | tmpl.id; }; +ProgramLib.prototype.getTemplate = function (name) { + return this._templates[name]; +} + /** * @param {string} name * @param {Object} options @@ -13500,9 +13512,9 @@ Base.prototype._draw = function _draw (item) { // } // set technique uniforms - for (var i = 0; i < technique._parameters.length; ++i) { - var prop = technique._parameters[i]; - var param = effect.getProperty(prop.name); + for (let name in effect._properties) { + let prop = effect._properties[name]; + let param = prop.value; if (param === undefined) { param = prop.val; @@ -14169,7 +14181,7 @@ var Material = (function (Asset$$1) { }; Material.prototype.updateHash = function updateHash (value) { - this._hash = value || computeHash(this); + // this._hash = value || computeHash(this); }; Object.defineProperties( Material.prototype, prototypeAccessors ); @@ -14859,6 +14871,8 @@ var renderEngine = { math: math, renderer: renderer, gfx: gfx, + + config: config, }; module.exports = renderEngine; diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/index.js b/cocos2d/core/renderer/webgl/assemblers/graphics/index.js index e80968dff0d..1d3b65a0adc 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/index.js @@ -71,7 +71,7 @@ let graphicsAssembler = { updateRenderData (graphics) { let datas = graphics._impl.getRenderDatas(); for (let i = 0, l = datas.length; i < l; i++) { - datas[i].material = graphics.getMaterial(); + datas[i].material = graphics.sharedMaterials[0]; } }, @@ -85,14 +85,6 @@ let graphicsAssembler = { }, renderIA (graphics, renderer) { - let node = graphics.node; - - let nodeColor = node.color, - nodeR = nodeColor.r / 255, - nodeG = nodeColor.g / 255, - nodeB = nodeColor.b / 255, - nodeA = nodeColor.a / 255; - let impl = graphics._impl; let renderDatas = impl.getRenderDatas(); for (let index = 0, length = renderDatas.length; index < length; index++) { @@ -123,7 +115,7 @@ let graphicsAssembler = { renderDatas[_impl._dataOffset] = renderData; } - renderData.material = graphics.getMaterial(); + renderData.material = graphics.sharedMaterials[0]; meshbuffer = renderData.meshbuffer; } diff --git a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js index ab585fae55f..ae89c69dcad 100644 --- a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js @@ -54,14 +54,14 @@ let maskFrontAssembler = { renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y); renderData.dataLength = 4; spriteAssembler.updateRenderData(mask); - renderData.material = mask._material; + renderData.material = mask.sharedMaterials[0]; } else { - mask._material = null; + mask.setMaterial(0, null); } } else { - mask._graphics._material = mask._material; + mask._graphics.setMaterial(0, mask.sharedMaterials[0]); graphicsAssembler.updateRenderData(mask._graphics); } }, @@ -79,7 +79,7 @@ let maskFrontAssembler = { // vertex buffer renderer.node = mask.node; - renderer.material = mask._material; + renderer.material = mask.sharedMaterials[0]; if (mask._type === Mask.Type.IMAGE_STENCIL) { spriteAssembler.fillBuffers(mask, renderer); renderer._flush(); @@ -95,7 +95,7 @@ let maskFrontAssembler = { }; let maskEndAssembler = { - fillBuffers (mask, renderer) { + fillBuffers (mask) { // Invalid state if (mask._type !== Mask.Type.IMAGE_STENCIL || mask.spriteFrame) { // HACK: Must pop mask after batch, so we can only put this logic in fillBuffers diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index 7eeffdecdea..f3171f64a32 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -84,7 +84,7 @@ var motionStreakAssembler = { let size = comp.node._contentSize; let anchor = comp.node._anchorPoint; renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y); - renderData.material = comp.getMaterial(); + renderData.material = comp.sharedMaterials[0]; }, update (comp, dt) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js index c9cb27d09e1..d26c4e6b942 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js @@ -25,6 +25,7 @@ const Sprite = require('../../../../../components/CCSprite'); const FillType = Sprite.FillType; +const utils = require('../utils'); const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; @@ -32,56 +33,44 @@ const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { useModel: false, updateRenderData (sprite) { - let frame = sprite.spriteFrame; - - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + utils.packToDynamicAtlas(sprite); let renderData = sprite._renderData; - if (renderData && frame) { - let uvDirty = renderData.uvDirty, - vertDirty = renderData.vertDirty; - - if (!uvDirty && !vertDirty) { - return sprite.__allocedDatas; - } - - let fillStart = sprite._fillStart; - let fillRange = sprite._fillRange; - - if (fillRange < 0) { - fillStart += fillRange; - fillRange = -fillRange; - } - - fillRange = fillStart + fillRange; - - fillStart = fillStart > 1.0 ? 1.0 : fillStart; - fillStart = fillStart < 0.0 ? 0.0 : fillStart; - - fillRange = fillRange > 1.0 ? 1.0 : fillRange; - fillRange = fillRange < 0.0 ? 0.0 : fillRange; - fillRange = fillRange - fillStart; - fillRange = fillRange < 0 ? 0 : fillRange; - - let fillEnd = fillStart + fillRange; - fillEnd = fillEnd > 1 ? 1 : fillEnd; - - if (uvDirty) { - this.updateUVs(sprite, fillStart, fillEnd); - } - if (vertDirty) { - this.updateVerts(sprite, fillStart, fillEnd); - this.updateWorldVerts(sprite); - } + if (!renderData || !sprite.spriteFrame) return; + let uvDirty = renderData.uvDirty, + vertDirty = renderData.vertDirty; + + if (!uvDirty && !vertDirty) { + return sprite.__allocedDatas; + } + + let fillStart = sprite._fillStart; + let fillRange = sprite._fillRange; + + if (fillRange < 0) { + fillStart += fillRange; + fillRange = -fillRange; + } + + fillRange = fillStart + fillRange; + + fillStart = fillStart > 1.0 ? 1.0 : fillStart; + fillStart = fillStart < 0.0 ? 0.0 : fillStart; + + fillRange = fillRange > 1.0 ? 1.0 : fillRange; + fillRange = fillRange < 0.0 ? 0.0 : fillRange; + fillRange = fillRange - fillStart; + fillRange = fillRange < 0 ? 0 : fillRange; + + let fillEnd = fillStart + fillRange; + fillEnd = fillEnd > 1 ? 1 : fillEnd; + + if (uvDirty) { + this.updateUVs(sprite, fillStart, fillEnd); + } + if (vertDirty) { + this.updateVerts(sprite, fillStart, fillEnd); + this.updateWorldVerts(sprite); } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js index 4e35b95ddca..50d39bf7016 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js @@ -23,6 +23,7 @@ THE SOFTWARE. ****************************************************************************/ +const utils = require('../utils'); const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; @@ -34,41 +35,30 @@ module.exports = { }, updateRenderData (sprite) { - let frame = sprite.spriteFrame; + utils.packToDynamicAtlas(sprite); - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); + let renderData = sprite._renderData; + let frame = sprite.spriteFrame; + if (!renderData || !frame) return; + let vertices = frame.vertices; + if (vertices) { + if (renderData.vertexCount !== vertices.x.length) { + renderData.vertexCount = vertices.x.length; + renderData.indiceCount = vertices.triangles.length; + + // 1 for world vertices, 2 for local vertices + renderData.dataLength = renderData.vertexCount * 2; + + renderData.uvDirty = renderData.vertDirty = true; } - } - let renderData = sprite._renderData; - if (renderData && frame) { - let vertices = frame.vertices; - if (vertices) { - if (renderData.vertexCount !== vertices.x.length) { - renderData.vertexCount = vertices.x.length; - renderData.indiceCount = vertices.triangles.length; - - // 1 for world vertices, 2 for local vertices - renderData.dataLength = renderData.vertexCount * 2; - - renderData.uvDirty = renderData.vertDirty = true; - } - - if (renderData.uvDirty) { - this.updateUVs(sprite); - } - let vertDirty = renderData.vertDirty; - if (vertDirty) { - this.updateVerts(sprite); - this.updateWorldVerts(sprite); - } + if (renderData.uvDirty) { + this.updateUVs(sprite); + } + let vertDirty = renderData.vertDirty; + if (vertDirty) { + this.updateVerts(sprite); + this.updateWorldVerts(sprite); } } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js index 88ed36b8fb1..f72f229302f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js @@ -23,6 +23,8 @@ THE SOFTWARE. ****************************************************************************/ +const utils = require('../utils'); + const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); const fillVertices = require('../../utils').fillVertices; @@ -218,106 +220,94 @@ module.exports = { }, updateRenderData (sprite) { - let frame = sprite.spriteFrame; - - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + utils.packToDynamicAtlas(sprite); let renderData = sprite._renderData; - if (renderData && frame) { - if (renderData.vertDirty || renderData.uvDirty) { - let data = renderData._data; - - let fillStart = sprite._fillStart; - let fillRange = sprite._fillRange; - if (fillRange < 0) { - fillStart += fillRange; - fillRange = -fillRange; - } + let frame = sprite.spriteFrame; + if (!renderData || !frame) return; + if (!renderData.vertDirty && !renderData.uvDirty) return; + let data = renderData._data; + + let fillStart = sprite._fillStart; + let fillRange = sprite._fillRange; + if (fillRange < 0) { + fillStart += fillRange; + fillRange = -fillRange; + } - //do round fill start [0,1), include 0, exclude 1 - while (fillStart >= 1.0) fillStart -= 1.0; - while (fillStart < 0.0) fillStart += 1.0; + //do round fill start [0,1), include 0, exclude 1 + while (fillStart >= 1.0) fillStart -= 1.0; + while (fillStart < 0.0) fillStart += 1.0; - fillStart *= PI_2; - fillRange *= PI_2; - let fillEnd = fillStart + fillRange; + fillStart *= PI_2; + fillRange *= PI_2; + let fillEnd = fillStart + fillRange; - //build vertices - _calculateVertices(sprite); - //build uvs - _calculateUVs(frame); + //build vertices + _calculateVertices(sprite); + //build uvs + _calculateUVs(frame); - _calcInsectedPoints(_vertices[0], _vertices[2], _vertices[1], _vertices[3], _center, fillStart, _intersectPoint_1); - _calcInsectedPoints(_vertices[0], _vertices[2], _vertices[1], _vertices[3], _center, fillStart + fillRange, _intersectPoint_2); + _calcInsectedPoints(_vertices[0], _vertices[2], _vertices[1], _vertices[3], _center, fillStart, _intersectPoint_1); + _calcInsectedPoints(_vertices[0], _vertices[2], _vertices[1], _vertices[3], _center, fillStart + fillRange, _intersectPoint_2); - let offset = 0; - for (let triangleIndex = 0; triangleIndex < 4; ++triangleIndex) { - let triangle = _triangles[triangleIndex]; - if (!triangle) { - continue; + let offset = 0; + for (let triangleIndex = 0; triangleIndex < 4; ++triangleIndex) { + let triangle = _triangles[triangleIndex]; + if (!triangle) { + continue; + } + //all in + if (fillRange >= PI_2) { + renderData.dataLength = offset + 3; + _generateTriangle(data, offset, _center, _vertPos[triangle[0]], _vertPos[triangle[1]]); + offset += 3; + continue; + } + //test against + let startAngle = _getVertAngle(_center, _vertPos[triangle[0]]); + let endAngle = _getVertAngle(_center, _vertPos[triangle[1]]); + if (endAngle < startAngle) endAngle += PI_2; + startAngle -= PI_2; + endAngle -= PI_2; + //testing + for (let testIndex = 0; testIndex < 3; ++testIndex) { + if (startAngle >= fillEnd) { + //all out + } else if (startAngle >= fillStart) { + renderData.dataLength = offset + 3; + if (endAngle >= fillEnd) { + //startAngle to fillEnd + _generateTriangle(data, offset, _center, _vertPos[triangle[0]], _intersectPoint_2[triangleIndex]); + } else { + //startAngle to endAngle + _generateTriangle(data, offset, _center, _vertPos[triangle[0]], _vertPos[triangle[1]]); } - //all in - if (fillRange >= PI_2) { + offset += 3; + } else { + //startAngle < fillStart + if (endAngle <= fillStart) { + //all out + } else if (endAngle <= fillEnd) { renderData.dataLength = offset + 3; - _generateTriangle(data, offset, _center, _vertPos[triangle[0]], _vertPos[triangle[1]]); + //fillStart to endAngle + _generateTriangle(data, offset, _center, _intersectPoint_1[triangleIndex], _vertPos[triangle[1]]); + offset += 3; + } else { + renderData.dataLength = offset + 3; + //fillStart to fillEnd + _generateTriangle(data, offset, _center, _intersectPoint_1[triangleIndex], _intersectPoint_2[triangleIndex]); offset += 3; - continue; - } - //test against - let startAngle = _getVertAngle(_center, _vertPos[triangle[0]]); - let endAngle = _getVertAngle(_center, _vertPos[triangle[1]]); - if (endAngle < startAngle) endAngle += PI_2; - startAngle -= PI_2; - endAngle -= PI_2; - //testing - for (let testIndex = 0; testIndex < 3; ++testIndex) { - if (startAngle >= fillEnd) { - //all out - } else if (startAngle >= fillStart) { - renderData.dataLength = offset + 3; - if (endAngle >= fillEnd) { - //startAngle to fillEnd - _generateTriangle(data, offset, _center, _vertPos[triangle[0]], _intersectPoint_2[triangleIndex]); - } else { - //startAngle to endAngle - _generateTriangle(data, offset, _center, _vertPos[triangle[0]], _vertPos[triangle[1]]); - } - offset += 3; - } else { - //startAngle < fillStart - if (endAngle <= fillStart) { - //all out - } else if (endAngle <= fillEnd) { - renderData.dataLength = offset + 3; - //fillStart to endAngle - _generateTriangle(data, offset, _center, _intersectPoint_1[triangleIndex], _vertPos[triangle[1]]); - offset += 3; - } else { - renderData.dataLength = offset + 3; - //fillStart to fillEnd - _generateTriangle(data, offset, _center, _intersectPoint_1[triangleIndex], _intersectPoint_2[triangleIndex]); - offset += 3; - } - } - //add 2 * PI - startAngle += PI_2; - endAngle += PI_2; } } - - renderData.indiceCount = renderData.vertexCount = offset; - renderData.vertDirty = renderData.uvDirty = false; + //add 2 * PI + startAngle += PI_2; + endAngle += PI_2; } } + + renderData.indiceCount = renderData.vertexCount = offset; + renderData.vertDirty = renderData.uvDirty = false; }, fillBuffers (comp, renderer) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js index 3cd5ceaf787..94b7e094c7b 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js @@ -23,30 +23,19 @@ THE SOFTWARE. ****************************************************************************/ +const utils = require('../utils'); const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { useModel: false, updateRenderData (sprite) { - let frame = sprite._spriteFrame; - - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + utils.packToDynamicAtlas(sprite); let renderData = sprite._renderData; - if (renderData && frame) { - if (renderData.vertDirty) { - this.updateVerts(sprite); - } + if (!renderData || !sprite.spriteFrame) return; + if (renderData.vertDirty) { + this.updateVerts(sprite); } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js index dccc3a79062..4c988a1861b 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js @@ -23,6 +23,7 @@ THE SOFTWARE. ****************************************************************************/ +const utils = require('../utils'); const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { @@ -39,27 +40,15 @@ module.exports = { return renderData; }, - updateRenderData (sprite, batchData) { - let frame = sprite.spriteFrame; - - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + updateRenderData (sprite) { + utils.packToDynamicAtlas(sprite); let renderData = sprite._renderData; - if (renderData && frame) { - let vertDirty = renderData.vertDirty; - if (vertDirty) { - this.updateVerts(sprite); - this.updateWorldVerts(sprite); - } + if (!renderData || !sprite.spriteFrame) return; + let vertDirty = renderData.vertDirty; + if (vertDirty) { + this.updateVerts(sprite); + this.updateWorldVerts(sprite); } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js index f38d7e11852..5a1aefdf465 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js @@ -23,6 +23,7 @@ THE SOFTWARE. ****************************************************************************/ +const utils = require('../utils'); const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { @@ -37,20 +38,10 @@ module.exports = { }, updateRenderData (sprite) { - let frame = sprite.spriteFrame; - - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + utils.packToDynamicAtlas(sprite); let renderData = sprite._renderData; + let frame = sprite.spriteFrame; if (!frame || !renderData || !(renderData.uvDirty || renderData.vertDirty)) return; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/utils.js b/cocos2d/core/renderer/webgl/assemblers/sprite/utils.js new file mode 100644 index 00000000000..9e1637f606c --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/utils.js @@ -0,0 +1,18 @@ +const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); + +module.exports = { + packToDynamicAtlas (sprite) { + let frame = sprite._spriteFrame; + + // TODO: Material API design and export from editor could affect the material activation process + // need to update the logic here + if (frame) { + if (!frame._original && dynamicAtlasManager) { + dynamicAtlasManager.insertSpriteFrame(frame); + } + if (sprite.sharedMaterials[0].getProperty('texture') !== frame._texture) { + sprite._activateMaterial(); + } + } + } +} \ No newline at end of file diff --git a/cocos2d/core/renderer/webgl/model-batcher.js b/cocos2d/core/renderer/webgl/model-batcher.js index bc3efc8068f..7acc6fea986 100644 --- a/cocos2d/core/renderer/webgl/model-batcher.js +++ b/cocos2d/core/renderer/webgl/model-batcher.js @@ -177,12 +177,13 @@ ModelBatcher.prototype = { }, _commitComp (comp, assembler, cullingMask) { - if (this.material._hash !== comp._material._hash || + let material = comp.sharedMaterials[0]; + if ((material && material._hash !== this.material._hash) || this.cullingMask !== cullingMask) { this._flush(); this.node = assembler.useModel ? comp.node : this._dummyNode; - this.material = comp._material; + this.material = material; this.cullingMask = cullingMask; } @@ -192,7 +193,7 @@ ModelBatcher.prototype = { _commitIA (comp, assembler, cullingMask) { this._flush(); this.cullingMask = cullingMask; - this.material = comp._material; + this.material = comp.sharedMaterials[0] || empty_material; this.node = assembler.useModel ? comp.node : this._dummyNode; assembler.renderIA(comp, this); diff --git a/cocos2d/core/renderer/webgl/stencil-manager.js b/cocos2d/core/renderer/webgl/stencil-manager.js index b25d4ac43d6..6b2af07086c 100644 --- a/cocos2d/core/renderer/webgl/stencil-manager.js +++ b/cocos2d/core/renderer/webgl/stencil-manager.js @@ -62,7 +62,6 @@ StencilManager.prototype = { let technique = effect.getTechnique('transparent'); let passes = technique.passes; if (this.stage === Stage.DISABLED) { - this.stage = Stage.DISABLED; for (let i = 0; i < passes.length; ++i) { let pass = passes[i]; if (pass._stencilTest) { diff --git a/cocos2d/core/value-types/index.js b/cocos2d/core/value-types/index.js index 59bc6c739be..3b5ae993366 100644 --- a/cocos2d/core/value-types/index.js +++ b/cocos2d/core/value-types/index.js @@ -25,12 +25,15 @@ ****************************************************************************/ require('./value-type'); -require('./vec2'); -require('./vec3'); -require('./quat'); -require('./mat4'); -require('./size'); -require('./rect'); -require('./color'); cc.vmath = require('../renderer/render-engine').math; + +module.exports = { + Vec2: require('./vec2'), + Vec3: require('./vec3'), + Quat: require('./quat'), + Mat4: require('./mat4'), + Size: require('./size'), + Rect: require('./rect'), + Color: require('./color'), +}; diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index f2ead2eba80..5c27225e023 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -31,9 +31,9 @@ const codec = require('../compression/ZipUtils'); const PNGReader = require('./CCPNGReader'); const tiffReader = require('./CCTIFFReader'); const textureUtil = require('../core/utils/texture-util'); -const renderEngine = require('../core/renderer/render-engine'); const RenderFlow = require('../core/renderer/render-flow'); const ParticleSimulator = require('./particle-simulator'); +const Material = require('../core/assets/CCMaterial'); function getImageFormatByData (imgData) { // if it is a png file buffer. @@ -840,7 +840,7 @@ var ParticleSystem = cc.Class({ }, update (dt) { - if (!this._simulator.finished && this._material) { + if (!this._simulator.finished && this.sharedMaterials[0]) { this._simulator.step(dt); } }, @@ -1129,11 +1129,11 @@ var ParticleSystem = cc.Class({ }, _activateMaterial: function () { - if (!this._material) { - this._material = new renderEngine.SpriteMaterial(); - this._material.useTexture = true; - this._material.useModel = true; - this._material.useColor = false; + let material = this.sharedMaterials[0]; + if (!material) { + material = Material.getInstantiatedBuiltinMaterial('sprite', this); + material.define('useTexture', true); + material.define('useModel', true); } if (!this._texture || !this._texture.loaded) { @@ -1145,8 +1145,8 @@ var ParticleSystem = cc.Class({ else { this.markForUpdateRenderData(true); this.markForCustomIARender(true); - this._material.texture = this._texture; - this._updateMaterial(this._material); + material.setProperty('texture', this._texture); + this.setMaterial(0, material); } }, diff --git a/cocos2d/particle/particle-system-assembler.js b/cocos2d/particle/particle-system-assembler.js index d9968d1229c..6184eee4718 100644 --- a/cocos2d/particle/particle-system-assembler.js +++ b/cocos2d/particle/particle-system-assembler.js @@ -52,7 +52,7 @@ var particleSystemAssembler = { comp._renderData = new renderEngine.IARenderData(); comp._renderData.ia = comp._ia; } - comp._renderData.material = comp._material; + comp._renderData.material = comp.sharedMaterials[0]; }, renderIA (comp, renderer) { diff --git a/cocos2d/renderer/build/build-mapping.js b/cocos2d/renderer/build/build-mapping.js new file mode 100644 index 00000000000..dcd2575b4b7 --- /dev/null +++ b/cocos2d/renderer/build/build-mapping.js @@ -0,0 +1,49 @@ +'use strict'; + +const Path = require('path'); +const resolve = require('rollup-plugin-node-resolve'); +const rollup = require('rollup'); + +let src = Path.join(__dirname, '../mappings/offline-mappings.js'); +let dest = '../mappings'; +let name = 'index'; +let sourcemap = true; +let globals = {}; + +console.log('rollup mappings...'); + +// see below for details on the options +const inputOptions = { + input: src, + plugins: [ + resolve({ + jsnext: false, + main: false, + root: process.cwd() + }), + ], +}; +const outputOptions = { + file: `${dest}/${name}.js`, + format: 'cjs', + name, + globals, + sourcemap, +}; + +async function build() { + // create a bundle + const bundle = await rollup.rollup(inputOptions); + + // console.log(bundle.imports); // an array of external dependencies + // console.log(bundle.exports); // an array of names exported by the entry point + // console.log(bundle.modules); // an array of module objects + + // generate code and a sourcemap + const { code, map } = await bundle.generate(outputOptions); + + // or write the bundle to disk + await bundle.write(outputOptions); +} + +build(); diff --git a/cocos2d/renderer/build/build-shader.js b/cocos2d/renderer/build/build-shader.js new file mode 100644 index 00000000000..7b09c121dd5 --- /dev/null +++ b/cocos2d/renderer/build/build-shader.js @@ -0,0 +1,104 @@ +'use strict'; + +const sha1 = require('js-sha1'); + +const shdcLib = require('./shdc-lib'); +const mappings = require('../mappings'); +const chunksCache = require('../chunks'); + +let queueRE = /(\w+)(?:([+-])(\d+))?/; +let parseQueue = function (queue) { + let m = queueRE.exec(queue); + if (m === null) return 0; + let q = mappings.RenderQueue[m[1].toUpperCase()]; + if (m.length === 4) { + if (m[2] === '+') q += parseInt(m[3]); + if (m[2] === '-') q -= parseInt(m[3]); + } + return q; +}; + +function mapPassParam(p) { + let num; + switch (typeof p) { + case 'string': + num = parseInt(p); + return isNaN(num) ? mappings.passParams[p.toUpperCase()] : num; + case 'object': + return ((p[0] * 255) << 24 | (p[1] * 255) << 16 | (p[2] * 255) << 8 | (p[3] || 0) * 255) >>> 0; + } + return p; +} + +function buildEffectJSON(json) { + // map param's type offline. + for (let j = 0; j < json.techniques.length; ++j) { + let jsonTech = json.techniques[j]; + if (jsonTech.queue) jsonTech.queue = parseQueue(jsonTech.queue); + for (let k = 0; k < jsonTech.passes.length; ++k) { + let pass = jsonTech.passes[k]; + for (let key in pass) { + if (key === "vert" || key === 'frag') continue; + pass[key] = mapPassParam(pass[key]); + } + } + } + for (let prop in json.properties) { + let info = json.properties[prop]; + info.type = mappings.typeParams[info.type.toUpperCase()]; + } + return json; +} + +let parseEffect = (function() { + let effectRE = /%{([^%]+)%}/; + let blockRE = /%%\s*([\w-]+)\s*{([^]+)}/; + let parenRE = /[{}]/g; + let trimToSize = content => { + let level = 1, end = content.length; + content.replace(parenRE, (p, i) => { + if (p === '{') level++; + else if (level === 1) { end = i; level = 1e9; } + else level--; + }); + return content.substring(0, end); + }; + return function (content) { + let effectCap = effectRE.exec(content); + let effect = JSON.parse(`{${effectCap[1]}}`), templates = {}; + content = content.substring(effectCap.index + effectCap[0].length); + let blockCap = blockRE.exec(content); + while (blockCap) { + let str = templates[blockCap[1]] = trimToSize(blockCap[2]); + content = content.substring(blockCap.index + str.length); + blockCap = blockRE.exec(content); + } + return { effect, templates }; + }; +})(); + +// ============================================================ +// build +// ============================================================ + +function buildEffect(content) { + let { effect, templates } = parseEffect(content); + effect = buildEffectJSON(effect); + Object.assign(templates, chunksCache); + let shaders = []; + for (let j = 0; j < effect.techniques.length; ++j) { + let jsonTech = effect.techniques[j]; + for (let k = 0; k < jsonTech.passes.length; ++k) { + let pass = jsonTech.passes[k]; + let vert = pass.vert, frag = pass.frag; + let shader = shdcLib.assembleAndBuild(vert, frag, templates); + let name = sha1(shader.vert + shader.frag); + shader.name = pass.program = name; + delete pass.vert; delete pass.frag; + shaders.push(shader); + } + } + return { effect, shaders }; +} + +module.exports = buildEffect; \ No newline at end of file diff --git a/cocos2d/renderer/build/shdc-lib.js b/cocos2d/renderer/build/shdc-lib.js new file mode 100644 index 00000000000..40cc47618c6 --- /dev/null +++ b/cocos2d/renderer/build/shdc-lib.js @@ -0,0 +1,305 @@ +'use strict'; + +const tokenizer = require('glsl-tokenizer/string'); +const mappings = require('../mappings'); + +let includeRE = /#include +<([\w-.]+)>/gm; +let defineRE = /#define\s+(\w+)\(([\w,\s]+)\)\s+(.*##.*)\n/g; +let whitespaces = /\s+/g; +let ident = /^[_a-zA-Z]\w*$/; +let extensionRE = /(?:GL_)?(\w+)/; +let comparators = /^[<=>]+$/; +let ifprocessor = /#(el)?if/; +let rangePragma = /range\(([\d.,\s]+)\)\s(\w+)/; +let defaultPragma = /default\(([\d.,]+)\)/; +let namePragma = /name\(([^)]+)\)/; +let precision = /(low|medium|high)p/; + +// (HACKY) extract all builtin uniforms to the ignore list +let uniformIgnoreList = {viewProj: true, model: true}; +// let uniformIgnoreList = (function() { +// let path = 'cocos/renderer/renderers/forward-renderer.js'; +// let renderer = fs.readFileSync(path, { encoding: 'utf8' }); +// let re = /set(Uniform|Texture)\([`'"](\w+)[`'"]/g, cap = re.exec(renderer); +// let result = []; +// while (cap) { result.push(cap[2]); cap = re.exec(renderer); } +// return result; +// })(); + +function convertType(t) { let tp = mappings.typeParams[t.toUpperCase()]; return tp === undefined ? t : tp; } + +function unwindIncludes(str, chunks) { + function replace(match, include) { + let replace = chunks[include]; + if (replace === undefined) { + console.error(`can not resolve #include <${include}>`); + } + return unwindIncludes(replace, chunks); + } + return str.replace(includeRE, replace); +} + +function glslStripComment(code) { + let tokens = tokenizer(code); + + let result = ''; + for (let i = 0; i < tokens.length; ++i) { + let t = tokens[i]; + if (t.type != 'block-comment' && t.type != 'line-comment' && t.type != 'eof') { + result += t.data; + } + } + + return result; +} + +function extractDefines(tokens, defines, cache) { + let curDefs = [], save = (line) => { + cache[line] = curDefs.reduce((acc, val) => acc.concat(val), []); + cache.lines.push(line); + }; + for (let i = 0; i < tokens.length; ++i) { + let t = tokens[i], str = t.data, id, df; + if (t.type !== 'preprocessor') continue; + str = str.split(whitespaces); + if (str[0] === '#endif') { + curDefs.pop(); save(t.line); continue; + } else if (str[0] === '#else') { + curDefs[curDefs.length - 1].length = 0; save(t.line); continue; + } else if (str[0] === '#pragma') { + if (str[1] === 'for') { curDefs.push(0); save(t.line); } + else if (str[1] === 'endFor') { curDefs.pop(); save(t.line); } + else if (str[1][0] === '#') cache[t.line] = str.splice(1); + else { + let mc = rangePragma.exec(t.data); + if (!mc) continue; + let def = defines.find(d => d.name === mc[2]); + if (!def) defines.push(def = { name: mc[2] }); + def.type = 'number'; + def.range = JSON.parse(`[${mc[1]}]`); + } + continue; + } else if (!ifprocessor.test(str[0])) continue; + if (str[0] === '#elif') { curDefs.pop(); save(t.line); } + let defs = []; + str.splice(1).some(s => { + id = s.match(ident); + if (id) { // is identifier + defs.push(id[0]); + df = defines.find(d => d.name === id[0]); + if (df) return; // first encounter + defines.push(df = { name: id[0], type: 'boolean' }); + } else if (comparators.test(s)) df.type = 'number'; + else if (s === '||') return true; + }); + curDefs.push(defs); save(t.line); + } + return defines; +} + +/* here the `define dependency` for some param is interpreted as + * the existance of some define ids directly desides the existance of that param. + * so basically therer is no logical expression support + * (all will be treated as '&&' operator) + * for wrapping unifom, attribute and extension declarations. + * try to write them in straightforward ways like: + * #ifdef USE_COLOR + * attribute vec4 a_color; + * #endif + * or nested when needed: + * #if USE_BILLBOARD && BILLBOARD_STRETCHED + * uniform vec3 stretch_color; + * #ifdef USE_NORMAL_TEXTURE + * uniform sampler2D tex_normal; + * #endif + * #endif // no else branch + */ +function extractParams(tokens, cache, uniforms, attributes, extensions) { + let getDefs = line => { + let idx = cache.lines.findIndex(i => i > line); + return cache[cache.lines[idx - 1]] || []; + }; + for (let i = 0; i < tokens.length; i++) { + let t = tokens[i], tp = t.type, str = t.data, dest; + if (tp === 'keyword' && str === 'uniform') dest = uniforms; + else if (tp === 'keyword' && str === 'attribute') dest = attributes; + else if (tp === 'preprocessor' && str.startsWith('#extension')) dest = extensions; + else continue; + let defines = getDefs(t.line), param = {}; + if (defines.findIndex(i => !i) >= 0) continue; // inside pragmas + if (dest === uniforms && uniformIgnoreList[tokens[i+4].data]) continue; + if (dest === extensions) { + if (defines.length > 1) console.warn('extensions must be under controll of no more than 1 define'); + param.name = extensionRE.exec(str.split(whitespaces)[1])[1]; + param.define = defines[0]; + dest.push(param); + continue; + } else { // uniforms and attributes + let offset = precision.exec(tokens[i+2].data) ? 4 : 2; + param.name = tokens[i+offset+2].data; + param.type = convertType(tokens[i+offset].data); + let tags = cache[t.line - 1]; + if (tags && tags[0][0] === '#') { // tags + let mc = defaultPragma.exec(tags.join('')); + if (mc && mc[1].length > 0) { + mc = JSON.parse(`[${mc[1]}]`); + if (mc.length === 1) param.value = mc[0]; + else param.value = mc; + } + mc = namePragma.exec(tags.join(' ')); + if (mc) param.displayName = mc[1]; + for (let j = 0; j < tags.length; j++) { + let tag = tags[j]; + if (tag === '#color') param.type = convertType(param.type); + else if (tag === '#property') param.property = true; + } + } + } + param.defines = defines; + dest.push(param); + } +} + +let expandStructMacro = (function() { + function matchParenthesisPair(string, startIdx) { + let parHead = startIdx; + let parTail = parHead; + let depth = 0; + for (let i = startIdx; i < string.length; i++) + if (string[i] === '(') { parHead = i; depth = 1; break; } + if (depth === 0) return parHead; + for (let i = parHead + 1; i < string.length; i++) { + if (string[i] === '(') depth++; + if (string[i] === ')') depth--; + if (depth === 0) { parTail = i; break; } + } + if (depth !== 0) return parHead; + return parTail; + } + function generateHypenRE(hyphen, macroParam) { + return '(' + [hyphen + macroParam + hyphen, hyphen + macroParam, macroParam + hyphen].join('|') + ')'; + } + function generateParamRE(param) { + return '\\b' + param + '\\b'; + } + return function (code) { + code = code.replace(/\\\n/g, ''); + let defineCapture = defineRE.exec(code); + //defineCapture[1] - the macro name + //defineCapture[2] - the macro parameters + //defineCapture[3] - the macro body + while (defineCapture != null) { + let macroRE = new RegExp('\\n.*' + defineCapture[1] + '\\s*\\(', 'g'); + let macroCapture = macroRE.exec(code); + while (macroCapture != null) { + let macroIndex = macroCapture[0].lastIndexOf(defineCapture[1]); + //the whole macro string,include name and arguments + let macroStr = code.slice(macroCapture.index + macroIndex, matchParenthesisPair(code, macroCapture.index + macroCapture[0].length - 1) + 1); + //the macro arguments list + let macroArguLine = macroStr.slice(macroCapture[0].length - macroIndex, -1); + //the string before macro's name in the matched line + let prefix = macroCapture[0].slice(0, macroIndex); + let containDefine = prefix.indexOf('#define') !== -1; + let containParenthesis = prefix.indexOf('(') !== -1; + let macroParams = defineCapture[2].split(','); + //erase the white space in the macro's parameters + for (let i = 0; i < macroParams.length; i++) { + macroParams[i] = macroParams[i].replace(/\s/g, ''); + } + let macroArgus = macroArguLine.split(','); + for (let i = 0; i < macroArgus.length; i++) { + macroArgus[i] = macroArgus[i].replace(/\s/g, ''); + } + //if the matched macro is defined in another macro, then just replace the parameters with the arguments + if (containDefine && containParenthesis) { + code = code.replace(new RegExp(defineCapture[1] + '\\(' + macroArguLine + '\\)', 'g'), (matched, offset) => { + //if the matched string is the marco we just found,the replace it + if (macroCapture.index + prefix.length == offset) { + let ret = defineCapture[3]; + for (let i = 0; i < macroParams.length; i++) { + ret = ret.replace(new RegExp(generateParamRE(macroParams[i]), 'g'), macroArgus[i]); + } + return ret; + } + return matched; + }); + //move the next match index to the beginning of the line,in case of the same macro on the same line. + macroRE.lastIndex -= macroCapture[0].length; + } + //if the matched macro is defined in the executable code block,we should consider the hypen sign('##') + if (!containDefine) { + let repStr = defineCapture[3]; + for (let i = 0; i < macroParams.length; i++) { + let hypenRE = new RegExp(generateHypenRE('##', macroParams[i]), 'g'); + if (hypenRE.test(repStr)) { + //replace the hypen sign + repStr = repStr.replace(hypenRE, macroArgus[i]); + } else { + repStr = repStr.replace(new RegExp(generateParamRE(macroParams[i]), 'g'), macroArgus[i]); + } + } + code = code.replace(macroStr, repStr); + //move the next match index to the beginning of the line,in case of the same macro on the same line. + macroRE.lastIndex -= macroCapture[0].length; + } + macroCapture = macroRE.exec(code); + } + defineCapture = defineRE.exec(code); + } + return code; + }; +})(); + +let assemble = (function() { + let entryRE = /([\w-]+)(?::(\w+))?/; + let integrity = /void\s+main\s*\(\s*\)/g; + let wrapperFactory = (vert, fn) => `\nvoid main() { ${vert ? 'gl_Position' : 'gl_FragColor'} = ${fn}(); }\n`; + return function(name, cache, vert) { + let entryCap = entryRE.exec(name), content = cache[entryCap[1]]; + if (!content) { console.error(`${entryCap[1]} not found, please check again.`); return ''; } + if (!entryCap[2]) { + if (!integrity.test(content)) console.error(`no main function found in ${name}!`); + return cache[name]; + } + return content + wrapperFactory(vert, entryCap[2]); + }; +})(); + +let build = function(vert, frag, cache) { + let defines = [], defCache = { lines: [] }, tokens; + let uniforms = [], attributes = [], extensions = []; + + vert = glslStripComment(vert); + vert = unwindIncludes(vert, cache); + vert = expandStructMacro(vert); + tokens = tokenizer(vert); + extractDefines(tokens, defines, defCache); + extractParams(tokens, defCache, uniforms, attributes, extensions); + + defCache = { lines: [] }; + frag = glslStripComment(frag); + frag = unwindIncludes(frag, cache); + frag = expandStructMacro(frag); + tokens = tokenizer(frag); + extractDefines(tokens, defines, defCache); + extractParams(tokens, defCache, uniforms, attributes, extensions); + + return { vert, frag, defines, uniforms, attributes, extensions }; +}; + +let assembleAndBuild = function(vertName, fragName, cache) { + let vert = assemble(vertName, cache, true); + let frag = assemble(fragName, cache); + return build(vert, frag, cache); +}; + +// ================== +// exports +// ================== + +module.exports = { + glslStripComment, + assemble, + build, + assembleAndBuild +}; diff --git a/cocos2d/renderer/chunks/index.js b/cocos2d/renderer/chunks/index.js new file mode 100644 index 00000000000..0b0ce35a0dd --- /dev/null +++ b/cocos2d/renderer/chunks/index.js @@ -0,0 +1,3 @@ +module.exports = { + "skinning": "\n\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n\n#ifdef useJointsTexture\nuniform sampler2D jointsTexture;\nuniform float jointsTextureSize;\n\nmat4 getBoneMatrix(const in float i) {\n float size = jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n\n y = dy * (y + 0.5);\n\n vec4 v1 = texture2D(jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(jointsTexture, vec2(dx * (x + 3.5), y));\n\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 jointMatrices[64];\n\nmat4 getBoneMatrix(const in float i) {\n return jointMatrices[int(i)];\n}\n#endif\n\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}" +} \ No newline at end of file diff --git a/cocos2d/renderer/chunks/skinning.inc b/cocos2d/renderer/chunks/skinning.inc new file mode 100644 index 00000000000..ba666f460b6 --- /dev/null +++ b/cocos2d/renderer/chunks/skinning.inc @@ -0,0 +1,43 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +attribute vec4 a_weights; +attribute vec4 a_joints; + +#ifdef useJointsTexture +uniform sampler2D jointsTexture; +uniform float jointsTextureSize; + +mat4 getBoneMatrix(const in float i) { + float size = jointsTextureSize; + float j = i * 4.0; + float x = mod(j, size); + float y = floor(j / size); + + float dx = 1.0 / size; + float dy = 1.0 / size; + + y = dy * (y + 0.5); + + vec4 v1 = texture2D(jointsTexture, vec2(dx * (x + 0.5), y)); + vec4 v2 = texture2D(jointsTexture, vec2(dx * (x + 1.5), y)); + vec4 v3 = texture2D(jointsTexture, vec2(dx * (x + 2.5), y)); + vec4 v4 = texture2D(jointsTexture, vec2(dx * (x + 3.5), y)); + + return mat4(v1, v2, v3, v4); +} +#else +uniform mat4 jointMatrices[64]; + +mat4 getBoneMatrix(const in float i) { + return jointMatrices[int(i)]; +} +#endif + +mat4 skinMatrix() { + return + getBoneMatrix(a_joints.x) * a_weights.x + + getBoneMatrix(a_joints.y) * a_weights.y + + getBoneMatrix(a_joints.z) * a_weights.z + + getBoneMatrix(a_joints.w) * a_weights.w + ; +} \ No newline at end of file diff --git a/cocos2d/renderer/effect.js b/cocos2d/renderer/effect.js new file mode 100644 index 00000000000..377962b41f2 --- /dev/null +++ b/cocos2d/renderer/effect.js @@ -0,0 +1,278 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import { Vec2, Vec3, Vec4, Color, Mat4 } from '../core/value-types'; +import { config, renderer, gfx } from '../core/renderer/render-engine'; +const { Technique, Pass } = renderer; +const enums = renderer; + +const { Texture2D, TextureCube } = gfx; +const CCObject = cc.Object; + +let _typeMap = { + [enums.PARAM_INT]: Number, + [enums.PARAM_INT2]: Vec2, + [enums.PARAM_INT3]: Vec3, + [enums.PARAM_INT4]: Vec4, + [enums.PARAM_FLOAT]: Number, + [enums.PARAM_FLOAT2]: Vec2, + [enums.PARAM_FLOAT3]: Vec3, + [enums.PARAM_FLOAT4]: Vec4, + [enums.PARAM_COLOR3]: Color, + [enums.PARAM_COLOR4]: Color, + [enums.PARAM_MAT4]: Mat4, + [enums.PARAM_TEXTURE_2D]: Texture2D, + [enums.PARAM_TEXTURE_CUBE]: TextureCube, + number: Number, + boolean: Boolean, + default: CCObject +}; +let getInstanceType = function(t) { return _typeMap[t] || _typeMap.default; }; +let typeCheck = function(value, type) { + let instanceType = getInstanceType(type); + switch (typeof value) { + case 'object': return (value === null) || (value instanceof instanceType); + case 'number': return instanceType === Number; + default: return false; + } +}; + +class Effect { + /** + * @param {Array} techniques + */ + constructor(techniques, properties = {}, defines = [], dependencies = []) { + this._techniques = techniques; + this._properties = properties; + this._defines = defines; + this._dependencies = dependencies; + + // TODO: check if params is valid for current technique??? + } + + clear() { + this._techniques.length = 0; + this._properties = null; + this._defines.length = 0; + } + + getTechnique(stage) { + let stageID = config.stageID(stage); + if (stageID === -1) { + return null; + } + + for (let i = 0; i < this._techniques.length; ++i) { + let tech = this._techniques[i]; + if (tech.stageIDs & stageID) { + return tech; + } + } + + return null; + } + + getProperty(name) { + if (!this._properties[name]) { + console.warn(`Failed to get property ${name}, property not found.`); + return null; + } + return this._properties[name].value; + } + + setProperty(name, value) { + let prop = this._properties[name]; + if (!prop) { + console.warn(`Failed to set property ${name}, property not found.`); + return; + } + // else if (!typeCheck(value, prop.type)) { // re-enable this after 3.x migration + // console.warn(`Failed to set property ${name}, property type mismatch.`); + // return; + // } + this._properties[name].value = value; + } + + getDefine(name) { + for (let i = 0; i < this._defines.length; ++i) { + let def = this._defines[i]; + if (def.name === name) { + return def.value; + } + } + + console.warn(`Failed to get define ${name}, define not found.`); + return null; + } + + define(name, value) { + for (let i = 0; i < this._defines.length; ++i) { + let def = this._defines[i]; + if (def.name === name) { + def.value = value; + return; + } + } + + console.warn(`Failed to set define ${name}, define not found.`); + } + + extractDefines(out = {}) { + for (let i = 0; i < this._defines.length; ++i) { + let def = this._defines[i]; + out[def.name] = def.value; + } + + return out; + } + + extractDependencies(out = {}) { + for (let i = 0; i < this._dependencies.length; ++i) { + let dep = this._dependencies[i]; + out[dep.define] = dep.extension; + } + + return out; + } +} + +let cloneObjArray = function(val) { return val.map(obj => Object.assign({}, obj)); }; + +let _ctorMap = { + [Number]: v => v || 0, + [Boolean]: v => v || false, + [Vec2]: v => v ? cc.v2(v[0], v[1]) : cc.v2(), + [Vec3]: v => v ? cc.v3(v[0], v[1], v[2]) : cc.v3(), + [Vec4]: v => v ? cc.v4(v[0], v[1], v[2], v[3]) : cc.v4(), + [Color]: v => v ? cc.color(v[0] * 255, v[1] * 255, v[2] * 255, + (v[3] || 1) * 255) : cc.color(), + [Mat4]: v => v ? cc.mat4( + v[0], v[1], v[2], v[3], + v[4], v[5], v[6], v[7], + v[8], v[9], v[10], v[11], + v[12], v[13], v[14], v[15], + ) : cc.mat4(), + [Texture2D]: () => null, + [TextureCube]: () => null, + [CCObject]: () => null +}; +let getInstanceCtor = function(t) { return _ctorMap[getInstanceType(t)]; }; + +let getInvolvedPrograms = function(json) { + let programs = [], lib = cc.renderer._forward._programLib; + json.techniques.forEach(tech => { + tech.passes.forEach(pass => { + programs.push(lib.getTemplate(pass.program)); + }); + }); + return programs; +}; +let parseProperties = (function() { + function genPropInfo(displayName, type, value) { + return { + type: type, + displayName: displayName, + instanceType: getInstanceType(type), + value: getInstanceCtor(type)(value) + }; + } + return function(json, programs) { + let props = {}; + // properties may be specified in the shader too + programs.forEach(pg => { + pg.uniforms.forEach(prop => { + if (!prop.property) return; + props[prop.name] = genPropInfo(prop.displayName, prop.type, prop.value); + }); + }); + for (let prop in json.properties) { + let propInfo = json.properties[prop], uniformInfo; + // always try getting the type from shaders first + if (propInfo.tech !== undefined && propInfo.pass !== undefined) { + let pname = json.techniques[propInfo.tech].passes[propInfo.pass].program; + let program = programs.find(p => p.name === pname); + uniformInfo = program.uniforms.find(u => u.name === prop); + } else { + for (let i = 0; i < programs.length; i++) { + uniformInfo = programs[i].uniforms.find(u => u.name === prop); + if (uniformInfo) break; + } + } + // the property is not defined in all the shaders used in techs + if (!uniformInfo) { + console.warn(`illegal property: ${prop}`); + continue; + } + // TODO: different param with same name for different passes + props[prop] = genPropInfo( + propInfo.displayName || uniformInfo.displayName, + propInfo.type || uniformInfo.type, + propInfo.value || uniformInfo.value); + } + return props; + }; +})(); + +Effect.parseEffect = function(json) { + // techniques + let techNum = json.techniques.length; + let techniques = new Array(techNum); + for (let j = 0; j < techNum; ++j) { + let tech = json.techniques[j]; + let passNum = tech.passes.length; + let passes = new Array(passNum); + for (let k = 0; k < passNum; ++k) { + let pass = tech.passes[k]; + passes[k] = new Pass(pass.program); + passes[k].setDepth(pass.depthTest, pass.depthWrite, pass.depthFunc); + passes[k].setCullMode(pass.cullMode); + passes[k].setBlend(pass.blend, pass.blendEq, pass.blendSrc, + pass.blendDst, pass.blendAlphaEq, pass.blendSrcAlpha, pass.blendDstAlpha, pass.blendColor); + passes[k].setStencilFront(pass.stencilTest, pass.stencilFuncFront, pass.stencilRefFront, pass.stencilMaskFront, + pass.stencilFailOpFront, pass.stencilZFailOpFront, pass.stencilZPassOpFront, pass.stencilWriteMaskFront); + passes[k].setStencilBack(pass.stencilTest, pass.stencilFuncBack, pass.stencilRefBack, pass.stencilMaskBack, + pass.stencilFailOpBack, pass.stencilZFailOpBack, pass.stencilZPassOpBack, pass.stencilWriteMaskBack); + } + techniques[j] = new Technique(tech.stages, passes, tech.layer); + } + let programs = getInvolvedPrograms(json); + // uniforms + let props = parseProperties(json, programs), uniforms = {}; + programs.forEach(p => { + p.uniforms.forEach(u => { + let name = u.name, uniform = uniforms[name] = Object.assign({}, u); + uniform.value = getInstanceCtor(u.type)(u.value); + if (props[name]) { // effect info override + uniform.type = props[name].type; + uniform.value = props[name].value; + } + }); + }); + // defines + let defines = programs.reduce((acc, cur) => acc = acc.concat(cur.defines), []); + defines = cloneObjArray(defines); + defines.forEach(d => d.value = getInstanceCtor(d.type)()); + // extensions + let extensions = programs.reduce((acc, cur) => acc = acc.concat(cur.extensions), []); + extensions = cloneObjArray(extensions); + + return new Effect(techniques, uniforms, defines, extensions); +}; + +if (CC_EDITOR) { + Effect.parseForInspector = function(json) { + let programs = getInvolvedPrograms(json); + let props = parseProperties(json, programs), defines = {}; + programs.forEach(program => { + program.defines.forEach(define => { + defines[define.name] = { + instanceType: getInstanceType(define.type), + value: getInstanceCtor(define.type)() + }; + }); + }); + return { props, defines }; + }; +} + +export default Effect; +cc.Effect = Effect; diff --git a/cocos2d/renderer/mappings/enums.js b/cocos2d/renderer/mappings/enums.js new file mode 100644 index 00000000000..62f638b02a6 --- /dev/null +++ b/cocos2d/renderer/mappings/enums.js @@ -0,0 +1,50 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +export default { + // projection + PROJ_PERSPECTIVE: 0, + PROJ_ORTHO: 1, + + // lights + LIGHT_DIRECTIONAL: 0, + LIGHT_POINT: 1, + LIGHT_SPOT: 2, + + // shadows + SHADOW_NONE: 0, + SHADOW_HARD: 1, + SHADOW_SOFT: 2, + + // parameter type + PARAM_INT: 0, + PARAM_INT2: 1, + PARAM_INT3: 2, + PARAM_INT4: 3, + PARAM_FLOAT: 4, + PARAM_FLOAT2: 5, + PARAM_FLOAT3: 6, + PARAM_FLOAT4: 7, + PARAM_COLOR3: 8, + PARAM_COLOR4: 9, + PARAM_MAT2: 10, + PARAM_MAT3: 11, + PARAM_MAT4: 12, + PARAM_TEXTURE_2D: 13, + PARAM_TEXTURE_CUBE: 14, + + // clear flags + CLEAR_COLOR: 1, + CLEAR_DEPTH: 2, + CLEAR_STENCIL: 4, + CLEAR_SKYBOX: 8, + + // + BUFFER_VIEW_INT8: 0, + BUFFER_VIEW_UINT8: 1, + BUFFER_VIEW_INT16: 2, + BUFFER_VIEW_UINT16: 3, + BUFFER_VIEW_INT32: 4, + BUFFER_VIEW_UINT32: 5, + BUFFER_VIEW_FLOAT32: 6, + }; + \ No newline at end of file diff --git a/cocos2d/renderer/mappings/gfx/enums.js b/cocos2d/renderer/mappings/gfx/enums.js new file mode 100644 index 00000000000..16e34dfc7a8 --- /dev/null +++ b/cocos2d/renderer/mappings/gfx/enums.js @@ -0,0 +1,336 @@ +const GL_NEAREST = 9728; // gl.NEAREST +const GL_LINEAR = 9729; // gl.LINEAR +const GL_NEAREST_MIPMAP_NEAREST = 9984; // gl.NEAREST_MIPMAP_NEAREST +const GL_LINEAR_MIPMAP_NEAREST = 9985; // gl.LINEAR_MIPMAP_NEAREST +const GL_NEAREST_MIPMAP_LINEAR = 9986; // gl.NEAREST_MIPMAP_LINEAR +const GL_LINEAR_MIPMAP_LINEAR = 9987; // gl.LINEAR_MIPMAP_LINEAR + +// const GL_BYTE = 5120; // gl.BYTE +const GL_UNSIGNED_BYTE = 5121; // gl.UNSIGNED_BYTE +// const GL_SHORT = 5122; // gl.SHORT +const GL_UNSIGNED_SHORT = 5123; // gl.UNSIGNED_SHORT +const GL_UNSIGNED_INT = 5125; // gl.UNSIGNED_INT +const GL_FLOAT = 5126; // gl.FLOAT +const GL_UNSIGNED_SHORT_5_6_5 = 33635; // gl.UNSIGNED_SHORT_5_6_5 +const GL_UNSIGNED_SHORT_4_4_4_4 = 32819; // gl.UNSIGNED_SHORT_4_4_4_4 +const GL_UNSIGNED_SHORT_5_5_5_1 = 32820; // gl.UNSIGNED_SHORT_5_5_5_1 +const GL_HALF_FLOAT_OES = 36193; // gl.HALF_FLOAT_OES + +const GL_DEPTH_COMPONENT = 6402; // gl.DEPTH_COMPONENT + +const GL_ALPHA = 6406; // gl.ALPHA +const GL_RGB = 6407; // gl.RGB +const GL_RGBA = 6408; // gl.RGBA +const GL_LUMINANCE = 6409; // gl.LUMINANCE +const GL_LUMINANCE_ALPHA = 6410; // gl.LUMINANCE_ALPHA + +const GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; // ext.COMPRESSED_RGB_S3TC_DXT1_EXT +const GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; // ext.COMPRESSED_RGBA_S3TC_DXT1_EXT +const GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; // ext.COMPRESSED_RGBA_S3TC_DXT3_EXT +const GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; // ext.COMPRESSED_RGBA_S3TC_DXT5_EXT + +const GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; // ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG +const GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; // ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG +const GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; // ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG +const GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; // ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG + +const GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; // ext.COMPRESSED_RGB_ETC1_WEBGL + +const _filterGL = [ + [ GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR ], + [ GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR ], +]; + +const _textureFmtGL = [ + // TEXTURE_FMT_RGB_DXT1: 0 + { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixelType: null }, + + // TEXTURE_FMT_RGBA_DXT1: 1 + { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixelType: null }, + + // TEXTURE_FMT_RGBA_DXT3: 2 + { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, pixelType: null }, + + // TEXTURE_FMT_RGBA_DXT5: 3 + { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, pixelType: null }, + + // TEXTURE_FMT_RGB_ETC1: 4 + { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_ETC1_WEBGL, pixelType: null }, + + // TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5 + { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, pixelType: null }, + + // TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6 + { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, pixelType: null }, + + // TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7 + { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, pixelType: null }, + + // TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8 + { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, pixelType: null }, + + // TEXTURE_FMT_A8: 9 + { format: GL_ALPHA, internalFormat: GL_ALPHA, pixelType: GL_UNSIGNED_BYTE }, + + // TEXTURE_FMT_L8: 10 + { format: GL_LUMINANCE, internalFormat: GL_LUMINANCE, pixelType: GL_UNSIGNED_BYTE }, + + // TEXTURE_FMT_L8_A8: 11 + { format: GL_LUMINANCE_ALPHA, internalFormat: GL_LUMINANCE_ALPHA, pixelType: GL_UNSIGNED_BYTE }, + + // TEXTURE_FMT_R5_G6_B5: 12 + { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_SHORT_5_6_5 }, + + // TEXTURE_FMT_R5_G5_B5_A1: 13 + { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_5_5_5_1 }, + + // TEXTURE_FMT_R4_G4_B4_A4: 14 + { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_4_4_4_4 }, + + // TEXTURE_FMT_RGB8: 15 + { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_BYTE }, + + // TEXTURE_FMT_RGBA8: 16 + { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_BYTE }, + + // TEXTURE_FMT_RGB16F: 17 + { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_HALF_FLOAT_OES }, + + // TEXTURE_FMT_RGBA16F: 18 + { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_HALF_FLOAT_OES }, + + // TEXTURE_FMT_RGB32F: 19 + { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_FLOAT }, + + // TEXTURE_FMT_RGBA32F: 20 + { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_FLOAT }, + + // TEXTURE_FMT_R32F: 21 + { format: null, internalFormat: null, pixelType: null }, + + // TEXTURE_FMT_111110F: 22 + { format: null, internalFormat: null, pixelType: null }, + + // TEXTURE_FMT_SRGB: 23 + { format: null, internalFormat: null, pixelType: null }, + + // TEXTURE_FMT_SRGBA: 24 + { format: null, internalFormat: null, pixelType: null }, + + // TEXTURE_FMT_D16: 25 + { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_SHORT }, + + // TEXTURE_FMT_D32: 26 + { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_INT }, + + // TEXTURE_FMT_D24S8: 27 + { format: null, internalFormat: null, pixelType: null }, +]; + +/** + * enums + */ +export const enums = { + // buffer usage + USAGE_STATIC: 35044, // gl.STATIC_DRAW + USAGE_DYNAMIC: 35048, // gl.DYNAMIC_DRAW + USAGE_STREAM: 35040, // gl.STREAM_DRAW + + // index buffer format + INDEX_FMT_UINT8: 5121, // gl.UNSIGNED_BYTE + INDEX_FMT_UINT16: 5123, // gl.UNSIGNED_SHORT + INDEX_FMT_UINT32: 5125, // gl.UNSIGNED_INT (OES_element_index_uint) + + // vertex attribute semantic + ATTR_POSITION: 'a_position', + ATTR_NORMAL: 'a_normal', + ATTR_TANGENT: 'a_tangent', + ATTR_BITANGENT: 'a_bitangent', + ATTR_WEIGHTS: 'a_weights', + ATTR_JOINTS: 'a_joints', + ATTR_COLOR: 'a_color', + ATTR_COLOR0: 'a_color0', + ATTR_COLOR1: 'a_color1', + ATTR_UV: 'a_uv', + ATTR_UV0: 'a_uv0', + ATTR_UV1: 'a_uv1', + ATTR_UV2: 'a_uv2', + ATTR_UV3: 'a_uv3', + ATTR_UV4: 'a_uv4', + ATTR_UV5: 'a_uv5', + ATTR_UV6: 'a_uv6', + ATTR_UV7: 'a_uv7', + + // vertex attribute type + ATTR_TYPE_INT8: 5120, // gl.BYTE + ATTR_TYPE_UINT8: 5121, // gl.UNSIGNED_BYTE + ATTR_TYPE_INT16: 5122, // gl.SHORT + ATTR_TYPE_UINT16: 5123, // gl.UNSIGNED_SHORT + ATTR_TYPE_INT32: 5124, // gl.INT + ATTR_TYPE_UINT32: 5125, // gl.UNSIGNED_INT + ATTR_TYPE_FLOAT32: 5126, // gl.FLOAT + + // texture filter + FILTER_NEAREST: 0, + FILTER_LINEAR: 1, + + // texture wrap mode + WRAP_REPEAT: 10497, // gl.REPEAT + WRAP_CLAMP: 33071, // gl.CLAMP_TO_EDGE + WRAP_MIRROR: 33648, // gl.MIRRORED_REPEAT + + // texture format + // compress formats + TEXTURE_FMT_RGB_DXT1: 0, + TEXTURE_FMT_RGBA_DXT1: 1, + TEXTURE_FMT_RGBA_DXT3: 2, + TEXTURE_FMT_RGBA_DXT5: 3, + TEXTURE_FMT_RGB_ETC1: 4, + TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5, + TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6, + TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7, + TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8, + + // normal formats + TEXTURE_FMT_A8: 9, + TEXTURE_FMT_L8: 10, + TEXTURE_FMT_L8_A8: 11, + TEXTURE_FMT_R5_G6_B5: 12, + TEXTURE_FMT_R5_G5_B5_A1: 13, + TEXTURE_FMT_R4_G4_B4_A4: 14, + TEXTURE_FMT_RGB8: 15, + TEXTURE_FMT_RGBA8: 16, + TEXTURE_FMT_RGB16F: 17, + TEXTURE_FMT_RGBA16F: 18, + TEXTURE_FMT_RGB32F: 19, + TEXTURE_FMT_RGBA32F: 20, + TEXTURE_FMT_R32F: 21, + TEXTURE_FMT_111110F: 22, + TEXTURE_FMT_SRGB: 23, + TEXTURE_FMT_SRGBA: 24, + + // depth formats + TEXTURE_FMT_D16: 25, + TEXTURE_FMT_D32: 26, + TEXTURE_FMT_D24S8: 27, + + // depth and stencil function + DS_FUNC_NEVER: 512, // gl.NEVER + DS_FUNC_LESS: 513, // gl.LESS + DS_FUNC_EQUAL: 514, // gl.EQUAL + DS_FUNC_LEQUAL: 515, // gl.LEQUAL + DS_FUNC_GREATER: 516, // gl.GREATER + DS_FUNC_NOTEQUAL: 517, // gl.NOTEQUAL + DS_FUNC_GEQUAL: 518, // gl.GEQUAL + DS_FUNC_ALWAYS: 519, // gl.ALWAYS + + // render-buffer format + RB_FMT_RGBA4: 32854, // gl.RGBA4 + RB_FMT_RGB5_A1: 32855, // gl.RGB5_A1 + RB_FMT_RGB565: 36194, // gl.RGB565 + RB_FMT_D16: 33189, // gl.DEPTH_COMPONENT16 + RB_FMT_S8: 36168, // gl.STENCIL_INDEX8 + RB_FMT_D24S8: 34041, // gl.DEPTH_STENCIL + + // blend-equation + BLEND_FUNC_ADD: 32774, // gl.FUNC_ADD + BLEND_FUNC_SUBTRACT: 32778, // gl.FUNC_SUBTRACT + BLEND_FUNC_REVERSE_SUBTRACT: 32779, // gl.FUNC_REVERSE_SUBTRACT + + // blend + BLEND_ZERO: 0, // gl.ZERO + BLEND_ONE: 1, // gl.ONE + BLEND_SRC_COLOR: 768, // gl.SRC_COLOR + BLEND_ONE_MINUS_SRC_COLOR: 769, // gl.ONE_MINUS_SRC_COLOR + BLEND_DST_COLOR: 774, // gl.DST_COLOR + BLEND_ONE_MINUS_DST_COLOR: 775, // gl.ONE_MINUS_DST_COLOR + BLEND_SRC_ALPHA: 770, // gl.SRC_ALPHA + BLEND_ONE_MINUS_SRC_ALPHA: 771, // gl.ONE_MINUS_SRC_ALPHA + BLEND_DST_ALPHA: 772, // gl.DST_ALPHA + BLEND_ONE_MINUS_DST_ALPHA: 773, // gl.ONE_MINUS_DST_ALPHA + BLEND_CONSTANT_COLOR: 32769, // gl.CONSTANT_COLOR + BLEND_ONE_MINUS_CONSTANT_COLOR: 32770, // gl.ONE_MINUS_CONSTANT_COLOR + BLEND_CONSTANT_ALPHA: 32771, // gl.CONSTANT_ALPHA + BLEND_ONE_MINUS_CONSTANT_ALPHA: 32772, // gl.ONE_MINUS_CONSTANT_ALPHA + BLEND_SRC_ALPHA_SATURATE: 776, // gl.SRC_ALPHA_SATURATE + + // stencil operation + STENCIL_OP_KEEP: 7680, // gl.KEEP + STENCIL_OP_ZERO: 0, // gl.ZERO + STENCIL_OP_REPLACE: 7681, // gl.REPLACE + STENCIL_OP_INCR: 7682, // gl.INCR + STENCIL_OP_INCR_WRAP: 34055, // gl.INCR_WRAP + STENCIL_OP_DECR: 7683, // gl.DECR + STENCIL_OP_DECR_WRAP: 34056, // gl.DECR_WRAP + STENCIL_OP_INVERT: 5386, // gl.INVERT + + // cull + CULL_NONE: 0, + CULL_FRONT: 1028, + CULL_BACK: 1029, + CULL_FRONT_AND_BACK: 1032, + + // primitive type + PT_POINTS: 0, // gl.POINTS + PT_LINES: 1, // gl.LINES + PT_LINE_LOOP: 2, // gl.LINE_LOOP + PT_LINE_STRIP: 3, // gl.LINE_STRIP + PT_TRIANGLES: 4, // gl.TRIANGLES + PT_TRIANGLE_STRIP: 5, // gl.TRIANGLE_STRIP + PT_TRIANGLE_FAN: 6, // gl.TRIANGLE_FAN +}; + +/** + * @method attrTypeBytes + * @param {ATTR_TYPE_*} attrType + */ +export function attrTypeBytes(attrType) { + if (attrType === enums.ATTR_TYPE_INT8) { + return 1; + } else if (attrType === enums.ATTR_TYPE_UINT8) { + return 1; + } else if (attrType === enums.ATTR_TYPE_INT16) { + return 2; + } else if (attrType === enums.ATTR_TYPE_UINT16) { + return 2; + } else if (attrType === enums.ATTR_TYPE_INT32) { + return 4; + } else if (attrType === enums.ATTR_TYPE_UINT32) { + return 4; + } else if (attrType === enums.ATTR_TYPE_FLOAT32) { + return 4; + } + + console.warn(`Unknown ATTR_TYPE: ${attrType}`); + return 0; +} + +/** + * @method glFilter + * @param {WebGLContext} gl + * @param {FILTER_*} filter + * @param {FILTER_*} mipFilter + */ +export function glFilter(gl, filter, mipFilter = -1) { + let result = _filterGL[filter][mipFilter+1]; + if (result === undefined) { + console.warn(`Unknown FILTER: ${filter}`); + return mipFilter === -1 ? gl.LINEAR : gl.LINEAR_MIPMAP_LINEAR; + } + + return result; +} + +/** + * @method glTextureFmt + * @param {TEXTURE_FMT_*} fmt + */ +export function glTextureFmt(fmt) { + let result = _textureFmtGL[fmt]; + if (result === undefined) { + console.warn(`Unknown TEXTURE_FMT: ${fmt}`); + return _textureFmtGL[enums.TEXTURE_FMT_RGBA8]; + } + + return result; +} \ No newline at end of file diff --git a/cocos2d/renderer/mappings/index.js b/cocos2d/renderer/mappings/index.js new file mode 100644 index 00000000000..64d5f60c5a2 --- /dev/null +++ b/cocos2d/renderer/mappings/index.js @@ -0,0 +1,276 @@ +'use strict'; + +/** + * enums + */ +const enums = { + // buffer usage + USAGE_STATIC: 35044, // gl.STATIC_DRAW + USAGE_DYNAMIC: 35048, // gl.DYNAMIC_DRAW + USAGE_STREAM: 35040, // gl.STREAM_DRAW + + // index buffer format + INDEX_FMT_UINT8: 5121, // gl.UNSIGNED_BYTE + INDEX_FMT_UINT16: 5123, // gl.UNSIGNED_SHORT + INDEX_FMT_UINT32: 5125, // gl.UNSIGNED_INT (OES_element_index_uint) + + // vertex attribute semantic + ATTR_POSITION: 'a_position', + ATTR_NORMAL: 'a_normal', + ATTR_TANGENT: 'a_tangent', + ATTR_BITANGENT: 'a_bitangent', + ATTR_WEIGHTS: 'a_weights', + ATTR_JOINTS: 'a_joints', + ATTR_COLOR: 'a_color', + ATTR_COLOR0: 'a_color0', + ATTR_COLOR1: 'a_color1', + ATTR_UV: 'a_uv', + ATTR_UV0: 'a_uv0', + ATTR_UV1: 'a_uv1', + ATTR_UV2: 'a_uv2', + ATTR_UV3: 'a_uv3', + ATTR_UV4: 'a_uv4', + ATTR_UV5: 'a_uv5', + ATTR_UV6: 'a_uv6', + ATTR_UV7: 'a_uv7', + + // vertex attribute type + ATTR_TYPE_INT8: 5120, // gl.BYTE + ATTR_TYPE_UINT8: 5121, // gl.UNSIGNED_BYTE + ATTR_TYPE_INT16: 5122, // gl.SHORT + ATTR_TYPE_UINT16: 5123, // gl.UNSIGNED_SHORT + ATTR_TYPE_INT32: 5124, // gl.INT + ATTR_TYPE_UINT32: 5125, // gl.UNSIGNED_INT + ATTR_TYPE_FLOAT32: 5126, // gl.FLOAT + + // texture filter + FILTER_NEAREST: 0, + FILTER_LINEAR: 1, + + // texture wrap mode + WRAP_REPEAT: 10497, // gl.REPEAT + WRAP_CLAMP: 33071, // gl.CLAMP_TO_EDGE + WRAP_MIRROR: 33648, // gl.MIRRORED_REPEAT + + // texture format + // compress formats + TEXTURE_FMT_RGB_DXT1: 0, + TEXTURE_FMT_RGBA_DXT1: 1, + TEXTURE_FMT_RGBA_DXT3: 2, + TEXTURE_FMT_RGBA_DXT5: 3, + TEXTURE_FMT_RGB_ETC1: 4, + TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5, + TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6, + TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7, + TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8, + + // normal formats + TEXTURE_FMT_A8: 9, + TEXTURE_FMT_L8: 10, + TEXTURE_FMT_L8_A8: 11, + TEXTURE_FMT_R5_G6_B5: 12, + TEXTURE_FMT_R5_G5_B5_A1: 13, + TEXTURE_FMT_R4_G4_B4_A4: 14, + TEXTURE_FMT_RGB8: 15, + TEXTURE_FMT_RGBA8: 16, + TEXTURE_FMT_RGB16F: 17, + TEXTURE_FMT_RGBA16F: 18, + TEXTURE_FMT_RGB32F: 19, + TEXTURE_FMT_RGBA32F: 20, + TEXTURE_FMT_R32F: 21, + TEXTURE_FMT_111110F: 22, + TEXTURE_FMT_SRGB: 23, + TEXTURE_FMT_SRGBA: 24, + + // depth formats + TEXTURE_FMT_D16: 25, + TEXTURE_FMT_D32: 26, + TEXTURE_FMT_D24S8: 27, + + // depth and stencil function + DS_FUNC_NEVER: 512, // gl.NEVER + DS_FUNC_LESS: 513, // gl.LESS + DS_FUNC_EQUAL: 514, // gl.EQUAL + DS_FUNC_LEQUAL: 515, // gl.LEQUAL + DS_FUNC_GREATER: 516, // gl.GREATER + DS_FUNC_NOTEQUAL: 517, // gl.NOTEQUAL + DS_FUNC_GEQUAL: 518, // gl.GEQUAL + DS_FUNC_ALWAYS: 519, // gl.ALWAYS + + // render-buffer format + RB_FMT_RGBA4: 32854, // gl.RGBA4 + RB_FMT_RGB5_A1: 32855, // gl.RGB5_A1 + RB_FMT_RGB565: 36194, // gl.RGB565 + RB_FMT_D16: 33189, // gl.DEPTH_COMPONENT16 + RB_FMT_S8: 36168, // gl.STENCIL_INDEX8 + RB_FMT_D24S8: 34041, // gl.DEPTH_STENCIL + + // blend-equation + BLEND_FUNC_ADD: 32774, // gl.FUNC_ADD + BLEND_FUNC_SUBTRACT: 32778, // gl.FUNC_SUBTRACT + BLEND_FUNC_REVERSE_SUBTRACT: 32779, // gl.FUNC_REVERSE_SUBTRACT + + // blend + BLEND_ZERO: 0, // gl.ZERO + BLEND_ONE: 1, // gl.ONE + BLEND_SRC_COLOR: 768, // gl.SRC_COLOR + BLEND_ONE_MINUS_SRC_COLOR: 769, // gl.ONE_MINUS_SRC_COLOR + BLEND_DST_COLOR: 774, // gl.DST_COLOR + BLEND_ONE_MINUS_DST_COLOR: 775, // gl.ONE_MINUS_DST_COLOR + BLEND_SRC_ALPHA: 770, // gl.SRC_ALPHA + BLEND_ONE_MINUS_SRC_ALPHA: 771, // gl.ONE_MINUS_SRC_ALPHA + BLEND_DST_ALPHA: 772, // gl.DST_ALPHA + BLEND_ONE_MINUS_DST_ALPHA: 773, // gl.ONE_MINUS_DST_ALPHA + BLEND_CONSTANT_COLOR: 32769, // gl.CONSTANT_COLOR + BLEND_ONE_MINUS_CONSTANT_COLOR: 32770, // gl.ONE_MINUS_CONSTANT_COLOR + BLEND_CONSTANT_ALPHA: 32771, // gl.CONSTANT_ALPHA + BLEND_ONE_MINUS_CONSTANT_ALPHA: 32772, // gl.ONE_MINUS_CONSTANT_ALPHA + BLEND_SRC_ALPHA_SATURATE: 776, // gl.SRC_ALPHA_SATURATE + + // stencil operation + STENCIL_OP_KEEP: 7680, // gl.KEEP + STENCIL_OP_ZERO: 0, // gl.ZERO + STENCIL_OP_REPLACE: 7681, // gl.REPLACE + STENCIL_OP_INCR: 7682, // gl.INCR + STENCIL_OP_INCR_WRAP: 34055, // gl.INCR_WRAP + STENCIL_OP_DECR: 7683, // gl.DECR + STENCIL_OP_DECR_WRAP: 34056, // gl.DECR_WRAP + STENCIL_OP_INVERT: 5386, // gl.INVERT + + // cull + CULL_NONE: 0, + CULL_FRONT: 1028, + CULL_BACK: 1029, + CULL_FRONT_AND_BACK: 1032, + + // primitive type + PT_POINTS: 0, // gl.POINTS + PT_LINES: 1, // gl.LINES + PT_LINE_LOOP: 2, // gl.LINE_LOOP + PT_LINE_STRIP: 3, // gl.LINE_STRIP + PT_TRIANGLES: 4, // gl.TRIANGLES + PT_TRIANGLE_STRIP: 5, // gl.TRIANGLE_STRIP + PT_TRIANGLE_FAN: 6, // gl.TRIANGLE_FAN +}; + +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +var rendererEnums = { + // projection + PROJ_PERSPECTIVE: 0, + PROJ_ORTHO: 1, + + // lights + LIGHT_DIRECTIONAL: 0, + LIGHT_POINT: 1, + LIGHT_SPOT: 2, + + // shadows + SHADOW_NONE: 0, + SHADOW_HARD: 1, + SHADOW_SOFT: 2, + + // parameter type + PARAM_INT: 0, + PARAM_INT2: 1, + PARAM_INT3: 2, + PARAM_INT4: 3, + PARAM_FLOAT: 4, + PARAM_FLOAT2: 5, + PARAM_FLOAT3: 6, + PARAM_FLOAT4: 7, + PARAM_COLOR3: 8, + PARAM_COLOR4: 9, + PARAM_MAT2: 10, + PARAM_MAT3: 11, + PARAM_MAT4: 12, + PARAM_TEXTURE_2D: 13, + PARAM_TEXTURE_CUBE: 14, + + // clear flags + CLEAR_COLOR: 1, + CLEAR_DEPTH: 2, + CLEAR_STENCIL: 4, + CLEAR_SKYBOX: 8, + + // + BUFFER_VIEW_INT8: 0, + BUFFER_VIEW_UINT8: 1, + BUFFER_VIEW_INT16: 2, + BUFFER_VIEW_UINT16: 3, + BUFFER_VIEW_INT32: 4, + BUFFER_VIEW_UINT32: 5, + BUFFER_VIEW_FLOAT32: 6, + }; + +// this file is used for offline effect building. + +const typeParams = { + INT: rendererEnums.PARAM_INT, + IVEC2: rendererEnums.PARAM_INT2, + IVEC3: rendererEnums.PARAM_INT3, + IVEC4: rendererEnums.PARAM_INT4, + FLOAT: rendererEnums.PARAM_FLOAT, + VEC2: rendererEnums.PARAM_FLOAT2, + VEC3: rendererEnums.PARAM_FLOAT3, + VEC4: rendererEnums.PARAM_FLOAT4, + COLOR3: rendererEnums.PARAM_COLOR3, + COLOR4: rendererEnums.PARAM_COLOR4, + MAT2: rendererEnums.PARAM_MAT2, + MAT3: rendererEnums.PARAM_MAT3, + MAT4: rendererEnums.PARAM_MAT4, + SAMPLER2D: rendererEnums.PARAM_TEXTURE_2D, + SAMPLERCUBE: rendererEnums.PARAM_TEXTURE_CUBE, + [rendererEnums.PARAM_FLOAT3]: rendererEnums.PARAM_COLOR3, + [rendererEnums.PARAM_FLOAT4]: rendererEnums.PARAM_COLOR4 +}; + +const passParams = { + BACK: enums.CULL_BACK, + FRONT: enums.CULL_FRONT, + NONE: enums.CULL_NONE, + + ADD: enums.BLEND_FUNC_ADD, + SUBTRACT: enums.BLEND_FUNC_SUBTRACT, + REVERSESUBTRACT: enums.BLEND_FUNC_REVERSE_SUBTRACT, + ZERO: enums.BLEND_ZERO, + ONE: enums.BLEND_ONE, + SRCCOLOR: enums.BLEND_SRC_COLOR, + ONEMINUSSRCCOLOR: enums.BLEND_ONE_MINUS_SRC_COLOR, + DSTCOLOR: enums.BLEND_DST_COLOR, + ONEMINUSDSTCOLOR: enums.BLEND_ONE_MINUS_DST_COLOR, + SRCALPHA: enums.BLEND_SRC_ALPHA, + ONEMINUSSRCALPHA: enums.BLEND_ONE_MINUS_SRC_ALPHA, + DSTALPHA: enums.BLEND_DST_ALPHA, + ONEMINUSDSTALPHA: enums.BLEND_ONE_MINUS_DST_ALPHA, + CONSTCOLOR: enums.BLEND_CONSTANT_COLOR, + ONEMINUSCONSTCOLOR: enums.BLEND_ONE_MINUS_CONSTANT_COLOR, + CONSTALPHA: enums.BLEND_CONSTANT_ALPHA, + ONEMINUSCONSTALPHA: enums.BLEND_ONE_MINUS_CONSTANT_ALPHA, + SRCALPHASATURATE: enums.BLEND_SRC_ALPHA_SATURATE, + + NEVER: enums.DS_FUNC_NEVER, + LESS: enums.DS_FUNC_LESS, + EQUAL: enums.DS_FUNC_EQUAL, + LEQUAL: enums.DS_FUNC_LEQUAL, + GREATER: enums.DS_FUNC_GREATER, + NOTEQUAL: enums.DS_FUNC_NOTEQUAL, + GEQUAL: enums.DS_FUNC_GEQUAL, + ALWAYS: enums.DS_FUNC_ALWAYS, + + KEEP: enums.STENCIL_OP_KEEP, + REPLACE: enums.STENCIL_OP_REPLACE, + INCR: enums.STENCIL_OP_INCR, + INCR_WRAP: enums.STENCIL_OP_INCR_WRAP, + DECR: enums.STENCIL_OP_DECR, + DECR_WRAP: enums.STENCIL_OP_DECR_WRAP, + INVERT: enums.STENCIL_OP_INVERT +}; + +let mappings = { + typeParams, + passParams, +}; + +module.exports = mappings; +//# sourceMappingURL=index.js.map diff --git a/cocos2d/renderer/mappings/index.js.map b/cocos2d/renderer/mappings/index.js.map new file mode 100644 index 00000000000..14ed6d899e3 --- /dev/null +++ b/cocos2d/renderer/mappings/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["gfx/enums.js","enums.js","offline-mappings.js"],"sourcesContent":["const GL_NEAREST = 9728; // gl.NEAREST\nconst GL_LINEAR = 9729; // gl.LINEAR\nconst GL_NEAREST_MIPMAP_NEAREST = 9984; // gl.NEAREST_MIPMAP_NEAREST\nconst GL_LINEAR_MIPMAP_NEAREST = 9985; // gl.LINEAR_MIPMAP_NEAREST\nconst GL_NEAREST_MIPMAP_LINEAR = 9986; // gl.NEAREST_MIPMAP_LINEAR\nconst GL_LINEAR_MIPMAP_LINEAR = 9987; // gl.LINEAR_MIPMAP_LINEAR\n\n// const GL_BYTE = 5120; // gl.BYTE\nconst GL_UNSIGNED_BYTE = 5121; // gl.UNSIGNED_BYTE\n// const GL_SHORT = 5122; // gl.SHORT\nconst GL_UNSIGNED_SHORT = 5123; // gl.UNSIGNED_SHORT\nconst GL_UNSIGNED_INT = 5125; // gl.UNSIGNED_INT\nconst GL_FLOAT = 5126; // gl.FLOAT\nconst GL_UNSIGNED_SHORT_5_6_5 = 33635; // gl.UNSIGNED_SHORT_5_6_5\nconst GL_UNSIGNED_SHORT_4_4_4_4 = 32819; // gl.UNSIGNED_SHORT_4_4_4_4\nconst GL_UNSIGNED_SHORT_5_5_5_1 = 32820; // gl.UNSIGNED_SHORT_5_5_5_1\nconst GL_HALF_FLOAT_OES = 36193; // gl.HALF_FLOAT_OES\n\nconst GL_DEPTH_COMPONENT = 6402; // gl.DEPTH_COMPONENT\n\nconst GL_ALPHA = 6406; // gl.ALPHA\nconst GL_RGB = 6407; // gl.RGB\nconst GL_RGBA = 6408; // gl.RGBA\nconst GL_LUMINANCE = 6409; // gl.LUMINANCE\nconst GL_LUMINANCE_ALPHA = 6410; // gl.LUMINANCE_ALPHA\n\nconst GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; // ext.COMPRESSED_RGB_S3TC_DXT1_EXT\nconst GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; // ext.COMPRESSED_RGBA_S3TC_DXT1_EXT\nconst GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; // ext.COMPRESSED_RGBA_S3TC_DXT3_EXT\nconst GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; // ext.COMPRESSED_RGBA_S3TC_DXT5_EXT\n\nconst GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; // ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG\nconst GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; // ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG\nconst GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; // ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG\nconst GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; // ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG\n\nconst GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; // ext.COMPRESSED_RGB_ETC1_WEBGL\n\nconst _filterGL = [\n [ GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR ],\n [ GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR ],\n];\n\nconst _textureFmtGL = [\n // TEXTURE_FMT_RGB_DXT1: 0\n { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixelType: null },\n\n // TEXTURE_FMT_RGBA_DXT1: 1\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixelType: null },\n\n // TEXTURE_FMT_RGBA_DXT3: 2\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, pixelType: null },\n\n // TEXTURE_FMT_RGBA_DXT5: 3\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, pixelType: null },\n\n // TEXTURE_FMT_RGB_ETC1: 4\n { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_ETC1_WEBGL, pixelType: null },\n\n // TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5\n { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, pixelType: null },\n\n // TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, pixelType: null },\n\n // TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7\n { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, pixelType: null },\n\n // TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, pixelType: null },\n\n // TEXTURE_FMT_A8: 9\n { format: GL_ALPHA, internalFormat: GL_ALPHA, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_L8: 10\n { format: GL_LUMINANCE, internalFormat: GL_LUMINANCE, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_L8_A8: 11\n { format: GL_LUMINANCE_ALPHA, internalFormat: GL_LUMINANCE_ALPHA, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_R5_G6_B5: 12\n { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_SHORT_5_6_5 },\n\n // TEXTURE_FMT_R5_G5_B5_A1: 13\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_5_5_5_1 },\n\n // TEXTURE_FMT_R4_G4_B4_A4: 14\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_4_4_4_4 },\n\n // TEXTURE_FMT_RGB8: 15\n { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_RGBA8: 16\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_RGB16F: 17\n { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_HALF_FLOAT_OES },\n\n // TEXTURE_FMT_RGBA16F: 18\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_HALF_FLOAT_OES },\n\n // TEXTURE_FMT_RGB32F: 19\n { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_FLOAT },\n\n // TEXTURE_FMT_RGBA32F: 20\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_FLOAT },\n\n // TEXTURE_FMT_R32F: 21\n { format: null, internalFormat: null, pixelType: null },\n\n // TEXTURE_FMT_111110F: 22\n { format: null, internalFormat: null, pixelType: null },\n\n // TEXTURE_FMT_SRGB: 23\n { format: null, internalFormat: null, pixelType: null },\n\n // TEXTURE_FMT_SRGBA: 24\n { format: null, internalFormat: null, pixelType: null },\n\n // TEXTURE_FMT_D16: 25\n { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_SHORT },\n\n // TEXTURE_FMT_D32: 26\n { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_INT },\n\n // TEXTURE_FMT_D24S8: 27\n { format: null, internalFormat: null, pixelType: null },\n];\n\n/**\n * enums\n */\nexport const enums = {\n // buffer usage\n USAGE_STATIC: 35044, // gl.STATIC_DRAW\n USAGE_DYNAMIC: 35048, // gl.DYNAMIC_DRAW\n USAGE_STREAM: 35040, // gl.STREAM_DRAW\n\n // index buffer format\n INDEX_FMT_UINT8: 5121, // gl.UNSIGNED_BYTE\n INDEX_FMT_UINT16: 5123, // gl.UNSIGNED_SHORT\n INDEX_FMT_UINT32: 5125, // gl.UNSIGNED_INT (OES_element_index_uint)\n\n // vertex attribute semantic\n ATTR_POSITION: 'a_position',\n ATTR_NORMAL: 'a_normal',\n ATTR_TANGENT: 'a_tangent',\n ATTR_BITANGENT: 'a_bitangent',\n ATTR_WEIGHTS: 'a_weights',\n ATTR_JOINTS: 'a_joints',\n ATTR_COLOR: 'a_color',\n ATTR_COLOR0: 'a_color0',\n ATTR_COLOR1: 'a_color1',\n ATTR_UV: 'a_uv',\n ATTR_UV0: 'a_uv0',\n ATTR_UV1: 'a_uv1',\n ATTR_UV2: 'a_uv2',\n ATTR_UV3: 'a_uv3',\n ATTR_UV4: 'a_uv4',\n ATTR_UV5: 'a_uv5',\n ATTR_UV6: 'a_uv6',\n ATTR_UV7: 'a_uv7',\n\n // vertex attribute type\n ATTR_TYPE_INT8: 5120, // gl.BYTE\n ATTR_TYPE_UINT8: 5121, // gl.UNSIGNED_BYTE\n ATTR_TYPE_INT16: 5122, // gl.SHORT\n ATTR_TYPE_UINT16: 5123, // gl.UNSIGNED_SHORT\n ATTR_TYPE_INT32: 5124, // gl.INT\n ATTR_TYPE_UINT32: 5125, // gl.UNSIGNED_INT\n ATTR_TYPE_FLOAT32: 5126, // gl.FLOAT\n\n // texture filter\n FILTER_NEAREST: 0,\n FILTER_LINEAR: 1,\n\n // texture wrap mode\n WRAP_REPEAT: 10497, // gl.REPEAT\n WRAP_CLAMP: 33071, // gl.CLAMP_TO_EDGE\n WRAP_MIRROR: 33648, // gl.MIRRORED_REPEAT\n\n // texture format\n // compress formats\n TEXTURE_FMT_RGB_DXT1: 0,\n TEXTURE_FMT_RGBA_DXT1: 1,\n TEXTURE_FMT_RGBA_DXT3: 2,\n TEXTURE_FMT_RGBA_DXT5: 3,\n TEXTURE_FMT_RGB_ETC1: 4,\n TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5,\n TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6,\n TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7,\n TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8,\n\n // normal formats\n TEXTURE_FMT_A8: 9,\n TEXTURE_FMT_L8: 10,\n TEXTURE_FMT_L8_A8: 11,\n TEXTURE_FMT_R5_G6_B5: 12,\n TEXTURE_FMT_R5_G5_B5_A1: 13,\n TEXTURE_FMT_R4_G4_B4_A4: 14,\n TEXTURE_FMT_RGB8: 15,\n TEXTURE_FMT_RGBA8: 16,\n TEXTURE_FMT_RGB16F: 17,\n TEXTURE_FMT_RGBA16F: 18,\n TEXTURE_FMT_RGB32F: 19,\n TEXTURE_FMT_RGBA32F: 20,\n TEXTURE_FMT_R32F: 21,\n TEXTURE_FMT_111110F: 22,\n TEXTURE_FMT_SRGB: 23,\n TEXTURE_FMT_SRGBA: 24,\n\n // depth formats\n TEXTURE_FMT_D16: 25,\n TEXTURE_FMT_D32: 26,\n TEXTURE_FMT_D24S8: 27,\n\n // depth and stencil function\n DS_FUNC_NEVER: 512, // gl.NEVER\n DS_FUNC_LESS: 513, // gl.LESS\n DS_FUNC_EQUAL: 514, // gl.EQUAL\n DS_FUNC_LEQUAL: 515, // gl.LEQUAL\n DS_FUNC_GREATER: 516, // gl.GREATER\n DS_FUNC_NOTEQUAL: 517, // gl.NOTEQUAL\n DS_FUNC_GEQUAL: 518, // gl.GEQUAL\n DS_FUNC_ALWAYS: 519, // gl.ALWAYS\n\n // render-buffer format\n RB_FMT_RGBA4: 32854, // gl.RGBA4\n RB_FMT_RGB5_A1: 32855, // gl.RGB5_A1\n RB_FMT_RGB565: 36194, // gl.RGB565\n RB_FMT_D16: 33189, // gl.DEPTH_COMPONENT16\n RB_FMT_S8: 36168, // gl.STENCIL_INDEX8\n RB_FMT_D24S8: 34041, // gl.DEPTH_STENCIL\n\n // blend-equation\n BLEND_FUNC_ADD: 32774, // gl.FUNC_ADD\n BLEND_FUNC_SUBTRACT: 32778, // gl.FUNC_SUBTRACT\n BLEND_FUNC_REVERSE_SUBTRACT: 32779, // gl.FUNC_REVERSE_SUBTRACT\n\n // blend\n BLEND_ZERO: 0, // gl.ZERO\n BLEND_ONE: 1, // gl.ONE\n BLEND_SRC_COLOR: 768, // gl.SRC_COLOR\n BLEND_ONE_MINUS_SRC_COLOR: 769, // gl.ONE_MINUS_SRC_COLOR\n BLEND_DST_COLOR: 774, // gl.DST_COLOR\n BLEND_ONE_MINUS_DST_COLOR: 775, // gl.ONE_MINUS_DST_COLOR\n BLEND_SRC_ALPHA: 770, // gl.SRC_ALPHA\n BLEND_ONE_MINUS_SRC_ALPHA: 771, // gl.ONE_MINUS_SRC_ALPHA\n BLEND_DST_ALPHA: 772, // gl.DST_ALPHA\n BLEND_ONE_MINUS_DST_ALPHA: 773, // gl.ONE_MINUS_DST_ALPHA\n BLEND_CONSTANT_COLOR: 32769, // gl.CONSTANT_COLOR\n BLEND_ONE_MINUS_CONSTANT_COLOR: 32770, // gl.ONE_MINUS_CONSTANT_COLOR\n BLEND_CONSTANT_ALPHA: 32771, // gl.CONSTANT_ALPHA\n BLEND_ONE_MINUS_CONSTANT_ALPHA: 32772, // gl.ONE_MINUS_CONSTANT_ALPHA\n BLEND_SRC_ALPHA_SATURATE: 776, // gl.SRC_ALPHA_SATURATE\n\n // stencil operation\n STENCIL_OP_KEEP: 7680, // gl.KEEP\n STENCIL_OP_ZERO: 0, // gl.ZERO\n STENCIL_OP_REPLACE: 7681, // gl.REPLACE\n STENCIL_OP_INCR: 7682, // gl.INCR\n STENCIL_OP_INCR_WRAP: 34055, // gl.INCR_WRAP\n STENCIL_OP_DECR: 7683, // gl.DECR\n STENCIL_OP_DECR_WRAP: 34056, // gl.DECR_WRAP\n STENCIL_OP_INVERT: 5386, // gl.INVERT\n\n // cull\n CULL_NONE: 0,\n CULL_FRONT: 1028,\n CULL_BACK: 1029,\n CULL_FRONT_AND_BACK: 1032,\n\n // primitive type\n PT_POINTS: 0, // gl.POINTS\n PT_LINES: 1, // gl.LINES\n PT_LINE_LOOP: 2, // gl.LINE_LOOP\n PT_LINE_STRIP: 3, // gl.LINE_STRIP\n PT_TRIANGLES: 4, // gl.TRIANGLES\n PT_TRIANGLE_STRIP: 5, // gl.TRIANGLE_STRIP\n PT_TRIANGLE_FAN: 6, // gl.TRIANGLE_FAN\n};\n\n/**\n * @method attrTypeBytes\n * @param {ATTR_TYPE_*} attrType\n */\nexport function attrTypeBytes(attrType) {\n if (attrType === enums.ATTR_TYPE_INT8) {\n return 1;\n } else if (attrType === enums.ATTR_TYPE_UINT8) {\n return 1;\n } else if (attrType === enums.ATTR_TYPE_INT16) {\n return 2;\n } else if (attrType === enums.ATTR_TYPE_UINT16) {\n return 2;\n } else if (attrType === enums.ATTR_TYPE_INT32) {\n return 4;\n } else if (attrType === enums.ATTR_TYPE_UINT32) {\n return 4;\n } else if (attrType === enums.ATTR_TYPE_FLOAT32) {\n return 4;\n }\n\n console.warn(`Unknown ATTR_TYPE: ${attrType}`);\n return 0;\n}\n\n/**\n * @method glFilter\n * @param {WebGLContext} gl\n * @param {FILTER_*} filter\n * @param {FILTER_*} mipFilter\n */\nexport function glFilter(gl, filter, mipFilter = -1) {\n let result = _filterGL[filter][mipFilter+1];\n if (result === undefined) {\n console.warn(`Unknown FILTER: ${filter}`);\n return mipFilter === -1 ? gl.LINEAR : gl.LINEAR_MIPMAP_LINEAR;\n }\n\n return result;\n}\n\n/**\n * @method glTextureFmt\n * @param {TEXTURE_FMT_*} fmt\n */\nexport function glTextureFmt(fmt) {\n let result = _textureFmtGL[fmt];\n if (result === undefined) {\n console.warn(`Unknown TEXTURE_FMT: ${fmt}`);\n return _textureFmtGL[enums.TEXTURE_FMT_RGBA8];\n }\n\n return result;\n}","// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.\n\nexport default {\n // projection\n PROJ_PERSPECTIVE: 0,\n PROJ_ORTHO: 1,\n \n // lights\n LIGHT_DIRECTIONAL: 0,\n LIGHT_POINT: 1,\n LIGHT_SPOT: 2,\n \n // shadows\n SHADOW_NONE: 0,\n SHADOW_HARD: 1,\n SHADOW_SOFT: 2,\n \n // parameter type\n PARAM_INT: 0,\n PARAM_INT2: 1,\n PARAM_INT3: 2,\n PARAM_INT4: 3,\n PARAM_FLOAT: 4,\n PARAM_FLOAT2: 5,\n PARAM_FLOAT3: 6,\n PARAM_FLOAT4: 7,\n PARAM_COLOR3: 8,\n PARAM_COLOR4: 9,\n PARAM_MAT2: 10,\n PARAM_MAT3: 11,\n PARAM_MAT4: 12,\n PARAM_TEXTURE_2D: 13,\n PARAM_TEXTURE_CUBE: 14,\n \n // clear flags\n CLEAR_COLOR: 1,\n CLEAR_DEPTH: 2,\n CLEAR_STENCIL: 4,\n CLEAR_SKYBOX: 8,\n \n //\n BUFFER_VIEW_INT8: 0,\n BUFFER_VIEW_UINT8: 1,\n BUFFER_VIEW_INT16: 2,\n BUFFER_VIEW_UINT16: 3,\n BUFFER_VIEW_INT32: 4,\n BUFFER_VIEW_UINT32: 5,\n BUFFER_VIEW_FLOAT32: 6,\n };\n ","// this file is used for offline effect building.\n\nimport { enums } from './gfx/enums';\nimport rendererEnums from './enums';\n\nconst typeParams = {\n INT: rendererEnums.PARAM_INT,\n IVEC2: rendererEnums.PARAM_INT2,\n IVEC3: rendererEnums.PARAM_INT3,\n IVEC4: rendererEnums.PARAM_INT4,\n FLOAT: rendererEnums.PARAM_FLOAT,\n VEC2: rendererEnums.PARAM_FLOAT2,\n VEC3: rendererEnums.PARAM_FLOAT3,\n VEC4: rendererEnums.PARAM_FLOAT4,\n COLOR3: rendererEnums.PARAM_COLOR3,\n COLOR4: rendererEnums.PARAM_COLOR4,\n MAT2: rendererEnums.PARAM_MAT2,\n MAT3: rendererEnums.PARAM_MAT3,\n MAT4: rendererEnums.PARAM_MAT4,\n SAMPLER2D: rendererEnums.PARAM_TEXTURE_2D,\n SAMPLERCUBE: rendererEnums.PARAM_TEXTURE_CUBE,\n [rendererEnums.PARAM_FLOAT3]: rendererEnums.PARAM_COLOR3,\n [rendererEnums.PARAM_FLOAT4]: rendererEnums.PARAM_COLOR4\n};\n\nconst passParams = {\n BACK: enums.CULL_BACK,\n FRONT: enums.CULL_FRONT,\n NONE: enums.CULL_NONE,\n\n ADD: enums.BLEND_FUNC_ADD,\n SUBTRACT: enums.BLEND_FUNC_SUBTRACT,\n REVERSESUBTRACT: enums.BLEND_FUNC_REVERSE_SUBTRACT,\n ZERO: enums.BLEND_ZERO,\n ONE: enums.BLEND_ONE,\n SRCCOLOR: enums.BLEND_SRC_COLOR,\n ONEMINUSSRCCOLOR: enums.BLEND_ONE_MINUS_SRC_COLOR,\n DSTCOLOR: enums.BLEND_DST_COLOR,\n ONEMINUSDSTCOLOR: enums.BLEND_ONE_MINUS_DST_COLOR,\n SRCALPHA: enums.BLEND_SRC_ALPHA,\n ONEMINUSSRCALPHA: enums.BLEND_ONE_MINUS_SRC_ALPHA,\n DSTALPHA: enums.BLEND_DST_ALPHA,\n ONEMINUSDSTALPHA: enums.BLEND_ONE_MINUS_DST_ALPHA,\n CONSTCOLOR: enums.BLEND_CONSTANT_COLOR,\n ONEMINUSCONSTCOLOR: enums.BLEND_ONE_MINUS_CONSTANT_COLOR,\n CONSTALPHA: enums.BLEND_CONSTANT_ALPHA,\n ONEMINUSCONSTALPHA: enums.BLEND_ONE_MINUS_CONSTANT_ALPHA,\n SRCALPHASATURATE: enums.BLEND_SRC_ALPHA_SATURATE,\n\n NEVER: enums.DS_FUNC_NEVER,\n LESS: enums.DS_FUNC_LESS,\n EQUAL: enums.DS_FUNC_EQUAL,\n LEQUAL: enums.DS_FUNC_LEQUAL,\n GREATER: enums.DS_FUNC_GREATER,\n NOTEQUAL: enums.DS_FUNC_NOTEQUAL,\n GEQUAL: enums.DS_FUNC_GEQUAL,\n ALWAYS: enums.DS_FUNC_ALWAYS,\n\n KEEP: enums.STENCIL_OP_KEEP,\n REPLACE: enums.STENCIL_OP_REPLACE,\n INCR: enums.STENCIL_OP_INCR,\n INCR_WRAP: enums.STENCIL_OP_INCR_WRAP,\n DECR: enums.STENCIL_OP_DECR,\n DECR_WRAP: enums.STENCIL_OP_DECR_WRAP,\n INVERT: enums.STENCIL_OP_INVERT\n};\n\nlet mappings = {\n typeParams,\n passParams,\n};\n\nexport default mappings;"],"names":[],"mappings":";;AAiIA;;;AAGA,AAAO,MAAM,KAAK,GAAG;;EAEnB,YAAY,EAAE,KAAK;EACnB,aAAa,EAAE,KAAK;EACpB,YAAY,EAAE,KAAK;;;EAGnB,eAAe,EAAE,IAAI;EACrB,gBAAgB,EAAE,IAAI;EACtB,gBAAgB,EAAE,IAAI;;;EAGtB,aAAa,EAAE,YAAY;EAC3B,WAAW,EAAE,UAAU;EACvB,YAAY,EAAE,WAAW;EACzB,cAAc,EAAE,aAAa;EAC7B,YAAY,EAAE,WAAW;EACzB,WAAW,EAAE,UAAU;EACvB,UAAU,EAAE,SAAS;EACrB,WAAW,EAAE,UAAU;EACvB,WAAW,EAAE,UAAU;EACvB,OAAO,EAAE,MAAM;EACf,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;;;EAGjB,cAAc,EAAE,IAAI;EACpB,eAAe,EAAE,IAAI;EACrB,eAAe,EAAE,IAAI;EACrB,gBAAgB,EAAE,IAAI;EACtB,eAAe,EAAE,IAAI;EACrB,gBAAgB,EAAE,IAAI;EACtB,iBAAiB,EAAE,IAAI;;;EAGvB,cAAc,EAAE,CAAC;EACjB,aAAa,EAAE,CAAC;;;EAGhB,WAAW,EAAE,KAAK;EAClB,UAAU,EAAE,KAAK;EACjB,WAAW,EAAE,KAAK;;;;EAIlB,oBAAoB,EAAE,CAAC;EACvB,qBAAqB,EAAE,CAAC;EACxB,qBAAqB,EAAE,CAAC;EACxB,qBAAqB,EAAE,CAAC;EACxB,oBAAoB,EAAE,CAAC;EACvB,4BAA4B,EAAE,CAAC;EAC/B,6BAA6B,EAAE,CAAC;EAChC,4BAA4B,EAAE,CAAC;EAC/B,6BAA6B,EAAE,CAAC;;;EAGhC,cAAc,EAAE,CAAC;EACjB,cAAc,EAAE,EAAE;EAClB,iBAAiB,EAAE,EAAE;EACrB,oBAAoB,EAAE,EAAE;EACxB,uBAAuB,EAAE,EAAE;EAC3B,uBAAuB,EAAE,EAAE;EAC3B,gBAAgB,EAAE,EAAE;EACpB,iBAAiB,EAAE,EAAE;EACrB,kBAAkB,EAAE,EAAE;EACtB,mBAAmB,EAAE,EAAE;EACvB,kBAAkB,EAAE,EAAE;EACtB,mBAAmB,EAAE,EAAE;EACvB,gBAAgB,EAAE,EAAE;EACpB,mBAAmB,EAAE,EAAE;EACvB,gBAAgB,EAAE,EAAE;EACpB,iBAAiB,EAAE,EAAE;;;EAGrB,eAAe,EAAE,EAAE;EACnB,eAAe,EAAE,EAAE;EACnB,iBAAiB,EAAE,EAAE;;;EAGrB,aAAa,EAAE,GAAG;EAClB,YAAY,EAAE,GAAG;EACjB,aAAa,EAAE,GAAG;EAClB,cAAc,EAAE,GAAG;EACnB,eAAe,EAAE,GAAG;EACpB,gBAAgB,EAAE,GAAG;EACrB,cAAc,EAAE,GAAG;EACnB,cAAc,EAAE,GAAG;;;EAGnB,YAAY,EAAE,KAAK;EACnB,cAAc,EAAE,KAAK;EACrB,aAAa,EAAE,KAAK;EACpB,UAAU,EAAE,KAAK;EACjB,SAAS,EAAE,KAAK;EAChB,YAAY,EAAE,KAAK;;;EAGnB,cAAc,EAAE,KAAK;EACrB,mBAAmB,EAAE,KAAK;EAC1B,2BAA2B,EAAE,KAAK;;;EAGlC,UAAU,EAAE,CAAC;EACb,SAAS,EAAE,CAAC;EACZ,eAAe,EAAE,GAAG;EACpB,yBAAyB,EAAE,GAAG;EAC9B,eAAe,EAAE,GAAG;EACpB,yBAAyB,EAAE,GAAG;EAC9B,eAAe,EAAE,GAAG;EACpB,yBAAyB,EAAE,GAAG;EAC9B,eAAe,EAAE,GAAG;EACpB,yBAAyB,EAAE,GAAG;EAC9B,oBAAoB,EAAE,KAAK;EAC3B,8BAA8B,EAAE,KAAK;EACrC,oBAAoB,EAAE,KAAK;EAC3B,8BAA8B,EAAE,KAAK;EACrC,wBAAwB,EAAE,GAAG;;;EAG7B,eAAe,EAAE,IAAI;EACrB,eAAe,EAAE,CAAC;EAClB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,oBAAoB,EAAE,KAAK;EAC3B,eAAe,EAAE,IAAI;EACrB,oBAAoB,EAAE,KAAK;EAC3B,iBAAiB,EAAE,IAAI;;;EAGvB,SAAS,EAAE,CAAC;EACZ,UAAU,EAAE,IAAI;EAChB,SAAS,EAAE,IAAI;EACf,mBAAmB,EAAE,IAAI;;;EAGzB,SAAS,EAAE,CAAC;EACZ,QAAQ,EAAE,CAAC;EACX,YAAY,EAAE,CAAC;EACf,aAAa,EAAE,CAAC;EAChB,YAAY,EAAE,CAAC;EACf,iBAAiB,EAAE,CAAC;EACpB,eAAe,EAAE,CAAC;CACnB,CAAC;;ACxRF;;AAEA,oBAAe;;IAEX,gBAAgB,EAAE,CAAC;IACnB,UAAU,EAAE,CAAC;;;IAGb,iBAAiB,EAAE,CAAC;IACpB,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,CAAC;;;IAGb,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,CAAC;;;IAGd,SAAS,cAAc,CAAC;IACxB,UAAU,aAAa,CAAC;IACxB,UAAU,aAAa,CAAC;IACxB,UAAU,aAAa,CAAC;IACxB,WAAW,YAAY,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,UAAU,YAAY,EAAE;IACxB,UAAU,YAAY,EAAE;IACxB,UAAU,YAAY,EAAE;IACxB,gBAAgB,MAAM,EAAE;IACxB,kBAAkB,IAAI,EAAE;;;IAGxB,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,CAAC;IACd,aAAa,EAAE,CAAC;IAChB,YAAY,EAAE,CAAC;;;IAGf,gBAAgB,EAAE,CAAC;IACnB,iBAAiB,EAAE,CAAC;IACpB,iBAAiB,EAAE,CAAC;IACpB,kBAAkB,EAAE,CAAC;IACrB,iBAAiB,EAAE,CAAC;IACpB,kBAAkB,EAAE,CAAC;IACrB,mBAAmB,EAAE,CAAC;GACvB,CAAC;;AChDJ;AACA,AAGA;AACA,MAAM,UAAU,GAAG;EACjB,GAAG,EAAE,aAAa,CAAC,SAAS;EAC5B,KAAK,EAAE,aAAa,CAAC,UAAU;EAC/B,KAAK,EAAE,aAAa,CAAC,UAAU;EAC/B,KAAK,EAAE,aAAa,CAAC,UAAU;EAC/B,KAAK,EAAE,aAAa,CAAC,WAAW;EAChC,IAAI,EAAE,aAAa,CAAC,YAAY;EAChC,IAAI,EAAE,aAAa,CAAC,YAAY;EAChC,IAAI,EAAE,aAAa,CAAC,YAAY;EAChC,MAAM,EAAE,aAAa,CAAC,YAAY;EAClC,MAAM,EAAE,aAAa,CAAC,YAAY;EAClC,IAAI,EAAE,aAAa,CAAC,UAAU;EAC9B,IAAI,EAAE,aAAa,CAAC,UAAU;EAC9B,IAAI,EAAE,aAAa,CAAC,UAAU;EAC9B,SAAS,EAAE,aAAa,CAAC,gBAAgB;EACzC,WAAW,EAAE,aAAa,CAAC,kBAAkB;EAC7C,CAAC,aAAa,CAAC,YAAY,GAAG,aAAa,CAAC,YAAY;EACxD,CAAC,aAAa,CAAC,YAAY,GAAG,aAAa,CAAC,YAAY;CACzD,CAAC;;AAEF,MAAM,UAAU,GAAG;EACjB,IAAI,EAAE,KAAK,CAAC,SAAS;EACrB,KAAK,EAAE,KAAK,CAAC,UAAU;EACvB,IAAI,EAAE,KAAK,CAAC,SAAS;;EAErB,GAAG,EAAE,KAAK,CAAC,cAAc;EACzB,QAAQ,EAAE,KAAK,CAAC,mBAAmB;EACnC,eAAe,EAAE,KAAK,CAAC,2BAA2B;EAClD,IAAI,EAAE,KAAK,CAAC,UAAU;EACtB,GAAG,EAAE,KAAK,CAAC,SAAS;EACpB,QAAQ,EAAE,KAAK,CAAC,eAAe;EAC/B,gBAAgB,EAAE,KAAK,CAAC,yBAAyB;EACjD,QAAQ,EAAE,KAAK,CAAC,eAAe;EAC/B,gBAAgB,EAAE,KAAK,CAAC,yBAAyB;EACjD,QAAQ,EAAE,KAAK,CAAC,eAAe;EAC/B,gBAAgB,EAAE,KAAK,CAAC,yBAAyB;EACjD,QAAQ,EAAE,KAAK,CAAC,eAAe;EAC/B,gBAAgB,EAAE,KAAK,CAAC,yBAAyB;EACjD,UAAU,EAAE,KAAK,CAAC,oBAAoB;EACtC,kBAAkB,EAAE,KAAK,CAAC,8BAA8B;EACxD,UAAU,EAAE,KAAK,CAAC,oBAAoB;EACtC,kBAAkB,EAAE,KAAK,CAAC,8BAA8B;EACxD,gBAAgB,EAAE,KAAK,CAAC,wBAAwB;;EAEhD,KAAK,EAAE,KAAK,CAAC,aAAa;EAC1B,IAAI,EAAE,KAAK,CAAC,YAAY;EACxB,KAAK,EAAE,KAAK,CAAC,aAAa;EAC1B,MAAM,EAAE,KAAK,CAAC,cAAc;EAC5B,OAAO,EAAE,KAAK,CAAC,eAAe;EAC9B,QAAQ,EAAE,KAAK,CAAC,gBAAgB;EAChC,MAAM,EAAE,KAAK,CAAC,cAAc;EAC5B,MAAM,EAAE,KAAK,CAAC,cAAc;;EAE5B,IAAI,EAAE,KAAK,CAAC,eAAe;EAC3B,OAAO,EAAE,KAAK,CAAC,kBAAkB;EACjC,IAAI,EAAE,KAAK,CAAC,eAAe;EAC3B,SAAS,EAAE,KAAK,CAAC,oBAAoB;EACrC,IAAI,EAAE,KAAK,CAAC,eAAe;EAC3B,SAAS,EAAE,KAAK,CAAC,oBAAoB;EACrC,MAAM,EAAE,KAAK,CAAC,iBAAiB;CAChC,CAAC;;AAEF,IAAI,QAAQ,GAAG;EACb,UAAU;EACV,UAAU;CACX,CAAC;;;;"} \ No newline at end of file diff --git a/cocos2d/renderer/mappings/offline-mappings.js b/cocos2d/renderer/mappings/offline-mappings.js new file mode 100644 index 00000000000..b3bb43bd626 --- /dev/null +++ b/cocos2d/renderer/mappings/offline-mappings.js @@ -0,0 +1,73 @@ +// this file is used for offline effect building. + +import { enums } from './gfx/enums'; +import rendererEnums from './enums'; + +const typeParams = { + INT: rendererEnums.PARAM_INT, + IVEC2: rendererEnums.PARAM_INT2, + IVEC3: rendererEnums.PARAM_INT3, + IVEC4: rendererEnums.PARAM_INT4, + FLOAT: rendererEnums.PARAM_FLOAT, + VEC2: rendererEnums.PARAM_FLOAT2, + VEC3: rendererEnums.PARAM_FLOAT3, + VEC4: rendererEnums.PARAM_FLOAT4, + COLOR3: rendererEnums.PARAM_COLOR3, + COLOR4: rendererEnums.PARAM_COLOR4, + MAT2: rendererEnums.PARAM_MAT2, + MAT3: rendererEnums.PARAM_MAT3, + MAT4: rendererEnums.PARAM_MAT4, + SAMPLER2D: rendererEnums.PARAM_TEXTURE_2D, + SAMPLERCUBE: rendererEnums.PARAM_TEXTURE_CUBE, + [rendererEnums.PARAM_FLOAT3]: rendererEnums.PARAM_COLOR3, + [rendererEnums.PARAM_FLOAT4]: rendererEnums.PARAM_COLOR4 +}; + +const passParams = { + BACK: enums.CULL_BACK, + FRONT: enums.CULL_FRONT, + NONE: enums.CULL_NONE, + + ADD: enums.BLEND_FUNC_ADD, + SUBTRACT: enums.BLEND_FUNC_SUBTRACT, + REVERSESUBTRACT: enums.BLEND_FUNC_REVERSE_SUBTRACT, + ZERO: enums.BLEND_ZERO, + ONE: enums.BLEND_ONE, + SRCCOLOR: enums.BLEND_SRC_COLOR, + ONEMINUSSRCCOLOR: enums.BLEND_ONE_MINUS_SRC_COLOR, + DSTCOLOR: enums.BLEND_DST_COLOR, + ONEMINUSDSTCOLOR: enums.BLEND_ONE_MINUS_DST_COLOR, + SRCALPHA: enums.BLEND_SRC_ALPHA, + ONEMINUSSRCALPHA: enums.BLEND_ONE_MINUS_SRC_ALPHA, + DSTALPHA: enums.BLEND_DST_ALPHA, + ONEMINUSDSTALPHA: enums.BLEND_ONE_MINUS_DST_ALPHA, + CONSTCOLOR: enums.BLEND_CONSTANT_COLOR, + ONEMINUSCONSTCOLOR: enums.BLEND_ONE_MINUS_CONSTANT_COLOR, + CONSTALPHA: enums.BLEND_CONSTANT_ALPHA, + ONEMINUSCONSTALPHA: enums.BLEND_ONE_MINUS_CONSTANT_ALPHA, + SRCALPHASATURATE: enums.BLEND_SRC_ALPHA_SATURATE, + + NEVER: enums.DS_FUNC_NEVER, + LESS: enums.DS_FUNC_LESS, + EQUAL: enums.DS_FUNC_EQUAL, + LEQUAL: enums.DS_FUNC_LEQUAL, + GREATER: enums.DS_FUNC_GREATER, + NOTEQUAL: enums.DS_FUNC_NOTEQUAL, + GEQUAL: enums.DS_FUNC_GEQUAL, + ALWAYS: enums.DS_FUNC_ALWAYS, + + KEEP: enums.STENCIL_OP_KEEP, + REPLACE: enums.STENCIL_OP_REPLACE, + INCR: enums.STENCIL_OP_INCR, + INCR_WRAP: enums.STENCIL_OP_INCR_WRAP, + DECR: enums.STENCIL_OP_DECR, + DECR_WRAP: enums.STENCIL_OP_DECR_WRAP, + INVERT: enums.STENCIL_OP_INVERT +}; + +let mappings = { + typeParams, + passParams, +}; + +export default mappings; \ No newline at end of file diff --git a/cocos2d/tilemap/CCTiledLayer.js b/cocos2d/tilemap/CCTiledLayer.js index 23da490a0c1..a8525ae91e5 100644 --- a/cocos2d/tilemap/CCTiledLayer.js +++ b/cocos2d/tilemap/CCTiledLayer.js @@ -24,8 +24,7 @@ THE SOFTWARE. ****************************************************************************/ const RenderComponent = require('../core/components/CCRenderComponent'); -const renderEngine = require('../core/renderer/render-engine'); -const SpriteMaterial = renderEngine.SpriteMaterial; +const Material = require('../core/assets/CCMaterial'); /** * !#en Render the TMX layer. @@ -631,15 +630,16 @@ let TiledLayer = cc.Class({ }, _activateMaterial () { - let material = this._material; + let material = this.sharedMaterials[0]; if (!material) { - material = this._material = new SpriteMaterial(); - material.useColor = false; + material = Material.getInstantiatedBuiltinMaterial('sprite', this); + material.define('useTexture', true); } if (this._texture) { // TODO: old texture in material have been released by loader - material.texture = this._texture; + material.setProperty('texture', this._texture); + this.setMaterial(0, material); this.markForUpdateRenderData(true); this.markForRender(true); } @@ -647,7 +647,7 @@ let TiledLayer = cc.Class({ this.disableRender(); } - this._updateMaterial(material); + this.setMaterial(0, material); }, }); diff --git a/cocos2d/tilemap/tmx-layer-assembler.js b/cocos2d/tilemap/tmx-layer-assembler.js index 6ab948cee7e..b0cf893776a 100644 --- a/cocos2d/tilemap/tmx-layer-assembler.js +++ b/cocos2d/tilemap/tmx-layer-assembler.js @@ -53,7 +53,7 @@ let tmxAssembler = { let size = comp.node._contentSize; let anchor = comp.node._anchorPoint; renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y); - renderData.material = comp.getMaterial(); + renderData.material = comp.sharedMaterials[0]; this.updateVertices(comp); }, diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 76208977c5b..0b04fd080f7 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -25,7 +25,7 @@ ****************************************************************************/ const RenderComponent = require('../../cocos2d/core/components/CCRenderComponent'); -const SpriteMaterial = require('../../cocos2d/core/renderer/render-engine').SpriteMaterial; +const Material = require('../../cocos2d/core/assets/CCMaterial'); let EventTarget = require('../../cocos2d/core/event/event-target'); @@ -354,14 +354,17 @@ let ArmatureDisplay = cc.Class({ _activateMaterial () { let texture = this.dragonAtlasAsset && this.dragonAtlasAsset.texture; - // Get material - let material = this._material || new SpriteMaterial(); - material.useColor = false; + let material = this.sharedMaterials[0]; + if (!material) { + material = Material.getInstantiatedBuiltinMaterial('sprite', this); + material.define('useTexture', true); + material.define('useColor', true); + } if (texture) { - material.texture = texture; + material.setProperty('texture', texture); this.markForUpdateRenderData(true); this.markForRender(true); } @@ -369,7 +372,7 @@ let ArmatureDisplay = cc.Class({ this.disableRender(); } - this._updateMaterial(material); + this.setMaterial(0, material); }, _buildArmature () { diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 0e36d66762d..2946723517e 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -58,7 +58,7 @@ let armatureAssembler = { let size = comp.node._contentSize; let anchor = comp.node._anchorPoint; renderData.updateSizeNPivot(size.width, size.height, anchor.x, anchor.y); - renderData.material = comp.getMaterial(); + renderData.material = comp.sharedMaterials[0]; renderData.vertexCount = 0; renderData.indiceCount = 0; diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 218db733d18..31afdab5c55 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -27,7 +27,7 @@ const TrackEntryListeners = require('./track-entry-listeners'); const RenderComponent = require('../../cocos2d/core/components/CCRenderComponent'); const spine = require('./lib/spine'); -const SpriteMaterial = require('../../cocos2d/core/renderer/render-engine').SpriteMaterial; +const Material = require('../../cocos2d/core/assets/CCMaterial'); const Graphics = require('../../cocos2d/core/graphics/graphics'); /** @@ -323,7 +323,7 @@ sp.Skeleton = cc.Class({ this._rootBone = null; this._listener = null; this._boundingBox = cc.rect(); - this._material = new SpriteMaterial(); + this._material = Material.getInstantiatedBuiltinMaterial('sprite', this); this._materials = {}; this._renderDatas = []; this._debugRenderer = null; @@ -405,7 +405,7 @@ sp.Skeleton = cc.Class({ // Destroyed and restored in Editor if (!this._material) { this._boundingBox = cc.rect(); - this._material = new SpriteMaterial(); + this._material = Material.getInstantiatedBuiltinMaterial('sprite', this); this._materials = {}; this._renderDatas = []; } diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 64c3f7159dd..7436b116fd1 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -28,20 +28,15 @@ const Skeleton = require('./Skeleton'); const spine = require('./lib/spine'); const renderer = require('../../cocos2d/core/renderer'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); +const Material = require('../../cocos2d/core/assets/CCMaterial'); const renderEngine = renderer.renderEngine; const gfx = renderEngine.gfx; -const SpriteMaterial = renderEngine.SpriteMaterial; const STENCIL_SEP = '@'; let _slotColor = cc.color(0, 0, 255, 255); let _boneColor = cc.color(255, 0, 0, 255); let _originColor = cc.color(0, 255, 0, 255); -let _debugMaterial = new SpriteMaterial(); -_debugMaterial.useModel = true; -_debugMaterial.useColor = false; -_debugMaterial.useTexture = false; -_debugMaterial.updateHash(); function _updateKeyWithStencilRef (key, stencilRef) { return key.replace(/@\d+$/, STENCIL_SEP + stencilRef); @@ -70,26 +65,26 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { } let key = tex.url + src + dst + STENCIL_SEP + '0'; - comp._material = comp._material || new SpriteMaterial(); + comp._material = comp._material || new Material(); let baseMaterial = comp._material; let materials = comp._materials; let material = materials[key]; if (!material) { - var baseKey = baseMaterial._hash; if (!materials[baseKey]) { material = baseMaterial; } else { - material = baseMaterial.clone(); + material = new Material(); + material.copy(baseMaterial); } - material.useModel = true; + material.define('useModel', true); + material.define('useTexture', true); // update texture - material.texture = tex; - material.useColor = false; + material.setProperty('texture', tex); // update blend function - let pass = material._mainTech.passes[0]; + let pass = material._effect.getTechnique('transparent').passes[0]; pass.setBlend( gfx.BLEND_FUNC_ADD, src, dst, @@ -99,8 +94,8 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { materials[key] = material; material.updateHash(key); } - else if (material.texture !== tex) { - material.texture = tex; + else if (material.getProperty('texture') !== tex) { + material.setProperty('texture', tex); material.updateHash(key); } return material; diff --git a/gulp/util/create-bundler.js b/gulp/util/create-bundler.js index b9729da214f..4a4e4a097a1 100644 --- a/gulp/util/create-bundler.js +++ b/gulp/util/create-bundler.js @@ -70,21 +70,22 @@ module.exports = function createBundler(entryFiles, options) { preludePath: Path.relative(process.cwd(), preludePath), }; - // var presets = [ - // [ 'es2015', { loose: true } ], - // ]; + var presets = [ + // [ 'es2015', { loose: true } ], + 'env' + ]; - var plugins = [ - // https://babeljs.io/docs/plugins/transform-es2015-shorthand-properties/ - 'babel-plugin-transform-es2015-shorthand-properties', - // https://babeljs.io/docs/plugins/transform-es2015-template-literals/ - 'babel-plugin-transform-es2015-template-literals', - // http://babeljs.io/docs/plugins/transform-es2015-block-scoping/ - 'babel-plugin-transform-es2015-block-scoping', + // var plugins = [ + // // https://babeljs.io/docs/plugins/transform-es2015-shorthand-properties/ + // 'babel-plugin-transform-es2015-shorthand-properties', + // // https://babeljs.io/docs/plugins/transform-es2015-template-literals/ + // 'babel-plugin-transform-es2015-template-literals', + // // http://babeljs.io/docs/plugins/transform-es2015-block-scoping/ + // 'babel-plugin-transform-es2015-block-scoping', - // < 6.16.0 - [ 'babel-plugin-parser-opts', { allowReturnOutsideFunction: true } ] - ]; + // // < 6.16.0 + // [ 'babel-plugin-parser-opts', { allowReturnOutsideFunction: true } ] + // ]; var Babelify; try { @@ -119,8 +120,8 @@ module.exports = function createBundler(entryFiles, options) { return b .exclude(Path.join(__dirname, '../../package.json')) .transform(Babelify, (options && options.babelifyOpt) || { - // presets: presets, - plugins: plugins, + presets: presets, + // plugins: plugins, // >= 6.16.0 // parserOpts: { diff --git a/package.json b/package.json index 765eb8b4e6d..509d12a21ef 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "gulp-sourcemaps": "1.5.2", "gulp-uglify": "^3.0.0", "gulp-util": "3.0.6", + "js-sha1": "^0.6.0", "jshint-stylish": "2.1.0", "multipipe": "0.3.0", "persistify": "^1.1.1", @@ -50,6 +51,10 @@ "vinyl": "1.1.0", "vinyl-buffer": "1.0.0", "vinyl-source-stream": "1.0.0", - "watchify": "^3.7.0" + "watchify": "^3.7.0", + "glsl-tokenizer": "^2.1.5", + "gulp-qunit": "^2.0.1", + "rollup": "^0.66.6", + "rollup-plugin-node-resolve": "^3.4.0" } } From e7009a4416a8461807c5e5a6115ae10dd8f96de5 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 4 Dec 2018 13:50:14 +0800 Subject: [PATCH 0241/1631] modify preloadScene API params (#3583) --- cocos2d/core/CCDirector.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/CCDirector.js b/cocos2d/core/CCDirector.js index cf4f0cff2dd..eac8affdbd7 100644 --- a/cocos2d/core/CCDirector.js +++ b/cocos2d/core/CCDirector.js @@ -579,6 +579,7 @@ cc.Director.prototype = { * @param {Object} onProgress.item - The latest item which flow out the pipeline * @param {Function} [onLoaded] - callback, will be called after scene loaded. * @param {Error} onLoaded.error - null or the error object. + * @param {cc.SceneAsset} onLoaded.asset - The scene asset itself. */ preloadScene: function (sceneName, onProgress, onLoaded) { if (onLoaded === undefined) { From 01d5d99bf8bf2d7c2c1022cbf2c48e43e7a922c1 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 5 Dec 2018 15:03:54 +0800 Subject: [PATCH 0242/1631] refine image type check (#3591) * refine image type check * refine code --- cocos2d/core/renderer/render-engine.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 16a874dd636..9b5a123439a 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -8284,7 +8284,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8343,7 +8343,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8632,7 +8632,7 @@ var TextureCube = (function (Texture$$1) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); } else { if (this._compressed) { @@ -8679,7 +8679,7 @@ var TextureCube = (function (Texture$$1) { } else { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { gl.texImage2D( gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, From ff97f404489cea1f6dd4dfbfeef2d86c1828cb61 Mon Sep 17 00:00:00 2001 From: mac <1053210246@qq.com> Date: Wed, 5 Dec 2018 17:18:05 +0800 Subject: [PATCH 0243/1631] dragonbones spine optimizing --- cocos2d/core/CCGame.js | 12 +- cocos2d/core/load-pipeline/downloader.js | 3 +- cocos2d/core/load-pipeline/loader.js | 1 + extensions/dragonbones/ArmatureDisplay.js | 142 ++++---- extensions/dragonbones/CCArmatureDisplay.js | 117 +++++++ extensions/dragonbones/CCFactory.js | 84 ++--- extensions/dragonbones/CCSlot.js | 162 +++++----- extensions/dragonbones/DragonBonesAsset.js | 89 ++++-- extensions/dragonbones/canvas-assembler.js | 78 ----- extensions/dragonbones/index.js | 207 ++++++------ extensions/dragonbones/webgl-assembler.js | 338 ++++++++++++++------ extensions/spine/Skeleton.js | 14 +- extensions/spine/index.js | 129 ++++---- extensions/spine/spine-assembler.js | 29 +- gulp/tasks/engine.js | 6 + modules.json | 3 +- 16 files changed, 835 insertions(+), 579 deletions(-) create mode 100644 extensions/dragonbones/CCArmatureDisplay.js delete mode 100644 extensions/dragonbones/canvas-assembler.js diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index b16db60889d..27b9770fc09 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -61,7 +61,7 @@ var game = { EVENT_HIDE: "game_on_hide", /** - * Event triggered when game back to foreground + * !#en Event triggered when game back to foreground * Please note that this event is not 100% guaranteed to be fired on Web platform, * on native platforms, it corresponds to enter foreground event. * !#zh 游戏进入前台运行时触发的事件。 @@ -73,6 +73,15 @@ var game = { */ EVENT_SHOW: "game_on_show", + /** + * !#en Event triggered when game restart + * !#zh 调用restart后,触发事件。 + * @property EVENT_RESTART + * @constant + * @type {String} + */ + EVENT_RESTART: "game_on_restart", + /** * Event triggered after game inited, at this point all engine objects and game scripts are loaded * @property EVENT_GAME_INITED @@ -343,6 +352,7 @@ var game = { cc.director.reset(); game.onStart(); + game.emit(game.EVENT_RESTART); }); }, diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index 83092e16903..2f554cd0a28 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -187,7 +187,8 @@ var defaultMap = { // Binary 'binary' : downloadBinary, 'bin': downloadBinary, - + 'dbbin' : downloadBinary, + 'default' : downloadText }; diff --git a/cocos2d/core/load-pipeline/loader.js b/cocos2d/core/load-pipeline/loader.js index b7543c4506c..842d0e4fed5 100644 --- a/cocos2d/core/load-pipeline/loader.js +++ b/cocos2d/core/load-pipeline/loader.js @@ -186,6 +186,7 @@ var defaultMap = { // binary 'binary' : loadBinary, + 'dbbin' : loadBinary, // Font 'font' : fontLoader.loadFont, diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 35e7a2b6e6e..00f9b4b41b0 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -120,7 +120,6 @@ let ArmatureDisplay = cc.Class({ // parse the atlas asset data this._parseDragonAtlasAsset(); this._buildArmature(); - this._activateMaterial(); }, tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.dragon_bones_atlas_asset' }, @@ -206,6 +205,7 @@ let ArmatureDisplay = cc.Class({ type: DefaultArmaturesEnum, visible: true, editorOnly: true, + animatable: false, displayName: "Armature", tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.armature_name' }, @@ -252,7 +252,9 @@ let ArmatureDisplay = cc.Class({ timeScale: { default: 1, notify () { - this._armature.animation.timeScale = this.timeScale; + if (this._armature) { + this._armature.animation.timeScale = this.timeScale; + } }, tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.time_scale' }, @@ -274,6 +276,20 @@ let ArmatureDisplay = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.play_times' }, + /** + * !#en Indicates whether to enable premultiplied alpha. + * You should disable this option when image's transparent area appears to have opaque pixels, + * or enable this option when image's half transparent area appears to be darken. + * !#zh 是否启用贴图预乘。 + * 当图片的透明区域出现色块时需要关闭该选项,当图片的半透明区域颜色变黑时需要启用该选项。 + * @property {Boolean} premultipliedAlpha + * @default false + */ + premultipliedAlpha: { + default: false, + tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.premultipliedAlpha' + }, + /** * !#en Indicates whether open debug bones. * !#zh 是否显示 bone 的 debug 信息。 @@ -290,10 +306,37 @@ let ArmatureDisplay = cc.Class({ }, ctor () { + this._renderDatas = []; + this._material = new SpriteMaterial; + // Property _materialCache Use to cache material,since dragonBones may use multiple texture, + // it will clone from the '_material' property,if the dragonbones only have one texture, + // it will just use the _material,won't clone it. + // So if invoke getMaterial,it only return _material,if you want to change all materialCache, + // you can change materialCache directly. + this._materialCache = {}; this._inited = false; this._factory = dragonBones.CCFactory.getInstance(); }, + onLoad () { + // Adapt to old code,remove unuse child which is created by old code. + // This logic can be remove after 2.2 or later. + var children = this.node.children; + for (var i = 0, n = children.length; i < n; i++) { + var child = children[i]; + var pos = child._name && child._name.search('CHILD_ARMATURE-'); + if (pos === 0) { + child.destroy(); + } + } + }, + + // override + _updateMaterial (material) { + this._super(material); + this._materialCache = {}; + }, + __preload () { this._init(); }, @@ -305,7 +348,6 @@ let ArmatureDisplay = cc.Class({ this._parseDragonAsset(); this._parseDragonAtlasAsset(); this._refresh(); - this._activateMaterial(); }, onEnable () { @@ -329,6 +371,7 @@ let ArmatureDisplay = cc.Class({ this._armature.dispose(); this._armature = null; } + this._renderDatas.length = 0; }, _initDebugDraw () { @@ -350,31 +393,16 @@ let ArmatureDisplay = cc.Class({ } }, - _activateMaterial () { - let texture = this.dragonAtlasAsset && this.dragonAtlasAsset.texture; - - - // Get material - let material = this._material || new SpriteMaterial(); - material.useColor = false; - - if (texture) { - material.texture = texture; - this.markForUpdateRenderData(true); - this.markForRender(true); - } - else { - this.disableRender(); - } - - this._updateMaterial(material); - }, - _buildArmature () { if (!this.dragonAsset || !this.dragonAtlasAsset || !this.armatureName) return; - let factory = dragonBones.CCFactory.getInstance(); - this._armature = factory.buildArmatureDisplay(this.armatureName, this.dragonAsset._dragonBonesData.name, this); + var displayProxy = this._factory.buildArmatureDisplay(this.armatureName, this.dragonAsset._dragonBonesData.name, this); + if (!displayProxy) return; + + this._displayProxy = displayProxy; + this._displayProxy._ccNode = this.node; + + this._armature = this._displayProxy._armature; this._armature.animation.timeScale = this.timeScale; if (this.animationName) { @@ -505,7 +533,9 @@ let ArmatureDisplay = cc.Class({ * @param {Object} [target] - The target (this object) to invoke the callback, can be null */ addEventListener (eventType, listener, target) { - this.addDBEventListener(eventType, listener, target); + if (this._displayProxy) { + this._displayProxy.addDBEventListener(eventType, listener, target); + } }, /** @@ -519,7 +549,9 @@ let ArmatureDisplay = cc.Class({ * @param {Object} [target] */ removeEventListener (eventType, listener, target) { - this.removeDBEventListener(eventType, listener, target); + if (this._displayProxy) { + this._displayProxy.removeDBEventListener(eventType, listener, target); + } }, /** @@ -533,7 +565,7 @@ let ArmatureDisplay = cc.Class({ * @return {dragonBones.ArmatureDisplay} */ buildArmature (armatureName, node) { - return dragonBones.CCFactory.getInstance().createArmatureNode(this, armatureName, node); + return this._factory.createArmatureNode(this, armatureName, node); }, /** @@ -547,60 +579,6 @@ let ArmatureDisplay = cc.Class({ armature () { return this._armature; }, - - //////////////////////////////////// - // dragonbones api - dbInit (armature) { - this._armature = armature; - }, - - dbClear () { - this._armature = null; - }, - - dbUpdate () { - if (!CC_DEBUG) return; - this._initDebugDraw(); - - let debugDraw = this._debugDraw; - if (!debugDraw) return; - - debugDraw.clear(); - let bones = this._armature.getBones(); - for (let i = 0, l = bones.length; i < l; i++) { - let bone = bones[i]; - let boneLength = Math.max(bone.boneData.length, 5); - let startX = bone.globalTransformMatrix.tx; - let startY = -bone.globalTransformMatrix.ty; - let endX = startX + bone.globalTransformMatrix.a * boneLength; - let endY = startY - bone.globalTransformMatrix.b * boneLength; - - debugDraw.moveTo(startX, startY); - debugDraw.lineTo(endX, endY); - debugDraw.stroke(); - } - }, - - advanceTimeBySelf (on) { - this.shouldAdvanced = !!on; - }, - - hasDBEventListener (type) { - return this.hasEventListener(type); - }, - - addDBEventListener (type, listener, target) { - this.on(type, listener, target); - }, - - removeDBEventListener (type, listener, target) { - this.off(type, listener, target); - }, - - dispatchDBEvent (type, eventObject) { - this.emit(type, eventObject); - }, - //////////////////////////////////// }); module.exports = dragonBones.ArmatureDisplay = ArmatureDisplay; diff --git a/extensions/dragonbones/CCArmatureDisplay.js b/extensions/dragonbones/CCArmatureDisplay.js new file mode 100644 index 00000000000..c1377b5b1de --- /dev/null +++ b/extensions/dragonbones/CCArmatureDisplay.js @@ -0,0 +1,117 @@ +/**************************************************************************** + Copyright (c) 2018 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. + ****************************************************************************/ +let EventTarget = require('../../cocos2d/core/event/event-target'); + +dragonBones.CCArmatureDisplay = cc.Class({ + name: 'dragonBones.CCArmatureDisplay', + mixins: [EventTarget], + + properties: { + // adapt old api + node: { + get () { + return this; + } + } + }, + + getRootDisplay () { + var parentSlot = this._armature._parent; + if (!parentSlot) { + return this; + } + + var slot; + while (parentSlot) + { + slot = parentSlot; + parentSlot = parentSlot._armature._parent; + } + return slot._armature.getDisplay(); + }, + + convertToRootSpace (pos) { + var slot = this._armature._parent; + if (!slot) + { + return pos; + } + slot.updateWorldMatrix(); + + let worldMatrix = slot._worldMatrix; + let newPos = cc.v2(0,0); + newPos.x = pos.x * worldMatrix.m00 + pos.y * worldMatrix.m04 + worldMatrix.m12; + newPos.y = pos.x * worldMatrix.m01 + pos.y * worldMatrix.m05 + worldMatrix.m13; + return newPos; + }, + + convertToWorldSpace (point) { + var newPos = this.convertToRootSpace(point); + var ccNode = this.getRootNode(); + var finalPos = ccNode.convertToWorldSpace(newPos); + return finalPos; + }, + + getRootNode () { + var rootDisplay = this.getRootDisplay(); + return rootDisplay && rootDisplay._ccNode; + }, + + //////////////////////////////////// + // dragonbones api + dbInit (armature) { + this._armature = armature; + }, + + dbClear () { + this._armature = null; + }, + + dbUpdate () { + + }, + + advanceTimeBySelf (on) { + this.shouldAdvanced = !!on; + }, + + hasDBEventListener (type) { + return this.hasEventListener(type); + }, + + addDBEventListener (type, listener, target) { + this.on(type, listener, target); + }, + + removeDBEventListener (type, listener, target) { + this.off(type, listener, target); + }, + + dispatchDBEvent (type, eventObject) { + this.emit(type, eventObject); + } + //////////////////////////////////// + +}); diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index d5aee21c2f8..919cf7701c5 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -23,7 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -let BaseObject = dragonBones.BaseObject; +let BaseObject = dragonBones.BaseObject, + BaseFactory = dragonBones.BaseFactory; /** * @module dragonBones @@ -35,7 +36,7 @@ let BaseObject = dragonBones.BaseObject; */ var CCFactory = dragonBones.CCFactory = cc.Class({ name: 'dragonBones.CCFactory', - extends: dragonBones.BaseFactory, + extends: BaseFactory, /** * @method getInstance * @return {CCFactory} @@ -56,21 +57,51 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ ctor () { this._dragonBones = new dragonBones.DragonBones(); - if (!CC_EDITOR && cc.director._scheduler) { - cc.director._scheduler.enableForTarget(this); - cc.director._scheduler.scheduleUpdate(this, cc.Scheduler.PRIORITY_SYSTEM, false); + if (!CC_JSB && !CC_EDITOR && cc.director._scheduler) { + cc.game.on(cc.game.EVENT_RESTART, this.initUpdate, this); + this.initUpdate(); } }, + initUpdate (dt) { + cc.director._scheduler.enableForTarget(this); + cc.director._scheduler.scheduleUpdate(this, cc.Scheduler.PRIORITY_SYSTEM, false); + }, + update (dt) { this._dragonBones.advanceTime(dt); }, - buildArmatureDisplay (armatureName, dragonBonesName, comp) { - this._display = comp; - let armature = this.buildArmature(armatureName, dragonBonesName, comp); - this._display = null; - return armature; + parseDragonBonesDataOnly (rawData, name, scale) { + if (name === undefined) { name = null; } + if (scale === undefined) { scale = 1.0; } + var dataParser = rawData instanceof ArrayBuffer ? BaseFactory._binaryParser : this._dataParser; + var dragonBonesData = dataParser.parseDragonBonesData(rawData, scale); + return dragonBonesData; + }, + + handleTextureAtlasData (isBinary, name, scale) { + if (name === undefined) { name = null; } + if (scale === undefined) { scale = 1.0; } + + var dataParser = isBinary ? BaseFactory._binaryParser : this._dataParser; + + while (true) { + var textureAtlasData = this._buildTextureAtlasData(null, null); + if (dataParser.parseTextureAtlasData(null, textureAtlasData, scale)) { + this.addTextureAtlasData(textureAtlasData, name); + } + else { + textureAtlasData.returnToPool(); + break; + } + } + }, + + // Build new aramture with a new display. + buildArmatureDisplay (armatureName, dragonBonesName) { + let armature = this.buildArmature(armatureName, dragonBonesName); + return armature && armature._display; }, parseTextureAtlasData (jsonString, texture) { @@ -78,6 +109,9 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ return this._super(atlasJsonObj, texture); }, + // Build sub armature from an exist armature component. + // It will share dragonAsset and dragonAtlasAsset. + // But node can not share,or will cause render error. createArmatureNode (comp, armatureName, node) { node = node || new cc.Node(); let display = node.getComponent(dragonBones.ArmatureDisplay); @@ -94,23 +128,7 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ return display; }, - - _buildChildArmature (dataPackage, slot, displayData) { - let temp = this._display; - - let name = 'CHILD_ARMATURE-' + displayData.path; - let node = this._display.node.getChildByName(name); - if (!node) { - node = new cc.Node(); - } - let display = this.createArmatureNode(temp, displayData.path, node); - node.name = name; - - this._display = temp; - return display._armature; - }, - _buildTextureAtlasData (textureAtlasData, textureAtlas) { if (textureAtlasData) { textureAtlasData.renderTexture = textureAtlas; @@ -155,8 +173,10 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ // fixed dragonbones sort issue // armature._sortSlots = this._sortSlots; + var display = new dragonBones.CCArmatureDisplay(); + armature.init(dataPackage.armature, - this._display, this._display, this._dragonBones + display, display, this._dragonBones ); return armature; @@ -164,17 +184,9 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ _buildSlot (dataPackage, slotData, displays) { let slot = BaseObject.borrowObject(dragonBones.CCSlot); - let displayList = []; - slot.name = slotData.name; - slot.reset(); - - // let display = new cc.Node(); - // display.name = slot.name; - let display = slot; slot.init(slotData, displays, display, display); - return slot; } -}); \ No newline at end of file +}); diff --git a/extensions/dragonbones/CCSlot.js b/extensions/dragonbones/CCSlot.js index ce59f5116be..fdb34c74397 100644 --- a/extensions/dragonbones/CCSlot.js +++ b/extensions/dragonbones/CCSlot.js @@ -33,19 +33,23 @@ dragonBones.CCSlot = cc.Class({ extends: dragonBones.Slot, ctor () { - this._vertices = []; this._localVertices = []; this._indices = []; this._matrix = math.mat4.create(); + this._worldMatrix = math.mat4.create(); + this._worldMatrixDirty = true; this._visible = false; this._color = cc.color(); }, - reset () { - this._vertices.length = 0; + _onClear () { + this._super(); this._localVertices.length = 0; this._indices.length = 0; math.mat4.identity(this._matrix); + math.mat4.identity(this._worldMatrix); + this._worldMatrixDirty = true; + this._color = cc.color(); this._visible = false; }, @@ -55,72 +59,40 @@ dragonBones.CCSlot = cc.Class({ } }, + // just for adapt to dragonbones api,no need to do any thing _onUpdateDisplay () { - if (this._childArmature) { - this._childArmature.display._isChildArmature = true; - } }, + // just for adapt to dragonbones api,no need to do any thing _initDisplay (value) { }, _addDisplay () { this._visible = true; - - if (!CC_EDITOR) { - this._rawDisplay.parent = this._armature.display.node; - } }, + // just for adapt to dragonbones api,no need to do any thing _replaceDisplay (value) { - if (value instanceof dragonBones.ArmatureDisplay) { - value.node.parent = null; - } - - if (this._display instanceof dragonBones.ArmatureDisplay) { - this._display.node.parent = this._armature.display.node; - } }, _removeDisplay () { this._visible = false; - - if (!CC_EDITOR) { - this._rawDisplay.parent = null; - } }, + // just for adapt to dragonbones api,no need to do any thing _disposeDisplay (object) { - }, + // just for adapt to dragonbones api,no need to do any thing _updateVisible () { }, - _updateZOrder: function() { + // just for adapt to dragonbones api,no need to do any thing + _updateZOrder () { }, _updateBlendMode () { - // TODO: new implementation needed - return; - if (this._renderDisplay instanceof cc.Scale9Sprite) { - switch (this._blendMode) { - case 0: // BlendMode Normal - break; - case 1: // BlendMode Add - let texture = this._renderDisplay._spriteFrame.getTexture(); - if (texture && texture.hasPremultipliedAlpha()) { - this._renderDisplay.setBlendFunc(BlendFactor.ONE, BlendFactor.ONE); - } - else { - this._renderDisplay.setBlendFunc(BlendFactor.SRC_ALPHA, BlendFactor.ONE); - } - break; - default: - break; - } - } - else if (this._childArmature) { + if (this._childArmature) { let childSlots = this._childArmature.getSlots(); for (let i = 0, l = childSlots.length; i < l; i++) { let slot = childSlots[i]; @@ -138,14 +110,16 @@ dragonBones.CCSlot = cc.Class({ c.a = this._colorTransform.alphaMultiplier * 255; }, + //return dragonBones.CCTexture2D + getTexture () { + return this._textureData && this._textureData.spriteFrame && this._textureData.spriteFrame.getTexture(); + }, + _updateFrame () { - this._vertices.length = 0; this._indices.length = 0; - let vertices = this._vertices, - indices = this._indices, + let indices = this._indices, localVertices = this._localVertices; - vertices.length = 0; indices.length = 0; localVertices.length = 0; @@ -153,7 +127,7 @@ dragonBones.CCSlot = cc.Class({ // update the frame if (!this._display || this._displayIndex < 0 || !currentTextureData) return; - let currentDisplayData = this._displayIndex < this.rawDisplayDatas.length ? this.rawDisplayDatas[this._displayIndex] : null;; + let currentDisplayData = this._displayIndex < this.rawDisplayDatas.length ? this.rawDisplayDatas[this._displayIndex] : null; let textureAtlas = this._armature._replacedTexture || currentTextureData.parent.renderTexture; if (textureAtlas && (!currentTextureData.spriteFrame || currentTextureData.spriteFrame.getTexture() !== textureAtlas)) { @@ -188,14 +162,13 @@ dragonBones.CCSlot = cc.Class({ const uvOffset = vertexOffset + vertexCount * 2; for (let i = 0, l = vertexCount; i < l; i++) { - let x = floatArray[vertexOffset + i*2]; - let y = -floatArray[vertexOffset + i*2 + 1]; + let x = floatArray[vertexOffset + i*2] * scale; + let y = -floatArray[vertexOffset + i*2 + 1] * scale; let u = (region.x + floatArray[uvOffset + i*2] * region.width) / textureAtlasWidth; let v = (region.y + floatArray[uvOffset + i*2 + 1] * region.height) / textureAtlasHeight; - vertices.push({ x, y, u, v}); - localVertices.push({ x, y}); + localVertices.push({ x, y, u, v}); } for (let i = 0; i < triangleCount * 3; ++i) { @@ -229,7 +202,6 @@ dragonBones.CCSlot = cc.Class({ this._pivotY -= region.height * scale; for (let i = 0; i < 4; i++) { - vertices.push({}); localVertices.push({}); } @@ -237,15 +209,15 @@ dragonBones.CCSlot = cc.Class({ let b = (region.y + region.height) / textureAtlasHeight; let r = (region.x + region.width) / textureAtlasWidth; let t = region.y / textureAtlasHeight; - vertices[0].u = l; vertices[0].v = b; - vertices[1].u = r; vertices[1].v = b; - vertices[2].u = l; vertices[2].v = t; - vertices[3].u = r; vertices[3].v = t; + localVertices[0].u = l; localVertices[0].v = b; + localVertices[1].u = r; localVertices[1].v = b; + localVertices[2].u = l; localVertices[2].v = t; + localVertices[3].u = r; localVertices[3].v = t; - localVertices[0].x = localVertices[2].x = vertices[0].x = vertices[2].x = 0; - localVertices[1].x = localVertices[3].x = vertices[1].x = vertices[3].x = region.width; - localVertices[0].y = localVertices[1].y = vertices[0].y = vertices[1].y = 0; - localVertices[2].y = localVertices[3].y = vertices[2].y = vertices[3].y = region.height; + localVertices[0].x = localVertices[2].x = 0; + localVertices[1].x = localVertices[3].x = region.width; + localVertices[0].y = localVertices[1].y = 0; + localVertices[2].y = localVertices[3].y = region.height; indices[0] = 0; indices[1] = 1; @@ -258,7 +230,7 @@ dragonBones.CCSlot = cc.Class({ } }, - _updateMesh : function() { + _updateMesh () { const scale = this._armature._armatureData.scale; const meshData = this._meshData; const hasDeform = this._deformVertices.length > 0 && meshData.inheritDeform; @@ -337,7 +309,6 @@ dragonBones.CCSlot = cc.Class({ } } - this._updateVertices(); }, _updateTransform () { @@ -349,28 +320,59 @@ dragonBones.CCSlot = cc.Class({ t.m12 = this.globalTransformMatrix.tx - (this.globalTransformMatrix.a * this._pivotX + this.globalTransformMatrix.c * this._pivotY); t.m13 = -(this.globalTransformMatrix.ty - (this.globalTransformMatrix.b * this._pivotX + this.globalTransformMatrix.d * this._pivotY)); - if (this._display instanceof dragonBones.ArmatureDisplay) { - let node = this._display.node; - math.mat4.copy(node._matrix, t); - node._localMatDirty = false; - node.setWorldDirty(); + this._worldMatrixDirty = true; + }, + + updateWorldMatrix () { + if (!this._armature) return; + + var parentSlot = this._armature._parent; + if (parentSlot) { + parentSlot.updateWorldMatrix(); } - this._updateVertices(); + if (this._worldMatrixDirty) { + this.calculWorldMatrix(); + var childArmature = this.childArmature; + if (!childArmature) return; + var slots = childArmature.getSlots(); + for (var i = 0,n = slots.length; i < n; i++) { + var slot = slots[i]; + if (slot) { + slot._worldMatrixDirty = true; + } + } + } }, - _updateVertices () { - let t = this._matrix; - let a = t.m00, b = t.m01, c = t.m04, d = t.m05, tx = t.m12, ty = t.m13; - - let vertices = this._vertices; - let localVertices = this._localVertices; - for (let i = 0, l = vertices.length; i < l; i++) { - let x = localVertices[i].x; - let y = localVertices[i].y; + _mulMat (out, a, b) { + let aa=a.m00, ab=a.m01, ac=a.m04, ad=a.m05, atx=a.m12, aty=a.m13; + let ba=b.m00, bb=b.m01, bc=b.m04, bd=b.m05, btx=b.m12, bty=b.m13; + if (ab !== 0 || ac !== 0) { + out.m00 = ba * aa + bb * ac; + out.m01 = ba * ab + bb * ad; + out.m04 = bc * aa + bd * ac; + out.m05 = bc * ab + bd * ad; + out.m12 = aa * btx + ac * bty + atx; + out.m13 = ab * btx + ad * bty + aty; + } + else { + out.m00 = ba * aa; + out.m01 = bb * ad; + out.m04 = bc * aa; + out.m05 = bd * ad; + out.m12 = aa * btx + atx; + out.m13 = ad * bty + aty; + } + }, - vertices[i].x = a * x + c * y + tx; - vertices[i].y = b * x + d * y + ty; + calculWorldMatrix () { + var parent = this._armature._parent; + if (parent) { + this._mulMat(this._worldMatrix ,parent._worldMatrix, this._matrix); + } else { + math.mat4.copy(this._worldMatrix, this._matrix); } + this._worldMatrixDirty = false; } }); diff --git a/extensions/dragonbones/DragonBonesAsset.js b/extensions/dragonbones/DragonBonesAsset.js index c98ee7e410e..fb3d3c0737a 100644 --- a/extensions/dragonbones/DragonBonesAsset.js +++ b/extensions/dragonbones/DragonBonesAsset.js @@ -58,7 +58,18 @@ var DragonBonesAsset = cc.Class({ this._dragonBonesJson = value; this.reset(); } - } + }, + + _nativeAsset: { + get () { + return this._buffer; + }, + set (bin) { + this._buffer = bin.buffer || bin; + this.reset(); + }, + override: true + }, }, statics: { @@ -80,48 +91,56 @@ var DragonBonesAsset = cc.Class({ } }, - init: function (factory) { + init (factory) { if (CC_EDITOR) { - factory = factory || new dragonBones.CCFactory(); + this._factory = factory || new dragonBones.CCFactory(); + } else { + this._factory = factory; } + if (this._dragonBonesData) { - let sameNamedDragonBonesData = factory.getDragonBonesData(this._dragonBonesData.name); - if (sameNamedDragonBonesData) { - // already added asset, see #2002 - for (let i = 0; i < this._dragonBonesData.armatureNames.length; i++) { - let armatureName = this._dragonBonesData.armatureNames[i]; - if (!sameNamedDragonBonesData.armatures[armatureName]) { - // merge with new armature - sameNamedDragonBonesData.addArmature(this._dragonBonesData.armatures[armatureName]); - } - } - this._dragonBonesData = sameNamedDragonBonesData; - } - else { - factory.addDragonBonesData(this._dragonBonesData); + let hasSame = this.checkSameNameData(this._dragonBonesData); + if (!hasSame) { + this._factory.addDragonBonesData(this._dragonBonesData); } } else { - let _dragonBonesJson = JSON.parse(this.dragonBonesJson); - let sameNamedDragonBonesData = factory.getDragonBonesData(_dragonBonesJson.name); - if (sameNamedDragonBonesData) { - // already added asset, see #2002 - let dragonBonesData; - for (let i = 0; i < _dragonBonesJson.armature.length; i++) { - let armatureName = _dragonBonesJson.armature[i].name; - if (!sameNamedDragonBonesData.armatures[armatureName]) { - // add new armature - if (!dragonBonesData) { - dragonBonesData = factory._dataParser.parseDragonBonesData(_dragonBonesJson); - } - sameNamedDragonBonesData.addArmature(dragonBonesData.armatures[armatureName]); - } - } - this._dragonBonesData = sameNamedDragonBonesData; + if (this.dragonBonesJson) { + this.initWithRawData(JSON.parse(this.dragonBonesJson), false); + } else { + this.initWithRawData(this._nativeAsset, true); } - else { - this._dragonBonesData = factory.parseDragonBonesData(_dragonBonesJson); + } + }, + + checkSameNameData (dragonBonesData) { + let sameNamedDragonBonesData = this._factory.getDragonBonesData(dragonBonesData.name); + if (sameNamedDragonBonesData) { + // already added asset, see #2002 + let armatureNames = dragonBonesData.armatureNames; + for (let i = 0; i < armatureNames.length; i++) { + let armatureName = armatureNames[i]; + if (!sameNamedDragonBonesData.armatures[armatureName]) { + sameNamedDragonBonesData.addArmature(dragonBonesData.armatures[armatureName]); + } } + this._dragonBonesData = sameNamedDragonBonesData; + return true; + } + return false; + }, + + initWithRawData (rawData, isBinary) { + if (!rawData) { + return; + } + + let dragonBonesData = this._factory.parseDragonBonesDataOnly(rawData); + let hasSame = this.checkSameNameData(dragonBonesData); + if (!hasSame) { + this._dragonBonesData = dragonBonesData; + this._factory.handleTextureAtlasData(isBinary); + this._factory.addDragonBonesData(dragonBonesData); } }, diff --git a/extensions/dragonbones/canvas-assembler.js b/extensions/dragonbones/canvas-assembler.js deleted file mode 100644 index e73c1d71aec..00000000000 --- a/extensions/dragonbones/canvas-assembler.js +++ /dev/null @@ -1,78 +0,0 @@ -const Armature = require('./ArmatureDisplay'); -const renderEngine = require('../../cocos2d/core/renderer/render-engine'); -const math = renderEngine.math; - -const utils = require('../../cocos2d/core/renderer/canvas/renderers/utils'); - -let _color = cc.color(); - -let _matrix = math.mat4.create(); -let _matrix2 = math.mat4.create(); - -let armatureAssembler = { - draw (ctx, comp) { - let armature = comp._armature; - if (!armature || comp._isChildArmature) return 0; - - ctx.save(); - - let node = comp.node; - let matrix = node._worldMatrix; - - let texture = comp.dragonAtlasAsset.texture; - this.drawArmature(ctx, armature, texture, matrix); - - ctx.restore(); - - return 1; - }, - - drawArmature (ctx, armature, texture, matrix) { - let slots = armature._slots; - - for (let i = 0, l = slots.length; i < l; i++) { - let slot = slots[i]; - if (!slot._visible || !slot._displayData) continue; - - if (slot.childArmature) { - math.mat4.mul(_matrix, matrix, slot._matrix); - this.drawArmature(ctx, slot.childArmature, texture, _matrix); - continue; - } - - let localVertices = slot._localVertices; - - if (localVertices.length !== 4) { - continue; - } - - ctx.save(); - - math.mat4.mul(_matrix2, matrix, slot._matrix); - - let m = _matrix2; - ctx.transform(m.m00, -m.m01, -m.m04, m.m05, m.m12, -m.m13); - - let vertices = slot._vertices; - let sx = vertices[0].u * texture.width; - let sy = vertices[3].v * texture.height; - let sw = vertices[3].u * texture.width - sx; - let sh = vertices[0].v * texture.height - sy; - - let x = localVertices[0].x; - let y = localVertices[0].y; - let w = localVertices[3].x - x; - let h = localVertices[3].y - y; - y = -y-h; - - _color._val = slot._color; - let image = utils.getFrameCache(texture, _color, sx, sy, sw, sh); - - ctx.drawImage(image, x, y, w, h); - - ctx.restore(); - } - } -}; - -module.exports = Armature._assembler = armatureAssembler; diff --git a/extensions/dragonbones/index.js b/extensions/dragonbones/index.js index cc405aff6e6..baa5d051de1 100644 --- a/extensions/dragonbones/index.js +++ b/extensions/dragonbones/index.js @@ -40,107 +40,110 @@ */ var _global = typeof window === 'undefined' ? global : window; -_global.dragonBones = require('./lib/dragonBones'); - -dragonBones.DisplayType = { - Image : 0, - Armature : 1, - Mesh : 2 -}; - -dragonBones.ArmatureType = { - Armature : 0, - MovieClip : 1, - Stage : 2 -}; - -dragonBones.ExtensionType = { - FFD : 0, - AdjustColor : 10, - BevelFilter : 11, - BlurFilter : 12, - DropShadowFilter : 13, - GlowFilter : 14, - GradientBevelFilter : 15, - GradientGlowFilter : 16 -}; - -dragonBones.EventType = { - Frame : 0, - Sound : 1 -}; - -dragonBones.ActionType = { - Play : 0, - Stop : 1, - GotoAndPlay : 2, - GotoAndStop : 3, - FadeIn : 4, - FadeOut : 5 -}; - -dragonBones.AnimationFadeOutMode = { - None : 0, - SameLayer : 1, - SameGroup : 2, - SameLayerAndGroup : 3, - All : 4 -}; - -dragonBones.BinaryOffset = { - WeigthBoneCount: 0, - WeigthFloatOffset: 1, - WeigthBoneIndices: 2, - - MeshVertexCount: 0, - MeshTriangleCount: 1, - MeshFloatOffset: 2, - MeshWeightOffset: 3, - MeshVertexIndices: 4, - - TimelineScale: 0, - TimelineOffset: 1, - TimelineKeyFrameCount: 2, - TimelineFrameValueCount: 3, - TimelineFrameValueOffset: 4, - TimelineFrameOffset: 5, - - FramePosition: 0, - FrameTweenType: 1, - FrameTweenEasingOrCurveSampleCount: 2, - FrameCurveSamples: 3, - - DeformMeshOffset: 0, - DeformCount: 1, - DeformValueCount: 2, - DeformValueOffset: 3, - DeformFloatOffset: 4 -}; - -dragonBones.BoneType = { - Bone: 0, - Surface: 1 -}; - -if (!CC_EDITOR || !Editor.isMainProcess) { - require('./CCFactory'); - require('./CCSlot'); - require('./CCTextureData'); - - // require the component for dragonbones - require('./DragonBonesAsset'); - require('./DragonBonesAtlasAsset'); - require('./ArmatureDisplay'); - - cc.game.once(cc.game.EVENT_ENGINE_INITED, function () { - if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { - require('./canvas-assembler'); - } - else { - require('./webgl-assembler'); +if (!CC_JSB) { + _global.dragonBones = require('./lib/dragonBones'); +} + +if (_global.dragonBones !== undefined) { + + dragonBones.DisplayType = { + Image : 0, + Armature : 1, + Mesh : 2 + }; + + dragonBones.ArmatureType = { + Armature : 0, + MovieClip : 1, + Stage : 2 + }; + + dragonBones.ExtensionType = { + FFD : 0, + AdjustColor : 10, + BevelFilter : 11, + BlurFilter : 12, + DropShadowFilter : 13, + GlowFilter : 14, + GradientBevelFilter : 15, + GradientGlowFilter : 16 + }; + + dragonBones.EventType = { + Frame : 0, + Sound : 1 + }; + + dragonBones.ActionType = { + Play : 0, + Stop : 1, + GotoAndPlay : 2, + GotoAndStop : 3, + FadeIn : 4, + FadeOut : 5 + }; + + dragonBones.AnimationFadeOutMode = { + None : 0, + SameLayer : 1, + SameGroup : 2, + SameLayerAndGroup : 3, + All : 4 + }; + + dragonBones.BinaryOffset = { + WeigthBoneCount: 0, + WeigthFloatOffset: 1, + WeigthBoneIndices: 2, + + MeshVertexCount: 0, + MeshTriangleCount: 1, + MeshFloatOffset: 2, + MeshWeightOffset: 3, + MeshVertexIndices: 4, + + TimelineScale: 0, + TimelineOffset: 1, + TimelineKeyFrameCount: 2, + TimelineFrameValueCount: 3, + TimelineFrameValueOffset: 4, + TimelineFrameOffset: 5, + + FramePosition: 0, + FrameTweenType: 1, + FrameTweenEasingOrCurveSampleCount: 2, + FrameCurveSamples: 3, + + DeformMeshOffset: 0, + DeformCount: 1, + DeformValueCount: 2, + DeformValueOffset: 3, + DeformFloatOffset: 4 + }; + + dragonBones.BoneType = { + Bone: 0, + Surface: 1 + }; + + if (!CC_EDITOR || !Editor.isMainProcess) { + + if (!CC_JSB) { + require('./CCFactory'); + require('./CCSlot'); + require('./CCTextureData'); + require('./CCArmatureDisplay'); } - }); -} else { - require('./DragonBonesAsset'); - require('./DragonBonesAtlasAsset'); + + // require the component for dragonbones + require('./DragonBonesAsset'); + require('./DragonBonesAtlasAsset'); + require('./ArmatureDisplay'); + + require('./webgl-assembler'); + } else { + require('./DragonBonesAsset'); + require('./DragonBonesAtlasAsset'); + } + } diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 73b8feb5895..4d6178cd09e 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -23,149 +23,305 @@ THE SOFTWARE. ****************************************************************************/ +const StencilManager = require('../../cocos2d/core/renderer/webgl/stencil-manager').sharedManager; const Armature = require('./ArmatureDisplay'); - const renderEngine = require('../../cocos2d/core/renderer/render-engine'); -const math = renderEngine.math; - -const js = require('../../cocos2d/core/platform/js'); - const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); +const gfx = renderEngine.gfx; +const SpriteMaterial = renderEngine.SpriteMaterial; +const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; + +let _boneColor = cc.color(255, 0, 0, 255); +let _slotColor = cc.color(0, 0, 255, 255); + +const STENCIL_SEP = '@'; + +function _updateKeyWithStencilRef (key, stencilRef) { + return key.replace(/@\d+$/, STENCIL_SEP + stencilRef); +} + +function _getSlotMaterial (comp, slot, premultiAlpha) { + premultiAlpha = premultiAlpha || false; + let tex = slot.getTexture(); + if(!tex)return null; + let src, dst; + + switch (slot._blendMode) { + case 1://additive + src = premultiAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; + dst = cc.macro.ONE; + break; + case 10://multiply + src = cc.macro.DST_COLOR; + dst = cc.macro.ONE_MINUS_SRC_ALPHA; + break; + case 12://screen + src = cc.macro.ONE; + dst = cc.macro.ONE_MINUS_SRC_COLOR; + break; + case 0://normal + default: + src = premultiAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; + dst = cc.macro.ONE_MINUS_SRC_ALPHA; + break; + } + + let key = tex.url + src + dst + STENCIL_SEP + '0'; + comp._material = comp._material || new SpriteMaterial(); + let baseMaterial = comp._material; + let materialCache = comp._materialCache; + let material = materialCache[key]; + if (!material) { + + var baseKey = baseMaterial._hash; + if (!materialCache[baseKey]) { + material = baseMaterial; + } else { + material = baseMaterial.clone(); + } -let _matrix = math.mat4.create(); + material.useModel = true; + // update texture + material.texture = tex; + material.useColor = false; + + // update blend function + let pass = material._mainTech.passes[0]; + pass.setBlend( + gfx.BLEND_FUNC_ADD, + src, dst, + gfx.BLEND_FUNC_ADD, + src, dst + ); + materialCache[key] = material; + material.updateHash(key); + } + else if (material.texture !== tex) { + material.texture = tex; + material.updateHash(key); + } + return material; +} -let _vbuf, _uintbuf, - _vertexId, _ibuf, - _vertexOffset, _indiceOffset, - _a, _b, _c, _d, _tx, _ty, +let _vertexOffset, _indiceOffset, _nodeR, _nodeG, _nodeB, _nodeA, - _worldMatrix; + _material, _currMaterial, + _dataId, _datas, _data, _newData; let armatureAssembler = { + useModel: true, + updateRenderData (comp) { + let armature = comp._armature; - if (!armature || comp._isChildArmature) { + if (!armature) { return; } - - let renderData = comp._renderData; - if (!renderData) { - renderData = comp._renderData = comp.requestRenderData(); - } - - renderData.material = comp.getMaterial(); - renderData.vertexCount = 0; - renderData.indiceCount = 0; - - this.calcBufferCount(renderData, armature); - }, - - calcBufferCount (renderData, armature) { - let slots = armature._slots; - for (let i = 0, l = slots.length; i < l; i++) { - let slot = slots[i]; - if (!slot._visible || !slot._displayData) continue; - if (slot.childArmature) { - this.calcBufferCount(renderData, slot.childArmature); - continue; - } - renderData.vertexCount += slot._vertices.length; - renderData.indiceCount += slot._indices.length; + _dataId = 0; + _datas = comp._renderDatas; + _data = _datas[_dataId]; + _newData = false; + if (!_data) { + _data = _datas[_dataId] = comp.requestRenderData(); } - }, - - fillBuffers (comp, renderer) { - let armature = comp._armature; - if (!armature || comp._isChildArmature) return; - - let buffer = renderer._meshBuffer, - renderData = comp._renderData; - - _vertexOffset = buffer.byteOffset >> 2; - _indiceOffset = buffer.indiceOffset; - _vertexId = buffer.vertexOffset; - - buffer.request(renderData.vertexCount, renderData.indiceCount); - - // buffer data may be realloc, need get reference after request. - _vbuf = buffer._vData; - _uintbuf = buffer._uintVData; - _ibuf = buffer._iData; + _data.dataLength = 0; + _material = null; + _currMaterial = null; + _vertexOffset = 0; + _indiceOffset = 0; let node = comp.node; - let nodeColor = node.color; _nodeR = nodeColor.r / 255; _nodeG = nodeColor.g / 255; _nodeB = nodeColor.b / 255; _nodeA = nodeColor.a / 255; - _worldMatrix = node._worldMatrix; - _a = _worldMatrix.m00; _b = _worldMatrix.m01; _c = _worldMatrix.m04; _d = _worldMatrix.m05; - _tx = _worldMatrix.m12; _ty = _worldMatrix.m13; - - this.fillIndexBufferWithArmature(armature); - this.fillVertexBufferWithArmature(armature); - - comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; - - _worldMatrix = _ibuf = _vbuf = _uintbuf = null; + this.traverseArmature(comp,armature); }, - fillVertexBufferWithArmature (armature) { + traverseArmature (comp,armature) { let slots = armature._slots; + let premultipliedAlpha = comp.premultipliedAlpha; for (let i = 0, l = slots.length; i < l; i++) { let slot = slots[i]; if (!slot._visible || !slot._displayData) continue; + slot.updateWorldMatrix(); + + // If slot has childArmature,then the slot has no + // vertices and indice info.It only has sub slots + // transform info,so multiply the slot's transform + // with parent transform and give the sub slots. if (slot.childArmature) { - math.mat4.mul(_matrix, _worldMatrix, slot._matrix); - _a = _matrix.m00; _b = _matrix.m01; _c = _matrix.m04; _d = _matrix.m05; - _tx = _matrix.m12; _ty = _matrix.m13; - this.fillVertexBufferWithArmature(slot.childArmature); - _a = _worldMatrix.m00; _b = _worldMatrix.m01; _c = _worldMatrix.m04; _d = _worldMatrix.m05; - _tx = _worldMatrix.m12; _ty = _worldMatrix.m13; + this.traverseArmature(comp, slot.childArmature); continue; } - let vertices = slot._vertices; + _material = _getSlotMaterial(comp, slot, premultipliedAlpha); + if (!_material) { + continue; + } + + // Check break + if (_currMaterial !== _material) { + if (_currMaterial) { + _newData = true; + _data.material = _currMaterial; + } + else { + // Init data material + _data.material = _material; + } + _currMaterial = _material; + } + + // Request new render data and new vertex content + if (_newData) { + // set old data vertex indice + _data.vertexCount = _vertexOffset; + _data.indiceCount = _indiceOffset; + // gen new data + _dataId++; + _data = _datas[_dataId]; + if (!_data) { + _data = _datas[_dataId] = comp.requestRenderData(); + } + _data.material = _currMaterial; + _data.dataLength = 0; + + // reset offset + _vertexOffset = 0; + _indiceOffset = 0; + } + + let indices = slot._indices; + let indiceBuffer = _data.indices; + for (let j = 0, il = indices.length; j < il; j++) { + indiceBuffer[_indiceOffset++] = _vertexOffset + indices[j]; + } + + let vertices = slot._localVertices; let slotColor = slot._color; + let worldMatrix = slot._worldMatrix; let cr = slotColor.r * _nodeR; let cg = slotColor.g * _nodeG; let cb = slotColor.b * _nodeB; let ca = slotColor.a * _nodeA; let color = ((ca<<24) >>> 0) + (cb<<16) + (cg<<8) + cr; + let vertexBuffer = _data.vertices; + _data.dataLength += vertices.length; for (let j = 0, vl = vertices.length; j < vl; j++) { let vertex = vertices[j]; - _vbuf[_vertexOffset++] = vertex.x * _a + vertex.y * _c + _tx; - _vbuf[_vertexOffset++] = vertex.x * _b + vertex.y * _d + _ty; - _vbuf[_vertexOffset++] = vertex.u; - _vbuf[_vertexOffset++] = vertex.v; - _uintbuf[_vertexOffset++] = color; + let content = vertexBuffer[_vertexOffset++]; + content.x = vertex.x * worldMatrix.m00 + vertex.y * worldMatrix.m04 + worldMatrix.m12; + content.y = vertex.x * worldMatrix.m01 + vertex.y * worldMatrix.m05 + worldMatrix.m13; + content.u = vertex.u; + content.v = vertex.v; + content.color = color; } } + + _data.vertexCount = _vertexOffset; + _data.indiceCount = _indiceOffset; + + // Check for last data valid or not + if (_vertexOffset > 0 && _indiceOffset > 0) { + _datas.length = _dataId + 1; + } + else { + _datas.length = _dataId; + } }, - fillIndexBufferWithArmature (armature) { - let slots = armature._slots; - for (let i = 0, l = slots.length; i < l; i++) { - let slot = slots[i]; - if (!slot._visible || !slot._displayData) continue; + fillBuffers (comp, renderer) { - if (slot.childArmature) { - this.fillIndexBufferWithArmature(slot.childArmature); - continue; + let armature = comp._armature; + if (!armature) return; + + let renderDatas = comp._renderDatas; + let materialCache = comp._materialCache; + + for (let index = 0, length = renderDatas.length; index < length; index++) { + let data = renderDatas[index]; + + let key = data.material._hash; + let newKey = _updateKeyWithStencilRef(key, StencilManager.getStencilRef()); + if (key !== newKey) { + data.material = materialCache[newKey] || data.material.clone(); + data.material.updateHash(newKey); + if (!materialCache[newKey]) { + materialCache[newKey] = data.material; + } } - let indices = slot._indices; - for (let j = 0, il = indices.length; j < il; j++) { - _ibuf[_indiceOffset++] = _vertexId + indices[j]; + if (data.material !== renderer.material) { + renderer._flush(); + renderer.node = comp.node; + renderer.material = data.material; + } + + let vertexs = data.vertices; + let indices = data.indices; + + let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), + vertexOffset = buffer.byteOffset >> 2, + vertexCount = data.vertexCount; + + let indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + buffer.request(vertexCount, data.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + ibuf = buffer._iData, + uintbuf = buffer._uintVData; + + // fill vertex buffer + let vert; + for (let i = 0, l = data.dataLength; i < l; i++) { + vert = vertexs[i]; + vbuf[vertexOffset++] = vert.x; + vbuf[vertexOffset++] = vert.y; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = vert.color; + } + + // index buffer + for (let i = 0, l = indices.length; i < l; i ++) { + ibuf[indiceOffset++] = vertexId + indices[i]; } + } + + if (comp.debugBones && comp._debugDraw) { + + var graphics = comp._debugDraw; + graphics.clear(); + + graphics.lineWidth = 5; + graphics.strokeColor = _boneColor; + graphics.fillColor = _slotColor; // Root bone color is same as slot color. - _vertexId += slot._vertices.length; + let bones = armature.getBones(); + for (let i = 0, l = bones.length; i < l; i++) { + let bone = bones[i]; + let boneLength = Math.max(bone.boneData.length, 5); + let startX = bone.globalTransformMatrix.tx; + let startY = -bone.globalTransformMatrix.ty; + let endX = startX + bone.globalTransformMatrix.a * boneLength; + let endY = startY - bone.globalTransformMatrix.b * boneLength; + + graphics.moveTo(startX, startY); + graphics.lineTo(endX, endY); + graphics.stroke(); + } } + + comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; } }; diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index a50737be299..57b9c74ce63 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -314,7 +314,7 @@ sp.Skeleton = cc.Class({ notify () { this._initDebugDraw(); } - } + }, }, // CONSTRUCTOR @@ -324,11 +324,17 @@ sp.Skeleton = cc.Class({ this._listener = null; this._boundingBox = cc.rect(); this._material = new SpriteMaterial(); + this._materialCache = {}; this._renderDatas = []; - this._debugRenderer = null; }, + // override + _updateMaterial (material) { + this._super(material); + this._materialCache = {}; + }, + /** * !#en * Sets runtime skeleton data to sp.Skeleton.
@@ -382,6 +388,7 @@ sp.Skeleton = cc.Class({ update (dt) { if (CC_EDITOR) return; + if (this.paused) return; let skeleton = this._skeleton; let state = this._state; if (skeleton) { @@ -398,7 +405,8 @@ sp.Skeleton = cc.Class({ // Destroyed and restored in Editor if (!this._material) { this._boundingBox = cc.rect(); - this._material = new SpriteMaterial(); + this._material = new SpriteMaterial(); + this._materialCache = {}; this._renderDatas = []; } }, diff --git a/extensions/spine/index.js b/extensions/spine/index.js index b5936ddcef2..0d7cf499b9d 100644 --- a/extensions/spine/index.js +++ b/extensions/spine/index.js @@ -42,71 +42,84 @@ */ var _global = typeof window === 'undefined' ? global : window; -_global.sp = {}; +var _isUseSpine = true; -// The attachment type of spine. It contains three type: REGION(0), BOUNDING_BOX(1), MESH(2) and SKINNED_MESH. -sp.ATTACHMENT_TYPE = { - REGION: 0, - BOUNDING_BOX: 1, - MESH: 2, - SKINNED_MESH:3 -}; +if (CC_JSB && _global.spine === undefined) { + _isUseSpine = false; +} + +if (_isUseSpine) { + _global.sp = {}; + + // The attachment type of spine. It contains three type: REGION(0), BOUNDING_BOX(1), MESH(2) and SKINNED_MESH. + sp.ATTACHMENT_TYPE = { + REGION: 0, + BOUNDING_BOX: 1, + MESH: 2, + SKINNED_MESH:3 + }; -/** - * !#en The event type of spine skeleton animation. - * !#zh 骨骼动画事件类型。 - * @enum AnimationEventType - */ -sp.AnimationEventType = cc.Enum({ - /** - * !#en The play spine skeleton animation start type. - * !#zh 开始播放骨骼动画。 - * @property {Number} START - */ - START: 0, - /** - * !#en Another entry has replaced this entry as the current entry. This entry may continue being applied for mixing. - * !#zh 当前的 entry 被其他的 entry 替换。当使用 mixing 时,当前的 entry 会继续运行。 - */ - INTERRUPT: 1, - /** - * !#en The play spine skeleton animation finish type. - * !#zh 播放骨骼动画结束。 - * @property {Number} END - */ - END: 2, - /** - * !#en The entry will be disposed. - * !#zh entry 将被销毁。 - */ - DISPOSE: 3, /** - * !#en The play spine skeleton animation complete type. - * !#zh 播放骨骼动画完成。 - * @property {Number} COMPLETE + * !#en The event type of spine skeleton animation. + * !#zh 骨骼动画事件类型。 + * @enum AnimationEventType */ - COMPLETE: 4, + sp.AnimationEventType = cc.Enum({ + /** + * !#en The play spine skeleton animation start type. + * !#zh 开始播放骨骼动画。 + * @property {Number} START + */ + START: 0, + /** + * !#en Another entry has replaced this entry as the current entry. This entry may continue being applied for mixing. + * !#zh 当前的 entry 被其他的 entry 替换。当使用 mixing 时,当前的 entry 会继续运行。 + */ + INTERRUPT: 1, + /** + * !#en The play spine skeleton animation finish type. + * !#zh 播放骨骼动画结束。 + * @property {Number} END + */ + END: 2, + /** + * !#en The entry will be disposed. + * !#zh entry 将被销毁。 + */ + DISPOSE: 3, + /** + * !#en The play spine skeleton animation complete type. + * !#zh 播放骨骼动画完成。 + * @property {Number} COMPLETE + */ + COMPLETE: 4, + /** + * !#en The spine skeleton animation event type. + * !#zh 骨骼动画事件。 + * @property {Number} EVENT + */ + EVENT: 5 + }); + /** - * !#en The spine skeleton animation event type. - * !#zh 骨骼动画事件。 - * @property {Number} EVENT + * @module sp */ - EVENT: 5 -}); + if (!CC_EDITOR || !Editor.isMainProcess) { + + if (CC_JSB) { + sp.spine = _global.spine; + } else { + sp.spine = require('./lib/spine'); + } -/** - * @module sp - */ -if (!CC_EDITOR || !Editor.isMainProcess) { - - sp.spine = require('./lib/spine'); - require('./skeleton-texture'); - require('./skeleton-data'); - require('./Skeleton'); - require('./spine-assembler'); -} -else { - require('./skeleton-data'); + require('./skeleton-texture'); + require('./skeleton-data'); + require('./Skeleton'); + require('./spine-assembler'); + } + else { + require('./skeleton-data'); + } } /** diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 731389bb2bc..b1811c50d75 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -34,8 +34,6 @@ const SpriteMaterial = renderEngine.SpriteMaterial; const STENCIL_SEP = '@'; -let _sharedMaterials = {}; - let _slotColor = cc.color(0, 0, 255, 255); let _boneColor = cc.color(255, 0, 0, 255); let _originColor = cc.color(0, 255, 0, 255); @@ -49,7 +47,7 @@ function _updateKeyWithStencilRef (key, stencilRef) { return key.replace(/@\d+$/, STENCIL_SEP + stencilRef); } -function _getSlotMaterial (slot, tex, premultiAlpha) { +function _getSlotMaterial (comp, slot, tex, premultiAlpha) { let src, dst; switch (slot.data.blendMode) { case spine.BlendMode.Additive: @@ -72,9 +70,19 @@ function _getSlotMaterial (slot, tex, premultiAlpha) { } let key = tex.url + src + dst + STENCIL_SEP + '0'; - let material = _sharedMaterials[key]; + comp._material = comp._material || new SpriteMaterial(); + let baseMaterial = comp._material; + let materialCache = comp._materialCache; + let material = materialCache[key]; if (!material) { - material = new SpriteMaterial(); + + var baseKey = baseMaterial._hash; + if (!materialCache[baseKey]) { + material = baseMaterial; + } else { + material = baseMaterial.clone(); + } + material.useModel = true; // update texture material.texture = tex; @@ -88,7 +96,7 @@ function _getSlotMaterial (slot, tex, premultiAlpha) { gfx.BLEND_FUNC_ADD, src, dst ); - _sharedMaterials[key] = material; + materialCache[key] = material; material.updateHash(key); } else if (material.texture !== tex) { @@ -196,7 +204,7 @@ var spineAssembler = { } newData = false; - material = _getSlotMaterial(slot, attachment.region.texture._texture, premultiAlpha); + material = _getSlotMaterial(comp, slot, attachment.region.texture._texture, premultiAlpha); if (!material) { continue; } @@ -300,6 +308,7 @@ var spineAssembler = { fillBuffers (comp, renderer) { let renderDatas = comp._renderDatas; + let materialCache = comp._materialCache; for (let index = 0, length = renderDatas.length; index < length; index++) { let data = renderDatas[index]; @@ -308,10 +317,10 @@ var spineAssembler = { let key = data.material._hash; let newKey = _updateKeyWithStencilRef(key, StencilManager.getStencilRef()); if (key !== newKey) { - data.material = _sharedMaterials[newKey] || data.material.clone(); + data.material = materialCache[newKey] || data.material.clone(); data.material.updateHash(newKey); - if (!_sharedMaterials[newKey]) { - _sharedMaterials[newKey] = data.material; + if (!materialCache[newKey]) { + materialCache[newKey] = data.material; } } diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index d7449919ceb..ad72b7e7649 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -40,6 +40,12 @@ const Optimizejs = require('gulp-optimize-js'); var jsbSkipModules = [ // modules need to skip in jsb + '../../extensions/spine/lib/spine.js', + '../../extensions/dragonbones/lib/dragonBones.js', + '../../extensions/dragonbones/CCArmatureDisplay.js', + '../../extensions/dragonbones/CCFactory.js', + '../../extensions/dragonbones/CCSlot.js', + '../../extensions/dragonbones/CCTextureData.js' ]; var jsbAliasify = { replacements: { diff --git a/modules.json b/modules.json index 4b3669fbb00..112c57e31fa 100644 --- a/modules.json +++ b/modules.json @@ -28,8 +28,7 @@ { "name": "Canvas Renderer", "entries": [ - "./cocos2d/core/renderer/canvas/index.js", - "./extensions/dragonbones/canvas-assembler.js" + "./cocos2d/core/renderer/canvas/index.js" ] }, { From 139d22f733fd8674ceddf77e891d8d69364c5f0b Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Wed, 5 Dec 2018 17:37:58 +0800 Subject: [PATCH 0244/1631] remove dragonBones canvas-assembler from modules.js (#3597) --- modules.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules.json b/modules.json index 0b831ccf824..985824f30ae 100644 --- a/modules.json +++ b/modules.json @@ -28,8 +28,7 @@ { "name": "Canvas Renderer", "entries": [ - "./cocos2d/core/renderer/canvas/index.js", - "./extensions/dragonbones/canvas-assembler.js" + "./cocos2d/core/renderer/canvas/index.js" ] }, { From 03cd13bd4a1c5edee6d6ed3f71e43f64b8f65844 Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 6 Dec 2018 15:55:42 +0800 Subject: [PATCH 0245/1631] fix onBMFontTextureLoaded (#3598) --- cocos2d/core/components/CCLabel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 93a77b5f1c1..8326a8c26a7 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -528,7 +528,7 @@ let Label = cc.Class({ self._activateMaterial(force); if (force) { - this._assembler && this._assembler.updateRenderData(this); + self._assembler && self._assembler.updateRenderData(self); } }; // cannot be activated if texture not loaded yet From cecbc5c9e3f1bdc4db47fe59e5d8ee076cce70d2 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Thu, 6 Dec 2018 15:56:51 +0800 Subject: [PATCH 0246/1631] fixed issue that error is empty array and modified unit test example (#3590) --- cocos2d/core/load-pipeline/CCLoader.js | 2 +- cocos2d/core/load-pipeline/loading-items.js | 20 ++++++++++++-------- cocos2d/core/platform/js.js | 12 ++++++++++++ test/qunit/unit-es5/test-pipeline.js | 3 +-- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/cocos2d/core/load-pipeline/CCLoader.js b/cocos2d/core/load-pipeline/CCLoader.js index 85dbf6bcf21..f9818b7d157 100644 --- a/cocos2d/core/load-pipeline/CCLoader.js +++ b/cocos2d/core/load-pipeline/CCLoader.js @@ -268,7 +268,7 @@ proto.load = function(resources, progressCallback, completeCallback) { if (completeCallback) { if (singleRes) { let id = res.url; - completeCallback.call(self, items.getError(id), items.getContent(id)); + completeCallback.call(self, errors, items.getContent(id)); } else { completeCallback.call(self, errors, items); diff --git a/cocos2d/core/load-pipeline/loading-items.js b/cocos2d/core/load-pipeline/loading-items.js index e2a18516dd5..55fe847883a 100644 --- a/cocos2d/core/load-pipeline/loading-items.js +++ b/cocos2d/core/load-pipeline/loading-items.js @@ -167,7 +167,7 @@ var LoadingItems = function (pipeline, urlList, onProgress, onComplete) { this._pipeline = pipeline; - this._errorUrls = []; + this._errorUrls = js.createMap(true); this._appending = false; @@ -523,7 +523,7 @@ proto._childOnProgress = function (item) { * @method allComplete */ proto.allComplete = function () { - var errors = this._errorUrls.length === 0 ? null : this._errorUrls; + var errors = js.isEmptyObject(this._errorUrls) === true ? null : this._errorUrls; if (this.onComplete) { this.onComplete(errors, this); } @@ -690,12 +690,16 @@ proto.itemComplete = function (id) { } // Register or unregister errors - var errorListId = this._errorUrls.indexOf(id); - if (item.error && errorListId === -1) { - this._errorUrls.push(id); + + var errorListId = id in this._errorUrls; + if (item.error instanceof Error || js.isString(item.error)) { + this._errorUrls[id] = item.error; + } + else if (item.error) { + js.mixin(this._errorUrls, item.error); } - else if (!item.error && errorListId !== -1) { - this._errorUrls.splice(errorListId, 1); + else if (!item.error && errorListId) { + delete this._errorUrls[id] } this.completed[id] = item; @@ -727,7 +731,7 @@ proto.destroy = function () { this._appending = false; this._pipeline = null; this._ownerQueue = null; - this._errorUrls.length = 0; + js.clear(this._errorUrls); this.onProgress = null; this.onComplete = null; diff --git a/cocos2d/core/platform/js.js b/cocos2d/core/platform/js.js index 1eb448b5a62..88b08adbb9a 100644 --- a/cocos2d/core/platform/js.js +++ b/cocos2d/core/platform/js.js @@ -221,6 +221,18 @@ var js = { } }, + /** + * Checks whether obj is an empty object + * @method isEmptyObject + * @param {any} obj + */ + isEmptyObject: function (obj) { + for (var key in obj) { + return false; + } + return true; + }, + /** * Get property descriptor in object and all its ancestors * @method getPropertyDescriptor diff --git a/test/qunit/unit-es5/test-pipeline.js b/test/qunit/unit-es5/test-pipeline.js index cb7609af6b6..996c413f315 100644 --- a/test/qunit/unit-es5/test-pipeline.js +++ b/test/qunit/unit-es5/test-pipeline.js @@ -99,8 +99,7 @@ test('pipeline flow', function () { ]); var onComplete = new Callback(function (error, items) { - ok(error instanceof Array, 'should return error array in onComplete when error happened'); - strictEqual(error[0], 'res/role', 'should contains correct errored url in error array'); + strictEqual('res/role' in error, true, 'should contains correct errored url in error object'); ok(items.getError('res/role') !== null, 'should set error property in errored item.'); }).enable(); var onProgress = new Callback().enable(); From f27cd5b98c560d55266b8e1f1836647cd9c1ca88 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 6 Dec 2018 16:02:10 +0800 Subject: [PATCH 0247/1631] Fix screen adaptation is invalid to close EditorBox (#3603) --- .../core/components/editbox/CCEditBoxImpl.js | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index 624e402e419..b7cef1d3da1 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -245,10 +245,7 @@ let EditBoxImpl = cc.Class({ this._node = null; this.setDelegate(null); this.removeDom(); - if (this.__orientationChanged) { - window.removeEventListener('orientationchange', this.__orientationChanged); - this.__orientationChanged = null; - } + this.removeOrientationchangeEvent(); }, _onTouchBegan (touch) { @@ -261,8 +258,8 @@ let EditBoxImpl = cc.Class({ _beginEditing () { if (cc.sys.isMobile && !this._editing) { - // Pre adaptation - this._beginEditingOnMobile(); + // Pre adaptation add orientationchange event + this.addOrientationchangeEvent(); } if (this._edTxt) { @@ -436,13 +433,8 @@ _p.createInput = function() { // Called before editbox focus to register cc.view status _p._beginEditingOnMobile = function () { - let self = this; - if (!this.__orientationChanged) { - this.__orientationChanged = function () { - self._adjustEditBoxPosition(); - }; - window.addEventListener('orientationchange', this.__orientationChanged); - } + // add orientationchange event + this.addOrientationchangeEvent(); if (cc.view.isAutoFullScreenEnabled()) { this.__fullscreen = true; @@ -471,10 +463,8 @@ _p._endEditingOnMobile = function () { this.__rotateScreen = false; } - if (this.__orientationChanged) { - window.removeEventListener('orientationchange', this.__orientationChanged); - this.__orientationChanged = null; - } + // remove orientationchange event + this.removeOrientationchangeEvent(); if(this.__fullscreen) { cc.view.enableAutoFullScreen(true); @@ -654,4 +644,21 @@ _p.removeDom = function () { this._edTxt = null; }; +_p.addOrientationchangeEvent = function () { + let self = this; + if (!self.__orientationChanged) { + self.__orientationChanged = function () { + self._adjustEditBoxPosition(); + }; + } + window.addEventListener('orientationchange', self.__orientationChanged); +}; + +_p.removeOrientationchangeEvent = function () { + if (this.__orientationChanged) { + window.removeEventListener('orientationchange', this.__orientationChanged); + this.__orientationChanged = null; + } +}; + module.exports = EditBoxImpl; From 84fc262faea215ead9baa543fcab773884615e3e Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 6 Dec 2018 17:50:55 +0800 Subject: [PATCH 0248/1631] add calculate each frame of Canvas in the editor pos (#3605) * add calculate each frame of Canvas in the editor pos * refine code --- cocos2d/core/components/CCCanvas.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cocos2d/core/components/CCCanvas.js b/cocos2d/core/components/CCCanvas.js index c1f09de84e3..f637e365a68 100644 --- a/cocos2d/core/components/CCCanvas.js +++ b/cocos2d/core/components/CCCanvas.js @@ -142,6 +142,7 @@ var Canvas = cc.Class({ Canvas.instance = this; if (CC_EDITOR) { + cc.director.on(cc.Director.EVENT_AFTER_UPDATE, this.alignWithScreen, this); cc.engine.on('design-resolution-changed', this._thisOnResized); } else { @@ -176,6 +177,7 @@ var Canvas = cc.Class({ onDestroy: function () { if (CC_EDITOR) { + cc.director.off(cc.Director.EVENT_AFTER_UPDATE, this.alignWithScreen, this); cc.engine.off('design-resolution-changed', this._thisOnResized); } else { From 9fedb74aee3d21aaf7ea475a89b994f555bc95db Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 7 Dec 2018 11:00:06 +0800 Subject: [PATCH 0249/1631] should not enumerate _iN$t after instantiation --- cocos2d/core/platform/instantiate-jit.js | 10 +++++----- cocos2d/core/platform/instantiate.js | 5 +++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/platform/instantiate-jit.js b/cocos2d/core/platform/instantiate-jit.js index 06277f993b7..0afe1acabbd 100644 --- a/cocos2d/core/platform/instantiate-jit.js +++ b/cocos2d/core/platform/instantiate-jit.js @@ -220,7 +220,7 @@ function Parser (obj, parent) { '}else{', LOCAL_OBJ + '=R=new ' + this.getFuncModule(obj.constructor, true) + '();', '}'); - obj._iN$t = { globalVar: 'R' }; + js.value(obj, '_iN$t', { globalVar: 'R' }, true); this.objsToClear_iN$t.push(obj); this.enumerateObject(this.codeArray, obj); //} @@ -348,10 +348,10 @@ proto.instantiateArray = function (value) { var codeArray = [declaration]; // assign a _iN$t flag to indicate that this object has been parsed. - value._iN$t = { + js.value(value, '_iN$t', { globalVar: '', // the name of declared global variable used to access this object source: codeArray, // the source code array for this object - }; + }, true); this.objsToClear_iN$t.push(value); for (var i = 0; i < value.length; ++i) { @@ -487,12 +487,12 @@ proto.instantiateObj = function (obj) { var codeArray = [createCode]; // assign a _iN$t flag to indicate that this object has been parsed. - obj._iN$t = { + js.value(obj, '_iN$t', { globalVar: '', // the name of declared global variable used to access this object source: codeArray, // the source code array for this object //propName: '', // the propName this object defined in its source code, // // if defined, use LOCAL_OBJ.propName to access the obj, else just use o - }; + }, true); this.objsToClear_iN$t.push(obj); this.enumerateObject(codeArray, obj); diff --git a/cocos2d/core/platform/instantiate.js b/cocos2d/core/platform/instantiate.js index 5fbe719c262..9c4bdc95014 100644 --- a/cocos2d/core/platform/instantiate.js +++ b/cocos2d/core/platform/instantiate.js @@ -29,6 +29,7 @@ var CCValueType = require('../value-types/value-type'); var Destroyed = CCObject.Flags.Destroyed; var PersistentMask = CCObject.Flags.PersistentMask; var _isDomNode = require('./utils').isDomNode; +var js = require('./js'); /** * !#en Clones the object `original` and returns the clone, or instantiate a node from the Prefab. @@ -183,7 +184,7 @@ function enumerateCCClass (klass, obj, clone, parent) { function enumerateObject (obj, clone, parent) { // 目前使用“_iN$t”这个特殊字段来存实例化后的对象,这样做主要是为了防止循环引用 // 注意,为了避免循环引用,所有新创建的实例,必须在赋值前被设为源对象的_iN$t - obj._iN$t = clone; + js.value(obj, '_iN$t', clone, true); objsToClearTmpVar.push(obj); var klass = obj.constructor; if (cc.Class._isCCClass(klass)) { @@ -231,7 +232,7 @@ function instantiateObj (obj, parent) { if (Array.isArray(obj)) { var len = obj.length; clone = new Array(len); - obj._iN$t = clone; + js.value(obj, '_iN$t', clone, true); for (var i = 0; i < len; ++i) { var value = obj[i]; if (typeof value === 'object' && value) { From e0a7319c3f44ec57ae7e876270158c0d62532d00 Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 7 Dec 2018 14:42:00 +0800 Subject: [PATCH 0250/1631] adapt baidu_game openDataContext in engine (#3606) * adapt baidu_game openDataContext * add baidu platform --- cocos2d/core/components/SwanSubContextView.js | 137 ++++++++++++++++++ cocos2d/core/components/index.js | 3 +- cocos2d/core/platform/CCSys.js | 4 +- gulp/tasks/engine.js | 4 +- gulp/util/utils.js | 2 +- 5 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 cocos2d/core/components/SwanSubContextView.js diff --git a/cocos2d/core/components/SwanSubContextView.js b/cocos2d/core/components/SwanSubContextView.js new file mode 100644 index 00000000000..258ba829722 --- /dev/null +++ b/cocos2d/core/components/SwanSubContextView.js @@ -0,0 +1,137 @@ +/**************************************************************************** + Copyright (c) 2018 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 Component = require('./CCComponent'); + +let SwanSubContextView; + +const isBaiduGame = (cc.sys.platform === cc.sys.BAIDU_GAME); +if (!CC_EDITOR && !isBaiduGame) { + SwanSubContextView = cc.Class({ + name: 'cc.SwanSubContextView', + extends: Component, + }) +} +else { + /** + * !#en SwanSubContextView is a view component which controls open data context viewport in Wechat game platform.
+ * The component's node size decide the viewport of the sub context content in main context, + * the entire sub context texture will be scaled to the node's bounding box area.
+ * This component provides multiple important features:
+ * 1. Sub context could use its own resolution size and policy.
+ * 2. Sub context could be minized to smallest size it needed.
+ * 3. Resolution of sub context content could be increased.
+ * 4. User touch input is transformed to the correct viewport.
+ * 5. Texture update is handled by this component. User don't need to worry.
+ * One important thing to be noted, whenever the node's bounding box change, + * you need to manually reset the viewport of sub context using updateSubContextViewport. + * !#zh SwanSubContextView 可以用来控制百度小游戏平台开放数据域在主域中的视窗的位置。
+ * 这个组件的节点尺寸决定了开放数据域内容在主域中的尺寸,整个开放数据域会被缩放到节点的包围盒范围内。
+ * 在这个组件的控制下,用户可以更自由得控制开放数据域:
+ * 1. 子域中可以使用独立的设计分辨率和适配模式
+ * 2. 子域区域尺寸可以缩小到只容纳内容即可
+ * 3. 子域的分辨率也可以被放大,以便获得更清晰的显示效果
+ * 4. 用户输入坐标会被自动转换到正确的子域视窗中
+ * 5. 子域内容贴图的更新由组件负责,用户不需要处理
+ * 唯一需要注意的是,当子域节点的包围盒发生改变时,开发者需要使用 `updateSubContextViewport` 来手动更新子域视窗。 + * @class SwanSubContextView + * @extends Component + */ + SwanSubContextView = cc.Class({ + name: 'cc.SwanSubContextView', + extends: Component, + + editor: CC_EDITOR && { + menu: 'i18n:MAIN_MENU.component.others/SwanSubContextView', + help: 'i18n:COMPONENT.help_url.swan_subcontext_view' + }, + + ctor () { + this._sprite = null; + this._tex = new cc.Texture2D(); + this._context = null; + }, + + onLoad () { + // Setup subcontext canvas size + if (swan.getOpenDataContext) { + this._context = swan.getOpenDataContext(); + let sharedCanvas = this._context.canvas; + if (sharedCanvas) { + sharedCanvas.width = this.node.width; + sharedCanvas.height = this.node.height; + } + this._tex.setPremultiplyAlpha(true); + this._tex.initWithElement(sharedCanvas); + + this._sprite = this.node.getComponent(cc.Sprite); + if (!this._sprite) { + this._sprite = this.node.addComponent(cc.Sprite); + this._sprite.srcBlendFactor = cc.macro.BlendFactor.ONE; + } + this._sprite.spriteFrame = new cc.SpriteFrame(this._tex); + } + else { + this.enabled = false; + } + }, + + onEnable () { + this.updateSubContextViewport(); + }, + + update () { + if (!this._tex || !this._context) { + return; + } + this._tex.initWithElement(this._context.canvas); + this._sprite._activateMaterial(); + }, + + /** + * !#en Update the sub context viewport manually, it should be called whenever the node's bounding box changes. + * !#zh 更新开放数据域相对于主域的 viewport,这个函数应该在节点包围盒改变时手动调用。 + * @method updateSubContextViewport + */ + updateSubContextViewport () { + if (this._context) { + let box = this.node.getBoundingBoxToWorld(); + let sx = cc.view._scaleX; + let sy = cc.view._scaleY; + this._context.postMessage({ + fromEngine: true, + event: 'viewport', + x: box.x * sx + cc.view._viewportRect.x, + y: box.y * sy + cc.view._viewportRect.y, + width: box.width * sx, + height: box.height * sy + }); + } + } + }); + +} + +cc.SwanSubContextView = module.exports = SwanSubContextView; \ No newline at end of file diff --git a/cocos2d/core/components/index.js b/cocos2d/core/components/index.js index b84dbb53a25..5e3417b67f0 100644 --- a/cocos2d/core/components/index.js +++ b/cocos2d/core/components/index.js @@ -52,7 +52,8 @@ var components = [ require('./CCToggle'), require('./CCBlockInputEvents'), require('./CCMotionStreak'), - require('./WXSubContextView') + require('./WXSubContextView'), + require('./SwanSubContextView'), ]; module.exports = components; \ No newline at end of file diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 36c9e46c548..482a1402c3e 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -28,7 +28,7 @@ let settingPlatform; if (!CC_EDITOR) { settingPlatform = window._CCSettings ? _CCSettings.platform: undefined; } -const isBaiduGame = (settingPlatform === 'baidugame'); +const isBaiduGame = (settingPlatform === 'baidugame' || settingPlatform === 'baidugame-subcontext'); const isVivoGame = (settingPlatform === 'vivogame'); const isOppoGame = (settingPlatform === 'oppogame'); @@ -757,7 +757,7 @@ function initSys () { }; } else if (isBaiduGame) { - let env = device.getSystemInfo(); + let env = __device.getSystemInfo(); sys.platform = env.platform; sys.browserType = env.browserType; sys.isMobile = env.isMobile; diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index ad72b7e7649..0836bfccad1 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -71,7 +71,7 @@ exports.buildCocosJs = function (sourceFile, outputFile, excludes, opt_macroFlag var opts = { sourcemaps: createMap !== false }; - if (opt_macroFlags && opt_macroFlags.wechatgameSub) { + if (opt_macroFlags && (opt_macroFlags.wechatgameSub || opt_macroFlags.baidugameSub)) { opts.aliasifyConfig = canvasAliasify; } var outDir = Path.dirname(outputFile); @@ -116,7 +116,7 @@ exports.buildCocosJsMin = function (sourceFile, outputFile, excludes, opt_macroF var opts = { sourcemaps: createMap !== false }; - if (opt_macroFlags && opt_macroFlags.wechatgameSub) { + if (opt_macroFlags && (opt_macroFlags.wechatgameSub || opt_macroFlags.baidugameSub)) { opts.aliasifyConfig = canvasAliasify; } var outDir = Path.dirname(outputFile); diff --git a/gulp/util/utils.js b/gulp/util/utils.js index 14319a4ca97..ad6dcc7f403 100644 --- a/gulp/util/utils.js +++ b/gulp/util/utils.js @@ -1,6 +1,6 @@ const PLATFORM_MACROS = ['CC_EDITOR', 'CC_PREVIEW', 'CC_BUILD', 'CC_TEST']; -const FLAGS = ['jsb', 'runtime', 'wechatgame', 'wechatgameSub', 'qqplay', 'debug', 'nativeRenderer']; +const FLAGS = ['jsb', 'runtime', 'wechatgame', 'wechatgameSub','baidugame', 'baidugameSub', 'qqplay', 'debug', 'nativeRenderer']; // generate macros for uglify's global_defs // available platforms: 'editor' | 'preview' | 'build' | 'test' From e9f9d7ad3c0cb49e774142ce53c04faa9fddf728 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Sun, 9 Dec 2018 23:05:09 +0800 Subject: [PATCH 0251/1631] Fix batch rendering issues of BMFont. (#3607) --- .../webgl/assemblers/label/2d/bmfont.js | 4 +- .../webgl/assemblers/label/3d/bmfont.js | 4 +- .../core/renderer/webgl/assemblers/utils.js | 84 +++++++++++++++++++ 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js index feb9b891253..42229af46c5 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js @@ -25,7 +25,7 @@ const js = require('../../../../../platform/js'); const bmfontUtls = require('../../../../utils/label/bmfont'); -const fillVertices = require('../../utils').fillVertices; +const fillMeshVertices = require('../../utils').fillMeshVertices; module.exports = js.addon({ createData (comp) { @@ -34,7 +34,7 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let node = comp.node; - fillVertices(node, renderer._quadBuffer, comp._renderData, node._color._val); + fillMeshVertices(node, renderer._meshBuffer, comp._renderData, node._color._val); }, appendQuad (renderData, texture, rect, rotated, x, y, scale) { diff --git a/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js index 35264daf92b..92d6856f62c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js @@ -25,11 +25,11 @@ const js = require('../../../../../platform/js'); const assembler = require('../2d/bmfont'); -const fillVertices3D = require('../../utils').fillVertices3D; +const fillMeshVertices3D = require('../../utils').fillMeshVertices3D; module.exports = js.addon({ fillBuffers (comp, renderer) { let node = comp.node; - fillVertices3D(node, renderer._quadBuffer3D, comp._renderData, node._color._val); + fillMeshVertices3D(node, renderer._meshBuffer3D, comp._renderData, node._color._val); }, }, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/utils.js b/cocos2d/core/renderer/webgl/assemblers/utils.js index e882620d102..7426d6925c1 100644 --- a/cocos2d/core/renderer/webgl/assemblers/utils.js +++ b/cocos2d/core/renderer/webgl/assemblers/utils.js @@ -26,6 +26,46 @@ function fillVertices (node, buffer, renderData, color) { } } +function fillMeshVertices (node, buffer, renderData, color) { + let data = renderData._data, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData, + ibuf = buffer._iData; + + let matrix = node._worldMatrix; + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + tx = matrix.m12, ty = matrix.m13; + for (let i = 0; i < vertexCount; i++) { + let vert = data[i]; + vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; + vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } + + // fill indice data + for (let i = 0, count = vertexCount / 4; i < count; i++) + { + let start = vertexId + i * 4; + ibuf[indiceOffset++] = start; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 2; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 3; + ibuf[indiceOffset++] = start + 2; + } +} + function fillVertices3D (node, buffer, renderData, color) { let data = renderData._data, vertexOffset = buffer.byteOffset >> 2; @@ -52,6 +92,48 @@ function fillVertices3D (node, buffer, renderData, color) { } } +function fillMeshVertices3D (node, buffer, renderData, color) { + let data = renderData._data, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData, + ibuf = buffer._iData; + + let matrix = node._worldMatrix; + + for (let i = 0; i < vertexCount; i++) { + let vert = data[i]; + vec3.set(vec3_temp, vert.x, vert.y, 0); + vec3.transformMat4(vec3_temp, vec3_temp, matrix); + vbuf[vertexOffset++] = vec3_temp.x; + vbuf[vertexOffset++] = vec3_temp.y; + vbuf[vertexOffset++] = vec3_temp.z; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } + + // fill indice data + for (let i = 0, count = vertexCount / 4; i < count; i++) + { + let start = vertexId + i * 4; + ibuf[indiceOffset++] = start; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 2; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 3; + ibuf[indiceOffset++] = start + 2; + } +} + function fillVerticesWithoutCalc (node, buffer, renderData, color) { let data = renderData._data, vertexOffset = buffer.byteOffset >> 2; @@ -97,7 +179,9 @@ function fillVerticesWithoutCalc3D (node, buffer, renderData, color) { module.exports = { fillVertices: fillVertices, + fillMeshVertices: fillMeshVertices, fillVertices3D: fillVertices3D, + fillMeshVertices3D: fillMeshVertices3D, fillVerticesWithoutCalc: fillVerticesWithoutCalc, fillVerticesWithoutCalc3D: fillVerticesWithoutCalc3D }; From c30df27a8728296a94c49bb08f9edff6dd0cf238 Mon Sep 17 00:00:00 2001 From: Knox Date: Sun, 9 Dec 2018 23:08:54 +0800 Subject: [PATCH 0252/1631] Fix emoji wrap failed on label for engine/issues/3589 (#3595) --- cocos2d/core/utils/text-utils.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/utils/text-utils.js b/cocos2d/core/utils/text-utils.js index 0ea9cd7c90b..eca99c198b7 100644 --- a/cocos2d/core/utils/text-utils.js +++ b/cocos2d/core/utils/text-utils.js @@ -30,13 +30,16 @@ var textUtils = { label_lastWordRex : /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôûаíìÍÌïÁÀáàÉÈÒÓòóŐőÙÚŰúűñÑæÆœŒÃÂãÔõěščřžýáíéóúůťďňĚŠČŘŽÁÍÉÓÚŤżźśóńłę湯ŹŚÓŃŁĘĆĄ-яА-ЯЁё]+|\S)$/, label_lastEnglish : /[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôûаíìÍÌïÁÀáàÉÈÒÓòóŐőÙÚŰúűñÑæÆœŒÃÂãÔõěščřžýáíéóúůťďňĚŠČŘŽÁÍÉÓÚŤżźśóńłę湯ŹŚÓŃŁĘĆĄ-яА-ЯЁё]+$/, label_firstEnglish : /^[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôûаíìÍÌïÁÀáàÉÈÒÓòóŐőÙÚŰúűñÑæÆœŒÃÂãÔõěščřžýáíéóúůťďňĚŠČŘŽÁÍÉÓÚŤżźśóńłę湯ŹŚÓŃŁĘĆĄ-яА-ЯЁё]/, + label_firstEmoji : /^[\uD83C\uDF00-\uDFFF\uDC00-\uDE4F]/, + label_lastEmoji : /([\uDF00-\uDFFF\uDC00-\uDE4F]+|\S)$/, label_wrapinspection : true, + __CHINESE_REG: /^[\u4E00-\u9FFF\u3400-\u4DFF]+$/, + __JAPANESE_REG: /[\u3000-\u303F]|[\u3040-\u309F]|[\u30A0-\u30FF]|[\uFF00-\uFFEF]|[\u4E00-\u9FAF]|[\u2605-\u2606]|[\u2190-\u2195]|\u203B/g, + __KOREAN_REG: /^[\u1100-\u11FF]|[\u3130-\u318F]|[\uA960-\uA97F]|[\uAC00-\uD7AF]|[\uD7B0-\uD7FF]+$/, + isUnicodeCJK: function(ch) { - var __CHINESE_REG = /^[\u4E00-\u9FFF\u3400-\u4DFF]+$/; - var __JAPANESE_REG = /[\u3000-\u303F]|[\u3040-\u309F]|[\u30A0-\u30FF]|[\uFF00-\uFFEF]|[\u4E00-\u9FAF]|[\u2605-\u2606]|[\u2190-\u2195]|\u203B/g; - var __KOREAN_REG = /^[\u1100-\u11FF]|[\u3130-\u318F]|[\uA960-\uA97F]|[\uAC00-\uD7AF]|[\uD7B0-\uD7FF]+$/; - return __CHINESE_REG.test(ch) || __JAPANESE_REG.test(ch) || __KOREAN_REG.test(ch); + return this.__CHINESE_REG.test(ch) || this.__JAPANESE_REG.test(ch) || this.__KOREAN_REG.test(ch); }, //Checking whether the character is a whitespace @@ -114,6 +117,17 @@ var textUtils = { } } + // To judge whether a Emoji words are truncated + // todo Some Emoji are not well adapted, such as 🚗 and 🇨🇳 + if (this.label_firstEmoji.test(sLine)) { + result = this.label_lastEmoji.exec(sText); + if (result && sText !== result[0]) { + fuzzyLen -= result[0].length; + sLine = text.substr(fuzzyLen); + sText = text.substr(0, fuzzyLen); + } + } + //To judge whether a English words are truncated if (this.label_firstEnglish.test(sLine)) { result = this.label_lastEnglish.exec(sText); From 10170a5c88f8f4d9f08f2028bf9b32c55ca4237c Mon Sep 17 00:00:00 2001 From: pandamicro Date: Mon, 10 Dec 2018 10:47:40 +0800 Subject: [PATCH 0253/1631] Support deserialize TypedArray --- cocos2d/core/platform/deserialize.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/platform/deserialize.js b/cocos2d/core/platform/deserialize.js index a3f90a403b1..bdee1b78712 100644 --- a/cocos2d/core/platform/deserialize.js +++ b/cocos2d/core/platform/deserialize.js @@ -219,7 +219,15 @@ var _Deserializer = (function () { var obj = null; // the obj to return var klass = null; var type = serialized.__type__; - if (type) { + if (type === 'TypedArray') { + var array = serialized.array; + obj = new window[serialized.ctor](array.length); + for (var i = 0; i < array.length; ++i) { + obj[i] = array[i]; + } + return obj; + } + else if (type) { // Type Object (including CCClass) From b738c0739e80b064e9a830f7ea6af69d0920d179 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Mon, 10 Dec 2018 10:48:19 +0800 Subject: [PATCH 0254/1631] Use TRS array to store data in Node --- cocos2d/core/3d/polyfill-3d.js | 48 +++-- cocos2d/core/CCNode.js | 274 ++++++++++++++---------- cocos2d/core/CCPrivateNode.js | 4 +- cocos2d/core/base-ui/CCWidgetManager.js | 19 +- cocos2d/core/renderer/render-flow.js | 6 +- cocos2d/core/utils/prefab-helper.js | 16 +- cocos2d/core/value-types/index.js | 41 +++- cocos2d/core/value-types/quat.js | 14 ++ cocos2d/core/value-types/vec2.js | 20 ++ cocos2d/core/value-types/vec3.js | 24 +++ cocos2d/particle/particle-simulator.js | 4 +- 11 files changed, 309 insertions(+), 161 deletions(-) diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index ffe00a49362..52abd1d368f 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -37,11 +37,13 @@ const POSITION_ON = 1 << 0; const SCALE_ON = 1 << 1; const ROTATION_ON = 1 << 2; +let _quat = cc.quat(); + function _updateLocalMatrix3d () { if (this._localMatDirty) { // Update transform let t = this._matrix; - math.mat4.fromRTS(t, this._quat, this._position, this._scale); + math.mat4.fromTRSArray(t, this._trs); // skew if (this._skewX || this._skewY) { @@ -92,18 +94,18 @@ function setPosition (newPosOrX, y, z) { z = z || 0 } - let pos = this._position; - if (pos.x === x && pos.y === y && pos.z === z) { + let trs = this._trs; + if (trs[1] === x && trs[2] === y && trs[3] === z) { return; } if (CC_EDITOR) { - var oldPosition = new cc.Vec3(pos); + var oldPosition = new cc.Vec3(trs[1], trs[2], trs[3]); } - pos.x = x; - pos.y = y; - pos.z = z; + trs[1] = x; + trs[2] = y; + trs[3] = z; this.setLocalDirty(DirtyFlag.POSITION); this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; @@ -131,10 +133,11 @@ function setScale (x, y, z) { else if (z === undefined) { z = 1; } - if (this._scale.x !== x || this._scale.y !== y || this._scale.z !== z) { - this._scale.x = x; - this._scale.y = y; - this._scale.z = z; + let trs = this._trs; + if (trs[8] !== x || trs[9] !== y || trs[10] !== z) { + trs[8] = x; + trs[9] = y; + trs[10] = z; this.setLocalDirty(DirtyFlag.SCALE); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -191,10 +194,10 @@ cc.js.getset(proto, 'is3DNode', function () { }); cc.js.getset(proto, 'scaleZ', function () { - return this._scale.z; + return this._trs[10]; }, function (v) { - if (this._scale.z !== value) { - this._scale.z = value; + if (this._trs[10] !== value) { + this._trs[10] = value; this.setLocalDirty(DirtyFlag.SCALE); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -205,12 +208,12 @@ cc.js.getset(proto, 'scaleZ', function () { }); cc.js.getset(proto, 'z', function () { - return this._position.z; + return this._trs[3]; }, function (value) { - let localPosition = this._position; - if (value !== localPosition.z) { + let trs = this._trs; + if (value !== trs[3]) { if (!CC_EDITOR || isFinite(value)) { - localPosition.z = value; + trs[3] = value; this.setLocalDirty(DirtyFlag.POSITION); this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; // fast check event @@ -229,14 +232,16 @@ cc.js.getset(proto, 'eulerAngles', function () { return this._eulerAngles; } else { - return this._quat.getEulerAngles(cc.v3()); + _quat.fromRotation(this._trs); + return _quat.getEulerAngles(cc.v3()); } }, function (v) { if (CC_EDITOR) { this._eulerAngles.set(v); } - math.quat.fromEuler(this._quat, v.x, v.y, v.z); + math.quat.fromEuler(_quat, v.x, v.y, v.z); + _quat.toRotation(this._trs); this.setLocalDirty(DirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; }); @@ -244,5 +249,6 @@ cc.js.getset(proto, 'eulerAngles', function () { // This property is used for Mesh Skeleton Animation // Should be rememoved when node.rotation upgrade to quaternion value cc.js.getset(proto, 'quat', function () { - return this._quat; + let trs = this._trs; + return cc.quat(trs[4], trs[5], trs[6], trs[7]); }, proto.setRotation); diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 26f72236f48..9048bc4bf65 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -45,8 +45,10 @@ const ONE_DEGREE = Math.PI / 180; var ActionManagerExist = !!cc.ActionManager; var emptyFunc = function () {}; -var _vec2a = cc.v2(); -var _vec2b = cc.v2(); +var _v3a = cc.v3(); +var _v3b = cc.v3(); +var _quata = cc.quat(); +var _quatb = cc.quat(); var _mat4_temp = math.mat4.create(); var _vec3_temp = math.vec3.create(); var _quat_temp = math.quat.create(); @@ -109,7 +111,7 @@ var LocalDirtyFlag = cc.Enum({ * @property {Number} RT * @static */ - RT: 1 << 0 | 1 << 1 | 1 << 2, + TRS: 1 << 0 | 1 << 1 | 1 << 2, /** * !#en Flag for all dirty properties * !#zh 覆盖所有 dirty 状态的标记位 @@ -540,9 +542,10 @@ let NodeDefines = { _color: cc.Color.WHITE, _contentSize: cc.Size, _anchorPoint: cc.v2(0.5, 0.5), - _position: cc.Vec3, - _scale: cc.Vec3, - _quat: cc.Quat, + _position: undefined, + _scale: undefined, + _quat: undefined, + _trs: null, _skewX: 0.0, _skewY: 0.0, _localZOrder: { @@ -613,17 +616,18 @@ let NodeDefines = { */ x: { get () { - return this._position.x; + return this._trs[1]; }, set (value) { - var localPosition = this._position; - if (value !== localPosition.x) { + let trs = this._trs; + if (value !== trs[1]) { if (!CC_EDITOR || isFinite(value)) { + let oldValue; if (CC_EDITOR) { - var oldValue = localPosition.x; + oldValue = trs[1]; } - localPosition.x = value; + trs[1] = value; this.setLocalDirty(LocalDirtyFlag.POSITION); this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; @@ -631,7 +635,7 @@ let NodeDefines = { if (this._eventMask & POSITION_ON) { // send event if (CC_EDITOR) { - this.emit(EventType.POSITION_CHANGED, new cc.Vec3(oldValue, localPosition.y, localPosition.z)); + this.emit(EventType.POSITION_CHANGED, new cc.Vec3(oldValue, trs[2], trs[3])); } else { this.emit(EventType.POSITION_CHANGED); @@ -656,17 +660,18 @@ let NodeDefines = { */ y: { get () { - return this._position.y; + return this._trs[2]; }, set (value) { - var localPosition = this._position; - if (value !== localPosition.y) { + let trs = this._trs; + if (value !== trs[2]) { if (!CC_EDITOR || isFinite(value)) { + let oldValue; if (CC_EDITOR) { - var oldValue = localPosition.y; + oldValue = trs[2]; } - localPosition.y = value; + trs[2] = value; this.setLocalDirty(LocalDirtyFlag.POSITION); this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; @@ -674,7 +679,7 @@ let NodeDefines = { if (this._eventMask & POSITION_ON) { // send event if (CC_EDITOR) { - this.emit(EventType.POSITION_CHANGED, new cc.Vec3(localPosition.x, oldValue, localPosition.z)); + this.emit(EventType.POSITION_CHANGED, new cc.Vec3(trs[1], oldValue, trs[3])); } else { this.emit(EventType.POSITION_CHANGED); @@ -728,7 +733,8 @@ let NodeDefines = { }, set (value) { this._eulerAngles.z = value; - math.quat.fromEuler(this._quat, 0, 0, value); + math.quat.fromEuler(_quata, 0, 0, value); + _quata.toRotation(this._trs); this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -764,11 +770,12 @@ let NodeDefines = { this._eulerAngles.x = value; // Update quaternion from rotation if (this._eulerAngles.x === this._eulerAngles.y) { - math.quat.fromEuler(this._quat, 0, 0, -value); + math.quat.fromEuler(_quat, 0, 0, -value); } else { - math.quat.fromEuler(this._quat, value, this._eulerAngles.y, 0); + math.quat.fromEuler(_quat, value, this._eulerAngles.y, 0); } + _quata.toRotation(this._trs); this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -798,11 +805,12 @@ let NodeDefines = { this._eulerAngles.y = value; // Update quaternion from rotation if (this._eulerAngles.x === this._eulerAngles.y) { - math.quat.fromEuler(this._quat, 0, 0, -value); + math.quat.fromEuler(_quat, 0, 0, -value); } else { - math.quat.fromEuler(this._quat, this._eulerAngles.x, value, 0); + math.quat.fromEuler(_quat, this._eulerAngles.x, value, 0); } + _quata.toRotation(this._trs); this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -823,7 +831,7 @@ let NodeDefines = { */ scale: { get () { - return this._scale.x; + return this._trs[8]; }, set (v) { this.setScale(v); @@ -841,11 +849,11 @@ let NodeDefines = { */ scaleX: { get () { - return this._scale.x; + return this._trs[8]; }, set (value) { - if (this._scale.x !== value) { - this._scale.x = value; + if (this._trs[8] !== value) { + this._trs[8] = value; this.setLocalDirty(LocalDirtyFlag.SCALE); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -867,11 +875,11 @@ let NodeDefines = { */ scaleY: { get () { - return this._scale.y; + return this._trs[9]; }, set (value) { - if (this._scale.y !== value) { - this._scale.y = value; + if (this._trs[9] !== value) { + this._trs[9] = value; this.setLocalDirty(LocalDirtyFlag.SCALE); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -1154,10 +1162,13 @@ let NodeDefines = { // Mouse event listener this._mouseListener = null; - // default scale - this._scale.x = 1; - this._scale.y = 1; - this._scale.z = 1; + // Transform / Rotation / Scale data slots, with local dirty flags at 0 + let trs = this._trs = new Float32Array(11); + trs[3] = 0; + trs[7] = 1; + trs[8] = 1; + trs[9] = 1; + trs[10] = 1; this._matrix = mathPools.mat4.get(); this._worldMatrix = mathPools.mat4.get(); @@ -1296,37 +1307,40 @@ let NodeDefines = { // INTERNAL _upgrade_1x_to_2x () { - // Upgrade scaleX, scaleY from v1.x + let trs = this._trs; + + // Upgrade _position from v2 // TODO: remove in future version, 3.0 ? - if (this._scaleX !== undefined) { - this._scale.x = this._scaleX; - this._scaleX = undefined; + if (this._position !== undefined) { + trs[1] = this._position.x; + trs[2] = this._position.y; + trs[3] = this._position.z; + this._position = undefined; } - if (this._scaleY !== undefined) { - this._scale.y = this._scaleY; - this._scaleY = undefined; + + // TODO: remove _quat in future version, 3.0 ? + let quat = this._quat; + if (quat !== undefined) { + trs[4] = quat.x; + trs[5] = quat.y; + trs[6] = quat.z; + trs[7] = quat.w; + this._quat = undefined; } + _quata.fromRotation(trs).toEuler(this._eulerAngles); - if (this._localZOrder !== 0) { - this._zIndex = (this._localZOrder & 0xffff0000) >> 16; + // Upgrade _scale from v2 + // TODO: remove in future version, 3.0 ? + if (this._scale !== undefined) { + trs[8] = this._scale.x; + trs[9] = this._scale.y; + trs[10] = this._scale.z; + this._scale = undefined; } - // TODO: remove _rotationX & _rotationY in future version, 3.0 ? - // Update quaternion from rotation, when upgrade from 1.x to 2.0 - // If rotation x & y is 0 in old version, then update rotation from default quaternion is ok too - let quat = this._quat; - if ((this._rotationX || this._rotationY) && - (quat.x === 0 && quat.y === 0 && quat.z === 0 && quat.w === 1)) { - if (this._rotationX === this._rotationY) { - math.quat.fromEuler(quat, 0, 0, -this._rotationX); - } - else { - math.quat.fromEuler(quat, this._rotationX, this._rotationY, 0); - } - this._rotationX = this._rotationY = undefined; + if (this._localZOrder !== 0) { + this._zIndex = (this._localZOrder & 0xffff0000) >> 16; } - - this._quat.toEuler(this._eulerAngles); // Upgrade from 2.0.0 preview 4 & earlier versions // TODO: Remove after final version @@ -1373,6 +1387,7 @@ let NodeDefines = { if (CC_JSB && CC_NATIVERENDERER) { this._proxy.setName(this._name); this._parent && this._proxy.updateParent(this._parent._proxy); + this._proxy.updateJSOwner(this); } }, @@ -1402,6 +1417,7 @@ let NodeDefines = { if (CC_JSB && CC_NATIVERENDERER) { this._proxy.setName(this._name); this._parent && this._proxy.updateParent(this._parent._proxy); + this._proxy.updateJSOwner(this); } }, @@ -1836,8 +1852,8 @@ let NodeDefines = { _hitTest (point, listener) { let w = this._contentSize.width, h = this._contentSize.height, - cameraPt = _vec2a, - testPt = _vec2b; + cameraPt = _v3a, + testPt = _v3b; let camera = cc.Camera.findCamera(this); if (camera) { @@ -2075,7 +2091,7 @@ let NodeDefines = { */ getPosition (out) { out = out || cc.v3(); - return out.set(this._position); + return out.fromTranslation(this._trs); }, /** @@ -2107,22 +2123,22 @@ let NodeDefines = { x = newPosOrX; } - var locPosition = this._position; - if (locPosition.x === x && locPosition.y === y) { + var trs = this._trs; + if (trs[1] === x && trs[2] === y) { return; } if (CC_EDITOR) { - var oldPosition = new cc.Vec3(locPosition); + var oldPosition = new cc.Vec3(trs[1], trs[2], trs[3]); } if (!CC_EDITOR || isFinite(x)) { - locPosition.x = x; + trs[1] = x; } else { return cc.error(ERR_INVALID_NUMBER, 'x of new position'); } if (!CC_EDITOR || isFinite(y)) { - locPosition.y = y; + trs[2] = y; } else { return cc.error(ERR_INVALID_NUMBER, 'y of new position'); @@ -2155,11 +2171,11 @@ let NodeDefines = { */ getScale (out) { if (out !== undefined) { - return out.set(this._scale); + return out.fromScale(this._trs); } else { cc.warnID(1400, 'cc.Node.getScale', 'cc.Node.scale or cc.Node.getScale(cc.Vec3)'); - return this._scale.x; + return this._trs[8]; } }, @@ -2187,9 +2203,10 @@ let NodeDefines = { else if (y === undefined) { y = x; } - if (this._scale.x !== x || this._scale.y !== y) { - this._scale.x = x; - this._scale.y = y; + let trs = this._trs; + if (trs[8] !== x || trs[9] !== y) { + trs[8] = x; + trs[9] = y; this.setLocalDirty(LocalDirtyFlag.SCALE); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -2211,7 +2228,7 @@ let NodeDefines = { */ getRotation (out) { if (out instanceof cc.Quat) { - return out.set(this._quat); + return out.fromRotation(this._trs); } else { cc.warnID(1400, 'cc.Node.getRotation', 'cc.Node.angle or cc.Node.getRotation(cc.Quat)'); @@ -2242,12 +2259,12 @@ let NodeDefines = { w = quat.w; } - let old = this._quat; - if (old.x !== x || old.y !== y || old.z !== z || old.w !== w) { - old.x = x; - old.y = y; - old.z = z; - old.w = w; + let trs = this._trs; + if (trs[4] !== x || trs[5] !== y || trs[6] !== z || trs[7] !== w) { + trs[4] = x; + trs[5] = y; + trs[6] = z; + trs[7] = w; this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -2256,7 +2273,8 @@ let NodeDefines = { } if (CC_EDITOR) { - old.toEuler(this._eulerAngles); + _quata.fromRotation(trs); + _quata.toEuler(this._eulerAngles); } } } @@ -2398,15 +2416,19 @@ let NodeDefines = { math.vec3.copy(out, pos); } + let trs = this._trs; // out = parent_inv_pos - pos - math.vec3.sub(out, out, this._position); + _v3a.fromTranslation(trs); + math.vec3.sub(out, out, _v3a); // out = inv(rot) * out - math.quat.conjugate(_quat_temp, this._quat); + _quata.fromRotation(trs); + math.quat.conjugate(_quat_temp, _quata); math.vec3.transformQuat(out, out, _quat_temp); // out = (1/scale) * out - math.vec3.inverseSafe(_vec3_temp, this._scale); + _v3a.fromScale(this._trs); + math.vec3.inverseSafe(_vec3_temp, _v3a); math.vec3.mul(out, out, _vec3_temp); return out; @@ -2420,15 +2442,20 @@ let NodeDefines = { * @return {Vec3} */ getWorldPosition (out) { - math.vec3.copy(out, this._position); + out.fromTranslation(this._trs); let curr = this._parent; + let trs; while (curr) { + trs = curr._trs; // out = parent_scale * pos - math.vec3.mul(out, out, curr._scale); + _v3a.fromScale(trs); + math.vec3.mul(out, out, _v3a); // out = parent_quat * out - math.vec3.transformQuat(out, out, curr._quat); + _quata.fromRotation(trs); + math.vec3.transformQuat(out, out, _quata); // out = out + pos - math.vec3.add(out, out, curr._position); + _v3a.fromTranslation(trs); + math.vec3.add(out, out, _v3a); curr = curr._parent; } return out; @@ -2441,16 +2468,18 @@ let NodeDefines = { * @param {Vec3} pos */ setWorldPosition (pos) { + let trs = this._trs; if (CC_EDITOR) { - var oldPosition = new cc.Vec3(this._position); + var oldPosition = new cc.Vec3(trs[1], trs[2], trs[3]); } // NOTE: this is faster than invert world matrix and transform the point if (this._parent) { - this._parent._invTransformPoint(this._position, pos); + this._parent._invTransformPoint(_v3a, pos); } else { - math.vec3.copy(this._position, pos); + math.vec3.copy(_v3a, pos); } + _v3a.toTranslation(trs); this.setLocalDirty(LocalDirtyFlag.POSITION); // fast check event @@ -2473,10 +2502,12 @@ let NodeDefines = { * @return {Quat} */ getWorldRotation (out) { - math.quat.copy(out, this._quat); + _quata.fromRotation(this._trs); + math.quat.copy(out, _quata); let curr = this._parent; while (curr) { - math.quat.mul(out, curr._quat, out); + _quata.fromRotation(curr._trs); + math.quat.mul(out, _quata, out); curr = curr._parent; } return out; @@ -2490,14 +2521,15 @@ let NodeDefines = { */ setWorldRotation (quat) { if (this._parent) { - this._parent.getWorldRotation(this._quat); - math.quat.conjugate(this._quat, this._quat); - math.quat.mul(this._quat, this._quat, quat); + this._parent.getWorldRotation(_quata); + math.quat.conjugate(_quata, _quata); + math.quat.mul(_quata, _quata, quat); } else { - math.quat.copy(this._quat, quat); + math.quat.copy(_quata, quat); } - this._quat.toEuler(this._eulerAngles); + _quata.toEuler(this._eulerAngles); + _quata.toRotation(this._trs); this.setLocalDirty(LocalDirtyFlag.ROTATION); }, @@ -2509,10 +2541,12 @@ let NodeDefines = { * @return {Vec3} */ getWorldScale (out) { - math.vec3.copy(out, this._scale); + _v3a.fromScale(this._trs); + math.vec3.copy(out, _v3a); let curr = this._parent; while (curr) { - math.vec3.mul(out, out, curr._scale); + _v3a.fromScale(curr._trs); + math.vec3.mul(out, out, _v3a); curr = curr._parent; } return out; @@ -2526,31 +2560,37 @@ let NodeDefines = { */ setWorldScale (scale) { if (this._parent) { - this._parent.getWorldScale(this._scale); - math.vec3.div(this._scale, scale, this._scale); + this._parent.getWorldScale(_v3a); + math.vec3.div(_v3a, scale, _v3a); } else { - math.vec3.copy(this._scale, scale); + math.vec3.copy(_v3a, scale); } + _v3a.toScale(this._trs); this.setLocalDirty(LocalDirtyFlag.SCALE); }, getWorldRT (out) { - let opos = _vec3_temp; - let orot = _quat_temp; - math.vec3.copy(opos, this._position); - math.quat.copy(orot, this._quat); + let opos = _v3a; + let orot = _quata; + let trs = this._trs; + opos.fromTranslation(trs); + orot.fromRotation(trs); let curr = this._parent; while (curr) { + trs = curr._trs; // opos = parent_lscale * lpos - math.vec3.mul(opos, opos, curr._scale); + _v3b.fromScale(trs); + math.vec3.mul(opos, opos, _v3b); // opos = parent_lrot * opos - math.vec3.transformQuat(opos, opos, curr._quat); + _quatb.fromRotation(trs); + math.vec3.transformQuat(opos, opos, _quatb); // opos = opos + lpos - math.vec3.add(opos, opos, curr._position); + _v3b.fromTranslation(trs); + math.vec3.add(opos, opos, _v3b); // orot = lrot * orot - math.quat.mul(orot, curr._quat, orot); + math.quat.mul(orot, _quatb, orot); curr = curr._parent; } math.mat4.fromRT(out, orot, opos); @@ -2579,12 +2619,12 @@ let NodeDefines = { // Update transform let t = this._matrix; - //math.mat4.fromRTS(t, this._quat, this._position, this._scale); + let trs = this._trs; - if (dirtyFlag & (LocalDirtyFlag.RT | LocalDirtyFlag.SKEW)) { + if (dirtyFlag & (LocalDirtyFlag.TRS | LocalDirtyFlag.SKEW)) { let rotation = -this._eulerAngles.z; let hasSkew = this._skewX || this._skewY; - let sx = this._scale.x, sy = this._scale.y; + let sx = trs[8], sy = trs[9]; if (rotation || hasSkew) { let a = 1, b = 0, c = 0, d = 1; @@ -2625,8 +2665,8 @@ let NodeDefines = { } // position - t.m12 = this._position.x; - t.m13 = this._position.y; + t.m12 = trs[1]; + t.m13 = trs[2]; this._localMatDirty = 0; // Register dirty status of world matrix so that it can be recalculated @@ -2686,7 +2726,7 @@ let NodeDefines = { }, setLocalDirty (flag) { - this._localMatDirty = this._localMatDirty | flag; + this._localMatDirty |= flag; this._worldMatDirty = true; }, @@ -3166,10 +3206,12 @@ let NodeDefines = { this._worldMatrix = mathPools.mat4.get(); } + let trs = this._trs; this._localMatDirty = LocalDirtyFlag.ALL; this._worldMatDirty = true; - this._quat.toEuler(this._eulerAngles); + _quata.fromRotation(trs); + _quata.toEuler(this._eulerAngles); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._renderComponent) { diff --git a/cocos2d/core/CCPrivateNode.js b/cocos2d/core/CCPrivateNode.js index bcdbecbcdab..db9705c1b8b 100644 --- a/cocos2d/core/CCPrivateNode.js +++ b/cocos2d/core/CCPrivateNode.js @@ -128,8 +128,8 @@ let PrivateNode = cc.Class({ let parent = this.parent; if (parent) { // Position correction for transform calculation - this._position.x = this._originPos.x - (parent._anchorPoint.x - 0.5) * parent._contentSize.width; - this._position.y = this._originPos.y - (parent._anchorPoint.y - 0.5) * parent._contentSize.height; + this._trs[1] = this._originPos.x - (parent._anchorPoint.x - 0.5) * parent._contentSize.width; + this._trs[2] = this._originPos.y - (parent._anchorPoint.y - 0.5) * parent._contentSize.height; } this._super(); diff --git a/cocos2d/core/base-ui/CCWidgetManager.js b/cocos2d/core/base-ui/CCWidgetManager.js index 537b97dacc9..2c2a0a49d57 100644 --- a/cocos2d/core/base-ui/CCWidgetManager.js +++ b/cocos2d/core/base-ui/CCWidgetManager.js @@ -52,14 +52,13 @@ function getReadonlyNodeSize (parent) { } function computeInverseTransForTarget (widgetNode, target, out_inverseTranslate, out_inverseScale) { - var scaleX = widgetNode._parent._scale.x; - var scaleY = widgetNode._parent._scale.y; + var scaleX = widgetNode._parent.scaleX; + var scaleY = widgetNode._parent.scaleY; var translateX = 0; var translateY = 0; for (var node = widgetNode._parent;;) { - var pos = node._position; - translateX += pos.x; - translateY += pos.y; + translateX += node.x; + translateY += node.y; node = node._parent; // loop increment if (!node) { // ERROR: widgetNode should be child of target @@ -68,8 +67,8 @@ function computeInverseTransForTarget (widgetNode, target, out_inverseTranslate, return; } if (node !== target) { - var sx = node._scale.x; - var sy = node._scale.y; + var sx = node.scaleX; + var sy = node.scaleY; translateX *= sx; translateY *= sy; scaleX *= sx; @@ -106,7 +105,7 @@ function align (node, widget) { var targetAnchor = target._anchorPoint; var isRoot = !CC_EDITOR && target instanceof cc.Scene; - var x = node._position.x, y = node._position.y; + var x = node.x, y = node.y; var anchor = node._anchorPoint; if (widget._alignFlags & HORIZONTAL) { @@ -132,7 +131,7 @@ function align (node, widget) { localRight *= inverseScale.x; } - var width, anchorX = anchor.x, scaleX = node._scale.x; + var width, anchorX = anchor.x, scaleX = node.scaleX; if (scaleX < 0) { anchorX = 1.0 - anchorX; scaleX = -scaleX; @@ -189,7 +188,7 @@ function align (node, widget) { localTop *= inverseScale.y; } - var height, anchorY = anchor.y, scaleY = node._scale.y; + var height, anchorY = anchor.y, scaleY = node.scaleY; if (scaleY < 0) { anchorY = 1.0 - anchorY; scaleY = -scaleY; diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index a9d47f21e37..ae6a3fbaa0a 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -35,9 +35,9 @@ _proto._worldTransform = function (node) { _batcher.worldMatDirty ++; let t = node._matrix; - let position = node._position; - t.m12 = position.x; - t.m13 = position.y; + let trs = node._trs; + t.m12 = trs[1]; + t.m13 = trs[2]; node._mulMat(node._worldMatrix, node._parent._worldMatrix, t); node._renderFlag &= ~WORLD_TRANSFORM; diff --git a/cocos2d/core/utils/prefab-helper.js b/cocos2d/core/utils/prefab-helper.js index 075e2e23365..a0dc898ea09 100644 --- a/cocos2d/core/utils/prefab-helper.js +++ b/cocos2d/core/utils/prefab-helper.js @@ -91,11 +91,12 @@ module.exports = { var _id = node._id; var _name = node._name; var _active = node._active; - var x = node._position.x; - var y = node._position.y; - var _quat = node._quat; var _localZOrder = node._localZOrder; var _globalZOrder = node._globalZOrder; + var trs = node._trs; + var x = trs[1]; + var y = trs[2]; + var qx = trs[4], qy = trs[5], qz = trs[6], qw = trs[7]; // instantiate prefab cc.game._isCloning = true; @@ -122,10 +123,13 @@ module.exports = { node._prefab = _prefab; node._name = _name; node._active = _active; - node._position.x = x; - node._position.y = y; - math.quat.copy(node._quat, _quat); node._localZOrder = _localZOrder; node._globalZOrder = _globalZOrder; + trs[1] = x; + trs[2] = y; + trs[4] = qx; + trs[5] = qy; + trs[6] = qz; + trs[7] = qw; } }; diff --git a/cocos2d/core/value-types/index.js b/cocos2d/core/value-types/index.js index 59bc6c739be..76211eac0e7 100644 --- a/cocos2d/core/value-types/index.js +++ b/cocos2d/core/value-types/index.js @@ -33,4 +33,43 @@ require('./size'); require('./rect'); require('./color'); -cc.vmath = require('../renderer/render-engine').math; +let math = cc.vmath = require('../renderer/render-engine').math; + +math.mat4.fromTRSArray = function (out, trs) { + var x = trs[4], y = trs[5], z = trs[6], w = trs[7]; + var x2 = x + x; + var y2 = y + y; + var z2 = z + z; + + var xx = x * x2; + var xy = x * y2; + var xz = x * z2; + var yy = y * y2; + var yz = y * z2; + var zz = z * z2; + var wx = w * x2; + var wy = w * y2; + var wz = w * z2; + var sx = trs[8]; + var sy = trs[9]; + var sz = trs[10]; + + out.m00 = (1 - (yy + zz)) * sx; + out.m01 = (xy + wz) * sx; + out.m02 = (xz - wy) * sx; + out.m03 = 0; + out.m04 = (xy - wz) * sy; + out.m05 = (1 - (xx + zz)) * sy; + out.m06 = (yz + wx) * sy; + out.m07 = 0; + out.m08 = (xz + wy) * sz; + out.m09 = (yz - wx) * sz; + out.m10 = (1 - (xx + yy)) * sz; + out.m11 = 0; + out.m12 = trs[1]; + out.m13 = trs[2]; + out.m14 = trs[3]; + out.m15 = 1; + + return out; +} \ No newline at end of file diff --git a/cocos2d/core/value-types/quat.js b/cocos2d/core/value-types/quat.js index aeeca3b04d2..235050df1ab 100644 --- a/cocos2d/core/value-types/quat.js +++ b/cocos2d/core/value-types/quat.js @@ -115,6 +115,20 @@ proto.equals = function (other) { return other && this.x === other.x && this.y === other.y && this.z === other.z && this.w === other.w; }; +proto.fromRotation = function (trs) { + this.x = trs[4]; + this.y = trs[5]; + this.z = trs[6]; + this.w = trs[7]; + return this; +}; +proto.toRotation = function (trs) { + trs[4] = this.x; + trs[5] = this.y; + trs[6] = this.z; + trs[7] = this.w; +}; + /** * !#en Convert quaternion to euler * !#zh 转换四元数到欧拉角 diff --git a/cocos2d/core/value-types/vec2.js b/cocos2d/core/value-types/vec2.js index 8ba14000d14..5cdb9ce84ee 100644 --- a/cocos2d/core/value-types/vec2.js +++ b/cocos2d/core/value-types/vec2.js @@ -592,6 +592,26 @@ proto.transformMat4 = function (m, out) { math.vec2.transformMat4(out, this, m); }; +proto.fromTranslation = function (trs) { + this.x = trs[1]; + this.y = trs[2]; + return this; +}; +proto.toTranslation = function (trs) { + trs[1] = this.x; + trs[2] = this.y; +}; + +proto.fromScale = function (trs) { + this.x = trs[8]; + this.y = trs[9]; + return this; +}; +proto.toScale = function (trs) { + trs[8] = this.x; + trs[9] = this.y; +}; + //_serialize: function () { // return [this.x, this.y]; //}, diff --git a/cocos2d/core/value-types/vec3.js b/cocos2d/core/value-types/vec3.js index 4bbf3e7694e..d5eae689081 100644 --- a/cocos2d/core/value-types/vec3.js +++ b/cocos2d/core/value-types/vec3.js @@ -455,6 +455,30 @@ proto.transformMat4 = function (m, out) { math.vec3.transformMat4(out, this, m); }; +proto.fromTranslation = function (trs) { + this.x = trs[1]; + this.y = trs[2]; + this.z = trs[3]; + return this; +}; +proto.toTranslation = function (trs) { + trs[1] = this.x; + trs[2] = this.y; + trs[3] = this.z; +}; + +proto.fromScale = function (trs) { + this.x = trs[8]; + this.y = trs[9]; + this.z = trs[10]; + return this; +}; +proto.toScale = function (trs) { + trs[8] = this.x; + trs[9] = this.y; + trs[10] = this.z; +}; + /** * !#en The convenience method to create a new {{#crossLink "Vec3"}}cc.Vec3{{/crossLink}}. * !#zh 通过该简便的函数进行创建 {{#crossLink "Vec3"}}cc.Vec3{{/crossLink}} 对象。 diff --git a/cocos2d/particle/particle-simulator.js b/cocos2d/particle/particle-simulator.js index bc11bf39041..fc31d50d3a5 100644 --- a/cocos2d/particle/particle-simulator.js +++ b/cocos2d/particle/particle-simulator.js @@ -272,8 +272,8 @@ Simulator.prototype.step = function (dt) { if (psys.positionType === cc.ParticleSystem.PositionType.FREE) { AffineTrans.transformVec2(_pos, ZERO_VEC2, _trans); } else if (psys.positionType === cc.ParticleSystem.PositionType.RELATIVE) { - _pos.x = node._position.x; - _pos.y = node._position.y; + _pos.x = node.x; + _pos.y = node.y; } // Get world to node trans only once From b770edfcb89b923e998fb02052ac4314975321e1 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Mon, 10 Dec 2018 16:32:53 +0800 Subject: [PATCH 0255/1631] Improve renderFlag & trs flag setting --- cocos2d/core/CCNode.js | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 9048bc4bf65..2432fe10383 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -629,7 +629,6 @@ let NodeDefines = { trs[1] = value; this.setLocalDirty(LocalDirtyFlag.POSITION); - this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; // fast check event if (this._eventMask & POSITION_ON) { @@ -673,7 +672,6 @@ let NodeDefines = { trs[2] = value; this.setLocalDirty(LocalDirtyFlag.POSITION); - this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; // fast check event if (this._eventMask & POSITION_ON) { @@ -736,7 +734,6 @@ let NodeDefines = { math.quat.fromEuler(_quata, 0, 0, value); _quata.toRotation(this._trs); this.setLocalDirty(LocalDirtyFlag.ROTATION); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._eventMask & ROTATION_ON) { this.emit(EventType.ROTATION_CHANGED); @@ -777,7 +774,6 @@ let NodeDefines = { } _quata.toRotation(this._trs); this.setLocalDirty(LocalDirtyFlag.ROTATION); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._eventMask & ROTATION_ON) { this.emit(EventType.ROTATION_CHANGED); @@ -812,7 +808,6 @@ let NodeDefines = { } _quata.toRotation(this._trs); this.setLocalDirty(LocalDirtyFlag.ROTATION); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._eventMask & ROTATION_ON) { this.emit(EventType.ROTATION_CHANGED); @@ -855,7 +850,6 @@ let NodeDefines = { if (this._trs[8] !== value) { this._trs[8] = value; this.setLocalDirty(LocalDirtyFlag.SCALE); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._eventMask & SCALE_ON) { this.emit(EventType.SCALE_CHANGED); @@ -881,7 +875,6 @@ let NodeDefines = { if (this._trs[9] !== value) { this._trs[9] = value; this.setLocalDirty(LocalDirtyFlag.SCALE); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._eventMask & SCALE_ON) { this.emit(EventType.SCALE_CHANGED); @@ -913,7 +906,6 @@ let NodeDefines = { set (value) { this._skewX = value; this.setLocalDirty(LocalDirtyFlag.SKEW); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; } }, @@ -933,7 +925,6 @@ let NodeDefines = { set (value) { this._skewY = value; this.setLocalDirty(LocalDirtyFlag.SKEW); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; } }, @@ -1164,6 +1155,7 @@ let NodeDefines = { // Transform / Rotation / Scale data slots, with local dirty flags at 0 let trs = this._trs = new Float32Array(11); + trs[0] = RenderFlow.FLAG_TRANSFORM; trs[3] = 0; trs[7] = 1; trs[8] = 1; @@ -1266,6 +1258,7 @@ let NodeDefines = { var actionManager = ActionManagerExist ? cc.director.getActionManager() : null; if (active) { // Refresh transform + this._trs[0] |= RenderFlow.FLAG_WORLD_TRANSFORM; this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; // ActionManager & EventManager actionManager && actionManager.resumeTarget(this); @@ -1292,6 +1285,7 @@ let NodeDefines = { if (this._parent) { this._parent._delaySort(); } + this._trs[0] |= RenderFlow.FLAG_WORLD_TRANSFORM; this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; this._onHierarchyChangedBase(oldParent); if (cc._widgetManager) { @@ -1337,6 +1331,7 @@ let NodeDefines = { trs[10] = this._scale.z; this._scale = undefined; } + trs[0] |= RenderFlow.FLAG_TRANSFORM; if (this._localZOrder !== 0) { this._zIndex = (this._localZOrder & 0xffff0000) >> 16; @@ -1387,7 +1382,7 @@ let NodeDefines = { if (CC_JSB && CC_NATIVERENDERER) { this._proxy.setName(this._name); this._parent && this._proxy.updateParent(this._parent._proxy); - this._proxy.updateJSOwner(this); + this._proxy.updateJSTRS(this._trs); } }, @@ -1417,7 +1412,7 @@ let NodeDefines = { if (CC_JSB && CC_NATIVERENDERER) { this._proxy.setName(this._name); this._parent && this._proxy.updateParent(this._parent._proxy); - this._proxy.updateJSOwner(this); + this._proxy.updateJSTRS(this._trs); } }, @@ -2144,7 +2139,6 @@ let NodeDefines = { return cc.error(ERR_INVALID_NUMBER, 'y of new position'); } this.setLocalDirty(LocalDirtyFlag.POSITION); - this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; // fast check event if (this._eventMask & POSITION_ON) { @@ -2208,7 +2202,6 @@ let NodeDefines = { trs[8] = x; trs[9] = y; this.setLocalDirty(LocalDirtyFlag.SCALE); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._eventMask & SCALE_ON) { this.emit(EventType.SCALE_CHANGED); @@ -2266,7 +2259,6 @@ let NodeDefines = { trs[6] = z; trs[7] = w; this.setLocalDirty(LocalDirtyFlag.ROTATION); - this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._eventMask & ROTATION_ON) { this.emit(EventType.ROTATION_CHANGED); @@ -2728,6 +2720,18 @@ let NodeDefines = { setLocalDirty (flag) { this._localMatDirty |= flag; this._worldMatDirty = true; + + if (CC_JSB) { + this._trs[0] |= RenderFlow.FLAG_TRANSFORM; + } + else { + if (flag === LocalDirtyFlag.POSITION) { + this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; + } + else { + this._renderFlag |= RenderFlow.FLAG_TRANSFORM; + } + } }, setWorldDirty () { @@ -3206,10 +3210,10 @@ let NodeDefines = { this._worldMatrix = mathPools.mat4.get(); } - let trs = this._trs; this._localMatDirty = LocalDirtyFlag.ALL; this._worldMatDirty = true; + let trs = this._trs; _quata.fromRotation(trs); _quata.toEuler(this._eulerAngles); From ea65cdf0244f088fa0288cef57156566229c32e0 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 11 Dec 2018 10:44:58 +0800 Subject: [PATCH 0256/1631] improve requestFullScreen function (#3615) --- cocos2d/core/platform/CCScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCScreen.js b/cocos2d/core/platform/CCScreen.js index 2247e57238e..b919f494e50 100644 --- a/cocos2d/core/platform/CCScreen.js +++ b/cocos2d/core/platform/CCScreen.js @@ -116,7 +116,7 @@ cc.screen = /** @lends cc.screen# */{ * @param {Function} onFullScreenChange */ requestFullScreen: function (element, onFullScreenChange) { - if (element.tagName.toLowerCase() === "video") { + if (element && element.tagName.toLowerCase() === "video") { if (cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && element.readyState > 0) { element.webkitEnterFullscreen && element.webkitEnterFullscreen(); return; From 1a6bafeb3fdcf93b1550cdbe0a8e593ab066c10c Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 11 Dec 2018 11:54:07 +0800 Subject: [PATCH 0257/1631] fixed game creator.t.ds decorator (#3473) (#3617) --- cocos2d/core/CCGame.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index e43fd181fb7..5ea17a98f8e 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -39,7 +39,6 @@ const dynamicAtlasManager = require('../core/renderer/utils/dynamic-atlas/manage * !#en An object to boot the game. * !#zh 包含游戏主体信息并负责驱动游戏的游戏对象。 * @class Game - * @static * @extends EventTarget */ var game = { From 69e0deb4500a4a1d1437f6b7e30149c566da32c9 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Tue, 11 Dec 2018 16:24:13 +0800 Subject: [PATCH 0258/1631] add comments for predefine.js (#3619) --- predefine.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/predefine.js b/predefine.js index dd0c9cdb484..83a151fcd90 100644 --- a/predefine.js +++ b/predefine.js @@ -117,6 +117,10 @@ // window may be undefined when first load engine from editor var _global = typeof window === 'undefined' ? global : window; + +/* + * @param defaultValue - The default value is only used in the editor or preview. + */ function defineMacro (name, defaultValue) { // if "global_defs" not preprocessed by uglify, just declare them globally, // this may happened in release version's preview page. @@ -128,6 +132,8 @@ function defined (name) { return typeof _global[name] === 'object'; } +// These default values only used in the editor or preview. +// If you need to modify in the runtime, please modify the `global_defs` in the option returned by `gulp/util/utils.js: getUglifyOptions`. defineMacro('CC_TEST', defined('tap') || defined('QUnit')); defineMacro('CC_EDITOR', defined('Editor') && defined('process') && ('electron' in process.versions)); defineMacro('CC_PREVIEW', !CC_EDITOR); From b2d6cdfb7a0cbcc3486b94cd98467e9e5c8a470e Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 11 Dec 2018 16:30:27 +0800 Subject: [PATCH 0259/1631] =?UTF-8?q?fix=20toggle=20event=20bug=20for=20to?= =?UTF-8?q?ggleGroup=20active=20false=20and=20update=20enabledI=E2=80=A6?= =?UTF-8?q?=20(#3620)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix toggle event bug for toggleGroup active false and update enabledInHierarchy code * refine code --- cocos2d/core/components/CCComponent.js | 2 +- cocos2d/core/components/CCToggle.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/components/CCComponent.js b/cocos2d/core/components/CCComponent.js index 3cdbf6a62d6..2496ecb5593 100644 --- a/cocos2d/core/components/CCComponent.js +++ b/cocos2d/core/components/CCComponent.js @@ -190,7 +190,7 @@ var Component = cc.Class({ */ enabledInHierarchy: { get () { - return (this._objFlags & IsOnEnableCalled) > 0; + return this._enabled && this.node._activeInHierarchy; }, visible: false }, diff --git a/cocos2d/core/components/CCToggle.js b/cocos2d/core/components/CCToggle.js index 4a808b84ed5..81b2209561f 100644 --- a/cocos2d/core/components/CCToggle.js +++ b/cocos2d/core/components/CCToggle.js @@ -127,7 +127,7 @@ let Toggle = cc.Class({ if (!CC_EDITOR) { this._registerToggleEvent(); } - if (this.toggleGroup && this.toggleGroup.enabled) { + if (this.toggleGroup && this.toggleGroup.enabledInHierarchy) { this.toggleGroup.addToggle(this); } }, @@ -137,7 +137,7 @@ let Toggle = cc.Class({ if (!CC_EDITOR) { this._unregisterToggleEvent(); } - if (this.toggleGroup && this.toggleGroup.enabled) { + if (this.toggleGroup && this.toggleGroup.enabledInHierarchy) { this.toggleGroup.removeToggle(this); } }, From dde072d778d6cd50af9389c3b7aecfd54a151fad Mon Sep 17 00:00:00 2001 From: mac <1053210246@qq.com> Date: Tue, 11 Dec 2018 19:41:25 +0800 Subject: [PATCH 0260/1631] particle system optimize --- cocos2d/particle/CCParticleSystem.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index ddc4eea09bb..3e839ae7e38 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -706,13 +706,17 @@ var ParticleSystem = cc.Class({ }, ctor () { + this.initProperties(); + }, + + initProperties () { + this._simulator = new ParticleSimulator(this); + this._previewTimer = null; this._focused = false; this._texture = null; this._renderData = null; - this._simulator = new ParticleSimulator(this); - // colors this._startColor = cc.color(255, 255, 255, 255); this._startColorVar = cc.color(0, 0, 0, 0); @@ -814,7 +818,7 @@ var ParticleSystem = cc.Class({ }, onLoad () { - if (!this._ia) { + if (!CC_JSB && !this._ia) { ParticleSystem._assembler.createIA(this); } }, From c517a8314c6b390eca4bfddbe73aa872b8bd1fff Mon Sep 17 00:00:00 2001 From: mac <1053210246@qq.com> Date: Tue, 11 Dec 2018 21:12:47 +0800 Subject: [PATCH 0261/1631] remove cc_jsb judge --- cocos2d/particle/CCParticleSystem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 3e839ae7e38..9719e8ea34a 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -818,7 +818,7 @@ var ParticleSystem = cc.Class({ }, onLoad () { - if (!CC_JSB && !this._ia) { + if (!this._ia) { ParticleSystem._assembler.createIA(this); } }, From 36de6791e579a87c3fa3e2d341cc6369a938b917 Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 11 Dec 2018 21:20:43 +0800 Subject: [PATCH 0262/1631] fix wechatGame subDomain (#3621) --- cocos2d/core/platform/CCSys.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 482a1402c3e..82be38a4de9 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -684,7 +684,7 @@ function initSys () { sys.osVersion = version ? version[0] : system; sys.osMainVersion = parseInt(sys.osVersion); // wechagame subdomain - if (!wx.getFileSystemManager) { + if (CC_WECHATGAME_SUB) { sys.browserType = sys.BROWSER_TYPE_WECHAT_GAME_SUB; } else { From 0c7d282b7c552ec1da2065d5c152fa7c6fe74219 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Wed, 12 Dec 2018 18:08:22 +0800 Subject: [PATCH 0263/1631] Fixed dragonbones not supporting multiple textures (#3623) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix dragonbones use diff texture,only show one shield spine and dragonbones blend * modify blend annotation --- cocos2d/core/components/CCRenderComponent.js | 2 +- extensions/dragonbones/ArmatureDisplay.js | 44 +++++++++++++++++++- extensions/dragonbones/CCFactory.js | 4 +- extensions/spine/Skeleton.js | 39 +++++++++++++++++ 4 files changed, 84 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 5f054168258..6106a3b59d2 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -54,7 +54,7 @@ let RenderComponent = cc.Class({ /** * !#en specify the source Blend Factor, this will generate a custom material object, please pay attention to the memory cost. - * !#zh 指定原图的混合模式,这会克隆一个新的材质对象,注意这带来的 + * !#zh 指定原图的混合模式,这会克隆一个新的材质对象,注意这带来的开销 * @property srcBlendFactor * @type {macro.BlendFactor} * @example diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 00f9b4b41b0..25ad040563e 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -31,6 +31,7 @@ let EventTarget = require('../../cocos2d/core/event/event-target'); const Node = require('../../cocos2d/core/CCNode'); const Graphics = require('../../cocos2d/core/graphics/graphics'); +const BlendFactor = require('../../cocos2d/core/platform/CCMacro').BlendFactor; /** * @module dragonBones @@ -70,7 +71,7 @@ let ArmatureDisplay = cc.Class({ editor: CC_EDITOR && { menu: 'i18n:MAIN_MENU.component.renderers/DragonBones', - //help: 'app://docs/html/components/spine.html', // TODO help document of dragonBones + //help: 'app://docs/html/components/dragonbones.html', // TODO help document of dragonBones }, properties: { @@ -80,6 +81,44 @@ let ArmatureDisplay = cc.Class({ serializable: false, }, + /** + * !#en don't try to get or set srcBlendFactor,it doesn't affect,if you want to change dragonbones blend mode,please set it in dragonbones editor directly. + * !#zh 不要试图去获取或者设置 srcBlendFactor,没有意义,如果你想设置 dragonbones 的 blendMode,直接在 dragonbones 编辑器中设置即可。 + * @property srcBlendFactor + * @type {macro.BlendFactor} + */ + srcBlendFactor: { + get: function() { + return this._srcBlendFactor; + }, + set: function(value) { + // shield set _srcBlendFactor + }, + animatable: false, + type:BlendFactor, + override: true, + visible: false + }, + + /** + * !#en don't try to get or set dstBlendFactor,it doesn't affect,if you want to change dragonbones blend mode,please set it in dragonbones editor directly. + * !#zh 不要试图去获取或者设置 dstBlendFactor,没有意义,如果想设置 dragonbones 的 blendMode,直接在 dragonbones 编辑器中设置即可。 + * @property dstBlendFactor + * @type {macro.BlendFactor} + */ + dstBlendFactor: { + get: function() { + return this._dstBlendFactor; + }, + set: function(value) { + // shield set _dstBlendFactor + }, + animatable: false, + type: BlendFactor, + override: true, + visible: false + }, + /** * !#en * The DragonBones data contains the armatures information (bind pose bones, slots, draw order, @@ -396,7 +435,8 @@ let ArmatureDisplay = cc.Class({ _buildArmature () { if (!this.dragonAsset || !this.dragonAtlasAsset || !this.armatureName) return; - var displayProxy = this._factory.buildArmatureDisplay(this.armatureName, this.dragonAsset._dragonBonesData.name, this); + var atlasName = this.dragonAtlasAsset._textureAtlasData.name; + var displayProxy = this._factory.buildArmatureDisplay(this.armatureName, this.dragonAsset._dragonBonesData.name, "", atlasName); if (!displayProxy) return; this._displayProxy = displayProxy; diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index 919cf7701c5..687da520443 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -99,8 +99,8 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ }, // Build new aramture with a new display. - buildArmatureDisplay (armatureName, dragonBonesName) { - let armature = this.buildArmature(armatureName, dragonBonesName); + buildArmatureDisplay (armatureName, dragonBonesName, skinName, textureAtlasName) { + let armature = this.buildArmature(armatureName, dragonBonesName, skinName, textureAtlasName); return armature && armature._display; }, diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 57b9c74ce63..2a2869041f4 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -29,6 +29,7 @@ const RenderComponent = require('../../cocos2d/core/components/CCRenderComponent const spine = require('./lib/spine'); const SpriteMaterial = require('../../cocos2d/core/renderer/render-engine').SpriteMaterial; const Graphics = require('../../cocos2d/core/graphics/graphics'); +const BlendFactor = require('../../cocos2d/core/platform/CCMacro').BlendFactor; /** * @module sp @@ -83,6 +84,44 @@ sp.Skeleton = cc.Class({ visible: false }, + /** + * !#en don't try to get or set srcBlendFactor,it doesn't affect,if you want to change spine blend mode,please set it in spine editor directly. + * !#zh 不要试图去获取或者设置 srcBlendFactor,没有意义,如果你想设置 spine 的 blendMode,直接在 spine 编辑器中设置即可。 + * @property srcBlendFactor + * @type {macro.BlendFactor} + */ + srcBlendFactor: { + get: function() { + return this._srcBlendFactor; + }, + set: function(value) { + // shield set _srcBlendFactor + }, + animatable: false, + type:BlendFactor, + override: true, + visible: false + }, + + /** + * !#en don't try to get or set dstBlendFactor,it doesn't affect,if you want to change spine blend mode,please set it in spine editor directly. + * !#zh 不要试图去获取或者设置 dstBlendFactor,没有意义,如果想设置 spine 的 blendMode,直接在 spine 编辑器中设置即可。 + * @property dstBlendFactor + * @type {macro.BlendFactor} + */ + dstBlendFactor: { + get: function() { + return this._dstBlendFactor; + }, + set: function(value) { + // shield set _dstBlendFactor + }, + animatable: false, + type: BlendFactor, + override: true, + visible: false + }, + /** * !#en * The skeleton data contains the skeleton information (bind pose bones, slots, draw order, From f001a9c27aaa6e1159965452285230f53e74f16c Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 14 Dec 2018 11:01:24 +0800 Subject: [PATCH 0264/1631] improve update font family code (#3630) --- cocos2d/core/renderer/utils/label/ttf.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index bfe352bcc5b..0c2e97b16eb 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -118,7 +118,7 @@ module.exports = { updateRenderData (comp) { if (!comp._renderData.vertDirty) return; - this._updateFontFamly(comp); + this._updateFontFamily(comp); this._updateProperties(comp); this._calculateLabelFont(); this._calculateSplitedStrings(); @@ -141,18 +141,21 @@ module.exports = { _updateVerts () { }, - _updateFontFamly (comp) { + _updateFontFamily (comp) { if (!comp.useSystemFont) { if (comp.font) { if (comp.font._nativeAsset) { _fontFamily = comp.font._nativeAsset; } else { - cc.loader.load(comp.font.nativeUrl, function (err, fontFamily) { - _fontFamily = fontFamily || 'Arial'; - comp.font._nativeAsset = fontFamily; - comp._updateRenderData(true); - }); + _fontFamily = cc.loader.getRes(comp.font.nativeUrl); + if (!_fontFamily) { + cc.loader.load(comp.font.nativeUrl, function (err, fontFamily) { + _fontFamily = fontFamily || 'Arial'; + comp.font._nativeAsset = fontFamily; + comp._updateRenderData(true); + }); + } } } else { From 01dba36d2a312f397e87bc1985322fb3cbc29f3e Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 14 Dec 2018 11:51:03 +0800 Subject: [PATCH 0265/1631] fix setMusicVolume as 0 (#3625) --- cocos2d/audio/CCAudioEngine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/audio/CCAudioEngine.js b/cocos2d/audio/CCAudioEngine.js index 40cf85031f1..df432a0f6be 100644 --- a/cocos2d/audio/CCAudioEngine.js +++ b/cocos2d/audio/CCAudioEngine.js @@ -91,7 +91,7 @@ let getAudioFromId = function (id) { }; let handleVolume = function (volume) { - if (!volume) { + if (volume === undefined) { // set default volume as 1 volume = 1; } From 0ec3ba44cf07997b0b05167aa24d873f331071b3 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 14 Dec 2018 18:52:10 +0800 Subject: [PATCH 0266/1631] fix when the width/height is zero, calculate anchor Infinity in layout (#3631) * fix when the width/height is zero, calculate anchor Infinity in layout * refine code --- cocos2d/core/components/CCLayout.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/CCLayout.js b/cocos2d/core/components/CCLayout.js index 4f10bd2af8b..f0fd50710d4 100644 --- a/cocos2d/core/components/CCLayout.js +++ b/cocos2d/core/components/CCLayout.js @@ -803,11 +803,14 @@ var Layout = cc.Class({ parseFloat((rightTopInParentSpace.y - leftBottomInParentSpace.y).toFixed(2))); var layoutPosition = this.node.getPosition(); - var newAnchorX = (layoutPosition.x - leftBottomInParentSpace.x) / newSize.width; - var newAnchorY = (layoutPosition.y - leftBottomInParentSpace.y) / newSize.height; - var newAnchor = cc.v2(parseFloat(newAnchorX.toFixed(2)), parseFloat(newAnchorY.toFixed(2))); - - this.node.setAnchorPoint(newAnchor); + if (newSize.width !== 0) { + var newAnchorX = (layoutPosition.x - leftBottomInParentSpace.x) / newSize.width; + this.node.anchorX = parseFloat(newAnchorX.toFixed(2)); + } + if (newSize.height !== 0) { + var newAnchorY = (layoutPosition.y - leftBottomInParentSpace.y) / newSize.height; + this.node.anchorY = parseFloat(newAnchorY.toFixed(2)); + } this.node.setContentSize(newSize); } }, From 6286ce58f8d92618917e7eecb2a4ce742a14fc5f Mon Sep 17 00:00:00 2001 From: caryliu Date: Sun, 16 Dec 2018 23:17:00 +0800 Subject: [PATCH 0267/1631] Add native-renderer graphics. --- cocos2d/core/graphics/graphics.js | 7 +++++++ cocos2d/core/renderer/webgl/assemblers/graphics/earcut.js | 2 +- cocos2d/core/renderer/webgl/assemblers/graphics/impl.js | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/graphics/graphics.js b/cocos2d/core/graphics/graphics.js index ef596a8e14c..06ba85bbe31 100644 --- a/cocos2d/core/graphics/graphics.js +++ b/cocos2d/core/graphics/graphics.js @@ -186,6 +186,11 @@ let Graphics = cc.Class({ this._impl = null; }, + initNativeHandle () { + this._renderHandle = new renderer.GraphicsRenderHandle(); + this._renderHandle.bind(this); + }, + _activateMaterial () { // Ignore material in canvas if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { @@ -384,3 +389,5 @@ let Graphics = cc.Class({ }); cc.Graphics = module.exports = Graphics; +cc.Graphics.types = Types; +cc.Graphics.helper = require('./helper'); diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/earcut.js b/cocos2d/core/renderer/webgl/assemblers/graphics/earcut.js index dbe5610a025..46fae36fda1 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/earcut.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/earcut.js @@ -25,7 +25,7 @@ 'use strict'; -module.exports = earcut; +cc.Graphics.earcut = module.exports = earcut; function earcut(data, holeIndices, dim) { diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js index 76946c8a764..9e633a0d335 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js @@ -8,7 +8,7 @@ const renderEngine = renderer.renderEngine; const IARenderData = renderEngine.IARenderData; const InputAssembler = renderEngine.InputAssembler; -let Point = cc.Class({ +let Point = cc.GraphicsPoint = cc.Class({ name: 'cc.GraphicsPoint', extends: cc.Vec2, From d062ab1c71fd984dcc24613e64309a5bf5c717fb Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 17 Dec 2018 10:02:22 +0800 Subject: [PATCH 0268/1631] remove CC_EDITOR in systemEvent (#3640) * remove CC_EDITOR in systemEvent * add cc_editor under system event --- cocos2d/core/event/system-event.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/event/system-event.js b/cocos2d/core/event/system-event.js index 05e0a531b38..baa562082eb 100644 --- a/cocos2d/core/event/system-event.js +++ b/cocos2d/core/event/system-event.js @@ -101,6 +101,9 @@ var SystemEvent = cc.Class({ * @param {Boolean} isEnable */ setAccelerometerEnabled: function (isEnable) { + if (CC_EDITOR) { + return; + } inputManger.setAccelerometerEnabled(isEnable); }, @@ -111,10 +114,16 @@ var SystemEvent = cc.Class({ * @param {Number} interval */ setAccelerometerInterval: function(interval) { + if (CC_EDITOR) { + return; + } inputManger.setAccelerometerInterval(interval); }, on: function (type, callback, target) { + if (CC_EDITOR) { + return; + } this._super(type, callback, target); // Keyboard @@ -156,6 +165,9 @@ var SystemEvent = cc.Class({ off: function (type, callback, target) { + if (CC_EDITOR) { + return; + } this._super(type, callback, target); // Keyboard @@ -176,8 +188,7 @@ var SystemEvent = cc.Class({ }); cc.SystemEvent = module.exports = SystemEvent; -if (!CC_EDITOR) { -/** +/** * @module cc */ @@ -186,6 +197,5 @@ if (!CC_EDITOR) { * !#zh 系统事件单例,方便全局使用 * @property systemEvent * @type {SystemEvent} - */ - cc.systemEvent = new cc.SystemEvent(); -} \ No newline at end of file + */ +cc.systemEvent = new cc.SystemEvent(); From eef64f24424fb684eff9330a08dd5ed243718097 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Mon, 17 Dec 2018 11:30:33 +0800 Subject: [PATCH 0269/1631] isPlainEmptyObj_DEV invoke isEmptyObject (#3641) --- cocos2d/core/load-pipeline/loading-items.js | 3 ++- cocos2d/core/platform/utils.js | 9 +++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/load-pipeline/loading-items.js b/cocos2d/core/load-pipeline/loading-items.js index 55fe847883a..2903a317224 100644 --- a/cocos2d/core/load-pipeline/loading-items.js +++ b/cocos2d/core/load-pipeline/loading-items.js @@ -523,7 +523,8 @@ proto._childOnProgress = function (item) { * @method allComplete */ proto.allComplete = function () { - var errors = js.isEmptyObject(this._errorUrls) === true ? null : this._errorUrls; + var errors = js.isEmptyObject(this._errorUrls) ? null : this._errorUrls; + if (this.onComplete) { this.onComplete(errors, this); } diff --git a/cocos2d/core/platform/utils.js b/cocos2d/core/platform/utils.js index 752821e8b13..d8c7e7839ff 100644 --- a/cocos2d/core/platform/utils.js +++ b/cocos2d/core/platform/utils.js @@ -25,6 +25,7 @@ ****************************************************************************/ // TODO - merge with misc.js +const js = require('./js'); module.exports = { contains: function (refNode, otherNode) { @@ -91,12 +92,8 @@ if (CC_DEV) { if (!obj || obj.constructor !== Object) { return false; } - // jshint ignore: start - for (var k in obj) { - return false; - } - // jshint ignore: end - return true; + + return js.isEmptyObject(obj); }; module.exports.cloneable_DEV = function (obj) { return obj && From 12ac35f365add3c5c861e98dcb04b57627bda20f Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Tue, 18 Dec 2018 14:40:40 +0800 Subject: [PATCH 0270/1631] add small test for decorator (#3645) --- test/qunit/unit/test-class.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/qunit/unit/test-class.js b/test/qunit/unit/test-class.js index 334c2bd28b7..4d044ed7e87 100644 --- a/test/qunit/unit/test-class.js +++ b/test/qunit/unit/test-class.js @@ -266,6 +266,11 @@ largeModule('Class ES6'); p1 = null; @property p2 = null; + @property({ + type: cc.Asset + }) + get p3 () {} + set p3 (value) {} } deepEqual(Class.__values__, ['p2'], 'should not contain non-serializable properties'); From 2373c060ded568d36c6f1ed5c0d313f246fc4a74 Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 18 Dec 2018 14:45:26 +0800 Subject: [PATCH 0271/1631] fix button scale setting in Scale Mode (#3636) --- cocos2d/core/components/CCButton.js | 39 ++++++++++++++++++----------- editor/i18n/en/localization.js | 2 +- editor/i18n/zh/localization.js | 2 +- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 0b8515a62b2..70e1928cc3d 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -25,7 +25,6 @@ ****************************************************************************/ const Component = require('./CCComponent'); -const misc = require('../utils/misc'); /** * !#en Enum for transition type. @@ -127,9 +126,10 @@ let Button = cc.Class({ this._toColor = null; this._time = 0; this._transitionFinished = true; - this._fromScale = 1.0; - this._toScale = 1.0; - this._originalScale = 1.0; + // init _originalScale in __preload() + this._fromScale = cc.Vec2.ZERO; + this._toScale = cc.Vec2.ZERO; + this._originalScale = cc.Vec2.ZERO; this._sprite = null; @@ -276,7 +276,9 @@ let Button = cc.Class({ /** * !#en When user press the button, the button will zoom to a scale. * The final scale of the button equals (button original scale * zoomScale) + * Setting zoomScale less than 1 is not adviced, which could fire the touchCancel event if the touch point is out of touch area after scaling. * !#zh 当用户点击按钮后,按钮会缩放到一个值,这个值等于 Button 原始 scale * zoomScale + * 不建议 zoomScale 的值小于 1, 否则缩放后如果触摸点在触摸区域外, 则会触发 touchCancel 事件。 * @property {Number} zoomScale */ zoomScale: { @@ -404,7 +406,8 @@ let Button = cc.Class({ if (transition === Transition.COLOR && this.interactable) { target.color = this.normalColor; } else if (transition === Transition.SCALE) { - target.scale = this._originalScale; + target.scaleX = this._originalScale.x; + target.scaleY = this._originalScale.y; } this._transitionFinished = true; }, @@ -470,7 +473,7 @@ let Button = cc.Class({ if (this.transition === Transition.COLOR) { target.color = this._fromColor.lerp(this._toColor, ratio); } else if (this.transition === Transition.SCALE) { - target.scale = misc.lerp(this._fromScale, this._toScale, ratio); + target.scale = this._fromScale.lerp(this._toScale, ratio); } }, @@ -496,7 +499,8 @@ let Button = cc.Class({ _applyTarget () { this._sprite = this._getTargetSprite(this.target); if (this.target) { - this._originalScale = this.target.scale; + this._originalScale.x = this.target.scaleX; + this._originalScale.y = this.target.scaleY; } }, @@ -518,13 +522,16 @@ let Button = cc.Class({ if (this.transition === Transition.SCALE && this.target) { if (hit) { - this._fromScale = this._originalScale; - this._toScale = this._originalScale * this.zoomScale; + this._fromScale.x = this._originalScale.x; + this._fromScale.y = this._originalScale.y; + this._toScale.x = this._originalScale.x * this.zoomScale; + this._toScale.y = this._originalScale.y * this.zoomScale; this._transitionFinished = false; } else { this.time = 0; this._transitionFinished = true; - this.target.scale = this._originalScale; + this.target.scaleX = this._originalScale.x; + this.target.scaleY = this._originalScale.y; } } else { let state; @@ -629,15 +636,19 @@ let Button = cc.Class({ }, _zoomUp () { - this._fromScale = this._originalScale; - this._toScale = this._originalScale * this.zoomScale; + this._fromScale.x = this._originalScale.x; + this._fromScale.y = this._originalScale.y; + this._toScale.x = this._originalScale.x * this.zoomScale; + this._toScale.y = this._originalScale.y * this.zoomScale; this.time = 0; this._transitionFinished = false; }, _zoomBack () { - this._fromScale = this.target.scale; - this._toScale = this._originalScale; + this._fromScale.x = this.target.scaleX; + this._fromScale.y = this.target.scaleY; + this._toScale.x = this._originalScale.x; + this._toScale.y = this._originalScale.y; this.time = 0; this._transitionFinished = false; }, diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 41acc1e97fe..3b30566ecfb 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -72,7 +72,7 @@ module.exports = { "hover_color": "Button color when the mouse hovers over it", "disabled_color": "Button color when disabled", "duration": "How long until the button color/scale transitions to a new color?", - "zoom_scale": "When user press the button, the button will zoom to a scale.The final scale of the button equals (button original scale * zoomScale), zoomScale could be negative value.", + "zoom_scale": "When user press the button, the button will zoom to a scale.The final scale of the button equals (button original scale * zoomScale). Setting zoomScale less than 1 is not adviced, which could fire the touchCancel event if the touch point is out of touch area after scaling.", "auto_gray_effect": "When this flag is true, Button target sprite will turn gray when interactable is false.", "normal_sprite": "The Sprite that is used when the button is in a normal sate.", "pressed_sprite": "The Sprite that is used when the button is in a pressed sate.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index b20c9cc166c..3361e97582d 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -75,7 +75,7 @@ module.exports = { 'hover_color': '悬停状态的按钮背景颜色', 'disabled_color': '禁用状态的按钮背景颜色', 'duration': '按钮颜色变化或者缩放变化的过渡时间', - 'zoom_scale': '当用户点击按钮后,按钮会缩放到一个值,这个值等于 Button 原始 scale * zoomScale, zoomScale 可以为负数', + 'zoom_scale': '当用户点击按钮后,按钮会缩放到一个值,这个值等于 Button 原始 scale * zoomScale。不建议 zoomScale 的值小于 1, 否则缩放后如果触摸点在触摸区域外, 则会触发 touchCancel 事件', 'auto_gray_effect': "如果这个标记为 true,当 button 的 interactable 属性为 false 的时候,会使用内置 shader 让 button 的 target 节点的 sprite 组件变灰", 'normal_sprite': '普通状态的按钮背景图资源', 'pressed_sprite': '按下状态的按钮背景图资源', From ea8b4200eeb7ba38a9bb51bad3ea587d47097e6f Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Tue, 18 Dec 2018 16:33:02 +0800 Subject: [PATCH 0272/1631] Modify label texture to join dynamic atlas. (#3525) * Modify label texture to join dynamic atlas. * Modify dynamicAtlas and spriteFrame. * Conflict resolution. * Delete duplicate files. * Modify spriteFrame and Frame class. * Delete duplicate code in SpriteFrame. * Modify comment of label frame. * Modify omission --- cocos2d/core/assets/CCSpriteFrame.js | 36 +++++- cocos2d/core/components/CCLabel.js | 55 +++++++- cocos2d/core/components/CCSprite.js | 16 +++ .../renderer/utils/dynamic-atlas/atlas.js | 28 ++--- .../renderer/utils/dynamic-atlas/manager.js | 14 ++- .../core/renderer/utils/label/label-frame.js | 117 ++++++++++++++++++ cocos2d/core/renderer/utils/label/ttf.js | 17 ++- .../renderer/webgl/assemblers/label/2d/ttf.js | 24 ++-- .../renderer/webgl/assemblers/label/3d/ttf.js | 4 +- .../webgl/assemblers/sprite/2d/bar-filled.js | 10 +- .../webgl/assemblers/sprite/2d/mesh.js | 10 +- .../assemblers/sprite/2d/radial-filled.js | 10 +- .../webgl/assemblers/sprite/2d/simple.js | 11 +- .../webgl/assemblers/sprite/2d/sliced.js | 11 +- .../webgl/assemblers/sprite/2d/tiled.js | 11 +- 15 files changed, 264 insertions(+), 110 deletions(-) create mode 100644 cocos2d/core/renderer/utils/label/label-frame.js diff --git a/cocos2d/core/assets/CCSpriteFrame.js b/cocos2d/core/assets/CCSpriteFrame.js index 51be49f73d7..9ce82755253 100644 --- a/cocos2d/core/assets/CCSpriteFrame.js +++ b/cocos2d/core/assets/CCSpriteFrame.js @@ -194,6 +194,12 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ // the location of the sprite on rendering texture this._rect = null; + // uv data of frame + this.uv = []; + // texture of frame + this._texture = null; + // store original info before packed to dynamic atlas + this._original = null; // for trimming this._offset = null; @@ -207,15 +213,10 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ this._capInsets = [0, 0, 0, 0]; - this.uv = []; this.uvSliced = []; - this._texture = null; this._textureFilename = ''; - // store original info before packed to dynamic atlas - this._original = null; - if (CC_EDITOR) { // Atlas asset uuid this._atlasUuid = ''; @@ -281,7 +282,7 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ if (this._texture) this._calculateUV(); }, - + /** * !#en Returns the original size of the trimmed image. * !#zh 获取修剪前的原始大小 @@ -582,6 +583,29 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ } }, + _setDynamicAtlasFrame (frame) { + if (!frame) return; + + this._original = { + _texture : this._texture, + _x : this._rect.x, + _y : this._rect.y + } + + this._texture = frame.texture; + this._rect.x = frame.x; + this._rect.y = frame.y; + this._calculateUV(); + }, + + _resetDynamicAtlasFrame () { + this._rect.x = this._original._x; + this._rect.y = this._original._y; + this._texture = this._original._texture; + this._original = null; + this._calculateUV(); + }, + _calculateUV () { let rect = this._rect, texture = this._texture, diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index d47ec4f2f30..d25341a4fe6 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -29,7 +29,8 @@ const RenderComponent = require('./CCRenderComponent'); const renderEngine = require('../renderer/render-engine'); const RenderFlow = require('../renderer/render-flow'); const SpriteMaterial = renderEngine.SpriteMaterial; - +const dynamicAtlasManager = require('../renderer/utils/dynamic-atlas/manager'); +const LabelFrame = require('../renderer/utils/label/label-frame'); /** * !#en Enum for text alignment. * !#zh 文本横向对齐类型 @@ -145,6 +146,7 @@ let Label = cc.Class({ this._actualFontSize = 0; this._assemblerData = null; + this._frame = null; this._ttfTexture = null; }, @@ -430,6 +432,24 @@ let Label = cc.Class({ } }, + _cacheAsBitmap: true, + /** + * !#en Whether cache label to static texture and draw in dynamicAtlas. + * !#zh 是否将label缓存成静态图像并加入到动态图集.(对于静态文本建议使用该选项,便于批次合并减少drawcall) + * @property {Boolean} cacheAsBitmap + */ + cacheAsBitmap: { + get () { + return this._cacheAsBitmap; + }, + set (value) { + if (this._cacheAsBitmap === value) return; + + this._cacheAsBitmap = value; + this._updateRenderData(); + }, + }, + _isBold: { default: false, serializable: false, @@ -547,6 +567,9 @@ let Label = cc.Class({ spriteFrame.ensureLoadTexture(); } } + + // TODO: old texture in material have been released by loader + this._frame = spriteFrame; } else { if (!this._ttfTexture) { @@ -557,8 +580,14 @@ let Label = cc.Class({ } this._assemblerData = this._assembler._getAssemblerData(); this._ttfTexture.initWithElement(this._assemblerData.canvas); + + if (!this._frame) { + this._frame = new LabelFrame(); + } + + this._frame._refreshTexture(this._ttfTexture); } - this._texture = this._ttfTexture; + this._activateMaterial(force); if (force) { @@ -575,7 +604,7 @@ let Label = cc.Class({ // Canvas if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { - this._texture.url = this.uuid + '_texture'; + this._frame._texture.url = this.uuid + '_texture'; } // WebGL else { @@ -583,13 +612,13 @@ let Label = cc.Class({ material = new SpriteMaterial(); } // Setup blend function for premultiplied ttf label texture - if (this._texture === this._ttfTexture) { + if (this._frame._texture === this._ttfTexture) { this._srcBlendFactor = cc.macro.BlendFactor.ONE; } else { this._srcBlendFactor = cc.macro.BlendFactor.SRC_ALPHA; } - material.texture = this._texture; + material.texture = this._frame._texture; // For batch rendering, do not use uniform color. material.useColor = false; this._updateMaterial(material); @@ -598,7 +627,7 @@ let Label = cc.Class({ this.markForUpdateRenderData(true); this.markForRender(true); }, - + _updateColor () { let font = this.font; if (font instanceof cc.BitmapFont) { @@ -624,6 +653,20 @@ let Label = cc.Class({ } }, + _calDynamicAtlas () { + if (!dynamicAtlasManager) return; + + if (!this._frame._original) { + let frame = dynamicAtlasManager.insertSpriteFrame(this._frame); + if (frame) { + this._frame._setDynamicAtlasFrame(frame); + } + } + if (this._material._texture !== this._frame._texture) { + this._activateMaterial(true); + } + }, + _enableBold (enabled) { this._isBold = !!enabled; }, diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index ef4ad542648..cc86e159648 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -31,6 +31,7 @@ const RenderFlow = require('../renderer/render-flow'); const renderEngine = require('../renderer/render-engine'); const SpriteMaterial = renderEngine.SpriteMaterial; const GraySpriteMaterial = renderEngine.GraySpriteMaterial; +const dynamicAtlasManager = require('../renderer/utils/dynamic-atlas/manager'); /** * !#en Enum for sprite type. @@ -651,6 +652,21 @@ var Sprite = cc.Class({ } } }, + + _calDynamicAtlas () + { + if (!this._spriteFrame) return; + + if (!this._spriteFrame._original && dynamicAtlasManager) { + let frame = dynamicAtlasManager.insertSpriteFrame(this._spriteFrame); + if (frame) { + this._spriteFrame._setDynamicAtlasFrame(frame); + } + } + if (this._material._texture !== this._spriteFrame._texture) { + this._activateMaterial(); + } + } }); if (CC_EDITOR) { diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js b/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js index 00f65b60daa..8c93a3b67f7 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js @@ -27,8 +27,8 @@ cc.js.mixin(Atlas.prototype, { let sx = rect.x, sy = rect.y; if (info) { - rect.x += info.x; - rect.y += info.y; + sx += info.x; + sy += info.y; } else { let width = texture.width, height = texture.height; @@ -43,7 +43,7 @@ cc.js.mixin(Atlas.prototype, { } if (this._nexty > this._height) { - return false; + return null; } // texture bleeding @@ -59,26 +59,23 @@ cc.js.mixin(Atlas.prototype, { texture: texture }; - rect.x += this._x; - rect.y += this._y; + sx += this._x; + sy += this._y; this._x += width + space; this._dirty = true; } - spriteFrame._original = { + let frame = { x: sx, y: sy, - texture: spriteFrame._texture + texture: this._texture } - - spriteFrame._texture = this._texture; - spriteFrame._calculateUV(); - + this._innerSpriteFrames.push(spriteFrame); - return true; + return frame; }, update () { @@ -98,12 +95,7 @@ cc.js.mixin(Atlas.prototype, { if (!frame.isValid) { continue; } - let oriInfo = frame._original; - frame._rect.x = oriInfo.x; - frame._rect.y = oriInfo.y; - frame._texture = oriInfo.texture; - frame._calculateUV(); - frame._original = null; + frame._resetDynamicAtlasFrame(); } this._innerSpriteFrames.length = 0; this._innerTextureInfos = {}; diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js index 291f46234b5..ab1a4861971 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js @@ -103,18 +103,18 @@ let dynamicAtlasManager = { * @param {SpriteFrame} spriteFrame */ insertSpriteFrame (spriteFrame) { - if (CC_EDITOR) return; + if (CC_EDITOR) return null; if (!_enabled || _atlasIndex === _maxAtlasCount || - !spriteFrame || spriteFrame._original) return; + !spriteFrame || spriteFrame._original) return null; let texture = spriteFrame._texture; - if (texture instanceof cc.RenderTexture || cc.Texture2D._isCompressed(texture)) return; + if (texture instanceof cc.RenderTexture || cc.Texture2D._isCompressed(texture)) return null; let w = texture.width, h = texture.height; let min = texture._minFilter, mag = texture._magFilter; let LINEAR = cc.Texture2D.Filter.LINEAR; if (w > _maxFrameSize || h > _maxFrameSize || w <= _minFrameSize || h <= _minFrameSize || (min & mag) !== LINEAR) { - return; + return null; } let atlas = _atlases[_atlasIndex]; @@ -122,10 +122,12 @@ let dynamicAtlasManager = { atlas = newAtlas(); } - if (!atlas.insertSpriteFrame(spriteFrame) && _atlasIndex !== _maxAtlasCount) { + let frame = atlas.insertSpriteFrame(spriteFrame); + if (!frame && _atlasIndex !== _maxAtlasCount) { atlas = newAtlas(); - atlas.insertSpriteFrame(spriteFrame); + return atlas.insertSpriteFrame(spriteFrame); } + return frame; }, /** diff --git a/cocos2d/core/renderer/utils/label/label-frame.js b/cocos2d/core/renderer/utils/label/label-frame.js new file mode 100644 index 00000000000..277e0a8d540 --- /dev/null +++ b/cocos2d/core/renderer/utils/label/label-frame.js @@ -0,0 +1,117 @@ +/**************************************************************************** + Copyright (c) 2018 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. + ****************************************************************************/ + +/** + * !#en Class for Label Frame. + * !#zh LabelFrame + */ +function LabelFrame () { + // the location of the label on rendering texture + this._rect = null; + // uv data of frame + this.uv = []; + // texture of frame + this._texture = null; + // store original info before packed to dynamic atlas + this._original = null; +} + +LabelFrame.prototype = { + constructor: LabelFrame, + + /** + * !#en Returns the rect of the label frame in the texture. + * !#zh 获取 LabelFrame 的纹理矩形区域 + * @method getRect + * @return {Rect} + */ + getRect: function () { + return cc.rect(this._rect); + }, + + /** + * !#en Sets the rect of the label frame in the texture. + * !#zh 设置 LabelFrame 的纹理矩形区域 + * @method setRect + * @param {Rect} rect + */ + setRect: function (rect) { + this._rect = rect; + if (this._texture) + this._calculateUV(); + }, + + _setDynamicAtlasFrame (frame) { + if (!frame) return; + + this._original = { + _texture : this._texture, + _x : this._rect.x, + _y : this._rect.y + } + + this._texture = frame.texture; + this._rect.x = frame.x; + this._rect.y = frame.y; + this._calculateUV(); + }, + _resetDynamicAtlasFrame () { + this._rect.x = this._original._x; + this._rect.y = this._original._y; + this._texture = this._original._texture; + this._original = null; + this._calculateUV(); + }, + + _refreshTexture: function (texture) { + this._texture = texture; + this._rect = cc.rect(0, 0, texture.width, texture.height); + this._calculateUV(); + }, + + _calculateUV() { + let rect = this._rect, + texture = this._texture, + uv = this.uv, + texw = texture.width, + texh = texture.height; + + let l = texw === 0 ? 0 : rect.x / texw; + let r = texw === 0 ? 0 : (rect.x + rect.width) / texw; + let b = texh === 0 ? 0 : (rect.y + rect.height) / texh; + let t = texh === 0 ? 0 : rect.y / texh; + + uv[0] = l; + uv[1] = b; + uv[2] = r; + uv[3] = b; + uv[4] = l; + uv[5] = t; + uv[6] = r; + uv[7] = t; + } +} + +module.exports = LabelFrame; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index ab0739c80d6..d9cebe8ed24 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -124,7 +124,8 @@ module.exports = { this._calculateSplitedStrings(); this._updateLabelDimensions(); this._calculateTextBaseline(); - this._updateTexture(comp); + this._updateTexture(); + this._calDynamicAtlas(comp); comp._actualFontSize = _fontSize; comp.node.setContentSize(_canvasSize); @@ -171,7 +172,7 @@ module.exports = { let assemblerData = comp._assemblerData; _context = assemblerData.context; _canvas = assemblerData.canvas; - _texture = comp._texture; + _texture = comp._frame._original ? comp._frame._original._texture : comp._frame._texture; _string = comp.string.toString(); _fontSize = comp._fontSize; @@ -278,6 +279,16 @@ module.exports = { _texture.handleLoadedTexture(); }, + _calDynamicAtlas (comp) { + if(!comp.cacheAsBitmap) return; + + if (!comp._frame._original) { + comp._frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height)); + } + // Add font images to the dynamic atlas for batch rendering. + comp._calDynamicAtlas(); + }, + _calculateUnderlineStartPosition () { let lineHeight = this._getLineHeight(); let lineCount = _splitedStrings.length; @@ -498,5 +509,5 @@ module.exports = { _context.font = _fontDesc; } } - } + }, }; diff --git a/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js index 810d5b29fc1..97c0513c062 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js @@ -25,7 +25,7 @@ const js = require('../../../../../platform/js'); const ttfUtls = require('../../../../utils/label/ttf'); -const fillVertices = require('../../utils').fillVertices; +const fillMeshVertices = require('../../utils').fillMeshVertices; const WHITE = cc.color(255, 255, 255, 255); @@ -37,25 +37,16 @@ module.exports = js.addon({ renderData.vertexCount = 4; renderData.indiceCount = 6; - let data = renderData._data; - data[0].u = 0; - data[0].v = 1; - data[1].u = 1; - data[1].v = 1; - data[2].u = 0; - data[2].v = 0; - data[3].u = 1; - data[3].v = 0; return renderData; }, fillBuffers (comp, renderer) { - fillVertices(comp.node, renderer._quadBuffer, comp._renderData, WHITE._val); + fillMeshVertices(comp.node, renderer._meshBuffer, comp._renderData, WHITE._val); }, _updateVerts (comp) { let renderData = comp._renderData; - + let uv = comp._frame.uv; let node = comp.node, width = node.width, height = node.height, @@ -71,5 +62,14 @@ module.exports = js.addon({ data[2].y = height - appy; data[3].x = width - appx; data[3].y = height - appy; + + data[0].u = uv[0]; + data[0].v = uv[1]; + data[1].u = uv[2]; + data[1].v = uv[3]; + data[2].u = uv[4]; + data[2].v = uv[5]; + data[3].u = uv[6]; + data[3].v = uv[7]; } }, ttfUtls); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js index 5d7a2b07614..99aa385535c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js @@ -25,12 +25,12 @@ const js = require('../../../../../platform/js'); const assembler = require('../2d/ttf'); -const fillVertices3D = require('../../utils').fillVertices3D; +const fillMeshVertices3D = require('../../utils').fillMeshVertices3D; const WHITE = cc.color(255, 255, 255, 255); module.exports = js.addon({ fillBuffers (comp, renderer) { - fillVertices3D(comp.node, renderer._quadBuffer3D, comp._renderData, WHITE._val); + fillMeshVertices3D(comp.node, renderer._meshBuffer3D, comp._renderData, WHITE._val); } }, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js index e2162b18569..53b55ecdc41 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js @@ -26,7 +26,6 @@ const Sprite = require('../../../../../components/CCSprite'); const FillType = Sprite.FillType; -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { @@ -36,14 +35,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js index 4e35b95ddca..74b4b958c3f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js @@ -23,7 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { @@ -38,14 +37,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js index 88ed36b8fb1..e4c6a1bd073 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js @@ -23,7 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); const fillVertices = require('../../utils').fillVertices; const PI_2 = Math.PI * 2; @@ -222,14 +221,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js index 3cd5ceaf787..6be7f5ff715 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js @@ -23,8 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); - module.exports = { useModel: false, @@ -33,14 +31,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js index dccc3a79062..ac9ba3bc978 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js @@ -23,8 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); - module.exports = { useModel: false, @@ -44,14 +42,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js index f38d7e11852..55413023820 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js @@ -23,8 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); - module.exports = { useModel: false, @@ -41,14 +39,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (!frame || !renderData || From 93d55e14198573e4a49dcc6bcf73d5337b9436a5 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Tue, 18 Dec 2018 17:46:45 +0800 Subject: [PATCH 0273/1631] fixed issue that callstack overflow while loading asset (#3648) --- cocos2d/core/load-pipeline/md5-pipe.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/load-pipeline/md5-pipe.js b/cocos2d/core/load-pipeline/md5-pipe.js index 0b536a8ed7e..3becdd2eddd 100644 --- a/cocos2d/core/load-pipeline/md5-pipe.js +++ b/cocos2d/core/load-pipeline/md5-pipe.js @@ -55,7 +55,7 @@ MD5Pipe.prototype.handle = function(item) { hashPatchInFolder = true; } item.url = this.transformURL(item.url, hashPatchInFolder); - return item; + return null; }; MD5Pipe.prototype.transformURL = function (url, hashPatchInFolder) { From d625b4bd24a74330ad94960fe9800f8531f3a9de Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 18 Dec 2018 17:47:53 +0800 Subject: [PATCH 0274/1631] fixed the findCamera problem (#3642) --- cocos2d/core/CCNode.js | 27 ++++++++++++++++++++++----- cocos2d/core/renderer/render-flow.js | 11 +---------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 18a05e52b7e..2bc386f98ce 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -589,7 +589,10 @@ var Node = cc.Class({ }, set (value) { + // update the groupIndex this.groupIndex = cc.game.groupList.indexOf(value); + let index = this._getActualGroupIndex(this); + this._cullingMask = 1 << index; this.emit(EventType.GROUP_CHANGED, this); } }, @@ -1114,7 +1117,7 @@ var Node = cc.Class({ */ ctor () { this._reorderChildDirty = false; - + // cache component this._widget = null; // fast render component access @@ -1138,7 +1141,7 @@ var Node = cc.Class({ this._worldMatDirty = true; this._eventMask = 0; - this._cullingMask = 1 << this.groupIndex; + this._cullingMask = 1; }, statics: { @@ -1308,6 +1311,9 @@ var Node = cc.Class({ this._updateOrderOfArrival(); + // synchronize _cullingMask + this._cullingMask = 1 << this._getActualGroupIndex(this); + let prefabInfo = this._prefab; if (prefabInfo && prefabInfo.sync && prefabInfo.root === this) { if (CC_DEV) { @@ -1339,6 +1345,8 @@ var Node = cc.Class({ _onBatchRestored () { this._upgrade_1x_to_2x(); + this._cullingMask = 1 << this._getActualGroupIndex(this); + if (!this._activeInHierarchy) { // deactivate ActionManager and EventManager by default if (ActionManagerExist) { @@ -1642,12 +1650,12 @@ var Node = cc.Class({ var listeners = useCapture ? this._capturingListeners : this._bubblingListeners; if (listeners) { listeners.remove(type, callback, target); - + if (target && target.__eventTargets) { js.array.fastRemove(target.__eventTargets, this); } } - + } }, @@ -1853,7 +1861,7 @@ var Node = cc.Class({ parent = parent.parent; } }, - + /** * Get all the targets listening to the supplied type of event in the target's bubbling phase. * The bubbling phase comprises any SUBSEQUENT nodes encountered on the return trip to the root of the tree. @@ -3053,6 +3061,15 @@ var Node = cc.Class({ eventManager.pauseTarget(this); } }, + + // traversal the node tree, child cullingMask must keep the same with the parent. + _getActualGroupIndex (node) { + let groupIndex = node.groupIndex; + if (groupIndex === 0 && node.parent) { + groupIndex = this._getActualGroupIndex(node.parent); + } + return groupIndex; + }, }); /** diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 01f1646775d..0c0edd2c967 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -13,9 +13,7 @@ const POST_RENDER = 1 << 9; const FINAL = 1 << 10; let _walker = null; -let _cullingMask = 0; -// function RenderFlow () { this._func = init; this._next = null; @@ -107,8 +105,6 @@ _proto._customIARender = function (node) { }; _proto._children = function (node) { - let cullingMask = _cullingMask; - let parentOpacity = _walker.parentOpacity; let opacity = (_walker.parentOpacity *= (node._opacity / 255)); @@ -122,8 +118,7 @@ _proto._children = function (node) { // Advance the modification of the flag to avoid node attribute modification is invalid when opacity === 0. c._renderFlag |= worldDirtyFlag; if (!c._activeInHierarchy || c._opacity === 0) continue; - _cullingMask = c._cullingMask = c.groupIndex === 0 ? cullingMask : 1 << c.groupIndex; - + // TODO: Maybe has better way to implement cascade opacity let colorVal = c._color._val; c._color._fastSetA(c._opacity * opacity); @@ -134,8 +129,6 @@ _proto._children = function (node) { _walker.parentOpacity = parentOpacity; this._next._func(node); - - _cullingMask = cullingMask; }; _proto._postUpdateRenderData = function (node) { @@ -213,8 +206,6 @@ function getFlow (flag) { function render (scene) { - _cullingMask = 1 << scene.groupIndex; - if (scene._renderFlag & WORLD_TRANSFORM) { _walker.worldMatDirty ++; scene._calculWorldMatrix(); From 8eddd2f69507cd48363ecb1adbbffdaed0a90114 Mon Sep 17 00:00:00 2001 From: caryliu Date: Wed, 19 Dec 2018 11:55:16 +0800 Subject: [PATCH 0275/1631] Fix native-renderer graphics issues. --- cocos2d/core/graphics/graphics.js | 9 ++++++--- cocos2d/core/renderer/webgl/assemblers/graphics/impl.js | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/graphics/graphics.js b/cocos2d/core/graphics/graphics.js index 06ba85bbe31..cb63696ae51 100644 --- a/cocos2d/core/graphics/graphics.js +++ b/cocos2d/core/graphics/graphics.js @@ -25,7 +25,9 @@ ****************************************************************************/ const RenderComponent = require('../components/CCRenderComponent'); -const SpriteMaterial = require('../renderer/render-engine').SpriteMaterial; +const renderEngine = require('../renderer/render-engine'); +const SpriteMaterial = renderEngine.SpriteMaterial; +const gfx = renderEngine.gfx; const Types = require('./types'); const LineCap = Types.LineCap; @@ -45,6 +47,7 @@ let Graphics = cc.Class({ ctor () { this._impl = Graphics._assembler.createImpl(this); + this._vertexFormat = gfx.VertexFormat.XY_Color; }, properties: { @@ -389,5 +392,5 @@ let Graphics = cc.Class({ }); cc.Graphics = module.exports = Graphics; -cc.Graphics.types = Types; -cc.Graphics.helper = require('./helper'); +cc.Graphics.Types = Types; +cc.Graphics.Helper = require('./helper'); diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js index 9e633a0d335..b108afe59a8 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js @@ -8,7 +8,7 @@ const renderEngine = renderer.renderEngine; const IARenderData = renderEngine.IARenderData; const InputAssembler = renderEngine.InputAssembler; -let Point = cc.GraphicsPoint = cc.Class({ +let Point = cc.Graphics.Point = cc.Class({ name: 'cc.GraphicsPoint', extends: cc.Vec2, From b6613921c918bf7a39ecf920a7ebec83a7e70be5 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 10 Aug 2018 14:19:18 +0800 Subject: [PATCH 0276/1631] cherry pick: Supports dynamically access macros from external scripts such as adapters and debugger (#3063) --- predefine.js | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/predefine.js b/predefine.js index 83a151fcd90..6a7e9db7562 100644 --- a/predefine.js +++ b/predefine.js @@ -132,20 +132,41 @@ function defined (name) { return typeof _global[name] === 'object'; } -// These default values only used in the editor or preview. -// If you need to modify in the runtime, please modify the `global_defs` in the option returned by `gulp/util/utils.js: getUglifyOptions`. -defineMacro('CC_TEST', defined('tap') || defined('QUnit')); -defineMacro('CC_EDITOR', defined('Editor') && defined('process') && ('electron' in process.versions)); -defineMacro('CC_PREVIEW', !CC_EDITOR); -defineMacro('CC_DEV', true); // (CC_EDITOR && !CC_BUILD) || CC_PREVIEW || CC_TEST -defineMacro('CC_DEBUG', true); // CC_DEV || Debug Build -defineMacro('CC_JSB', defined('jsb')); +// ensure CC_BUILD is defined +// should not use window.CC_BUILD because we need get global_defs defined in uglify defineMacro('CC_BUILD', false); -defineMacro('CC_WECHATGAME_SUB', !!(defined('wx') && wx.getSharedCanvas)); -defineMacro('CC_WECHATGAME', !!(defined('wx') && (wx.getSystemInfoSync || wx.getSharedCanvas))); -defineMacro('CC_QQPLAY', defined('bk')); -defineMacro('CC_RUNTIME', 'function' === typeof loadRuntime); -defineMacro('CC_SUPPORT_JIT', !(CC_WECHATGAME || CC_QQPLAY || CC_RUNTIME)); + +if (CC_BUILD) { + // Supports dynamically access from external scripts such as adapters and debugger. + // So macros should still defined in global even if inlined in engine. + _global.CC_TEST = CC_TEST; + _global.CC_EDITOR = CC_EDITOR; + _global.CC_PREVIEW = CC_PREVIEW; + _global.CC_DEV = CC_DEV; + _global.CC_DEBUG = CC_DEBUG; + _global.CC_JSB = CC_JSB; + _global.CC_BUILD = CC_BUILD; + _global.CC_WECHATGAME_SUB = CC_WECHATGAME_SUB; + _global.CC_WECHATGAME = CC_WECHATGAME; + _global.CC_QQPLAY = CC_QQPLAY; + _global.CC_RUNTIME = CC_RUNTIME; + _global.CC_SUPPORT_JIT = CC_SUPPORT_JIT; +} +else { + // These default values only used in the editor or preview. + // If you need to modify in the runtime, please modify the `global_defs` in the option returned by `gulp/util/utils.js: getUglifyOptions`. + defineMacro('CC_TEST', defined('tap') || defined('QUnit')); + defineMacro('CC_EDITOR', defined('Editor') && defined('process') && ('electron' in process.versions)); + defineMacro('CC_PREVIEW', !CC_EDITOR); + defineMacro('CC_DEV', true); // (CC_EDITOR && !CC_BUILD) || CC_PREVIEW || CC_TEST + defineMacro('CC_DEBUG', true); // CC_DEV || Debug Build + defineMacro('CC_JSB', defined('jsb')); + defineMacro('CC_WECHATGAME_SUB', !!(defined('wx') && wx.getSharedCanvas)); + defineMacro('CC_WECHATGAME', !!(defined('wx') && (wx.getSystemInfoSync || wx.getSharedCanvas))); + defineMacro('CC_QQPLAY', defined('bk')); + defineMacro('CC_RUNTIME', 'function' === typeof loadRuntime); + defineMacro('CC_SUPPORT_JIT', !(CC_WECHATGAME || CC_QQPLAY || CC_RUNTIME)); +} // From c4fd37d9bd20d82b22d876d3af3c457b165c3c33 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 4 Sep 2018 19:03:30 +0800 Subject: [PATCH 0277/1631] cherry pick: fixed init animation clip (#3189) --- cocos2d/animation/animation-animator.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cocos2d/animation/animation-animator.js b/cocos2d/animation/animation-animator.js index be3f64388fb..2780e546b34 100644 --- a/cocos2d/animation/animation-animator.js +++ b/cocos2d/animation/animation-animator.js @@ -253,7 +253,9 @@ function initClipData (root, state) { } function createPropCurve (target, propPath, keyframes) { - var isMotionPathProp = (target instanceof cc.Node) && (propPath === 'position'); + var isMotionPathProp = (target instanceof cc.Node) + && (propPath === 'position') + && (keyframes[0] && Array.isArray(keyframes[0].value)); var motionPaths = []; var curve = new DynamicAnimCurve(); From a3ad409391a0532f2f0f769bbf3f6abdbb790bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=BA=E6=98=8E?= Date: Wed, 12 Sep 2018 01:04:14 +0800 Subject: [PATCH 0278/1631] cherry pick: change CC_WECHATGAME_SUB to CC_WECHATGAMESUB (#3233) Commit: 19b042ab0a90eaf4786c583d52fc685e95586b49 --- cocos2d/core/platform/CCSys.js | 2 +- predefine.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 82be38a4de9..0eaadce531e 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -684,7 +684,7 @@ function initSys () { sys.osVersion = version ? version[0] : system; sys.osMainVersion = parseInt(sys.osVersion); // wechagame subdomain - if (CC_WECHATGAME_SUB) { + if (CC_WECHATGAMESUB) { sys.browserType = sys.BROWSER_TYPE_WECHAT_GAME_SUB; } else { diff --git a/predefine.js b/predefine.js index 6a7e9db7562..842db989e2c 100644 --- a/predefine.js +++ b/predefine.js @@ -139,14 +139,14 @@ defineMacro('CC_BUILD', false); if (CC_BUILD) { // Supports dynamically access from external scripts such as adapters and debugger. // So macros should still defined in global even if inlined in engine. + _global.CC_BUILD = CC_BUILD; _global.CC_TEST = CC_TEST; _global.CC_EDITOR = CC_EDITOR; _global.CC_PREVIEW = CC_PREVIEW; _global.CC_DEV = CC_DEV; _global.CC_DEBUG = CC_DEBUG; _global.CC_JSB = CC_JSB; - _global.CC_BUILD = CC_BUILD; - _global.CC_WECHATGAME_SUB = CC_WECHATGAME_SUB; + _global.CC_WECHATGAMESUB = CC_WECHATGAMESUB; _global.CC_WECHATGAME = CC_WECHATGAME; _global.CC_QQPLAY = CC_QQPLAY; _global.CC_RUNTIME = CC_RUNTIME; @@ -161,7 +161,7 @@ else { defineMacro('CC_DEV', true); // (CC_EDITOR && !CC_BUILD) || CC_PREVIEW || CC_TEST defineMacro('CC_DEBUG', true); // CC_DEV || Debug Build defineMacro('CC_JSB', defined('jsb')); - defineMacro('CC_WECHATGAME_SUB', !!(defined('wx') && wx.getSharedCanvas)); + defineMacro('CC_WECHATGAMESUB', !!(defined('wx') && wx.getSharedCanvas)); defineMacro('CC_WECHATGAME', !!(defined('wx') && (wx.getSystemInfoSync || wx.getSharedCanvas))); defineMacro('CC_QQPLAY', defined('bk')); defineMacro('CC_RUNTIME', 'function' === typeof loadRuntime); From 93e135d72d58fa4d81fc2e37be1ba57c6bc3424f Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 14 Sep 2018 23:55:53 +0800 Subject: [PATCH 0279/1631] expose js._registeredClassIds js._registeredClassNames to unload scripts dynamically (#3174) --- cocos2d/core/platform/js.js | 77 +++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/cocos2d/core/platform/js.js b/cocos2d/core/platform/js.js index 88b08adbb9a..104d0805010 100644 --- a/cocos2d/core/platform/js.js +++ b/cocos2d/core/platform/js.js @@ -392,7 +392,16 @@ function isTempClassId (id) { var _idToClass = {}; var _nameToClass = {}; - function getRegister (key, table) { + function setup (key, publicName, table) { + js.getset(js, publicName, + function () { + return Object.assign({}, table); + }, + function (value) { + js.clear(table); + Object.assign(table, value); + } + ); return function (id, constructor) { // deregister old if (constructor.prototype.hasOwnProperty(key)) { @@ -428,9 +437,37 @@ cc.js.unregisterClass to remove the id of unused class'; * @param {Function} constructor * @private */ - js._setClassId = getRegister('__cid__', _idToClass); + /** + * !#en All classes registered in the engine, indexed by ID. + * !#zh 引擎中已注册的所有类型,通过 ID 进行索引。 + * @property _registeredClassIds + * @example + * // save all registered classes before loading scripts + * let builtinClassIds = cc.js._registeredClassIds; + * let builtinClassNames = cc.js._registeredClassNames; + * // load some scripts that contain CCClass + * ... + * // clear all loaded classes + * cc.js._registeredClassIds = builtinClassIds; + * cc.js._registeredClassNames = builtinClassNames; + */ + js._setClassId = setup('__cid__', '_registeredClassIds', _idToClass); - var doSetClassName = getRegister('__classname__', _nameToClass); + /** + * !#en All classes registered in the engine, indexed by name. + * !#zh 引擎中已注册的所有类型,通过名称进行索引。 + * @property _registeredClassNames + * @example + * // save all registered classes before loading scripts + * let builtinClassIds = cc.js._registeredClassIds; + * let builtinClassNames = cc.js._registeredClassNames; + * // load some scripts that contain CCClass + * ... + * // clear all loaded classes + * cc.js._registeredClassIds = builtinClassIds; + * cc.js._registeredClassNames = builtinClassNames; + */ + var doSetClassName = setup('__classname__', '_registeredClassNames', _nameToClass); /** * Register the class by specified name manually @@ -524,40 +561,6 @@ cc.js.unregisterClass to remove the id of unused class'; } return ''; }; - - if (CC_DEV) { - js.getset(js, '_registeredClassIds', - function () { - var dump = {}; - for (var id in _idToClass) { - dump[id] = _idToClass[id]; - } - return dump; - }, - function (value) { - js.clear(_idToClass); - for (var id in value) { - _idToClass[id] = value[id]; - } - } - ); - js.getset(js, '_registeredClassNames', - function () { - var dump = {}; - for (var id in _nameToClass) { - dump[id] = _nameToClass[id]; - } - return dump; - }, - function (value) { - js.clear(_nameToClass); - for (var id in value) { - _nameToClass[id] = value[id]; - } - } - ); - } - })(); /** From a152065ea73908a007c45690ce7f756ed4e0bbe7 Mon Sep 17 00:00:00 2001 From: colin Date: Wed, 19 Dec 2018 17:32:52 +0800 Subject: [PATCH 0280/1631] (+1 squashed commit) Squashed commits: [03baf84f] (+1 squashed commit) Squashed commits: [c285e31a] (+1 squashed commit) Squashed commits: [c112a226] adjust the getActualGroupIndex function --- cocos2d/core/CCNode.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 2bc386f98ce..52dac7e5475 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -514,6 +514,15 @@ function _doDispatchEvent (owner, event) { _cachedArray.length = 0; }; +// traversal the node tree, child cullingMask must keep the same with the parent. +function _getActualGroupIndex (node) { + let groupIndex = node.groupIndex; + if (groupIndex === 0 && node.parent) { + groupIndex = _getActualGroupIndex(node.parent); + } + return groupIndex; +} + /** * !#en * Class of all entities in Cocos Creator scenes.
@@ -591,7 +600,7 @@ var Node = cc.Class({ set (value) { // update the groupIndex this.groupIndex = cc.game.groupList.indexOf(value); - let index = this._getActualGroupIndex(this); + let index = _getActualGroupIndex(this); this._cullingMask = 1 << index; this.emit(EventType.GROUP_CHANGED, this); } @@ -1312,7 +1321,7 @@ var Node = cc.Class({ this._updateOrderOfArrival(); // synchronize _cullingMask - this._cullingMask = 1 << this._getActualGroupIndex(this); + this._cullingMask = 1 << _getActualGroupIndex(this); let prefabInfo = this._prefab; if (prefabInfo && prefabInfo.sync && prefabInfo.root === this) { @@ -1345,7 +1354,7 @@ var Node = cc.Class({ _onBatchRestored () { this._upgrade_1x_to_2x(); - this._cullingMask = 1 << this._getActualGroupIndex(this); + this._cullingMask = 1 << _getActualGroupIndex(this); if (!this._activeInHierarchy) { // deactivate ActionManager and EventManager by default @@ -3060,16 +3069,7 @@ var Node = cc.Class({ actionManager && actionManager.pauseTarget(this); eventManager.pauseTarget(this); } - }, - - // traversal the node tree, child cullingMask must keep the same with the parent. - _getActualGroupIndex (node) { - let groupIndex = node.groupIndex; - if (groupIndex === 0 && node.parent) { - groupIndex = this._getActualGroupIndex(node.parent); - } - return groupIndex; - }, + } }); /** From b0a8bde1a4b78b5a853d9b2d17c1e5a276aa3b35 Mon Sep 17 00:00:00 2001 From: leda Date: Thu, 27 Sep 2018 19:45:46 -0700 Subject: [PATCH 0281/1631] cherry pick: call jsb.device.setMotion when set setAccelerometer on native (#3332) Commit: 4e380bf5653f070c87c96612d13dfc529e0c425b [4e380bf5] --- cocos2d/core/platform/CCInputExtension.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cocos2d/core/platform/CCInputExtension.js b/cocos2d/core/platform/CCInputExtension.js index 3bee4aaa707..1c71067ca77 100644 --- a/cocos2d/core/platform/CCInputExtension.js +++ b/cocos2d/core/platform/CCInputExtension.js @@ -73,6 +73,10 @@ inputManager.setAccelerometerEnabled = function (isEnable) { _t._accelCurTime = 0; scheduler.unscheduleUpdate(_t); } + + if (CC_JSB) { + jsb.device.setMotionEnabled(isEnable); + } }; /** @@ -83,6 +87,10 @@ inputManager.setAccelerometerEnabled = function (isEnable) { inputManager.setAccelerometerInterval = function (interval) { if (this._accelInterval !== interval) { this._accelInterval = interval; + + if (CC_JSB) { + jsb.device.setMotionInterval(interval); + } } }; From 785cfae548130939658f13465a9f38f894bb197a Mon Sep 17 00:00:00 2001 From: PP Date: Sun, 30 Sep 2018 15:59:34 +0800 Subject: [PATCH 0282/1631] cherry pick: fix button bug for 2.1-release Commit: f06d8ee7d6b19d32e7c0f2933685b9d152f0a18d [f06d8ee7] Parents: e447af6bcf --- cocos2d/core/CCNode.js | 2 +- cocos2d/core/components/CCButton.js | 141 +++++++++++++++++++++++----- 2 files changed, 119 insertions(+), 24 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index c5224baa7c4..ff1bc8c36e0 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -62,6 +62,7 @@ const SIZE_ON = 1 << 3; const ANCHOR_ON = 1 << 4; const COLOR_ON = 1 << 5; + let BuiltinGroupIndex = cc.Enum({ DEBUG: 31 }) @@ -1485,7 +1486,6 @@ var Node = cc.Class({ case EventType.COLOR_CHANGED: this._eventMask |= COLOR_ON; break; - } if (!this._bubblingListeners) { this._bubblingListeners = new EventTarget(); diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index c61d27bbd6e..160ace334f8 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -60,6 +60,13 @@ let Transition = cc.Enum({ SCALE: 3 }); +const State = cc.Enum({ + NORMAL: 0, + HOVER: 1, + PRESSED: 2, + DISABLED: 3, +}); + /** * !#en * Button has 4 Transition types
@@ -132,10 +139,6 @@ let Button = cc.Class({ this._originalScale = cc.Vec2.ZERO; this._sprite = null; - - if (CC_EDITOR) { - this._previousNormalSprite = null; - } }, editor: CC_EDITOR && { @@ -158,14 +161,7 @@ let Button = cc.Class({ interactable: { default: true, tooltip: CC_DEV && 'i18n:COMPONENT.button.interactable', - notify (oldValue) { - if (CC_EDITOR) { - if (oldValue) { - this._previousNormalSprite = this.normalSprite; - } else { - this.normalSprite = this._previousNormalSprite; - } - } + notify () { this._updateState(); if (!this.interactable) { @@ -207,7 +203,10 @@ let Button = cc.Class({ default: Transition.NONE, tooltip: CC_DEV && 'i18n:COMPONENT.button.transition', type: Transition, - animatable: false + animatable: false, + notify (oldValue) { + this._updateTransition(oldValue); + }, }, // color transition @@ -222,6 +221,9 @@ let Button = cc.Class({ displayName: 'Normal', tooltip: CC_DEV && 'i18n:COMPONENT.button.normal_color', notify () { + if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL) { + this.target.opacity = this.normalColor.a; + } this._updateState(); } }, @@ -235,6 +237,12 @@ let Button = cc.Class({ default: cc.color(211, 211, 211), displayName: 'Pressed', tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color', + notify () { + if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED) { + this.target.opacity = this.pressedColor.a; + } + this._updateState(); + } }, /** @@ -246,6 +254,12 @@ let Button = cc.Class({ default: cc.Color.WHITE, displayName: 'Hover', tooltip: CC_DEV && 'i18n:COMPONENT.button.hover_color', + notify () { + if (this.transition === Transition.Color && this._getButtonState() === State.HOVER) { + this.target.opacity = this.hoverColor.a; + } + this._updateState(); + } }, /** @@ -258,6 +272,9 @@ let Button = cc.Class({ displayName: 'Disabled', tooltip: CC_DEV && 'i18n:COMPONENT.button.disabled_color', notify () { + if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED) { + this.target.opacity = this.disabledColor.a; + } this._updateState(); } }, @@ -432,12 +449,77 @@ let Button = cc.Class({ } else { this.node.on('spriteframe-changed', function (comp) { if (this.transition === Transition.SPRITE) { - this.normalSprite = comp.spriteFrame; + this._setCurrentStateSprite(comp.spriteFrame); + } + }.bind(this)); + this.node.on('color-changed', function (color) { + if (this.transition === Transition.COLOR) { + this._setCurrentStateColor(color); } }.bind(this)); } }, + _getStateColor (state) { + switch (state) { + case State.NORMAL: + return this.normalColor; + case State.HOVER: + return this.hoverColor; + case State.PRESSED: + return this.pressedColor; + case State.DISABLED: + return this.disabledColor; + } + }, + + _getStateSprite (state) { + switch (state) { + case State.NORMAL: + return this.normalSprite; + case State.HOVER: + return this.hoverSprite; + case State.PRESSED: + return this.pressedSprite; + case State.DISABLED: + return this.disabledSprite; + } + }, + + _setCurrentStateColor (color) { + switch ( this._getButtonState() ) { + case State.NORMAL: + this.normalColor = color; + break; + case State.HOVER: + this.hoverColor = color; + break; + case State.PRESSED: + this.pressedColor = color; + break; + case State.DISABLED: + this.disabledColor = color; + break; + } + }, + + _setCurrentStateSprite (spriteFrame) { + switch ( this._getButtonState() ) { + case State.NORMAL: + this.normalSprite = spriteFrame; + break; + case State.HOVER: + this.hoverSprite = spriteFrame; + break; + case State.PRESSED: + this.pressedSprite = spriteFrame; + break; + case State.DISABLED: + this.disabledSprite = spriteFrame; + break; + } + }, + onDisable () { this._resetState(); @@ -472,6 +554,7 @@ let Button = cc.Class({ if (this.transition === Transition.COLOR) { target.color = this._fromColor.lerp(this._toColor, ratio); + target.opacity = target.color.a; } else if (this.transition === Transition.SCALE) { target.scale = this._fromScale.lerp(this._toScale, ratio); } @@ -536,9 +619,9 @@ let Button = cc.Class({ } else { let state; if (hit) { - state = 'pressed'; + state = State.PRESSED; } else { - state = 'normal'; + state = State.NORMAL; } this._applyTransition(state); } @@ -591,26 +674,27 @@ let Button = cc.Class({ _getButtonState () { let state; if (!this.interactable) { - state = 'disabled'; + state = State.DISABLED; } else if (this._pressed) { - state = 'pressed'; + state = State.PRESSED; } else if (this._hovered) { - state = 'hover'; + state = State.HOVER; } else { - state = 'normal'; + state = State.NORMAL; } return state; }, _updateColorTransition (state) { - let color = this[state + 'Color']; + let color = this._getStateColor(state); let target = this.target; if (CC_EDITOR) { target.color = color; + target.opacity = color.a; } else { this._fromColor = target.color.clone(); @@ -621,14 +705,14 @@ let Button = cc.Class({ }, _updateSpriteTransition (state) { - let sprite = this[state + 'Sprite']; + let sprite = this._getStateSprite(state); if (this._sprite && sprite) { this._sprite.spriteFrame = sprite; } }, _updateScaleTransition (state) { - if (state === 'pressed') { + if (state === State.PRESSED) { this._zoomUp(); } else { this._zoomBack(); @@ -653,6 +737,17 @@ let Button = cc.Class({ this._transitionFinished = false; }, + _updateTransition (oldTransition) { + // Reset to normal data when change transition. + if (oldTransition === Transition.COLOR) { + this._updateColorTransition(State.NORMAL); + } + else if (oldTransition === Transition.SPRITE) { + this._updateSpriteTransition(State.NORMAL); + } + this._updateState(); + }, + _applyTransition (state) { let transition = this.transition; if (transition === Transition.COLOR) { From 745d494e35d94d9cc5a782134b023e1a8678b636 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 8 Oct 2018 19:12:04 +0800 Subject: [PATCH 0283/1631] fix button bug in engine for 2.1-release (#3354) --- cocos2d/core/components/CCButton.js | 30 ++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 160ace334f8..43731a79638 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -421,7 +421,7 @@ let Button = cc.Class({ let target = this.target; let transition = this.transition; if (transition === Transition.COLOR && this.interactable) { - target.color = this.normalColor; + this._setTargetColor(this.normalColor); } else if (transition === Transition.SCALE) { target.scaleX = this._originalScale.x; target.scaleY = this._originalScale.y; @@ -460,6 +460,15 @@ let Button = cc.Class({ } }, + _setTargetColor(color) { + let target = this.target; + if (!target) { + return; + } + target.color = color; + target.opacity = color.a; + }, + _getStateColor (state) { switch (state) { case State.NORMAL: @@ -553,8 +562,8 @@ let Button = cc.Class({ } if (this.transition === Transition.COLOR) { - target.color = this._fromColor.lerp(this._toColor, ratio); - target.opacity = target.color.a; + let color = this._fromColor.lerp(this._toColor, ratio); + this._setTargetColor(color); } else if (this.transition === Transition.SCALE) { target.scale = this._fromScale.lerp(this._toScale, ratio); } @@ -688,15 +697,18 @@ let Button = cc.Class({ return state; }, - _updateColorTransition (state) { + _updateColorTransitionImmediately (state) { let color = this._getStateColor(state); - let target = this.target; + this._setTargetColor(color); + }, - if (CC_EDITOR) { - target.color = color; - target.opacity = color.a; + _updateColorTransition (state) { + if (CC_EDITOR || state === State.DISABLED) { + this._updateColorTransitionImmediately(state); } else { + let color = this._getStateColor(state); + let target = this.target; this._fromColor = target.color.clone(); this._toColor = color; this.time = 0; @@ -740,7 +752,7 @@ let Button = cc.Class({ _updateTransition (oldTransition) { // Reset to normal data when change transition. if (oldTransition === Transition.COLOR) { - this._updateColorTransition(State.NORMAL); + this._updateColorTransitionImmediately(State.NORMAL); } else if (oldTransition === Transition.SPRITE) { this._updateSpriteTransition(State.NORMAL); From 222ce3905af024caaa135f74f5ef59f5f719bec3 Mon Sep 17 00:00:00 2001 From: kenshin <420373550@qq.com> Date: Tue, 9 Oct 2018 11:39:52 +0800 Subject: [PATCH 0284/1631] add cross origin flag for script download. (#3356) --- cocos2d/core/load-pipeline/downloader.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index aca582ea22f..0a157de53de 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -49,6 +49,11 @@ function downloadScript (item, callback, isAsync) { var url = item.url, d = document, s = document.createElement('script'); + + if (window.location.protocol !== 'file:') { + s.crossOrigin = 'anonymous'; + } + s.async = isAsync; s.src = urlAppendTimestamp(url); function loadHandler () { From 49c408a5a0085f788263c6d991ad4a36372d4c76 Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 12 Oct 2018 10:45:58 +0800 Subject: [PATCH 0285/1631] fix audio setCurrentTime unbindEnded (#3373) --- cocos2d/audio/CCAudio.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/audio/CCAudio.js b/cocos2d/audio/CCAudio.js index 3e52db2402e..68845a4a536 100644 --- a/cocos2d/audio/CCAudio.js +++ b/cocos2d/audio/CCAudio.js @@ -235,8 +235,8 @@ Audio.State = { return; } - this._unbindEnded(); if (!(CC_QQPLAY || CC_WECHATGAME)) { + this._unbindEnded(); this._bindEnded(function () { this._bindEnded(); }.bind(this)); From 2a00d8420a1dcf9aead95a86c3ff6da2a6ccb86b Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 17 Oct 2018 14:09:01 +0800 Subject: [PATCH 0286/1631] cherry pick: fix outline color invalid #3396 --- cocos2d/core/renderer/webgl/assemblers/label/ttf.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index 5a4373ceb3a..1283f442982 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -26,6 +26,8 @@ const js = require('../../../../platform/js'); const ttfUtls = require('../../../utils/label/ttf'); +const WHITE = cc.color(255, 255, 255, 255); + module.exports = js.addon({ createData (comp) { let renderData = comp.requestRenderData(); @@ -49,6 +51,7 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let data = comp._renderData._data, node = comp.node, + color = WHITE._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; From c6e8817f9939a2203764ce16056808b8fbc27395 Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 24 Oct 2018 09:56:49 +0800 Subject: [PATCH 0287/1631] fix editBox bug when can't find camera (#3412) --- .../core/components/editbox/CCEditBoxImpl.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index b7cef1d3da1..341fe1f3df1 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -350,6 +350,16 @@ let EditBoxImpl = cc.Class({ _updateMatrix () { if (!this._edTxt) return; + + let camera; + // can't find camera in editor + if (CC_EDITOR) { + camera = cc.Camera.main; + } + else { + camera = cc.Camera.findCamera(this._node); + } + if (!camera) return; let node = this._node, scaleX = cc.view._scaleX, scaleY = cc.view._scaleY, @@ -362,15 +372,6 @@ let EditBoxImpl = cc.Class({ _vec3.y = -node._anchorPoint.y * contentSize.height; math.mat4.translate(_matrix, _matrix, _vec3); - - let camera; - // can't find camera in editor - if (CC_EDITOR) { - camera = cc.Camera.main; - } - else { - camera = cc.Camera.findCamera(node); - } camera.getWorldToCameraMatrix(_matrix_temp); math.mat4.mul(_matrix_temp, _matrix_temp, _matrix); From c820e7ecc8da58b323c4e9f62f38f054306df980 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 29 Oct 2018 11:03:59 +0800 Subject: [PATCH 0288/1631] implement Object.getOwnPropertyDescriptors polyfill for Baidu browser (#3433) --- polyfill/object.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/polyfill/object.js b/polyfill/object.js index 3b0819887ff..8b73fd13cee 100644 --- a/polyfill/object.js +++ b/polyfill/object.js @@ -4,4 +4,20 @@ if (!Object.assign) { Object.assign = function (target, source) { cc.js.mixin(target, source); } +} + +// for Baidu browser +// Implementation reference to: +// http://2ality.com/2016/02/object-getownpropertydescriptors.html +// http://docs.w3cub.com/javascript/global_objects/reflect/ownkeys/ +if (!Object.getOwnPropertyDescriptors) { + Object.getOwnPropertyDescriptors = function (obj) { + let descriptors = {}; + let ownKeys = Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)); // equals to Reflect.ownKeys(obj) in ES6 + for(let i = 0; i < ownKeys.length; ++i){ + let key = ownKeys[i]; + descriptors[key] = Object.getOwnPropertyDescriptor(obj, key); + } + return descriptors; + } } \ No newline at end of file From f8a11427fce1162b364aff278229607a72b23775 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 1 Nov 2018 14:18:42 +0800 Subject: [PATCH 0289/1631] node should remove from scene after destroy (#3456) --- cocos2d/core/utils/base-node.js | 23 +---------------------- test/qunit/lib/polyfill-for-phantom.js | 8 +++++++- test/qunit/unit-es5/test-node.js | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/cocos2d/core/utils/base-node.js b/cocos2d/core/utils/base-node.js index fbf69401575..9c5934a6a82 100644 --- a/cocos2d/core/utils/base-node.js +++ b/cocos2d/core/utils/base-node.js @@ -1089,30 +1089,9 @@ var BaseNode = cc.Class({ } }, - _disableChildComps () { - // leave this._activeInHierarchy unmodified - var i, len = this._components.length; - for (i = 0; i < len; ++i) { - var component = this._components[i]; - if (component._enabled) { - cc.director._compScheduler.disableComp(component); - } - } - // deactivate recursively - for (i = 0, len = this._children.length; i < len; ++i) { - var node = this._children[i]; - if (node._active) { - node._disableChildComps(); - } - } - }, - destroy () { if (cc.Object.prototype.destroy.call(this)) { - // disable hierarchy - if (this._activeInHierarchy) { - this._disableChildComps(); - } + this.parent = null; } }, diff --git a/test/qunit/lib/polyfill-for-phantom.js b/test/qunit/lib/polyfill-for-phantom.js index 227c70e68cc..9752b43255e 100644 --- a/test/qunit/lib/polyfill-for-phantom.js +++ b/test/qunit/lib/polyfill-for-phantom.js @@ -151,4 +151,10 @@ if (!Object.assign) { return to; } }); - } \ No newline at end of file +} + +if (!Object.getOwnPropertySymbols) { + Object.getOwnPropertySymbols = function () { + return []; + }; +} diff --git a/test/qunit/unit-es5/test-node.js b/test/qunit/unit-es5/test-node.js index 82d23cfe9b7..f842c983ef6 100644 --- a/test/qunit/unit-es5/test-node.js +++ b/test/qunit/unit-es5/test-node.js @@ -123,6 +123,20 @@ test('activeInHierarchy', function () { strictEqual(child.activeInHierarchy, false, 'child should not activeInHierarchy after remove from scene'); }); +test('activeInHierarchy should be false after destroy', function () { + var parent = new cc.Node(); + var child = new cc.Node(); + child.parent = parent; + + cc.director.getScene().addChild(parent); + + parent.destroy(); + cc.game.step(); + + strictEqual(parent.activeInHierarchy, false, 'parent should not activeInHierarchy after destroy'); + strictEqual(child.activeInHierarchy, false, 'child should not activeInHierarchy after destroy'); +}); + test('activation logic for component', function () { // 这里主要测试node,不是测试component From 1f3e74da4758e27846acfc89d5281356836824b5 Mon Sep 17 00:00:00 2001 From: PP Date: Sun, 4 Nov 2018 11:19:50 +0800 Subject: [PATCH 0290/1631] fix different editbox blur behaviour in iOS and Android (#3446) --- cocos2d/core/components/editbox/CCEditBoxImpl.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index 341fe1f3df1..3b1711ab086 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -494,6 +494,7 @@ function _inputValueHandle (input, editBoxImpl) { function registerInputEventListener (tmpEdTxt, editBoxImpl, isTextarea) { let inputLock = false; + let blurWhenComposition = false; let cbs = editBoxImpl.__eventListeners; cbs.compositionstart = function () { inputLock = true; @@ -502,6 +503,11 @@ function registerInputEventListener (tmpEdTxt, editBoxImpl, isTextarea) { cbs.compositionend = function () { inputLock = false; + if (blurWhenComposition) { + // restore input value when composition not complete and blur input + this.value = editBoxImpl._text; + blurWhenComposition = false; + } _inputValueHandle(this, editBoxImpl); }; tmpEdTxt.addEventListener('compositionend', cbs.compositionend); @@ -550,7 +556,12 @@ function registerInputEventListener (tmpEdTxt, editBoxImpl, isTextarea) { tmpEdTxt.addEventListener('keypress', cbs.keypress); cbs.blur = function () { - editBoxImpl._text = this.value; + if (inputLock) { + blurWhenComposition = true; + } + else { + editBoxImpl._text = this.value; + } editBoxImpl._endEditing(); }; tmpEdTxt.addEventListener('blur', cbs.blur); From 9e09f130874ec0a5b165f5213ce0557b99543261 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Mon, 5 Nov 2018 19:35:48 +0800 Subject: [PATCH 0291/1631] cherry pick: Add label API to update contentSize immediately. (#3452) Commit: cf2d4d15203a4ce540f6dadb9d2b19cc80e21b26 [cf2d4d15] Parents: bd3942c049 --- cocos2d/core/components/CCLabel.js | 5 ++--- cocos2d/core/renderer/utils/label/ttf.js | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 8326a8c26a7..8f5b4883273 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -467,8 +467,7 @@ let Label = cc.Class({ this.node.on(cc.Node.EventType.ANCHOR_CHANGED, this._updateRenderData, this); this._checkStringEmpty(); - this._updateAssembler(); - this._applyFontTexture(); + this._updateRenderData(true); }, onDisable () { @@ -486,7 +485,7 @@ let Label = cc.Class({ } this._super(); }, - + _canRender () { let result = this._super(); let font = this.font; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 0c2e97b16eb..ab0739c80d6 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -422,7 +422,6 @@ module.exports = { let paragraphedStrings = _string.split('\n'); let paragraphLength = this._calculateParagraphLength(paragraphedStrings, _context); - _splitedStrings = paragraphedStrings; let i = 0; let totalHeight = 0; let maxLength = 0; @@ -457,7 +456,6 @@ module.exports = { _fontDesc = this._getFontDesc(); _context.font = _fontDesc; - _splitedStrings = []; totalHeight = 0; for (i = 0; i < paragraphedStrings.length; ++i) { let j = 0; @@ -472,7 +470,6 @@ module.exports = { totalHeight += this._getLineHeight(); ++j; } - _splitedStrings = _splitedStrings.concat(textFragment); } if (tryDivideByTwo) { From d32e3ef8445c410bce99ed0e08632a8cd105d9fc Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 5 Nov 2018 19:37:01 +0800 Subject: [PATCH 0292/1631] fix error when set volume as a string value (#3455) --- cocos2d/audio/CCAudioEngine.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/cocos2d/audio/CCAudioEngine.js b/cocos2d/audio/CCAudioEngine.js index 8a44b64c0ae..40cf85031f1 100644 --- a/cocos2d/audio/CCAudioEngine.js +++ b/cocos2d/audio/CCAudioEngine.js @@ -90,6 +90,17 @@ let getAudioFromId = function (id) { return _id2audio[id]; }; +let handleVolume = function (volume) { + if (!volume) { + // set default volume as 1 + volume = 1; + } + else if (typeof volume === 'string') { + volume = Number.parseFloat(volume); + } + return volume; +}; + /** * !#en cc.audioEngine is the singleton object, it provide simple audio APIs. * !#zh @@ -150,9 +161,7 @@ var audioEngine = { } audio.setLoop(loop || false); - if (typeof volume !== 'number') { - volume = 1; - } + volume = handleVolume(volume); audio.setVolume(volume); audio.play(); @@ -647,6 +656,7 @@ var audioEngine = { * cc.audioEngine.setMusicVolume(0.5); */ setMusicVolume: function (volume) { + volume = handleVolume(volume); var music = this._music; music.volume = volume; this.setVolume(music.id, music.volume); @@ -690,6 +700,7 @@ var audioEngine = { * cc.audioEngine.setEffectsVolume(0.5); */ setEffectsVolume: function (volume) { + volume = handleVolume(volume); var musicId = this._music.id; this._effect.volume = volume; for (var id in _id2audio) { From bff683fbcdc7a01afd57a576899bf030bf53b940 Mon Sep 17 00:00:00 2001 From: FengXuner <32702270+FengXuner@users.noreply.github.com> Date: Mon, 5 Nov 2018 19:43:20 +0800 Subject: [PATCH 0293/1631] Add onTouchCancel function to CCMouseJoint (#3380) * Add onTouchCancel function to CCMouseJoint * Use onTouchEnd function to process TOUCH_CANCEL event --- cocos2d/core/physics/joint/CCMouseJoint.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/physics/joint/CCMouseJoint.js b/cocos2d/core/physics/joint/CCMouseJoint.js index b75bf91434c..f16869cf51e 100644 --- a/cocos2d/core/physics/joint/CCMouseJoint.js +++ b/cocos2d/core/physics/joint/CCMouseJoint.js @@ -211,6 +211,7 @@ var MouseJoint = cc.Class({ mouseRegion.on(cc.Node.EventType.TOUCH_START, this.onTouchBegan, this); mouseRegion.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this); mouseRegion.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this); + mouseRegion.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this); }, onEnable: function () { From fcfd62dc88978f5346767db7fc1a6994ad36b29b Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 5 Nov 2018 19:44:39 +0800 Subject: [PATCH 0294/1631] cherry pick: fix this.target is null (#3458) Commit: 240d54e5998627cece95a8b05029a4f2ce09b6e1 [240d54e5] Parents: efa1a9350d --- cocos2d/core/components/CCButton.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 43731a79638..61267e30553 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -221,7 +221,7 @@ let Button = cc.Class({ displayName: 'Normal', tooltip: CC_DEV && 'i18n:COMPONENT.button.normal_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL) { + if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL && this.target) { this.target.opacity = this.normalColor.a; } this._updateState(); @@ -238,7 +238,7 @@ let Button = cc.Class({ displayName: 'Pressed', tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED) { + if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED && this.target) { this.target.opacity = this.pressedColor.a; } this._updateState(); @@ -255,7 +255,7 @@ let Button = cc.Class({ displayName: 'Hover', tooltip: CC_DEV && 'i18n:COMPONENT.button.hover_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.HOVER) { + if (this.transition === Transition.Color && this._getButtonState() === State.HOVER && this.target) { this.target.opacity = this.hoverColor.a; } this._updateState(); @@ -272,7 +272,7 @@ let Button = cc.Class({ displayName: 'Disabled', tooltip: CC_DEV && 'i18n:COMPONENT.button.disabled_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED) { + if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED && this.target) { this.target.opacity = this.disabledColor.a; } this._updateState(); @@ -419,6 +419,9 @@ let Button = cc.Class({ this._hovered = false; // // Restore button status let target = this.target; + if (!target) { + return; + } let transition = this.transition; if (transition === Transition.COLOR && this.interactable) { this._setTargetColor(this.normalColor); @@ -547,6 +550,9 @@ let Button = cc.Class({ update (dt) { let target = this.target; + if (!target) { + return; + } if (this._transitionFinished) return; if (this.transition !== Transition.COLOR && this.transition !== Transition.SCALE) return; @@ -707,8 +713,11 @@ let Button = cc.Class({ this._updateColorTransitionImmediately(state); } else { - let color = this._getStateColor(state); let target = this.target; + if (!target) { + return; + } + let color = this._getStateColor(state); this._fromColor = target.color.clone(); this._toColor = color; this.time = 0; @@ -741,6 +750,9 @@ let Button = cc.Class({ }, _zoomBack () { + if (!this.target) { + return; + } this._fromScale.x = this.target.scaleX; this._fromScale.y = this.target.scaleY; this._toScale.x = this._originalScale.x; From 8baf50663f4c789f50b2ea3aa30040119646887a Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 5 Nov 2018 19:45:21 +0800 Subject: [PATCH 0295/1631] add scale calculate in layout when child scale changed (#3467) --- cocos2d/core/components/CCLayout.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/core/components/CCLayout.js b/cocos2d/core/components/CCLayout.js index f0fd50710d4..f7bf7d3d46a 100644 --- a/cocos2d/core/components/CCLayout.js +++ b/cocos2d/core/components/CCLayout.js @@ -462,6 +462,7 @@ var Layout = cc.Class({ child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); + child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, @@ -473,6 +474,7 @@ var Layout = cc.Class({ child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); + child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, @@ -481,6 +483,7 @@ var Layout = cc.Class({ child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); + child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); @@ -490,6 +493,7 @@ var Layout = cc.Class({ child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); + child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); From 425f2d02f6a9343c5e2b7bca1620e13771195e52 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 8 Nov 2018 10:57:59 +0800 Subject: [PATCH 0296/1631] fix button transition serialized value error for 2d-tasks/issues/755 (#3474) --- cocos2d/core/components/CCButton.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 61267e30553..9901896474c 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -207,6 +207,7 @@ let Button = cc.Class({ notify (oldValue) { this._updateTransition(oldValue); }, + formerlySerializedAs: 'transition' }, // color transition @@ -242,7 +243,8 @@ let Button = cc.Class({ this.target.opacity = this.pressedColor.a; } this._updateState(); - } + }, + formerlySerializedAs: 'pressedColor' }, /** @@ -259,7 +261,8 @@ let Button = cc.Class({ this.target.opacity = this.hoverColor.a; } this._updateState(); - } + }, + formerlySerializedAs: 'hoverColor' }, /** From dcb91c5e40fd9fe4e0c45ffcdaf07d5ea6f4a61c Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 8 Nov 2018 14:24:31 +0800 Subject: [PATCH 0297/1631] fix button _resetState error, the isvalid of the button target must be true (#3476) --- cocos2d/core/components/CCButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 9901896474c..8afdd864013 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -422,7 +422,7 @@ let Button = cc.Class({ this._hovered = false; // // Restore button status let target = this.target; - if (!target) { + if (!target || !target.isValid) { return; } let transition = this.transition; From 8bbe77f2b500a0c274c5b267ea9d2bf5ed30fa5c Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 9 Nov 2018 16:14:34 +0800 Subject: [PATCH 0298/1631] nodes should be destroyed with the scene. fix #3456 (#3483) --- cocos2d/core/CCScene.js | 8 +++++++- cocos2d/core/node-activator.js | 4 ++-- cocos2d/core/utils/base-node.js | 2 +- test/qunit/unit-es5/test-component-scheduler.js | 6 +++--- test/qunit/unit-es5/test-node.js | 11 +++++++++++ 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/CCScene.js b/cocos2d/core/CCScene.js index da03a5c525e..e1f02f91dc8 100644 --- a/cocos2d/core/CCScene.js +++ b/cocos2d/core/CCScene.js @@ -70,7 +70,13 @@ cc.Scene = cc.Class({ }, destroy: function () { - this._super(); + if (cc.Object.prototype.destroy.call(this)) { + var children = this._children; + for (var i = 0; i < children.length; ++i) { + children[i].active = false; + } + } + this._active = false; this._activeInHierarchy = false; }, diff --git a/cocos2d/core/node-activator.js b/cocos2d/core/node-activator.js index 47afcaab5b8..77f171cb1c1 100644 --- a/cocos2d/core/node-activator.js +++ b/cocos2d/core/node-activator.js @@ -248,7 +248,7 @@ var NodeActivator = cc.Class({ activateComp: CC_EDITOR ? function (comp, preloadInvoker, onLoadInvoker, onEnableInvoker) { if (!cc.isValid(comp, true)) { - // destroied before activating + // destroyed before activating return; } if (cc.engine._isPlaying || comp.constructor._executeInEditMode) { @@ -288,7 +288,7 @@ var NodeActivator = cc.Class({ } } : function (comp, preloadInvoker, onLoadInvoker, onEnableInvoker) { if (!cc.isValid(comp, true)) { - // destroied before activating + // destroyed before activating return; } if (!(comp._objFlags & IsPreloadStarted)) { diff --git a/cocos2d/core/utils/base-node.js b/cocos2d/core/utils/base-node.js index 9c5934a6a82..dcca2fd1978 100644 --- a/cocos2d/core/utils/base-node.js +++ b/cocos2d/core/utils/base-node.js @@ -1091,7 +1091,7 @@ var BaseNode = cc.Class({ destroy () { if (cc.Object.prototype.destroy.call(this)) { - this.parent = null; + this.active = false; } }, diff --git a/test/qunit/unit-es5/test-component-scheduler.js b/test/qunit/unit-es5/test-component-scheduler.js index a1fab6658a6..5ec0d7d464e 100644 --- a/test/qunit/unit-es5/test-component-scheduler.js +++ b/test/qunit/unit-es5/test-component-scheduler.js @@ -544,16 +544,16 @@ test('set sibling index during onDisable', function () { compOfChild.onEnable.once('child component should be re-enabled'); }); - test('component might be destroied when destroy() called before node activating', function () { + test('component might be destroyed when destroy() called before node activating', function () { var node = new cc.Node(); - var comp = createDisabledComp(node, 'destroied'); + var comp = createDisabledComp(node, 'destroyed'); comp.onDestroy = new Callback().disable('onDestroy should not be called'); comp.destroy(); cc.director.getScene().addChild(node); cc.game.step(); - strictEqual(comp.isValid, false, 'component should be destroied'); + strictEqual(comp.isValid, false, 'component should be destroyed'); }); // test('could deactivate parent in onLoad', function () { diff --git a/test/qunit/unit-es5/test-node.js b/test/qunit/unit-es5/test-node.js index f842c983ef6..a9657f1e84b 100644 --- a/test/qunit/unit-es5/test-node.js +++ b/test/qunit/unit-es5/test-node.js @@ -137,6 +137,17 @@ test('activeInHierarchy should be false after destroy', function () { strictEqual(child.activeInHierarchy, false, 'child should not activeInHierarchy after destroy'); }); +test('nodes should be destroyed with the scene', function () { + var child = new cc.Node(); + var scene = cc.director.getScene(); + child.parent = scene; + + cc.director.runSceneImmediate(new cc.Scene()); + + strictEqual(child.activeInHierarchy, false, 'nodes should not activeInHierarchy after destroy'); + strictEqual(child.isValid, false, 'nodes should be destroyed with the scene'); +}); + test('activation logic for component', function () { // 这里主要测试node,不是测试component From e3904169cd400d74063de902e65fff113e1cf853 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 9 Nov 2018 18:09:48 +0800 Subject: [PATCH 0299/1631] revert #3476, already fixed in #3483 (#3490) --- cocos2d/core/components/CCButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 8afdd864013..9901896474c 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -422,7 +422,7 @@ let Button = cc.Class({ this._hovered = false; // // Restore button status let target = this.target; - if (!target || !target.isValid) { + if (!target) { return; } let transition = this.transition; From ea4040952587443674f15fa88cb902ac0c4ae2b0 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Wed, 19 Dec 2018 20:48:59 +0800 Subject: [PATCH 0300/1631] fixed the issue that deferred loading makes cc.Mask throw exceptions with image stencil --- cocos2d/core/components/CCMask.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index b8fcf9ecf58..e029e28457e 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -273,6 +273,7 @@ let Mask = cc.Class({ // Do not render when sprite frame is not ready this.markForRender(false); if (this._spriteFrame) { + this.markForUpdateRenderData(false); this._spriteFrame.once('load', this._onTextureLoaded, this); this._spriteFrame.ensureLoadTexture(); } From 13409bf63adfe2f43c2b234734a7fca8a8b8ef76 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 20 Dec 2018 09:41:42 +0800 Subject: [PATCH 0301/1631] improve ttf code to reduce cached objects (#3658) small improvement to ttf code for memory footprint --- cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js index 97c0513c062..764a64f29de 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js @@ -27,7 +27,7 @@ const js = require('../../../../../platform/js'); const ttfUtls = require('../../../../utils/label/ttf'); const fillMeshVertices = require('../../utils').fillMeshVertices; -const WHITE = cc.color(255, 255, 255, 255); +const WHITE_VAL = cc.Color.WHITE._val; module.exports = js.addon({ createData (comp) { @@ -41,7 +41,7 @@ module.exports = js.addon({ }, fillBuffers (comp, renderer) { - fillMeshVertices(comp.node, renderer._meshBuffer, comp._renderData, WHITE._val); + fillMeshVertices(comp.node, renderer._meshBuffer, comp._renderData, WHITE_VAL); }, _updateVerts (comp) { From c39acefc25642bf6f5b594f0030b668e12e01604 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 20 Dec 2018 09:58:33 +0800 Subject: [PATCH 0302/1631] cherry pick: set button.node for default button.target (#3491) Commit: 6b0e185762bc5cb3c0f1548616e7e936f4a7101a [6b0e1857] Parents: c749ba8ec1 (+1 squashed commit) --- cocos2d/core/components/CCButton.js | 71 ++++++++++++----------------- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 9901896474c..37378899675 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -222,8 +222,8 @@ let Button = cc.Class({ displayName: 'Normal', tooltip: CC_DEV && 'i18n:COMPONENT.button.normal_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL && this.target) { - this.target.opacity = this.normalColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL) { + this._getTarget().opacity = this.normalColor.a; } this._updateState(); } @@ -239,8 +239,8 @@ let Button = cc.Class({ displayName: 'Pressed', tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED && this.target) { - this.target.opacity = this.pressedColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED) { + this._getTarget().opacity = this.pressedColor.a; } this._updateState(); }, @@ -257,8 +257,8 @@ let Button = cc.Class({ displayName: 'Hover', tooltip: CC_DEV && 'i18n:COMPONENT.button.hover_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.HOVER && this.target) { - this.target.opacity = this.hoverColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.HOVER) { + this._getTarget().opacity = this.hoverColor.a; } this._updateState(); }, @@ -275,8 +275,8 @@ let Button = cc.Class({ displayName: 'Disabled', tooltip: CC_DEV && 'i18n:COMPONENT.button.disabled_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED && this.target) { - this.target.opacity = this.disabledColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED) { + this._getTarget().opacity = this.disabledColor.a; } this._updateState(); } @@ -410,9 +410,6 @@ let Button = cc.Class({ }, __preload () { - if (!this.target) { - this.target = this.node; - } this._applyTarget(); this._updateState(); }, @@ -421,10 +418,7 @@ let Button = cc.Class({ this._pressed = false; this._hovered = false; // // Restore button status - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); let transition = this.transition; if (transition === Transition.COLOR && this.interactable) { this._setTargetColor(this.normalColor); @@ -466,11 +460,12 @@ let Button = cc.Class({ } }, + _getTarget () { + return this.target ? this.target : this.node; + }, + _setTargetColor(color) { - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); target.color = color; target.opacity = color.a; }, @@ -552,10 +547,7 @@ let Button = cc.Class({ }, update (dt) { - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); if (this._transitionFinished) return; if (this.transition !== Transition.COLOR && this.transition !== Transition.SCALE) return; @@ -598,11 +590,10 @@ let Button = cc.Class({ }, _applyTarget () { - this._sprite = this._getTargetSprite(this.target); - if (this.target) { - this._originalScale.x = this.target.scaleX; - this._originalScale.y = this.target.scaleY; - } + let target = this._getTarget(); + this._sprite = this._getTargetSprite(target); + this._originalScale.x = target.scaleX; + this._originalScale.y = target.scaleY; }, // touch event handler @@ -620,8 +611,9 @@ let Button = cc.Class({ // so we have to do hit test when touch moving let touch = event.touch; let hit = this.node._hitTest(touch.getLocation()); + let target = this._getTarget(); - if (this.transition === Transition.SCALE && this.target) { + if (this.transition === Transition.SCALE) { if (hit) { this._fromScale.x = this._originalScale.x; this._fromScale.y = this._originalScale.y; @@ -631,8 +623,8 @@ let Button = cc.Class({ } else { this.time = 0; this._transitionFinished = true; - this.target.scaleX = this._originalScale.x; - this.target.scaleY = this._originalScale.y; + target.scaleX = this._originalScale.x; + target.scaleY = this._originalScale.y; } } else { let state; @@ -716,10 +708,7 @@ let Button = cc.Class({ this._updateColorTransitionImmediately(state); } else { - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); let color = this._getStateColor(state); this._fromColor = target.color.clone(); this._toColor = color; @@ -753,11 +742,9 @@ let Button = cc.Class({ }, _zoomBack () { - if (!this.target) { - return; - } - this._fromScale.x = this.target.scaleX; - this._fromScale.y = this.target.scaleY; + let target = this._getTarget(); + this._fromScale.x = target.scaleX; + this._fromScale.y = target.scaleY; this._toScale.x = this._originalScale.x; this._toScale.y = this._originalScale.y; this.time = 0; @@ -787,9 +774,7 @@ let Button = cc.Class({ }, _resizeNodeToTargetNode: CC_EDITOR && function () { - if (this.target) { - this.node.setContentSize(this.target.getContentSize()); - } + this.node.setContentSize(this._getTarget().getContentSize()); }, _updateDisabledState () { From 5bbf7fcfc43768654810416a3a5974d91f643941 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Wed, 14 Nov 2018 14:56:56 +0800 Subject: [PATCH 0303/1631] Modify the material's hash value judgment to be strictly. (#3506) --- cocos2d/core/renderer/webgl/render-component-walker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/render-component-walker.js index db1971688c3..459ecc6c168 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/render-component-walker.js @@ -186,7 +186,7 @@ RenderComponentWalker.prototype = { }, _commitComp (comp, assembler, cullingMask) { - if (this.material._hash != comp._material._hash || + if (this.material._hash !== comp._material._hash || this.cullingMask !== cullingMask) { this._flush(); From 903afc7d88335535dc5a0e8cdd9fc0d4f2984f40 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 15 Nov 2018 13:48:17 +0800 Subject: [PATCH 0304/1631] fix video play fullscreen bug for 2d-tasks/issues/749/421/337 (#3496) * fix video play fullscreen bug for 2d-tasks/issues/749/421/337 * improve code * update className to tagName --- cocos2d/core/platform/CCScreen.js | 21 ++++- cocos2d/videoplayer/video-player-impl.js | 114 ++++++++++------------- 2 files changed, 69 insertions(+), 66 deletions(-) diff --git a/cocos2d/core/platform/CCScreen.js b/cocos2d/core/platform/CCScreen.js index 553c18bdf93..2247e57238e 100644 --- a/cocos2d/core/platform/CCScreen.js +++ b/cocos2d/core/platform/CCScreen.js @@ -116,6 +116,16 @@ cc.screen = /** @lends cc.screen# */{ * @param {Function} onFullScreenChange */ requestFullScreen: function (element, onFullScreenChange) { + if (element.tagName.toLowerCase() === "video") { + if (cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && element.readyState > 0) { + element.webkitEnterFullscreen && element.webkitEnterFullscreen(); + return; + } + else { + element.setAttribute("x5-video-player-fullscreen", "true"); + } + } + if (!this._supportsFullScreen) { return; } @@ -139,7 +149,16 @@ cc.screen = /** @lends cc.screen# */{ * @method exitFullScreen * @return {Boolean} */ - exitFullScreen: function () { + exitFullScreen: function (element) { + if (element.tagName.toLowerCase() === "video") { + if (cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser) { + element.webkitExitFullscreen && element.webkitExitFullscreen(); + return; + } + else { + element.setAttribute("x5-video-player-fullscreen", "false"); + } + } return this._supportsFullScreen ? document[this._fn.exitFullscreen]() : true; }, diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index d828c3228f9..58e8b320310 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -28,20 +28,16 @@ const sys = require('../core/platform/CCSys'); const renderEngine = require('../core/renderer/render-engine'); const math = renderEngine.math; -let _mat4_temp = math.mat4.create(); - -// ios brower need to wait until the video's loadedmetadata event -// has been fired before calling webkitEnterFullScreen() -function triggerFullScene (video, enable) { - if (!video) return; - if (enable) { - video.webkitEnterFullscreen && video.webkitEnterFullscreen(); - } - else { - video.webkitExitFullscreen && video.webkitExitFullscreen(); - } +const READY_STATE = { + HAVE_NOTHING: 0, + HAVE_METADATA: 1, + HAVE_CURRENT_DATA: 2, + HAVE_FUTURE_DATA: 3, + HAVE_ENOUGH_DATA: 4 } +let _mat4_temp = math.mat4.create(); + let VideoPlayerImpl = cc.Class({ name: 'VideoPlayerImpl', @@ -57,8 +53,6 @@ let VideoPlayerImpl = cc.Class({ this._loadedmeta = false; this._loaded = false; this._visible = false; - // 有一些浏览器第一次播放视频需要特殊处理,这个标记用来标识是否播放过 - this._played = false; this._playing = false; this._ignorePause = false; @@ -82,8 +76,11 @@ let VideoPlayerImpl = cc.Class({ let cbs = this.__eventListeners; cbs.loadedmetadata = function () { self._loadedmeta = true; - if (sys.os === sys.OS_IOS && sys.isBrowser) { - triggerFullScene(video, self._fullScreenEnabled); + if (self._fullScreenEnabled) { + cc.screen.requestFullScreen(video); + } + else { + cc.screen.exitFullScreen(video); } self._dispatchEvent(VideoPlayerImpl.EventType.META_LOADED); }; @@ -95,12 +92,21 @@ let VideoPlayerImpl = cc.Class({ cbs.play = function () { if (self._video !== video) return; self._playing = true; + self._updateVisibility(); self._dispatchEvent(VideoPlayerImpl.EventType.PLAYING); }; + // pause and stop callback cbs.pause = function () { - if (self._ignorePause || self._video !== video) return; + if (self._video !== video) { + return; + } self._playing = false; - self._dispatchEvent(VideoPlayerImpl.EventType.PAUSED); + if (self._ignorePause) { + return; + } + else { + self._dispatchEvent(VideoPlayerImpl.EventType.PAUSED); + } }; cbs.click = function () { self._dispatchEvent(VideoPlayerImpl.EventType.CLICKED); @@ -113,36 +119,37 @@ let VideoPlayerImpl = cc.Class({ video.addEventListener("click", cbs.click); function onCanPlay () { - if (this._loaded) + if (self._loaded || self._loadedmeta || self._playing) return; - let video = this._video; - if (video.readyState === 4) { - this._loaded = true; - // node.setContentSize(node._contentSize.width, node._contentSize.height); + let video = self._video; + if (video.readyState === READY_STATE.HAVE_ENOUGH_DATA) { video.currentTime = 0; - this._dispatchEvent(VideoPlayerImpl.EventType.READY_TO_PLAY); - this._updateVisibility(); + self._loaded = true; + self._dispatchEvent(VideoPlayerImpl.EventType.READY_TO_PLAY); + self._updateVisibility(); } } - cbs.onCanPlay = onCanPlay.bind(this); + cbs.onCanPlay = onCanPlay; video.addEventListener('canplay', cbs.onCanPlay); video.addEventListener('canplaythrough', cbs.onCanPlay); video.addEventListener('suspend', cbs.onCanPlay); }, _updateVisibility () { - if (!this._video) return; let video = this._video; + if (!video) return; + if (this._visible) { video.style.visibility = 'visible'; + this._forceUpdate = true; } else { video.style.visibility = 'hidden'; video.pause(); this._playing = false; + this._forceUpdate = false; } - this._forceUpdate = true; }, _updateSize (width, height) { @@ -164,10 +171,10 @@ let VideoPlayerImpl = cc.Class({ video.setAttribute('playsinline', ''); // Stupid tencent x5 adaptation - let orientation = cc.winSize.width > cc.winSize.height ? "landscape" : "portrait"; video.setAttribute("x5-playsinline", ""); video.setAttribute("x5-video-player-type", "h5"); - video.setAttribute("x5-video-player-fullscreen", "false"); + video.setAttribute("x5-video-player-fullscreen", this._fullScreenEnabled ? "true" : "false"); + let orientation = cc.winSize.width > cc.winSize.height ? "landscape" : "portrait"; video.setAttribute("x5-video-orientation", orientation); this._video = video; @@ -223,7 +230,6 @@ let VideoPlayerImpl = cc.Class({ let video = this._video; video.style["visibility"] = "hidden"; this._loaded = false; - this._played = false; this._playing = false; this._loadedmeta = false; @@ -248,34 +254,22 @@ let VideoPlayerImpl = cc.Class({ play: function () { let video = this._video; - if (!video || !this._visible) return; - - this._played = true; - if (this._playing) { - return; - } + if (!video || !this._visible || this._playing) return; if (VideoPlayerImpl._polyfill.autoplayAfterOperation) { let self = this; setTimeout(function () { video.play(); - self._playing = !video.paused; }, 20); } else { video.play(); - this._playing = !video.paused; } }, pause: function () { let video = this._video; - if (!this._playing) return; - - this._playing = false; - if (!video) { - return; - } + if (!this._playing || !video) return; video.pause(); }, @@ -287,15 +281,13 @@ let VideoPlayerImpl = cc.Class({ let video = this._video; if (!video || !this._visible) return; this._ignorePause = true; + video.currentTime = 0; video.pause(); - let self = this; setTimeout(function () { - self._dispatchEvent(VideoPlayerImpl.EventType.STOPPED); - self._ignorePause = false; - }, 0); - // 恢复到视频起始位置 - video.currentTime = 0; - this._playing = false; + this._dispatchEvent(VideoPlayerImpl.EventType.STOPPED); + this._ignorePause = false; + }.bind(this), 0); + }, setVolume: function (volume) { @@ -368,24 +360,16 @@ let VideoPlayerImpl = cc.Class({ }, setFullScreenEnabled: function (enable) { - let video = this._video; + let video = this._video; if (!video) { return; } this._fullScreenEnabled = enable; - if (sys.os === sys.OS_IOS && sys.isBrowser) { - if (this._loadedmeta) { - triggerFullScene(video, enable); - } + if (enable) { + cc.screen.requestFullScreen(video); } else { - if (enable) { - cc.screen.requestFullScreen(video); - } - else { - cc.screen.exitFullScreen(video); - } - video.setAttribute("x5-video-player-fullscreen", enable ? "true" : "false"); + cc.screen.exitFullScreen(video); } }, @@ -481,9 +465,9 @@ let VideoPlayerImpl = cc.Class({ h = this._h * scaleY; } else { - this._updateSize(this._w, this._h); w = this._w * scaleX; h = this._h * scaleY; + this._updateSize(this._w, this._h); } let appx = (w * _mat4_temp.m00) * node._anchorPoint.x; From 1c8076c897a6d6b98a43197bafbb300d14544c0f Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 19 Nov 2018 11:43:33 +0800 Subject: [PATCH 0305/1631] improve toggle component (#3450) --- cocos2d/core/components/CCToggle.js | 128 +++++++++---------- cocos2d/core/components/CCToggleContainer.js | 28 +++- cocos2d/core/components/CCToggleGroup.js | 4 +- 3 files changed, 82 insertions(+), 78 deletions(-) diff --git a/cocos2d/core/components/CCToggle.js b/cocos2d/core/components/CCToggle.js index 7a34233182d..4a808b84ed5 100644 --- a/cocos2d/core/components/CCToggle.js +++ b/cocos2d/core/components/CCToggle.js @@ -31,7 +31,7 @@ * @class Toggle * @extends Button */ -var Toggle = cc.Class({ +let Toggle = cc.Class({ name: 'cc.Toggle', extends: require('./CCButton'), editor: CC_EDITOR && { @@ -47,12 +47,34 @@ var Toggle = cc.Class({ * !#zh 如果这个设置为 true,则 check mark 组件会处于 enabled 状态,否则处于 disabled 状态。 * @property {Boolean} isChecked */ + _N$isChecked: true, isChecked: { - default: true, - tooltip: CC_DEV && 'i18n:COMPONENT.toggle.isChecked', - notify: function () { + get: function () { + return this._N$isChecked; + }, + set: function (value) { + if (value === this._N$isChecked) { + return; + } + + var group = this.toggleGroup || this._toggleContainer; + if (group && group.enabled && this._N$isChecked) { + if (!group.allowSwitchOff) { + return; + } + + } + + this._N$isChecked = value; this._updateCheckMark(); - } + + if (group && group.enabled) { + group.updateToggles(this); + } + + this._emitToggleEvents(); + }, + tooltip: CC_DEV && 'i18n:COMPONENT.toggle.isChecked', }, /** @@ -120,6 +142,33 @@ var Toggle = cc.Class({ } }, + _hideCheckMark () { + this._N$isChecked = false; + this._updateCheckMark(); + }, + + toggle: function (event) { + this.isChecked = !this.isChecked; + }, + + /** + * !#en Make the toggle button checked. + * !#zh 使 toggle 按钮处于选中状态 + * @method check + */ + check: function () { + this.isChecked = true; + }, + + /** + * !#en Make the toggle button unchecked. + * !#zh 使 toggle 按钮处于未选中状态 + * @method uncheck + */ + uncheck: function () { + this.isChecked = false; + }, + _updateCheckMark: function () { if (this.checkMark) { this.checkMark.node.active = !!this.isChecked; @@ -147,85 +196,22 @@ var Toggle = cc.Class({ this.node.off('click', this.toggle, this); }, - toggle: function (event) { - var group = this.toggleGroup || this._toggleContainer; - - if (group && group.enabled && this.isChecked) { - if (!group.allowSwitchOff) { - return; - } - } - - this.isChecked = !this.isChecked; - - this._updateCheckMark(); - - if (group && group.enabled) { - group.updateToggles(this); - } - - this._emitToggleEvents(); - }, - _emitToggleEvents: function () { - if (CC_EDITOR) { return; } this.node.emit('toggle', this); if (this.checkEvents) { cc.Component.EventHandler.emitEvents(this.checkEvents, this); } - }, - - /** - * !#en Make the toggle button checked. - * !#zh 使 toggle 按钮处于选中状态 - * @method check - */ - check: function () { - var group = this.toggleGroup || this._toggleContainer; - - if (group && group.enabled && this.isChecked) { - if (!group.allowSwitchOff) { - return; - } - } - - this.isChecked = true; - - if (group && group.enabled) { - group.updateToggles(this); - } - - this._emitToggleEvents(); - }, - - /** - * !#en Make the toggle button unchecked. - * !#zh 使 toggle 按钮处于未选中状态 - * @method uncheck - */ - uncheck: function () { - var group = this.toggleGroup || this._toggleContainer; - - if (group && group.enabled && this.isChecked) { - if (!group.allowSwitchOff) { - return; - } - } - - this.isChecked = false; - - this._emitToggleEvents(); } + }); cc.Toggle = module.exports = Toggle; - -var js = require('../platform/js'); +const js = require('../platform/js'); js.get(Toggle.prototype, '_toggleContainer', function () { - var parent = this.node.parent; + let parent = this.node.parent; if (cc.Node.isNode(parent)) { return parent.getComponent(cc.ToggleContainer); } diff --git a/cocos2d/core/components/CCToggleContainer.js b/cocos2d/core/components/CCToggleContainer.js index ad400d0e108..f7fb2560aaf 100644 --- a/cocos2d/core/components/CCToggleContainer.js +++ b/cocos2d/core/components/CCToggleContainer.js @@ -55,21 +55,39 @@ var ToggleContainer = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.toggle_group.allowSwitchOff', default: false }, + + /** + * !#en If Toggle is clicked, it will trigger event's handler + * !#zh Toggle 按钮的点击事件列表。 + * @property {Component.EventHandler[]} checkEvents + */ + checkEvents: { + default: [], + type: cc.Component.EventHandler + }, }, updateToggles: function (toggle) { - this.toggleItems.forEach(function (item) { - if (toggle.isChecked && item !== toggle) { - item.isChecked = false; + if(!this.enabledInHierarchy) return; + + if (toggle.isChecked) { + this.toggleItems.forEach(function (item) { + if (item !== toggle && item.isChecked && item.enabled) { + item._hideCheckMark(); + } + }); + + if (this.checkEvents) { + cc.Component.EventHandler.emitEvents(this.checkEvents, toggle); } - }); + } }, _allowOnlyOneToggleChecked: function () { var isChecked = false; this.toggleItems.forEach(function (item) { if (isChecked) { - item.isChecked = false; + item._hideCheckMark(); } else if (item.isChecked) { isChecked = true; diff --git a/cocos2d/core/components/CCToggleGroup.js b/cocos2d/core/components/CCToggleGroup.js index 81ffa4397d8..2443e20862e 100644 --- a/cocos2d/core/components/CCToggleGroup.js +++ b/cocos2d/core/components/CCToggleGroup.js @@ -74,7 +74,7 @@ var ToggleGroup = cc.Class({ this._toggleItems.forEach(function (item){ if(toggle.isChecked) { if (item !== toggle && item.isChecked && item.enabled) { - item.isChecked = false; + item._hideCheckMark(); } } }); @@ -100,7 +100,7 @@ var ToggleGroup = cc.Class({ var isChecked = false; this._toggleItems.forEach(function (item) { if(isChecked && item.enabled) { - item.isChecked = false; + item._hideCheckMark(); } if (item.isChecked && item.enabled) { From bfba4bf47a187a204b04623f9a1662fc20b7b1e4 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 19 Nov 2018 12:34:07 +0800 Subject: [PATCH 0306/1631] adapter wx.onShow params (#3515) --- cocos2d/core/CCGame.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 5ea17a98f8e..1afdc004695 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -833,10 +833,11 @@ var game = { game.emit(game.EVENT_HIDE); } } - function onShown () { + // In order to adapt the most of platforms the onshow API. + function onShown (arg0, arg1, arg2, arg3, arg4) { if (hidden) { hidden = false; - game.emit(game.EVENT_SHOW); + game.emit(game.EVENT_SHOW, arg0, arg1, arg2, arg3, arg4); } } From 7eb432b8ceef5d1cba8c8c3e44693557035d39ab Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 20 Nov 2018 16:57:43 +0800 Subject: [PATCH 0307/1631] add a new prop to layout to controll the scale affect (#3529) --- cocos2d/core/components/CCLayout.js | 50 +++++++++++++++++++++-------- editor/i18n/en/localization.js | 3 +- editor/i18n/zh/localization.js | 3 +- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/cocos2d/core/components/CCLayout.js b/cocos2d/core/components/CCLayout.js index f7bf7d3d46a..bc068b0da41 100644 --- a/cocos2d/core/components/CCLayout.js +++ b/cocos2d/core/components/CCLayout.js @@ -395,6 +395,23 @@ var Layout = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.layout.horizontal_direction', animatable: false }, + + /** + * !#en Adjust the layout if the children scaled. + * !#zh 子节点缩放比例是否影响布局。 + * @property affectedByScale + * @type {Boolean} + * @default false + */ + affectedByScale: { + default: false, + notify: function () { + // every time you switch this state, the layout will be calculated. + this._doLayoutDirty(); + }, + animatable: false, + tooltip: CC_DEV && 'i18n:COMPONENT.layout.affected_by_scale' + } }, statics: { @@ -435,6 +452,10 @@ var Layout = cc.Class({ this._layoutDirty = true; }, + _doScaleDirty: function () { + this._layoutDirty = this._layoutDirty || this.affectedByScale; + }, + _addEventListeners: function () { cc.director.on(cc.Director.EVENT_AFTER_UPDATE, this.updateLayout, this); this.node.on(NodeEvent.SIZE_CHANGED, this._resized, this); @@ -459,10 +480,10 @@ var Layout = cc.Class({ var children = this.node.children; for (var i = 0; i < children.length; ++i) { var child = children[i]; + child.on(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, @@ -471,29 +492,29 @@ var Layout = cc.Class({ var children = this.node.children; for (var i = 0; i < children.length; ++i) { var child = children[i]; + child.off(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, _childAdded: function (child) { + child.on(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); }, _childRemoved: function (child) { + child.off(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); @@ -541,8 +562,8 @@ var Layout = cc.Class({ for (var i = 0; i < children.length; ++i) { var child = children[i]; - let childScaleX = Math.abs(child.scaleX); - let childScaleY = Math.abs(child.scaleY); + let childScaleX = this._getUsedScaleValue(child.scaleX); + let childScaleY = this._getUsedScaleValue(child.scaleY); if (!child.activeInHierarchy) { continue; } @@ -639,7 +660,7 @@ var Layout = cc.Class({ var child = children[i]; if (child.activeInHierarchy) { activeChildCount++; - newHeight += child.height * Math.abs(child.scaleY); + newHeight += child.height * this._getUsedScaleValue(child.scaleY); } } @@ -687,8 +708,8 @@ var Layout = cc.Class({ for (var i = 0; i < children.length; ++i) { var child = children[i]; - let childScaleX = Math.abs(child.scaleX); - let childScaleY = Math.abs(child.scaleY); + let childScaleX = this._getUsedScaleValue(child.scaleX); + let childScaleY = this._getUsedScaleValue(child.scaleY); if (!child.activeInHierarchy) { continue; } @@ -832,7 +853,7 @@ var Layout = cc.Class({ } var fnPositionY = function (child, topOffset, row) { - return bottomBoundaryOfLayout + sign * (topOffset + child.anchorY * child.height * Math.abs(child.scaleY) + paddingY + row * this.spacingY); + return bottomBoundaryOfLayout + sign * (topOffset + child.anchorY * child.height * this._getUsedScaleValue(child.scaleY) + paddingY + row * this.spacingY); }.bind(this); @@ -873,7 +894,7 @@ var Layout = cc.Class({ } var fnPositionX = function (child, leftOffset, column) { - return leftBoundaryOfLayout + sign * (leftOffset + child.anchorX * child.width * Math.abs(child.scaleX) + paddingX + column * this.spacingX); + return leftBoundaryOfLayout + sign * (leftOffset + child.anchorX * child.width * this._getUsedScaleValue(child.scaleX) + paddingX + column * this.spacingX); }.bind(this); var newWidth = 0; @@ -921,7 +942,7 @@ var Layout = cc.Class({ var child = children[i]; if (child.activeInHierarchy) { activeChildCount++; - newWidth += child.width * Math.abs(child.scaleX); + newWidth += child.width * this._getUsedScaleValue(child.scaleX); } } newWidth += (activeChildCount - 1) * this.spacingX + this.paddingLeft + this.paddingRight; @@ -966,6 +987,10 @@ var Layout = cc.Class({ } }, + _getUsedScaleValue (value) { + return this.affectedByScale ? Math.abs(value) : 1; + }, + /** * !#en Perform the layout update * !#zh 立即执行更新布局 @@ -985,7 +1010,6 @@ var Layout = cc.Class({ this._layoutDirty = false; } } - }); /** diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 3b30566ecfb..4e55aea4797 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -197,7 +197,8 @@ module.exports = { "vertical_direction": "Vertically align in the direction of the child Nodes: \n 1. TOP_TO_BOTTOM, \n 2. BOTTOM_TO_TOP", "horizontal_direction": "Horizontally align in the direction of the child Nodes: \n 1. LEFT_TO_RIGHT \n 2. RIGHT_TO_LEFT", "cell_size": "In Grid layout, the size of each child element.", - "start_axis": "In Grid layout, the arrangement direction of children elements." + "start_axis": "In Grid layout, the arrangement direction of children elements.", + "affected_by_scale": "Whether the scaling of the child node affects the layout." }, "particle": { "export_title": "Export custom particle data to plist file.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 3361e97582d..4f1fa16a57f 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -201,7 +201,8 @@ module.exports = { 'vertical_direction': '垂直排列子节点的方向,包括:\n 1. TOP_TO_BOTTOM, 从上到下排列 \n 2. BOTTOM_TO_TOP, 从下到上排列', 'horizontal_direction': '水平排列子节点的方向,包括:\n 1. LEFT_TO_RIGHT, 从左到右排列 \n 2. RIGHT_TO_LEFT, 从右到左排列', 'cell_size': '网格布局中,规定每一个网格的大小', - 'start_axis': '网格布局中,子物体排版时的起始方向轴,支持水平和垂直两个方向。', + 'start_axis': '网格布局中,子物体排版时的起始方向轴,支持水平和垂直两个方向', + "affected_by_scale": "子节点的缩放是否影响布局" }, 'particle': { 'export_title': "将自定义的粒子数据导出成 plist 文件", From 1252d8fa3095917bf98cf559c8d3fdf23aaedf0e Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 30 Nov 2018 15:48:00 +0800 Subject: [PATCH 0308/1631] fixed texture image check in wechat game platform (#3576) --- cocos2d/core/renderer/render-engine.js | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 91369a6ac6f..48690ae35ea 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -8048,6 +8048,8 @@ function _createShader(gl, type, src) { return shader; } +const ArrayBufferView = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array)).constructor; + var Texture = function Texture(device) { this._device = device; @@ -8246,11 +8248,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { + if (!(img instanceof ArrayBufferView)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8309,11 +8307,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { + if (!(img instanceof ArrayBufferView)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8602,11 +8596,7 @@ var TextureCube = (function (Texture$$1) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { + if (!(img instanceof ArrayBufferView)) { gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); } else { if (this._compressed) { @@ -8653,11 +8643,7 @@ var TextureCube = (function (Texture$$1) { } else { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { + if (!(img instanceof ArrayBufferView)) { gl.texImage2D( gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, From 1cb0668bf703758419b30d29f6bf5333492925a9 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 30 Nov 2018 16:45:54 +0800 Subject: [PATCH 0309/1631] refine buffer view check (#3578) --- cocos2d/core/renderer/render-engine.js | 10 ++++------ index.js | 1 + polyfill/array-buffer.js | 6 ++++++ 3 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 polyfill/array-buffer.js diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 48690ae35ea..2d26caeec56 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -8048,8 +8048,6 @@ function _createShader(gl, type, src) { return shader; } -const ArrayBufferView = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array)).constructor; - var Texture = function Texture(device) { this._device = device; @@ -8248,7 +8246,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if (!(img instanceof ArrayBufferView)) { + if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8307,7 +8305,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if (!(img instanceof ArrayBufferView)) { + if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8596,7 +8594,7 @@ var TextureCube = (function (Texture$$1) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if (!(img instanceof ArrayBufferView)) { + if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); } else { if (this._compressed) { @@ -8643,7 +8641,7 @@ var TextureCube = (function (Texture$$1) { } else { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if (!(img instanceof ArrayBufferView)) { + if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { gl.texImage2D( gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, diff --git a/index.js b/index.js index ba16a62b359..4af245b191a 100644 --- a/index.js +++ b/index.js @@ -49,6 +49,7 @@ require('./polyfill/string'); require('./polyfill/misc'); require('./polyfill/array'); require('./polyfill/object'); +require('./polyfill/array-buffer'); if (!(CC_EDITOR && Editor.isMainProcess)) { require('./polyfill/typescript'); } diff --git a/polyfill/array-buffer.js b/polyfill/array-buffer.js new file mode 100644 index 00000000000..8ea63dd7642 --- /dev/null +++ b/polyfill/array-buffer.js @@ -0,0 +1,6 @@ +if (!ArrayBuffer.isView) { + const ArrayBufferView = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array)).constructor; + ArrayBuffer.isView = function (view) { + return view instanceof ArrayBufferView; + }; +} \ No newline at end of file From 4020ccf714511c329e1c99d75cf1c2bb83bb55b8 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 4 Dec 2018 13:50:14 +0800 Subject: [PATCH 0310/1631] modify preloadScene API params (#3583) --- cocos2d/core/CCDirector.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/CCDirector.js b/cocos2d/core/CCDirector.js index cf4f0cff2dd..eac8affdbd7 100644 --- a/cocos2d/core/CCDirector.js +++ b/cocos2d/core/CCDirector.js @@ -579,6 +579,7 @@ cc.Director.prototype = { * @param {Object} onProgress.item - The latest item which flow out the pipeline * @param {Function} [onLoaded] - callback, will be called after scene loaded. * @param {Error} onLoaded.error - null or the error object. + * @param {cc.SceneAsset} onLoaded.asset - The scene asset itself. */ preloadScene: function (sceneName, onProgress, onLoaded) { if (onLoaded === undefined) { From e22da68f21df707fc1303395f332afadfef2fad9 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 5 Dec 2018 15:03:54 +0800 Subject: [PATCH 0311/1631] refine image type check (#3591) * refine image type check * refine code --- cocos2d/core/renderer/render-engine.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 2d26caeec56..7252acac440 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -8246,7 +8246,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8305,7 +8305,7 @@ var Texture2D = (function (Texture$$1) { var premultiplyAlpha = options.premultiplyAlpha; var img = options.image; - if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { if (flipY === undefined) { gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); } else { @@ -8594,7 +8594,7 @@ var TextureCube = (function (Texture$$1) { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); } else { if (this._compressed) { @@ -8641,7 +8641,7 @@ var TextureCube = (function (Texture$$1) { } else { gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); } - if (!ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { gl.texImage2D( gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, From 67d8d91d8ec264eb2b68224ab7b1e866e765adcd Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 11 Dec 2018 10:44:58 +0800 Subject: [PATCH 0312/1631] improve requestFullScreen function (#3615) --- cocos2d/core/platform/CCScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCScreen.js b/cocos2d/core/platform/CCScreen.js index 2247e57238e..b919f494e50 100644 --- a/cocos2d/core/platform/CCScreen.js +++ b/cocos2d/core/platform/CCScreen.js @@ -116,7 +116,7 @@ cc.screen = /** @lends cc.screen# */{ * @param {Function} onFullScreenChange */ requestFullScreen: function (element, onFullScreenChange) { - if (element.tagName.toLowerCase() === "video") { + if (element && element.tagName.toLowerCase() === "video") { if (cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && element.readyState > 0) { element.webkitEnterFullscreen && element.webkitEnterFullscreen(); return; From b2b64f21103f458d65208aadce7afae5ec835379 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 11 Dec 2018 16:30:27 +0800 Subject: [PATCH 0313/1631] =?UTF-8?q?fix=20toggle=20event=20bug=20for=20to?= =?UTF-8?q?ggleGroup=20active=20false=20and=20update=20enabledI=E2=80=A6?= =?UTF-8?q?=20(#3620)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix toggle event bug for toggleGroup active false and update enabledInHierarchy code * refine code --- cocos2d/core/components/CCComponent.js | 2 +- cocos2d/core/components/CCToggle.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/components/CCComponent.js b/cocos2d/core/components/CCComponent.js index 3cdbf6a62d6..2496ecb5593 100644 --- a/cocos2d/core/components/CCComponent.js +++ b/cocos2d/core/components/CCComponent.js @@ -190,7 +190,7 @@ var Component = cc.Class({ */ enabledInHierarchy: { get () { - return (this._objFlags & IsOnEnableCalled) > 0; + return this._enabled && this.node._activeInHierarchy; }, visible: false }, diff --git a/cocos2d/core/components/CCToggle.js b/cocos2d/core/components/CCToggle.js index 4a808b84ed5..81b2209561f 100644 --- a/cocos2d/core/components/CCToggle.js +++ b/cocos2d/core/components/CCToggle.js @@ -127,7 +127,7 @@ let Toggle = cc.Class({ if (!CC_EDITOR) { this._registerToggleEvent(); } - if (this.toggleGroup && this.toggleGroup.enabled) { + if (this.toggleGroup && this.toggleGroup.enabledInHierarchy) { this.toggleGroup.addToggle(this); } }, @@ -137,7 +137,7 @@ let Toggle = cc.Class({ if (!CC_EDITOR) { this._unregisterToggleEvent(); } - if (this.toggleGroup && this.toggleGroup.enabled) { + if (this.toggleGroup && this.toggleGroup.enabledInHierarchy) { this.toggleGroup.removeToggle(this); } }, From 772ce209c4a37f67e742aa008a2e6f9fc19faded Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 14 Dec 2018 11:51:03 +0800 Subject: [PATCH 0314/1631] fix setMusicVolume as 0 (#3625) --- cocos2d/audio/CCAudioEngine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/audio/CCAudioEngine.js b/cocos2d/audio/CCAudioEngine.js index 40cf85031f1..df432a0f6be 100644 --- a/cocos2d/audio/CCAudioEngine.js +++ b/cocos2d/audio/CCAudioEngine.js @@ -91,7 +91,7 @@ let getAudioFromId = function (id) { }; let handleVolume = function (volume) { - if (!volume) { + if (volume === undefined) { // set default volume as 1 volume = 1; } From 91c358b4f33c6a031a59b5a684ebc099b8fc8abb Mon Sep 17 00:00:00 2001 From: caryliu Date: Thu, 20 Dec 2018 14:28:18 +0800 Subject: [PATCH 0315/1631] Add native-renderer mask. --- cocos2d/core/components/CCMask.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 34340112322..09fe760789b 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -301,7 +301,7 @@ let Mask = cc.Class({ this.node.off(cc.Node.EventType.SCALE_CHANGED, this._updateGraphics, this); this.node.off(cc.Node.EventType.SIZE_CHANGED, this._updateGraphics, this); this.node.off(cc.Node.EventType.ANCHOR_CHANGED, this._updateGraphics, this); - + this.node._renderFlag &= ~RenderFlow.FLAG_POST_RENDER; }, @@ -310,6 +310,11 @@ let Mask = cc.Class({ this._removeGraphics(); }, + initNativeHandle () { + this._renderHandle = new renderer.MaskRenderHandle(); + this._renderHandle.bind(this); + }, + _resizeNodeToTargetNode: CC_EDITOR && function () { if(this.spriteFrame) { let rect = this.spriteFrame.getRect(); @@ -384,8 +389,11 @@ let Mask = cc.Class({ this._graphics.node = this.node; this._graphics.lineWidth = 0; this._graphics.strokeColor = cc.color(0, 0, 0, 0); + if (CC_JSB && CC_NATIVERENDERER) { + this._renderHandle.addHandle("render", this._graphics._renderHandle); + } } - + if (!this._clearGraphics) { this._clearGraphics = new Graphics(); this._clearGraphics.node = new Node(); @@ -393,6 +401,9 @@ let Mask = cc.Class({ this._clearGraphics.lineWidth = 0; this._clearGraphics.rect(0, 0, cc.visibleRect.width, cc.visibleRect.height); this._clearGraphics.fill(); + if (CC_JSB && CC_NATIVERENDERER) { + this._renderHandle.addHandle("clear", this._clearGraphics._renderHandle); + } } }, From 0361c4eb4fe09021b8cecb8d2122fa05220e68fa Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 20 Dec 2018 17:17:16 +0800 Subject: [PATCH 0316/1631] Fix TypedArray instantiation in Prefab --- cocos2d/core/platform/instantiate-jit.js | 28 +++++++++++++++++++ cocos2d/particle/particle-system-assembler.js | 1 - 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/platform/instantiate-jit.js b/cocos2d/core/platform/instantiate-jit.js index 06277f993b7..cf88c5cc3f3 100644 --- a/cocos2d/core/platform/instantiate-jit.js +++ b/cocos2d/core/platform/instantiate-jit.js @@ -362,6 +362,31 @@ proto.instantiateArray = function (value) { return codeArray; }; +proto.instantiateTypedArray = function (value) { + let type = value.constructor.name; + if (value.length === 0) { + return 'new ' + type; + } + + let arrayVar = LOCAL_ARRAY + (++this.localVariableId); + let declaration = new Declaration(arrayVar, 'new ' + type + '(' + value.length + ')'); + let codeArray = [declaration]; + + // assign a _iN$t flag to indicate that this object has been parsed. + value._iN$t = { + globalVar: '', // the name of declared global variable used to access this object + source: codeArray, // the source code array for this object + }; + this.objsToClear_iN$t.push(value); + + for (var i = 0; i < value.length; ++i) { + var statement = arrayVar + '[' + i + ']='; + var expression = this.enumerateField(value, i, value[i]); + writeAssignment(codeArray, statement, expression); + } + return codeArray; +}; + proto.enumerateField = function (obj, key, value) { if (typeof value === 'object' && value) { var _iN$t = value._iN$t; @@ -383,6 +408,9 @@ proto.enumerateField = function (obj, key, value) { } return globalVar; } + else if (ArrayBuffer.isView(value)) { + return this.instantiateTypedArray(value); + } else if (Array.isArray(value)) { return this.instantiateArray(value); } diff --git a/cocos2d/particle/particle-system-assembler.js b/cocos2d/particle/particle-system-assembler.js index d9968d1229c..8bd33cecfc6 100644 --- a/cocos2d/particle/particle-system-assembler.js +++ b/cocos2d/particle/particle-system-assembler.js @@ -33,7 +33,6 @@ var particleSystemAssembler = { useModel: true, createIA (comp) { - let device = renderer.device; // Vertex format defines vertex buffer layout: x, y, u, v color comp._vertexFormat = vfmtPosUvColor; From f0cdedcd57b3d0e3a5fb4742740b9b945562aefa Mon Sep 17 00:00:00 2001 From: caryliu Date: Thu, 20 Dec 2018 19:07:20 +0800 Subject: [PATCH 0317/1631] Improve mask render handle. --- cocos2d/core/components/CCMask.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 09fe760789b..ee81149062c 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -390,7 +390,7 @@ let Mask = cc.Class({ this._graphics.lineWidth = 0; this._graphics.strokeColor = cc.color(0, 0, 0, 0); if (CC_JSB && CC_NATIVERENDERER) { - this._renderHandle.addHandle("render", this._graphics._renderHandle); + this._renderHandle.setNativeRenderHandle(this._graphics._renderHandle); } } @@ -402,7 +402,7 @@ let Mask = cc.Class({ this._clearGraphics.rect(0, 0, cc.visibleRect.width, cc.visibleRect.height); this._clearGraphics.fill(); if (CC_JSB && CC_NATIVERENDERER) { - this._renderHandle.addHandle("clear", this._clearGraphics._renderHandle); + this._renderHandle.setNativeClearHandle(this._clearGraphics._renderHandle); } } }, From 3d5b91eeb0622d4fd43d3c46f9777d32a40491be Mon Sep 17 00:00:00 2001 From: caryliu Date: Thu, 20 Dec 2018 23:19:44 +0800 Subject: [PATCH 0318/1631] Merge v2.1-release #3368 to v2.0-release. --- cocos2d/core/components/CCLabel.js | 2 + cocos2d/core/components/CCSprite.js | 2 + .../renderer/webgl/assemblers/label/bmfont.js | 6 ++- .../renderer/webgl/assemblers/label/ttf.js | 5 ++- .../webgl/assemblers/motion-streak.js | 3 +- .../webgl/assemblers/sprite/bar-filled.js | 5 ++- .../renderer/webgl/assemblers/sprite/mesh.js | 5 ++- .../webgl/assemblers/sprite/radial-filled.js | 7 ++- .../webgl/assemblers/sprite/simple.js | 33 ++++++++------ .../webgl/assemblers/sprite/sliced.js | 4 ++ .../renderer/webgl/assemblers/sprite/tiled.js | 45 +++++++++++-------- .../renderer/webgl/render-component-walker.js | 2 +- cocos2d/tilemap/tmx-layer-assembler.js | 3 +- extensions/dragonbones/webgl-assembler.js | 21 +++++++++ extensions/spine/spine-assembler.js | 3 +- 15 files changed, 100 insertions(+), 46 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 8326a8c26a7..c30894c033a 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -586,6 +586,8 @@ let Label = cc.Class({ this._srcBlendFactor = cc.macro.BlendFactor.SRC_ALPHA; } material.texture = this._texture; + // For batch rendering, do not use uniform color. + material.useColor = false; this._updateMaterial(material); } diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index e9e4dde4bc2..578549dd156 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -500,6 +500,8 @@ var Sprite = cc.Class({ } material = this._spriteMaterial; } + // For batch rendering, do not use uniform color. + material.useColor = false; // Set texture if (spriteFrame && spriteFrame.textureLoaded()) { let texture = spriteFrame.getTexture(); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js index 9b405cc4443..11b6e1296a9 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js @@ -35,7 +35,7 @@ module.exports = js.addon({ let node = comp.node, renderData = comp._renderData, data = renderData._data, - color = node.color._val; + color = node._color._val; let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, @@ -48,7 +48,8 @@ module.exports = js.addon({ buffer.request(vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData; + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; for (let i = 0; i < vertexCount; i++) { let vert = data[i]; @@ -56,6 +57,7 @@ module.exports = js.addon({ vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset++] = vert.u; vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index 5a4373ceb3a..0f945ac0f80 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -49,6 +49,7 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let data = comp._renderData._data, node = comp.node, + color = node._color._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; @@ -59,7 +60,8 @@ module.exports = js.addon({ buffer.request(4, 6); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData; + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; // vertex for (let i = 0; i < 4; i++) { @@ -68,6 +70,7 @@ module.exports = js.addon({ vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset++] = vert.u; vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index 6ea30f8b819..4721da89370 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -25,7 +25,6 @@ const MotionStreak = require('../../../components/CCMotionStreak'); const RenderFlow = require('../../render-flow'); -const vfmtPosUvColor = require('../vertex-format').vfmtPosUvColor; function Point (point, dir) { this.point = point || cc.v2(); @@ -195,7 +194,7 @@ var motionStreakAssembler = { renderData = comp._renderData, data = renderData._data; - let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), + let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, vertexCount = renderData.vertexCount; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index 5f35a71b822..ca8978d9ca2 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -224,6 +224,7 @@ module.exports = { let data = sprite._renderData._data, node = sprite.node, + color = node._color._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; @@ -234,7 +235,8 @@ module.exports = { buffer.request(4, 6); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData; + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; // vertex for (let i = 0; i < 4; i++) { @@ -243,6 +245,7 @@ module.exports = { vbuf[vertexOffset++] = vert.y; vbuf[vertexOffset++] = vert.u; vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; } } }; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js index 3d50d10afa7..ada3e2f5381 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js @@ -25,7 +25,7 @@ const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - module.exports = { +module.exports = { useModel: false, createData (sprite) { @@ -155,6 +155,7 @@ const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); fillBuffers (sprite, renderer) { let node = sprite.node, + color = node._color._val, renderData = sprite._renderData, data = renderData._data; @@ -179,6 +180,7 @@ const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, + uintbuf = buffer._uintVData, ibuf = buffer._iData; for (let i = 0, l = renderData.vertexCount; i < l; i++) { @@ -187,6 +189,7 @@ const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); vbuf[vertexOffset++] = vertice.y; vbuf[vertexOffset++] = vertice.u; vbuf[vertexOffset++] = vertice.v; + uintbuf[vertexOffset++] = color; } let triangles = vertices.triangles; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js index cd7969dba61..302d203cb6e 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js @@ -331,7 +331,8 @@ module.exports = { fillBuffers (sprite, renderer) { let renderData = sprite._renderData, data = renderData._data, - node = sprite.node; + node = sprite.node, + color = node._color._val; let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, @@ -340,7 +341,8 @@ module.exports = { // buffer let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, - vbuf = buffer._vData; + vbuf = buffer._vData, + uintbuf = buffer._uintVData; let ibuf = buffer._iData, indiceOffset = buffer.indiceOffset, @@ -355,6 +357,7 @@ module.exports = { vbuf[vertexOffset ++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset ++] = vert.u; vbuf[vertexOffset ++] = vert.v; + uintbuf[vertexOffset ++] = color; } for (let i = 0; i < count; i++) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js index e6722a738eb..faa38412bfe 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js @@ -53,6 +53,7 @@ module.exports = { fillBuffers (sprite, renderer) { let data = sprite._renderData._data, node = sprite.node, + color = node._color._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; @@ -63,18 +64,19 @@ module.exports = { buffer.request(4, 6); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData; + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; // get uv from sprite frame directly let uv = sprite._spriteFrame.uv; vbuf[vertexOffset+2] = uv[0]; vbuf[vertexOffset+3] = uv[1]; - vbuf[vertexOffset+6] = uv[2]; - vbuf[vertexOffset+7] = uv[3]; - vbuf[vertexOffset+10] = uv[4]; - vbuf[vertexOffset+11] = uv[5]; - vbuf[vertexOffset+14] = uv[6]; - vbuf[vertexOffset+15] = uv[7]; + vbuf[vertexOffset+7] = uv[2]; + vbuf[vertexOffset+8] = uv[3]; + vbuf[vertexOffset+12] = uv[4]; + vbuf[vertexOffset+13] = uv[5]; + vbuf[vertexOffset+17] = uv[6]; + vbuf[vertexOffset+18] = uv[7]; let data0 = data[0], data3 = data[3], vl = data0.x, vr = data3.x, @@ -89,14 +91,19 @@ module.exports = { vbuf[vertexOffset] = al + cb + tx; vbuf[vertexOffset+1] = bl + db + ty; // right bottom - vbuf[vertexOffset+4] = ar + cb + tx; - vbuf[vertexOffset+5] = br + db + ty; + vbuf[vertexOffset+5] = ar + cb + tx; + vbuf[vertexOffset+6] = br + db + ty; // left top - vbuf[vertexOffset+8] = al + ct + tx; - vbuf[vertexOffset+9] = bl + dt + ty; + vbuf[vertexOffset+10] = al + ct + tx; + vbuf[vertexOffset+11] = bl + dt + ty; // right top - vbuf[vertexOffset+12] = ar + ct + tx; - vbuf[vertexOffset+13] = br + dt + ty; + vbuf[vertexOffset+15] = ar + ct + tx; + vbuf[vertexOffset+16] = br + dt + ty; + // color + uintbuf[vertexOffset+4] = color; + uintbuf[vertexOffset+9] = color; + uintbuf[vertexOffset+14] = color; + uintbuf[vertexOffset+19] = color; }, createData (sprite) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js index 06da24db920..369f1ba7e2c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js @@ -103,6 +103,8 @@ module.exports = { } let renderData = sprite._renderData, + node = sprite.node, + color = node._color._val, data = renderData._data; let buffer = renderer._meshBuffer, @@ -118,6 +120,7 @@ module.exports = { // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, + uintbuf = buffer._uintVData, ibuf = buffer._iData; for (let i = 4; i < 20; ++i) { @@ -128,6 +131,7 @@ module.exports = { vbuf[vertexOffset++] = vert.y; vbuf[vertexOffset++] = uvs.u; vbuf[vertexOffset++] = uvs.v; + uintbuf[vertexOffset++] = color; } for (let r = 0; r < 3; ++r) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js index 97ed6a64b18..55d0cf7b49d 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js @@ -88,6 +88,7 @@ module.exports = { fillBuffers (sprite, renderer) { let node = sprite.node, + color = node._color._val, renderData = sprite._renderData, data = renderData._data; @@ -102,6 +103,7 @@ module.exports = { // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, + uintbuf = buffer._uintVData, ibuf = buffer._iData; let rotated = sprite.spriteFrame._rotated; @@ -133,14 +135,14 @@ module.exports = { vbuf[vertexOffset] = x * a + y * c + tx; vbuf[vertexOffset+1] = x * b + y * d + ty; // rb - vbuf[vertexOffset+4] = x1 * a + y * c + tx; - vbuf[vertexOffset+5] = x1 * b + y * d + ty; + vbuf[vertexOffset+5] = x1 * a + y * c + tx; + vbuf[vertexOffset+6] = x1 * b + y * d + ty; // lt - vbuf[vertexOffset+8] = x * a + y1 * c + tx; - vbuf[vertexOffset+9] = x * b + y1 * d + ty; + vbuf[vertexOffset+10] = x * a + y1 * c + tx; + vbuf[vertexOffset+11] = x * b + y1 * d + ty; // rt - vbuf[vertexOffset+12] = x1 * a + y1 * c + tx; - vbuf[vertexOffset+13] = x1 * b + y1 * d + ty; + vbuf[vertexOffset+15] = x1 * a + y1 * c + tx; + vbuf[vertexOffset+16] = x1 * b + y1 * d + ty; // UV if (rotated) { @@ -148,30 +150,35 @@ module.exports = { vbuf[vertexOffset+2] = uv[0]; vbuf[vertexOffset+3] = uv[1]; // rb - vbuf[vertexOffset+6] = uv[0]; - vbuf[vertexOffset+7] = uv[1] + (uv[7] - uv[1]) * coefu; + vbuf[vertexOffset+7] = uv[0]; + vbuf[vertexOffset+8] = uv[1] + (uv[7] - uv[1]) * coefu; // lt - vbuf[vertexOffset+10] = uv[0] + (uv[6] - uv[0]) * coefv; - vbuf[vertexOffset+11] = uv[1]; + vbuf[vertexOffset+12] = uv[0] + (uv[6] - uv[0]) * coefv; + vbuf[vertexOffset+13] = uv[1]; // rt - vbuf[vertexOffset+14] = vbuf[vertexOffset+10]; - vbuf[vertexOffset+15] = vbuf[vertexOffset+7]; + vbuf[vertexOffset+17] = vbuf[vertexOffset+12]; + vbuf[vertexOffset+18] = vbuf[vertexOffset+8]; } else { // lb vbuf[vertexOffset+2] = uv[0]; vbuf[vertexOffset+3] = uv[1]; // rb - vbuf[vertexOffset+6] = uv[0] + (uv[6] - uv[0]) * coefu; - vbuf[vertexOffset+7] = uv[1]; + vbuf[vertexOffset+7] = uv[0] + (uv[6] - uv[0]) * coefu; + vbuf[vertexOffset+8] = uv[1]; // lt - vbuf[vertexOffset+10] = uv[0]; - vbuf[vertexOffset+11] = uv[1] + (uv[7] - uv[1]) * coefv; + vbuf[vertexOffset+12] = uv[0]; + vbuf[vertexOffset+13] = uv[1] + (uv[7] - uv[1]) * coefv; // rt - vbuf[vertexOffset+14] = vbuf[vertexOffset+6]; - vbuf[vertexOffset+15] = vbuf[vertexOffset+11]; + vbuf[vertexOffset+17] = vbuf[vertexOffset+7]; + vbuf[vertexOffset+18] = vbuf[vertexOffset+13]; } - vertexOffset += 16; + // color + uintbuf[vertexOffset+4] = color; + uintbuf[vertexOffset+9] = color; + uintbuf[vertexOffset+14] = color; + uintbuf[vertexOffset+19] = color; + vertexOffset += 20; } } diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/render-component-walker.js index db1971688c3..4338799396f 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/render-component-walker.js @@ -25,7 +25,7 @@ const macro = require('../../platform/CCMacro'); const renderEngine = require('../render-engine'); -const defaultVertexFormat = require('./vertex-format').vfmtPosUv; +const defaultVertexFormat = require('./vertex-format').vfmtPosUvColor; const StencilManager = require('./stencil-manager'); const dynamicAtlasManager = require('../utils/dynamic-atlas/manager'); const RenderFlow = require('../render-flow'); diff --git a/cocos2d/tilemap/tmx-layer-assembler.js b/cocos2d/tilemap/tmx-layer-assembler.js index 4800b8ece5a..6ab948cee7e 100644 --- a/cocos2d/tilemap/tmx-layer-assembler.js +++ b/cocos2d/tilemap/tmx-layer-assembler.js @@ -28,7 +28,6 @@ const TiledMap = require('./CCTiledMap'); const renderEngine = require('../core/renderer/render-engine'); const RenderFlow = require('../core/renderer/render-flow'); -const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; const Orientation = TiledMap.Orientation; const TileFlag = TiledMap.TileFlag; @@ -63,7 +62,7 @@ let tmxAssembler = { let renderData = comp._renderData; let data = renderData._data; - let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), + let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, vertexCount = renderData.vertexCount; diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index c352845dc91..e7dc528b92f 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -27,6 +27,7 @@ const StencilManager = require('../../cocos2d/core/renderer/webgl/stencil-manage const Armature = require('./ArmatureDisplay'); const renderEngine = require('../../cocos2d/core/renderer/render-engine'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); + const gfx = renderEngine.gfx; const SpriteMaterial = renderEngine.SpriteMaterial; const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; @@ -125,11 +126,31 @@ let armatureAssembler = { if (!_data) { _data = _datas[_dataId] = comp.requestRenderData(); } + _data.dataLength = 0; _material = null; _currMaterial = null; _vertexOffset = 0; _indiceOffset = 0; + }, + + fillBuffers (comp, renderer) { + let armature = comp._armature; + if (!armature || comp._isChildArmature) return; + + let buffer = renderer._meshBuffer, + renderData = comp._renderData; + + _vertexOffset = buffer.byteOffset >> 2; + _indiceOffset = buffer.indiceOffset; + _vertexId = buffer.vertexOffset; + + buffer.request(renderData.vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + _vbuf = buffer._vData; + _uintbuf = buffer._uintVData; + _ibuf = buffer._iData; let node = comp.node; let nodeColor = node.color; diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index ac1bb9f563d..955823148ec 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -28,7 +28,6 @@ const Skeleton = require('./Skeleton'); const spine = require('./lib/spine'); const renderer = require('../../cocos2d/core/renderer'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); -const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; const renderEngine = renderer.renderEngine; const gfx = renderEngine.gfx; const SpriteMaterial = renderEngine.SpriteMaterial; @@ -335,7 +334,7 @@ var spineAssembler = { let vertexs = data._data; let indices = data._indices; - let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), + let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, vertexCount = data.vertexCount; From 7ab90f447dbc5c71f0f75788b17c3649738e1a34 Mon Sep 17 00:00:00 2001 From: caryliu Date: Thu, 20 Dec 2018 23:22:27 +0800 Subject: [PATCH 0319/1631] Merge v2.1-release #3381 to v2.0-release. --- .../webgl/assemblers/sprite/simple.js | 20 ++++++++++++++----- .../webgl/assemblers/sprite/sliced.js | 7 +++---- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js index faa38412bfe..3f140451a1e 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - https://www.cocos.com/ + http://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, @@ -58,14 +58,17 @@ module.exports = { a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; + let buffer = renderer._meshBuffer, + vertexOffset = buffer.byteOffset >> 2, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; buffer.request(4, 6); - + // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, - uintbuf = buffer._uintVData; + uintbuf = buffer._uintVData, + ibuf = buffer._iData; // get uv from sprite frame directly let uv = sprite._spriteFrame.uv; @@ -104,6 +107,13 @@ module.exports = { uintbuf[vertexOffset+9] = color; uintbuf[vertexOffset+14] = color; uintbuf[vertexOffset+19] = color; + // fill indice data + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId+1; + ibuf[indiceOffset++] = vertexId+2; + ibuf[indiceOffset++] = vertexId+1; + ibuf[indiceOffset++] = vertexId+3; + ibuf[indiceOffset++] = vertexId+2; }, createData (sprite) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js index 369f1ba7e2c..8c64a94e19c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - https://www.cocos.com/ + http://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, @@ -109,9 +109,8 @@ module.exports = { let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, - vertexCount = renderData.vertexCount; - - let indiceOffset = buffer.indiceOffset, + vertexCount = renderData.vertexCount, + indiceOffset = buffer.indiceOffset, vertexId = buffer.vertexOffset; let uvSliced = sprite.spriteFrame.uvSliced; From 9425ed7c0486e12de47393b0aa6c35b25a88fbfc Mon Sep 17 00:00:00 2001 From: caryliu Date: Thu, 20 Dec 2018 23:27:18 +0800 Subject: [PATCH 0320/1631] Merge v2.1-release #3607 to v2.0-release. --- .../renderer/webgl/assemblers/label/bmfont.js | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js index 11b6e1296a9..4b543d3c615 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js @@ -35,21 +35,25 @@ module.exports = js.addon({ let node = comp.node, renderData = comp._renderData, data = renderData._data, - color = node._color._val; + color = node.color._val; let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; + let buffer = renderer._meshBuffer, + vertexOffset = buffer.byteOffset >> 2, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; let vertexCount = renderData.vertexCount; buffer.request(vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, - uintbuf = buffer._uintVData; + uintbuf = buffer._uintVData, + ibuf = buffer._iData; + for (let i = 0; i < vertexCount; i++) { let vert = data[i]; @@ -59,6 +63,18 @@ module.exports = js.addon({ vbuf[vertexOffset++] = vert.v; uintbuf[vertexOffset++] = color; } + + // fill indice data + for (let i = 0, count = vertexCount / 4; i < count; i++) + { + let start = vertexId + i * 4; + ibuf[indiceOffset++] = start; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 2; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 3; + ibuf[indiceOffset++] = start + 2; + } }, appendQuad (renderData, texture, rect, rotated, x, y, scale) { From 396d848c035b07b97f1e061cb1b0a01116660ec8 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Tue, 18 Dec 2018 16:33:02 +0800 Subject: [PATCH 0321/1631] Merge v2.1-release #3525 to v2.0-release. --- cocos2d/core/assets/CCSpriteFrame.js | 36 +++++- cocos2d/core/components/CCLabel.js | 55 +++++++- cocos2d/core/components/CCSprite.js | 16 +++ .../renderer/utils/dynamic-atlas/atlas.js | 28 ++--- .../renderer/utils/dynamic-atlas/manager.js | 14 ++- .../core/renderer/utils/label/label-frame.js | 117 ++++++++++++++++++ cocos2d/core/renderer/utils/label/ttf.js | 17 ++- .../webgl/assemblers/sprite/bar-filled.js | 11 +- .../renderer/webgl/assemblers/sprite/mesh.js | 11 +- .../webgl/assemblers/sprite/radial-filled.js | 11 +- .../webgl/assemblers/sprite/simple.js | 11 +- .../webgl/assemblers/sprite/sliced.js | 11 +- .../renderer/webgl/assemblers/sprite/tiled.js | 11 +- 13 files changed, 250 insertions(+), 99 deletions(-) create mode 100644 cocos2d/core/renderer/utils/label/label-frame.js diff --git a/cocos2d/core/assets/CCSpriteFrame.js b/cocos2d/core/assets/CCSpriteFrame.js index 945415d719b..b5e06776f70 100644 --- a/cocos2d/core/assets/CCSpriteFrame.js +++ b/cocos2d/core/assets/CCSpriteFrame.js @@ -194,6 +194,12 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ // the location of the sprite on rendering texture this._rect = null; + // uv data of frame + this.uv = []; + // texture of frame + this._texture = null; + // store original info before packed to dynamic atlas + this._original = null; // for trimming this._offset = null; @@ -207,15 +213,10 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ this._capInsets = [0, 0, 0, 0]; - this.uv = []; this.uvSliced = []; - this._texture = null; this._textureFilename = ''; - // store original info before packed to dynamic atlas - this._original = null; - if (CC_EDITOR) { // Atlas asset uuid this._atlasUuid = ''; @@ -281,7 +282,7 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ if (this._texture) this._calculateUV(); }, - + /** * !#en Returns the original size of the trimmed image. * !#zh 获取修剪前的原始大小 @@ -582,6 +583,29 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ } }, + _setDynamicAtlasFrame (frame) { + if (!frame) return; + + this._original = { + _texture : this._texture, + _x : this._rect.x, + _y : this._rect.y + } + + this._texture = frame.texture; + this._rect.x = frame.x; + this._rect.y = frame.y; + this._calculateUV(); + }, + + _resetDynamicAtlasFrame () { + this._rect.x = this._original._x; + this._rect.y = this._original._y; + this._texture = this._original._texture; + this._original = null; + this._calculateUV(); + }, + _calculateUV () { let rect = this._rect, texture = this._texture, diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index c30894c033a..b541c3ba2f5 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -29,7 +29,8 @@ const RenderComponent = require('./CCRenderComponent'); const renderEngine = require('../renderer/render-engine'); const RenderFlow = require('../renderer/render-flow'); const SpriteMaterial = renderEngine.SpriteMaterial; - +const dynamicAtlasManager = require('../renderer/utils/dynamic-atlas/manager'); +const LabelFrame = require('../renderer/utils/label/label-frame'); /** * !#en Enum for text alignment. * !#zh 文本横向对齐类型 @@ -145,6 +146,7 @@ let Label = cc.Class({ this._actualFontSize = 0; this._assemblerData = null; + this._frame = null; this._ttfTexture = null; }, @@ -430,6 +432,24 @@ let Label = cc.Class({ } }, + _cacheAsBitmap: true, + /** + * !#en Whether cache label to static texture and draw in dynamicAtlas. + * !#zh 是否将label缓存成静态图像并加入到动态图集.(对于静态文本建议使用该选项,便于批次合并减少drawcall) + * @property {Boolean} cacheAsBitmap + */ + cacheAsBitmap: { + get () { + return this._cacheAsBitmap; + }, + set (value) { + if (this._cacheAsBitmap === value) return; + + this._cacheAsBitmap = value; + this._updateRenderData(); + }, + }, + _isBold: { default: false, serializable: false, @@ -543,6 +563,9 @@ let Label = cc.Class({ spriteFrame.ensureLoadTexture(); } } + + // TODO: old texture in material have been released by loader + this._frame = spriteFrame; } else { if (!this._ttfTexture) { @@ -553,8 +576,14 @@ let Label = cc.Class({ } this._assemblerData = this._assembler._getAssemblerData(); this._ttfTexture.initWithElement(this._assemblerData.canvas); + + if (!this._frame) { + this._frame = new LabelFrame(); + } + + this._frame._refreshTexture(this._ttfTexture); } - this._texture = this._ttfTexture; + this._activateMaterial(force); if (force) { @@ -571,7 +600,7 @@ let Label = cc.Class({ // Canvas if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { - this._texture.url = this.uuid + '_texture'; + this._frame._texture.url = this.uuid + '_texture'; } // WebGL else { @@ -579,13 +608,13 @@ let Label = cc.Class({ material = new SpriteMaterial(); } // Setup blend function for premultiplied ttf label texture - if (this._texture === this._ttfTexture) { + if (this._frame._texture === this._ttfTexture) { this._srcBlendFactor = cc.macro.BlendFactor.ONE; } else { this._srcBlendFactor = cc.macro.BlendFactor.SRC_ALPHA; } - material.texture = this._texture; + material.texture = this._frame._texture; // For batch rendering, do not use uniform color. material.useColor = false; this._updateMaterial(material); @@ -594,7 +623,7 @@ let Label = cc.Class({ this.markForUpdateRenderData(true); this.markForRender(true); }, - + _updateColor () { let font = this.font; if (font instanceof cc.BitmapFont) { @@ -620,6 +649,20 @@ let Label = cc.Class({ } }, + _calDynamicAtlas () { + if (!dynamicAtlasManager) return; + + if (!this._frame._original) { + let frame = dynamicAtlasManager.insertSpriteFrame(this._frame); + if (frame) { + this._frame._setDynamicAtlasFrame(frame); + } + } + if (this._material._texture !== this._frame._texture) { + this._activateMaterial(true); + } + }, + _enableBold (enabled) { this._isBold = !!enabled; }, diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 578549dd156..e2e0a9a2be9 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -31,6 +31,7 @@ const RenderFlow = require('../renderer/render-flow'); const renderEngine = require('../renderer/render-engine'); const SpriteMaterial = renderEngine.SpriteMaterial; const GraySpriteMaterial = renderEngine.GraySpriteMaterial; +const dynamicAtlasManager = require('../renderer/utils/dynamic-atlas/manager'); /** * !#en Enum for sprite type. @@ -647,6 +648,21 @@ var Sprite = cc.Class({ } } }, + + _calDynamicAtlas () + { + if (!this._spriteFrame) return; + + if (!this._spriteFrame._original && dynamicAtlasManager) { + let frame = dynamicAtlasManager.insertSpriteFrame(this._spriteFrame); + if (frame) { + this._spriteFrame._setDynamicAtlasFrame(frame); + } + } + if (this._material._texture !== this._spriteFrame._texture) { + this._activateMaterial(); + } + } }); if (CC_EDITOR) { diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js b/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js index 00f65b60daa..8c93a3b67f7 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js @@ -27,8 +27,8 @@ cc.js.mixin(Atlas.prototype, { let sx = rect.x, sy = rect.y; if (info) { - rect.x += info.x; - rect.y += info.y; + sx += info.x; + sy += info.y; } else { let width = texture.width, height = texture.height; @@ -43,7 +43,7 @@ cc.js.mixin(Atlas.prototype, { } if (this._nexty > this._height) { - return false; + return null; } // texture bleeding @@ -59,26 +59,23 @@ cc.js.mixin(Atlas.prototype, { texture: texture }; - rect.x += this._x; - rect.y += this._y; + sx += this._x; + sy += this._y; this._x += width + space; this._dirty = true; } - spriteFrame._original = { + let frame = { x: sx, y: sy, - texture: spriteFrame._texture + texture: this._texture } - - spriteFrame._texture = this._texture; - spriteFrame._calculateUV(); - + this._innerSpriteFrames.push(spriteFrame); - return true; + return frame; }, update () { @@ -98,12 +95,7 @@ cc.js.mixin(Atlas.prototype, { if (!frame.isValid) { continue; } - let oriInfo = frame._original; - frame._rect.x = oriInfo.x; - frame._rect.y = oriInfo.y; - frame._texture = oriInfo.texture; - frame._calculateUV(); - frame._original = null; + frame._resetDynamicAtlasFrame(); } this._innerSpriteFrames.length = 0; this._innerTextureInfos = {}; diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js index 196b3c7940a..ab1a4861971 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js @@ -103,18 +103,18 @@ let dynamicAtlasManager = { * @param {SpriteFrame} spriteFrame */ insertSpriteFrame (spriteFrame) { - if (CC_EDITOR) return; + if (CC_EDITOR) return null; if (!_enabled || _atlasIndex === _maxAtlasCount || - !spriteFrame || spriteFrame._original) return; + !spriteFrame || spriteFrame._original) return null; let texture = spriteFrame._texture; - if (texture instanceof cc.RenderTexture) return; + if (texture instanceof cc.RenderTexture || cc.Texture2D._isCompressed(texture)) return null; let w = texture.width, h = texture.height; let min = texture._minFilter, mag = texture._magFilter; let LINEAR = cc.Texture2D.Filter.LINEAR; if (w > _maxFrameSize || h > _maxFrameSize || w <= _minFrameSize || h <= _minFrameSize || (min & mag) !== LINEAR) { - return; + return null; } let atlas = _atlases[_atlasIndex]; @@ -122,10 +122,12 @@ let dynamicAtlasManager = { atlas = newAtlas(); } - if (!atlas.insertSpriteFrame(spriteFrame) && _atlasIndex !== _maxAtlasCount) { + let frame = atlas.insertSpriteFrame(spriteFrame); + if (!frame && _atlasIndex !== _maxAtlasCount) { atlas = newAtlas(); - atlas.insertSpriteFrame(spriteFrame); + return atlas.insertSpriteFrame(spriteFrame); } + return frame; }, /** diff --git a/cocos2d/core/renderer/utils/label/label-frame.js b/cocos2d/core/renderer/utils/label/label-frame.js new file mode 100644 index 00000000000..277e0a8d540 --- /dev/null +++ b/cocos2d/core/renderer/utils/label/label-frame.js @@ -0,0 +1,117 @@ +/**************************************************************************** + Copyright (c) 2018 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. + ****************************************************************************/ + +/** + * !#en Class for Label Frame. + * !#zh LabelFrame + */ +function LabelFrame () { + // the location of the label on rendering texture + this._rect = null; + // uv data of frame + this.uv = []; + // texture of frame + this._texture = null; + // store original info before packed to dynamic atlas + this._original = null; +} + +LabelFrame.prototype = { + constructor: LabelFrame, + + /** + * !#en Returns the rect of the label frame in the texture. + * !#zh 获取 LabelFrame 的纹理矩形区域 + * @method getRect + * @return {Rect} + */ + getRect: function () { + return cc.rect(this._rect); + }, + + /** + * !#en Sets the rect of the label frame in the texture. + * !#zh 设置 LabelFrame 的纹理矩形区域 + * @method setRect + * @param {Rect} rect + */ + setRect: function (rect) { + this._rect = rect; + if (this._texture) + this._calculateUV(); + }, + + _setDynamicAtlasFrame (frame) { + if (!frame) return; + + this._original = { + _texture : this._texture, + _x : this._rect.x, + _y : this._rect.y + } + + this._texture = frame.texture; + this._rect.x = frame.x; + this._rect.y = frame.y; + this._calculateUV(); + }, + _resetDynamicAtlasFrame () { + this._rect.x = this._original._x; + this._rect.y = this._original._y; + this._texture = this._original._texture; + this._original = null; + this._calculateUV(); + }, + + _refreshTexture: function (texture) { + this._texture = texture; + this._rect = cc.rect(0, 0, texture.width, texture.height); + this._calculateUV(); + }, + + _calculateUV() { + let rect = this._rect, + texture = this._texture, + uv = this.uv, + texw = texture.width, + texh = texture.height; + + let l = texw === 0 ? 0 : rect.x / texw; + let r = texw === 0 ? 0 : (rect.x + rect.width) / texw; + let b = texh === 0 ? 0 : (rect.y + rect.height) / texh; + let t = texh === 0 ? 0 : rect.y / texh; + + uv[0] = l; + uv[1] = b; + uv[2] = r; + uv[3] = b; + uv[4] = l; + uv[5] = t; + uv[6] = r; + uv[7] = t; + } +} + +module.exports = LabelFrame; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 0c2e97b16eb..b79ba6a682b 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -124,7 +124,8 @@ module.exports = { this._calculateSplitedStrings(); this._updateLabelDimensions(); this._calculateTextBaseline(); - this._updateTexture(comp); + this._updateTexture(); + this._calDynamicAtlas(comp); comp._actualFontSize = _fontSize; comp.node.setContentSize(_canvasSize); @@ -171,7 +172,7 @@ module.exports = { let assemblerData = comp._assemblerData; _context = assemblerData.context; _canvas = assemblerData.canvas; - _texture = comp._texture; + _texture = comp._frame._original ? comp._frame._original._texture : comp._frame._texture; _string = comp.string.toString(); _fontSize = comp._fontSize; @@ -278,6 +279,16 @@ module.exports = { _texture.handleLoadedTexture(); }, + _calDynamicAtlas (comp) { + if(!comp.cacheAsBitmap) return; + + if (!comp._frame._original) { + comp._frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height)); + } + // Add font images to the dynamic atlas for batch rendering. + comp._calDynamicAtlas(); + }, + _calculateUnderlineStartPosition () { let lineHeight = this._getLineHeight(); let lineCount = _splitedStrings.length; @@ -501,5 +512,5 @@ module.exports = { _context.font = _fontDesc; } } - } + }, }; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index ca8978d9ca2..1a5eb5ec954 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -26,8 +26,6 @@ const Sprite = require('../../../../components/CCSprite'); const FillType = Sprite.FillType; -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - module.exports = { useModel: false, updateRenderData (sprite) { @@ -35,14 +33,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js index ada3e2f5381..089801e292a 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js @@ -23,8 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - module.exports = { useModel: false, @@ -37,14 +35,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js index 302d203cb6e..e3915de0394 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js @@ -23,8 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - const PI_2 = Math.PI * 2; module.exports = { @@ -47,14 +45,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js index 3f140451a1e..86cb966862f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js @@ -23,8 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - module.exports = { useModel: false, @@ -33,14 +31,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js index 8c64a94e19c..c2c1a2635f5 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js @@ -23,8 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - module.exports = { useModel: false, @@ -44,14 +42,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (renderData && frame) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js index 55d0cf7b49d..a4baccef6ef 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js @@ -23,8 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - module.exports = { useModel: false, @@ -37,14 +35,7 @@ module.exports = { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } + sprite._calDynamicAtlas(); let renderData = sprite._renderData; if (!frame || !renderData || From aebb7262c6fad68c9c49695ff9f0a07f16521f7d Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 20 Dec 2018 09:41:42 +0800 Subject: [PATCH 0322/1631] Merge v2.1-release #3658 to v2.0-release. --- cocos2d/core/renderer/webgl/assemblers/label/ttf.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index 0f945ac0f80..1bb414b44aa 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -23,8 +23,10 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('../../../../platform/js'); -const ttfUtls = require('../../../utils/label/ttf'); +const js = require('../../../../../platform/js'); +const ttfUtls = require('../../../../utils/label/ttf'); + +const WHITE_VAL = cc.Color.WHITE._val; module.exports = js.addon({ createData (comp) { @@ -49,7 +51,7 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let data = comp._renderData._data, node = comp.node, - color = node._color._val, + color = WHITE_VAL, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; From 2351d3ae59a7d980b02e6495e5d0d60e1ea5e492 Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 21 Dec 2018 11:56:38 +0800 Subject: [PATCH 0323/1631] Fix merge error. --- .../renderer/utils/dynamic-atlas/manager.js | 2 +- .../renderer/webgl/assemblers/label/ttf.js | 41 ++++++++++++------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js index ab1a4861971..34531252796 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js @@ -108,7 +108,7 @@ let dynamicAtlasManager = { !spriteFrame || spriteFrame._original) return null; let texture = spriteFrame._texture; - if (texture instanceof cc.RenderTexture || cc.Texture2D._isCompressed(texture)) return null; + if (texture instanceof cc.RenderTexture) return null; let w = texture.width, h = texture.height; let min = texture._minFilter, mag = texture._magFilter; diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index 1bb414b44aa..d0252c20b6b 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('../../../../../platform/js'); -const ttfUtls = require('../../../../utils/label/ttf'); +const js = require('../../../../platform/js'); +const ttfUtls = require('../../../utils/label/ttf'); const WHITE_VAL = cc.Color.WHITE._val; @@ -36,15 +36,6 @@ module.exports = js.addon({ renderData.vertexCount = 4; renderData.indiceCount = 6; - let data = renderData._data; - data[0].u = 0; - data[0].v = 1; - data[1].u = 1; - data[1].v = 1; - data[2].u = 0; - data[2].v = 0; - data[3].u = 1; - data[3].v = 0; return renderData; }, @@ -56,14 +47,17 @@ module.exports = js.addon({ a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; + let buffer = renderer._meshBuffer, + vertexOffset = buffer.byteOffset >> 2, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; buffer.request(4, 6); // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, - uintbuf = buffer._uintVData; + uintbuf = buffer._uintVData, + ibuf = buffer._iData; // vertex for (let i = 0; i < 4; i++) { @@ -74,11 +68,19 @@ module.exports = js.addon({ vbuf[vertexOffset++] = vert.v; uintbuf[vertexOffset++] = color; } + + // fill indice data + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; }, _updateVerts (comp) { let renderData = comp._renderData; - + let uv = comp._frame.uv; let node = comp.node, width = node.width, height = node.height, @@ -94,5 +96,14 @@ module.exports = js.addon({ data[2].y = height - appy; data[3].x = width - appx; data[3].y = height - appy; + + data[0].u = uv[0]; + data[0].v = uv[1]; + data[1].u = uv[2]; + data[1].v = uv[3]; + data[2].u = uv[4]; + data[2].v = uv[5]; + data[3].u = uv[6]; + data[3].v = uv[7]; } }, ttfUtls); From a744c1a7f49f3a40c6811912d1437b368e44b6e9 Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 21 Dec 2018 13:57:16 +0800 Subject: [PATCH 0324/1631] Fix BMFont simulator error. --- cocos2d/core/components/CCLabel.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index b541c3ba2f5..6e23b39aca8 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -541,10 +541,11 @@ let Label = cc.Class({ let font = this.font; if (font instanceof cc.BitmapFont) { let spriteFrame = font.spriteFrame; + this._frame = spriteFrame; let self = this; let onBMFontTextureLoaded = function () { // TODO: old texture in material have been released by loader - self._texture = spriteFrame._texture; + self._frame._texture = spriteFrame._texture; self._activateMaterial(force); if (force) { @@ -563,9 +564,6 @@ let Label = cc.Class({ spriteFrame.ensureLoadTexture(); } } - - // TODO: old texture in material have been released by loader - this._frame = spriteFrame; } else { if (!this._ttfTexture) { From 24d30c564e60c4f6fb578b50cd6c38a5b146d3b1 Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 21 Dec 2018 14:09:57 +0800 Subject: [PATCH 0325/1631] Set default cacheAsMap to false. --- cocos2d/core/components/CCLabel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 6e23b39aca8..ea68f78686f 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -432,7 +432,7 @@ let Label = cc.Class({ } }, - _cacheAsBitmap: true, + _cacheAsBitmap: false, /** * !#en Whether cache label to static texture and draw in dynamicAtlas. * !#zh 是否将label缓存成静态图像并加入到动态图集.(对于静态文本建议使用该选项,便于批次合并减少drawcall) From bf45e1b6bfb2dc87003e1bbe72ae4b15c12e7301 Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 21 Dec 2018 15:27:01 +0800 Subject: [PATCH 0326/1631] Fix some lable issues because of dynamicatlas change. --- cocos2d/core/components/CCLabel.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index ea68f78686f..58b53a97eec 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -446,6 +446,11 @@ let Label = cc.Class({ if (this._cacheAsBitmap === value) return; this._cacheAsBitmap = value; + + if (!this._cacheAsBitmap && !(this.font instanceof cc.BitmapFont)) { + this._frame._resetDynamicAtlasFrame(); + } + this._activateMaterial(true); this._updateRenderData(); }, }, @@ -530,6 +535,7 @@ let Label = cc.Class({ if (this._assembler !== assembler) { this._assembler = assembler; this._renderData = null; + this._frame = null; } if (!this._renderData) { @@ -574,14 +580,14 @@ let Label = cc.Class({ } this._assemblerData = this._assembler._getAssemblerData(); this._ttfTexture.initWithElement(this._assemblerData.canvas); - - if (!this._frame) { - this._frame = new LabelFrame(); - } + } - this._frame._refreshTexture(this._ttfTexture); + if (!this._frame) { + this._frame = new LabelFrame(); } + this._frame._refreshTexture(this._ttfTexture); + this._activateMaterial(force); if (force) { From 286763141b2a100aa3d7a230cddf721f76634257 Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 21 Dec 2018 16:27:20 +0800 Subject: [PATCH 0327/1631] Revert dragonbones change. --- extensions/dragonbones/webgl-assembler.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index e7dc528b92f..513d99add18 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -132,25 +132,6 @@ let armatureAssembler = { _currMaterial = null; _vertexOffset = 0; _indiceOffset = 0; - }, - - fillBuffers (comp, renderer) { - let armature = comp._armature; - if (!armature || comp._isChildArmature) return; - - let buffer = renderer._meshBuffer, - renderData = comp._renderData; - - _vertexOffset = buffer.byteOffset >> 2; - _indiceOffset = buffer.indiceOffset; - _vertexId = buffer.vertexOffset; - - buffer.request(renderData.vertexCount, renderData.indiceCount); - - // buffer data may be realloc, need get reference after request. - _vbuf = buffer._vData; - _uintbuf = buffer._uintVData; - _ibuf = buffer._iData; let node = comp.node; let nodeColor = node.color; From 9a55b6aed4f28e6c224f7dcf87629ebe9dbdbb98 Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 21 Dec 2018 16:19:05 +0800 Subject: [PATCH 0328/1631] Increase the fault tolerance judgment of original. --- cocos2d/core/assets/CCSpriteFrame.js | 1 + cocos2d/core/renderer/utils/label/label-frame.js | 1 + 2 files changed, 2 insertions(+) diff --git a/cocos2d/core/assets/CCSpriteFrame.js b/cocos2d/core/assets/CCSpriteFrame.js index b5e06776f70..be124f3be0f 100644 --- a/cocos2d/core/assets/CCSpriteFrame.js +++ b/cocos2d/core/assets/CCSpriteFrame.js @@ -599,6 +599,7 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ }, _resetDynamicAtlasFrame () { + if (!this._original) return; this._rect.x = this._original._x; this._rect.y = this._original._y; this._texture = this._original._texture; diff --git a/cocos2d/core/renderer/utils/label/label-frame.js b/cocos2d/core/renderer/utils/label/label-frame.js index 277e0a8d540..ac42c02b59f 100644 --- a/cocos2d/core/renderer/utils/label/label-frame.js +++ b/cocos2d/core/renderer/utils/label/label-frame.js @@ -78,6 +78,7 @@ LabelFrame.prototype = { this._calculateUV(); }, _resetDynamicAtlasFrame () { + if (!this._original) return; this._rect.x = this._original._x; this._rect.y = this._original._y; this._texture = this._original._texture; From 9bec8b2cc53d6a8817c2df8ea2f54dba4de6308d Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 21 Dec 2018 16:34:22 +0800 Subject: [PATCH 0329/1631] Modify the variable name of cacheAsBitmap to batchAsBitmap. --- cocos2d/core/components/CCLabel.js | 14 +++++++------- cocos2d/core/renderer/utils/label/ttf.js | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 8f7f658bd4a..ad9911481da 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -432,22 +432,22 @@ let Label = cc.Class({ } }, - _cacheAsBitmap: false, + _batchAsBitmap: false, /** * !#en Whether cache label to static texture and draw in dynamicAtlas. * !#zh 是否将label缓存成静态图像并加入到动态图集.(对于静态文本建议使用该选项,便于批次合并减少drawcall) - * @property {Boolean} cacheAsBitmap + * @property {Boolean} batchAsBitmap */ - cacheAsBitmap: { + batchAsBitmap: { get () { - return this._cacheAsBitmap; + return this._batchAsBitmap; }, set (value) { - if (this._cacheAsBitmap === value) return; + if (this._batchAsBitmap === value) return; - this._cacheAsBitmap = value; + this._batchAsBitmap = value; - if (!this._cacheAsBitmap && !(this.font instanceof cc.BitmapFont)) { + if (!this._batchAsBitmap && !(this.font instanceof cc.BitmapFont)) { this._frame._resetDynamicAtlasFrame(); } this._activateMaterial(true); diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index d9cebe8ed24..27ff10f2173 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -280,7 +280,7 @@ module.exports = { }, _calDynamicAtlas (comp) { - if(!comp.cacheAsBitmap) return; + if(!comp.batchAsBitmap) return; if (!comp._frame._original) { comp._frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height)); From 832ab1c8cb12d07f5e089ad9ab529cf4a2ccf1f3 Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 21 Dec 2018 16:41:42 +0800 Subject: [PATCH 0330/1631] Reset dragonbones change. --- extensions/dragonbones/webgl-assembler.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 513d99add18..c352845dc91 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -27,7 +27,6 @@ const StencilManager = require('../../cocos2d/core/renderer/webgl/stencil-manage const Armature = require('./ArmatureDisplay'); const renderEngine = require('../../cocos2d/core/renderer/render-engine'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); - const gfx = renderEngine.gfx; const SpriteMaterial = renderEngine.SpriteMaterial; const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; @@ -126,7 +125,6 @@ let armatureAssembler = { if (!_data) { _data = _datas[_dataId] = comp.requestRenderData(); } - _data.dataLength = 0; _material = null; _currMaterial = null; From b16d8dbc51d4764561552672206494cfb6547d83 Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 21 Dec 2018 18:17:28 +0800 Subject: [PATCH 0331/1631] Add editor support. --- cocos2d/core/components/CCLabel.js | 2 ++ editor/i18n/en/localization.js | 3 ++- editor/i18n/zh/localization.js | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index ad9911481da..ae85451e296 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -453,6 +453,8 @@ let Label = cc.Class({ this._activateMaterial(true); this._updateRenderData(); }, + animatable: false, + tooltip: CC_DEV && 'i18n:COMPONENT.label.batch_as_bitmap', }, _isBold: { diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 4e55aea4797..c2a60f8b069 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -96,7 +96,8 @@ module.exports = { "overflow": "Text layout modes: \n 1. CLAMP: text nodes outside the bounding box will be truncated \n 2. SHRINK: automatically shrink text box according to the constraint node \n 3. RESIZE: Automatically updates the Node based on heightof the text.", "wrap": "Wrap text?", "font": "What font to use", - "system_font": "Whether to use the system default font" + "system_font": "Whether to use the system default font", + 'batch_as_bitmap': 'Whether to set to static text for batch merging, select this will add text to the dynamic atlas for batch merging, but can not dynamically modify the text content' }, "progress": { "bar_sprite": "A progress bar is displayed with the Sprite node that can dynamically change the size", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 4f1fa16a57f..80437e1df87 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -100,6 +100,7 @@ module.exports = { 'wrap': '是否允许自动换行', 'font': 'Label 使用的字体资源', 'system_font': '是否使用系统默认字体,选中此项会将 file 属性置空', + 'batch_as_bitmap': '是否设置为静态文本进行批次合并,选中此项将会把文本加入动态图集进行批次合并,但是不能够动态修改文本内容' }, 'progress': { 'bar_sprite': '进度条显示用的 Sprite 节点,可以动态改变尺寸', From 809619c90d8c9b9d2f9d7e19d4ef1cf07668e7c3 Mon Sep 17 00:00:00 2001 From: caryliu Date: Sun, 23 Dec 2018 10:49:49 +0800 Subject: [PATCH 0332/1631] change batch_as_bitmap content --- editor/i18n/en/localization.js | 2 +- editor/i18n/zh/localization.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index c2a60f8b069..5a7e8269c51 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -97,7 +97,7 @@ module.exports = { "wrap": "Wrap text?", "font": "What font to use", "system_font": "Whether to use the system default font", - 'batch_as_bitmap': 'Whether to set to static text for batch merging, select this will add text to the dynamic atlas for batch merging, but can not dynamically modify the text content' + 'batch_as_bitmap': 'Whether to set to static text for batch merging, select this will add text to the dynamic atlas for batch merging, but can not dynamically modify text content frequently' }, "progress": { "bar_sprite": "A progress bar is displayed with the Sprite node that can dynamically change the size", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 80437e1df87..85f72f2beb7 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -100,7 +100,7 @@ module.exports = { 'wrap': '是否允许自动换行', 'font': 'Label 使用的字体资源', 'system_font': '是否使用系统默认字体,选中此项会将 file 属性置空', - 'batch_as_bitmap': '是否设置为静态文本进行批次合并,选中此项将会把文本加入动态图集进行批次合并,但是不能够动态修改文本内容' + 'batch_as_bitmap': '是否设置为静态文本进行批次合并,选中此项将会把文本加入动态图集进行批次合并,但是不能频繁动态修改文本内容' }, 'progress': { 'bar_sprite': '进度条显示用的 Sprite 节点,可以动态改变尺寸', From c6cf6bb3a331e750a410d52403db318d57111b3c Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Sun, 23 Dec 2018 21:31:56 +0800 Subject: [PATCH 0333/1631] Fix some label problems caused by dynamicAtlas change. (#3667) * Fix BMFont simulator error. * Set default cacheAsMap to false. * Fix some lable issues because of dynamicatlas change. * Increase the fault tolerance judgment of original. * Modify the variable name of cacheAsBitmap to batchAsBitmap. * Add editor support. * change batch_as_bitmap content --- cocos2d/core/assets/CCSpriteFrame.js | 1 + cocos2d/core/components/CCLabel.js | 36 +++++++++++-------- .../core/renderer/utils/label/label-frame.js | 1 + cocos2d/core/renderer/utils/label/ttf.js | 2 +- editor/i18n/en/localization.js | 3 +- editor/i18n/zh/localization.js | 1 + 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/cocos2d/core/assets/CCSpriteFrame.js b/cocos2d/core/assets/CCSpriteFrame.js index 9ce82755253..890bbc5b248 100644 --- a/cocos2d/core/assets/CCSpriteFrame.js +++ b/cocos2d/core/assets/CCSpriteFrame.js @@ -599,6 +599,7 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ }, _resetDynamicAtlasFrame () { + if (!this._original) return; this._rect.x = this._original._x; this._rect.y = this._original._y; this._texture = this._original._texture; diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index d25341a4fe6..583c22b5834 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -432,22 +432,29 @@ let Label = cc.Class({ } }, - _cacheAsBitmap: true, + _batchAsBitmap: false, /** * !#en Whether cache label to static texture and draw in dynamicAtlas. * !#zh 是否将label缓存成静态图像并加入到动态图集.(对于静态文本建议使用该选项,便于批次合并减少drawcall) - * @property {Boolean} cacheAsBitmap + * @property {Boolean} batchAsBitmap */ - cacheAsBitmap: { + batchAsBitmap: { get () { - return this._cacheAsBitmap; + return this._batchAsBitmap; }, set (value) { - if (this._cacheAsBitmap === value) return; + if (this._batchAsBitmap === value) return; - this._cacheAsBitmap = value; + this._batchAsBitmap = value; + + if (!this._batchAsBitmap && !(this.font instanceof cc.BitmapFont)) { + this._frame._resetDynamicAtlasFrame(); + } + this._activateMaterial(true); this._updateRenderData(); }, + animatable: false, + tooltip: CC_DEV && 'i18n:COMPONENT.label.batch_as_bitmap', }, _isBold: { @@ -533,6 +540,7 @@ let Label = cc.Class({ if (this._assembler !== assembler) { this._assembler = assembler; this._renderData = null; + this._frame = null; } if (!this._renderData) { @@ -545,10 +553,11 @@ let Label = cc.Class({ let font = this.font; if (font instanceof cc.BitmapFont) { let spriteFrame = font.spriteFrame; + this._frame = spriteFrame; let self = this; let onBMFontTextureLoaded = function () { // TODO: old texture in material have been released by loader - self._texture = spriteFrame._texture; + self._frame._texture = spriteFrame._texture; self._activateMaterial(force); if (force) { @@ -567,9 +576,6 @@ let Label = cc.Class({ spriteFrame.ensureLoadTexture(); } } - - // TODO: old texture in material have been released by loader - this._frame = spriteFrame; } else { if (!this._ttfTexture) { @@ -580,14 +586,14 @@ let Label = cc.Class({ } this._assemblerData = this._assembler._getAssemblerData(); this._ttfTexture.initWithElement(this._assemblerData.canvas); - - if (!this._frame) { - this._frame = new LabelFrame(); - } + } - this._frame._refreshTexture(this._ttfTexture); + if (!this._frame) { + this._frame = new LabelFrame(); } + this._frame._refreshTexture(this._ttfTexture); + this._activateMaterial(force); if (force) { diff --git a/cocos2d/core/renderer/utils/label/label-frame.js b/cocos2d/core/renderer/utils/label/label-frame.js index 277e0a8d540..ac42c02b59f 100644 --- a/cocos2d/core/renderer/utils/label/label-frame.js +++ b/cocos2d/core/renderer/utils/label/label-frame.js @@ -78,6 +78,7 @@ LabelFrame.prototype = { this._calculateUV(); }, _resetDynamicAtlasFrame () { + if (!this._original) return; this._rect.x = this._original._x; this._rect.y = this._original._y; this._texture = this._original._texture; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index d9cebe8ed24..27ff10f2173 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -280,7 +280,7 @@ module.exports = { }, _calDynamicAtlas (comp) { - if(!comp.cacheAsBitmap) return; + if(!comp.batchAsBitmap) return; if (!comp._frame._original) { comp._frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height)); diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 97640906899..10b4df4cf2f 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -96,7 +96,8 @@ module.exports = { "overflow": "Text layout modes: \n 1. CLAMP: text nodes outside the bounding box will be truncated \n 2. SHRINK: automatically shrink text box according to the constraint node \n 3. RESIZE: Automatically updates the Node based on heightof the text.", "wrap": "Wrap text?", "font": "What font to use", - "system_font": "Whether to use the system default font" + "system_font": "Whether to use the system default font", + 'batch_as_bitmap': 'Whether to set to static text for batch merging, select this will add text to the dynamic atlas for batch merging, but can not dynamically modify text content frequently' }, "progress": { "bar_sprite": "A progress bar is displayed with the Sprite node that can dynamically change the size", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index e69ae2d24ed..3a2d9f57281 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -100,6 +100,7 @@ module.exports = { 'wrap': '是否允许自动换行', 'font': 'Label 使用的字体资源', 'system_font': '是否使用系统默认字体,选中此项会将 file 属性置空', + 'batch_as_bitmap': '是否设置为静态文本进行批次合并,选中此项将会把文本加入动态图集进行批次合并,但是不能频繁动态修改文本内容' }, 'progress': { 'bar_sprite': '进度条显示用的 Sprite 节点,可以动态改变尺寸', From 1b03af9d264d2919d52be6869bf1ae69862f6226 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 24 Dec 2018 14:42:29 +0800 Subject: [PATCH 0334/1631] Improve label vertical align for 2d-tasks/issues/886 (#3664) --- cocos2d/core/renderer/utils/label/ttf.js | 107 +++++++++-------------- 1 file changed, 43 insertions(+), 64 deletions(-) diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 27ff10f2173..67d52c3c664 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -34,6 +34,9 @@ const Overflow = Label.Overflow; const WHITE = cc.Color.WHITE; const OUTLINE_SUPPORTED = cc.js.isChildClassOf(LabelOutline, Component); +const BASELINE_RATIO = 0.25; +const MIDDLE_RATIO = (BASELINE_RATIO + 1) / 2 - BASELINE_RATIO; + let _context = null; let _canvas = null; let _texture = null; @@ -41,7 +44,7 @@ let _texture = null; let _fontDesc = ''; let _string = ''; let _fontSize = 0; -let _drawFontsize = 0; +let _drawFontSize = 0; let _splitedStrings = []; let _canvasSize = cc.size(); let _lineHeight = 0; @@ -61,6 +64,10 @@ let _margin = 0; let _isBold = false; let _isItalic = false; let _isUnderline = false; +let _underlineThickness = 0; + +let _drawTextPos = cc.v2(); +let _drawUnderlinePos = cc.v2(); let _sharedLabelData; @@ -173,10 +180,11 @@ module.exports = { _context = assemblerData.context; _canvas = assemblerData.canvas; _texture = comp._frame._original ? comp._frame._original._texture : comp._frame._texture; - + _string = comp.string.toString(); _fontSize = comp._fontSize; - _drawFontsize = _fontSize; + _drawFontSize = _fontSize; + _underlineThickness = _drawFontSize / 8; _overflow = comp.overflow; _canvasSize.width = comp.node.width; _canvasSize.height = comp.node.height; @@ -214,11 +222,7 @@ module.exports = { }, _calculateFillTextStartPosition () { - let lineHeight = this._getLineHeight(); - let lineCount = _splitedStrings.length; - let labelX; - let firstLinelabelY; - + let labelX = 0; if (_hAlign === macro.TextAlignment.RIGHT) { labelX = _canvasSize.width - _margin; } @@ -229,14 +233,17 @@ module.exports = { labelX = 0 + _margin; } + let firstLinelabelY = 0; + let lineHeight = this._getLineHeight(); + let drawStartY = lineHeight * (_splitedStrings.length - 1); if (_vAlign === macro.VerticalTextAlignment.TOP) { - firstLinelabelY = 0; + firstLinelabelY = lineHeight + _margin; } else if (_vAlign === macro.VerticalTextAlignment.CENTER) { - firstLinelabelY = _canvasSize.height / 2 - lineHeight * (lineCount - 1) / 2; + firstLinelabelY = (_canvasSize.height - drawStartY) * 0.5 + _drawFontSize * MIDDLE_RATIO; } else { - firstLinelabelY = _canvasSize.height - lineHeight * (lineCount - 1); + firstLinelabelY = _canvasSize.height - drawStartY - _drawFontSize * BASELINE_RATIO - _margin; } return cc.v2(labelX, firstLinelabelY); @@ -251,37 +258,40 @@ module.exports = { //use round for line join to avoid sharp intersect point _context.lineJoin = 'round'; _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_color.a / 255})`; - let underlineStartPosition; //do real rendering for (let i = 0; i < _splitedStrings.length; ++i) { - if (_isOutlined) { - let strokeColor = _outlineColor || WHITE; - _context.strokeStyle = `rgba(${strokeColor.r}, ${strokeColor.g}, ${strokeColor.b}, ${strokeColor.a / 255})`; - _context.lineWidth = _outlineWidth * 2; - _context.strokeText(_splitedStrings[i], startPosition.x, startPosition.y + i * lineHeight); - } - _context.fillText(_splitedStrings[i], startPosition.x, startPosition.y + i * lineHeight); + _drawTextPos.x = startPosition.x; + _drawTextPos.y = startPosition.y + i * lineHeight; if (_isUnderline) { - underlineStartPosition = this._calculateUnderlineStartPosition(); + _drawUnderlinePos.x = 0 + _margin; + _drawUnderlinePos.y = _drawTextPos.y + _underlineThickness; _context.save(); _context.beginPath(); - _context.lineWidth = _fontSize / 8; + _context.lineWidth = _underlineThickness; _context.strokeStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_color.a / 255})`; - _context.moveTo(underlineStartPosition.x, underlineStartPosition.y + i * lineHeight - 1); - _context.lineTo(underlineStartPosition.x + _canvas.width, underlineStartPosition.y + i * lineHeight - 1); + _context.moveTo(_drawUnderlinePos.x, _drawUnderlinePos.y); + _context.lineTo(_drawUnderlinePos.x + _canvas.width, _drawUnderlinePos.y); _context.stroke(); _context.restore(); } + + if (_isOutlined) { + let strokeColor = _outlineColor || WHITE; + _context.strokeStyle = `rgba(${strokeColor.r}, ${strokeColor.g}, ${strokeColor.b}, ${strokeColor.a / 255})`; + _context.lineWidth = _outlineWidth * 2; + _context.strokeText(_splitedStrings[i], _drawTextPos.x, _drawTextPos.y); + } + _context.fillText(_splitedStrings[i], _drawTextPos.x, _drawTextPos.y); } _texture.handleLoadedTexture(); }, _calDynamicAtlas (comp) { - if(!comp.batchAsBitmap) return; - + if(!comp.cacheAsBitmap) return; + if (!comp._frame._original) { comp._frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height)); } @@ -289,32 +299,11 @@ module.exports = { comp._calDynamicAtlas(); }, - _calculateUnderlineStartPosition () { - let lineHeight = this._getLineHeight(); - let lineCount = _splitedStrings.length; - let labelX; - let firstLinelabelY; - - labelX = 0 + _margin; - - if (_vAlign === macro.VerticalTextAlignment.TOP) { - firstLinelabelY = _fontSize; - } - else if (_vAlign === macro.VerticalTextAlignment.CENTER) { - firstLinelabelY = _canvasSize.height / 2 - lineHeight * (lineCount - 1) / 2 + _fontSize / 2; - } - else { - firstLinelabelY = _canvasSize.height - lineHeight * (lineCount - 1); - } - - return cc.v2(labelX, firstLinelabelY); - }, - _updateLabelDimensions () { let paragraphedStrings = _string.split('\n'); if (_overflow === Overflow.RESIZE_HEIGHT) { - _canvasSize.height = _splitedStrings.length * this._getLineHeight(); + _canvasSize.height = (_splitedStrings.length + BASELINE_RATIO) * this._getLineHeight() + 2 * _margin; } else if (_overflow === Overflow.NONE) { _splitedStrings = paragraphedStrings; @@ -324,13 +313,13 @@ module.exports = { let paraLength = textUtils.safeMeasureText(_context, paragraphedStrings[i]); canvasSizeX = canvasSizeX > paraLength ? canvasSizeX : paraLength; } - canvasSizeY = _splitedStrings.length * this._getLineHeight(); + canvasSizeY = (_splitedStrings.length + BASELINE_RATIO) * this._getLineHeight(); _canvasSize.width = parseFloat(canvasSizeX.toFixed(2)) + 2 * _margin; - _canvasSize.height = parseFloat(canvasSizeY.toFixed(2)); + _canvasSize.height = parseFloat(canvasSizeY.toFixed(2)) + 2 * _margin; if (_isItalic) { //0.0174532925 = 3.141592653 / 180 - _canvasSize.width += _drawFontsize * Math.tan(12 * 0.0174532925); + _canvasSize.width += _drawFontSize * Math.tan(12 * 0.0174532925); } } @@ -353,17 +342,7 @@ module.exports = { hAlign = 'left'; } _context.textAlign = hAlign; - - if (_vAlign === macro.VerticalTextAlignment.TOP) { - vAlign = 'top'; - } - else if (_vAlign === macro.VerticalTextAlignment.CENTER) { - vAlign = 'middle'; - } - else { - vAlign = 'bottom'; - } - _context.textBaseline = vAlign; + _context.textBaseline = 'alphabetic'; }, _calculateSplitedStrings () { @@ -402,7 +381,7 @@ module.exports = { if (nodeSpacingY === 0) { nodeSpacingY = _fontSize; } else { - nodeSpacingY = nodeSpacingY * _fontSize / _drawFontsize; + nodeSpacingY = nodeSpacingY * _fontSize / _drawFontSize; } return nodeSpacingY | 0; @@ -432,7 +411,7 @@ module.exports = { if (_overflow === Overflow.SHRINK) { let paragraphedStrings = _string.split('\n'); let paragraphLength = this._calculateParagraphLength(paragraphedStrings, _context); - + let i = 0; let totalHeight = 0; let maxLength = 0; @@ -504,7 +483,7 @@ module.exports = { let scaleX = (_canvasSize.width - 2 * _margin) / maxLength; let scaleY = _canvasSize.height / totalHeight; - _fontSize = (_drawFontsize * Math.min(1, scaleX, scaleY)) | 0; + _fontSize = (_drawFontSize * Math.min(1, scaleX, scaleY)) | 0; _fontDesc = this._getFontDesc(); _context.font = _fontDesc; } From 5491200bb670e842a0233633c5af854894c7bd75 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 24 Dec 2018 14:50:08 +0800 Subject: [PATCH 0335/1631] RichText component change to the default color as the color of the node (#3672) --- cocos2d/core/components/CCRichText.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index d6113103123..7ed506d6a1a 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -871,7 +871,7 @@ let RichText = cc.Class({ if (textStyle && textStyle.color) { labelNode.color = this._convertLiteralColorValue(textStyle.color); }else { - labelNode.color = this._convertLiteralColorValue("white"); + labelNode.color = this.node.color; } labelComponent._enableBold(textStyle && textStyle.bold); From add42371a88946f5f1fc28941d35ef32327db6fa Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 24 Dec 2018 14:55:11 +0800 Subject: [PATCH 0336/1631] add full language api (#3671) * add full language api * refine code --- cocos2d/core/platform/CCSys.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 0eaadce531e..13adec3270a 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -579,6 +579,7 @@ function initSys () { sys.isMobile = false; sys.platform = sys.EDITOR_CORE; sys.language = sys.LANGUAGE_UNKNOWN; + sys.languageCode = sys.LANGUAGE_UNKNOWN; sys.os = ({ darwin: sys.OS_OSX, win32: sys.OS_WINDOWS, @@ -615,6 +616,7 @@ function initSys () { sys.os = __getOS(); sys.language = __getCurrentLanguage(); + sys.languageCode = __getCurrentLanguageCode(); sys.osVersion = __getOSVersion(); sys.osMainVersion = parseInt(sys.osVersion); sys.browserType = null; @@ -659,6 +661,7 @@ function initSys () { sys.isMobile = true; sys.platform = sys.WECHAT_GAME; sys.language = env.language.substr(0, 2); + sys.languageCode = env.language; var system = env.system.toLowerCase(); if (env.platform === "android") { sys.os = sys.OS_ANDROID; @@ -719,6 +722,7 @@ function initSys () { sys.isMobile = true; sys.platform = sys.QQ_PLAY; sys.language = sys.LANGUAGE_UNKNOWN; + sys.languageCode = sys.LANGUAGE_UNKNOWN; if (env.platform === "android") { sys.os = sys.OS_ANDROID; } @@ -762,6 +766,7 @@ function initSys () { sys.browserType = env.browserType; sys.isMobile = env.isMobile; sys.language = env.language; + sys.languageCode = env.language; sys.os = env.os; sys.osVersion = env.osVersion; sys.osMainVersion = env.osMainVersion; @@ -801,6 +806,13 @@ function initSys () { var currLanguage = nav.language; currLanguage = currLanguage ? currLanguage : nav.browserLanguage; + + /** + * Get current language iso 639-1 code. + * @property {String} languageCode + */ + sys.languageCode = currLanguage; + currLanguage = currLanguage ? currLanguage.split("-")[0] : sys.LANGUAGE_ENGLISH; /** From a36e2c5c7568b1a1bf99ac7a23ef80fd612d12d1 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 24 Dec 2018 15:50:23 +0800 Subject: [PATCH 0337/1631] improve languageCode (#3673) * improve languageCode * update api --- cocos2d/core/platform/CCSys.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 13adec3270a..c2bb0178811 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -579,7 +579,7 @@ function initSys () { sys.isMobile = false; sys.platform = sys.EDITOR_CORE; sys.language = sys.LANGUAGE_UNKNOWN; - sys.languageCode = sys.LANGUAGE_UNKNOWN; + sys.languageCode = undefined; sys.os = ({ darwin: sys.OS_OSX, win32: sys.OS_WINDOWS, @@ -616,7 +616,8 @@ function initSys () { sys.os = __getOS(); sys.language = __getCurrentLanguage(); - sys.languageCode = __getCurrentLanguageCode(); + var languageCode = __getCurrentLanguageCode(); + sys.languageCode = languageCode ? languageCode.toLowerCase() : undefined; sys.osVersion = __getOSVersion(); sys.osMainVersion = parseInt(sys.osVersion); sys.browserType = null; @@ -661,7 +662,7 @@ function initSys () { sys.isMobile = true; sys.platform = sys.WECHAT_GAME; sys.language = env.language.substr(0, 2); - sys.languageCode = env.language; + sys.languageCode = env.language.toLowerCase(); var system = env.system.toLowerCase(); if (env.platform === "android") { sys.os = sys.OS_ANDROID; @@ -722,7 +723,7 @@ function initSys () { sys.isMobile = true; sys.platform = sys.QQ_PLAY; sys.language = sys.LANGUAGE_UNKNOWN; - sys.languageCode = sys.LANGUAGE_UNKNOWN; + sys.languageCode = undefined; if (env.platform === "android") { sys.os = sys.OS_ANDROID; } @@ -766,7 +767,7 @@ function initSys () { sys.browserType = env.browserType; sys.isMobile = env.isMobile; sys.language = env.language; - sys.languageCode = env.language; + sys.languageCode = env.language.toLowerCase(); sys.os = env.os; sys.osVersion = env.osVersion; sys.osMainVersion = env.osMainVersion; @@ -809,9 +810,11 @@ function initSys () { /** * Get current language iso 639-1 code. + * Examples of valid language codes include "zh-tw", "en", "en-us", "fr", "fr-fr", "es-es", etc. + * The actual value totally depends on results provided by destination platform. * @property {String} languageCode */ - sys.languageCode = currLanguage; + sys.languageCode = currLanguage.toLowerCase(); currLanguage = currLanguage ? currLanguage.split("-")[0] : sys.LANGUAGE_ENGLISH; From 01171aaa663e94edaec06cf8ef1fd48a8232b4a4 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Mon, 24 Dec 2018 16:25:13 +0800 Subject: [PATCH 0338/1631] Fix the error of Mask's lack of _calDynamicAtlas method. (#3675) --- cocos2d/core/components/CCMask.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index e029e28457e..d215e221ff6 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -32,6 +32,7 @@ const RenderComponent = require('./CCRenderComponent'); const RenderFlow = require('../renderer/render-flow'); const Graphics = require('../graphics/graphics'); const Node = require('../CCNode'); +const dynamicAtlasManager = require('../renderer/utils/dynamic-atlas/manager'); let _vec2_temp = cc.v2(); let _mat4_temp = math.mat4.create(); @@ -491,6 +492,21 @@ let Mask = cc.Class({ this.node._renderFlag &= ~(RenderFlow.FLAG_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_POST_RENDER); }, + + _calDynamicAtlas () + { + if (!this._spriteFrame) return; + + if (!this._spriteFrame._original && dynamicAtlasManager) { + let frame = dynamicAtlasManager.insertSpriteFrame(this._spriteFrame); + if (frame) { + this._spriteFrame._setDynamicAtlasFrame(frame); + } + } + if (this._material._texture !== this._spriteFrame._texture) { + this._activateMaterial(); + } + } }); cc.Mask = module.exports = Mask; From 4846b1303e322c81ffcffe6bb6d6ed31069a230c Mon Sep 17 00:00:00 2001 From: benloong Date: Tue, 25 Dec 2018 11:39:26 +0800 Subject: [PATCH 0339/1631] Change argument of clickEvents for consistency (#3659) * Change argument of clickEvents for consistency All UI component events should pass `this` to event handler instead of `event` for consistency. * add this parameter for clickEvents --- cocos2d/core/components/CCButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 8afc509c016..260404065d5 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -635,7 +635,7 @@ let Button = cc.Class({ if (!this.interactable || !this.enabledInHierarchy) return; if (this._pressed) { - cc.Component.EventHandler.emitEvents(this.clickEvents, event); + cc.Component.EventHandler.emitEvents(this.clickEvents, event, this); this.node.emit('click', this); } this._pressed = false; From e335d281f67be3630d8910c5b1514c86e2ab402c Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 25 Dec 2018 15:56:16 +0800 Subject: [PATCH 0340/1631] vec2 API note modify (#3678) --- cocos2d/core/value-types/vec2.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/value-types/vec2.js b/cocos2d/core/value-types/vec2.js index 8ba14000d14..828ba7e01c5 100644 --- a/cocos2d/core/value-types/vec2.js +++ b/cocos2d/core/value-types/vec2.js @@ -167,9 +167,9 @@ proto.lerp = function (to, ratio, out) { * @example * var min_inclusive = cc.v2(0, 0); * var max_inclusive = cc.v2(20, 20); - * var v1 = cc.v2(20, 20).clamp(min_inclusive, max_inclusive); // Vec2 {x: 20, y: 20}; - * var v2 = cc.v2(0, 0).clamp(min_inclusive, max_inclusive); // Vec2 {x: 0, y: 0}; - * var v3 = cc.v2(10, 10).clamp(min_inclusive, max_inclusive); // Vec2 {x: 10, y: 10}; + * var v1 = cc.v2(20, 20).clampf(min_inclusive, max_inclusive); // Vec2 {x: 20, y: 20}; + * var v2 = cc.v2(0, 0).clampf(min_inclusive, max_inclusive); // Vec2 {x: 0, y: 0}; + * var v3 = cc.v2(10, 10).clampf(min_inclusive, max_inclusive); // Vec2 {x: 10, y: 10}; */ proto.clampf = function (min_inclusive, max_inclusive) { this.x = misc.clampf(this.x, min_inclusive.x, max_inclusive.x); From b5c41c8ba1b82daa4ba6db5c957d3dea69f31536 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 25 Dec 2018 18:43:53 +0800 Subject: [PATCH 0341/1631] fixed the children cullingMask don't change when parent cullingMask changed (#3677) --- cocos2d/core/CCNode.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 01770d726d0..88fc24ec00d 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -524,6 +524,14 @@ function _getActualGroupIndex (node) { return groupIndex; } +function _updateCullingMask (node) { + let index = _getActualGroupIndex(node); + node._cullingMask = 1 << index; + for (let i = 0; i < node._children.length; i++) { + _updateCullingMask(node._children[i]); + } +} + /** * !#en * Class of all entities in Cocos Creator scenes.
@@ -601,8 +609,7 @@ var Node = cc.Class({ set (value) { // update the groupIndex this.groupIndex = cc.game.groupList.indexOf(value); - let index = _getActualGroupIndex(this); - this._cullingMask = 1 << index; + _updateCullingMask(this); this.emit(EventType.GROUP_CHANGED, this); } }, @@ -1253,6 +1260,7 @@ var Node = cc.Class({ _onHierarchyChanged (oldParent) { this._updateOrderOfArrival(); + _updateCullingMask(this); if (this._parent) { this._parent._delaySort(); } From faa5c04fb0eb27e7bb35e34c1e1adcb43ad80a22 Mon Sep 17 00:00:00 2001 From: caryliu Date: Tue, 25 Dec 2018 18:58:47 +0800 Subject: [PATCH 0342/1631] fix the error caused by trs not initialized. --- cocos2d/core/CCNode.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 2432fe10383..6567dcce180 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1153,14 +1153,7 @@ let NodeDefines = { // Mouse event listener this._mouseListener = null; - // Transform / Rotation / Scale data slots, with local dirty flags at 0 - let trs = this._trs = new Float32Array(11); - trs[0] = RenderFlow.FLAG_TRANSFORM; - trs[3] = 0; - trs[7] = 1; - trs[8] = 1; - trs[9] = 1; - trs[10] = 1; + this._initTrs(); this._matrix = mathPools.mat4.get(); this._worldMatrix = mathPools.mat4.get(); @@ -1285,6 +1278,9 @@ let NodeDefines = { if (this._parent) { this._parent._delaySort(); } + if (!this._trs) { + this._initTrs(); + } this._trs[0] |= RenderFlow.FLAG_WORLD_TRANSFORM; this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; this._onHierarchyChangedBase(oldParent); @@ -1298,11 +1294,24 @@ let NodeDefines = { } }, + _initTrs () { + // Transform / Rotation / Scale data slots, with local dirty flags at 0 + let trs = this._trs = new Float32Array(11); + trs[0] = RenderFlow.FLAG_TRANSFORM; + trs[3] = 0; + trs[7] = 1; + trs[8] = 1; + trs[9] = 1; + trs[10] = 1; + }, + // INTERNAL _upgrade_1x_to_2x () { + if (!this._trs) { + this._initTrs(); + } let trs = this._trs; - // Upgrade _position from v2 // TODO: remove in future version, 3.0 ? if (this._position !== undefined) { From dfeb08e627a03c173e839fbaf27664d0ced11f91 Mon Sep 17 00:00:00 2001 From: caryliu Date: Wed, 26 Dec 2018 11:30:44 +0800 Subject: [PATCH 0343/1631] fix trs access error --- cocos2d/core/CCNode.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 6567dcce180..2e3f4e3cdbd 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1278,10 +1278,9 @@ let NodeDefines = { if (this._parent) { this._parent._delaySort(); } - if (!this._trs) { - this._initTrs(); + if (this._trs) { + this._trs[0] |= RenderFlow.FLAG_WORLD_TRANSFORM; } - this._trs[0] |= RenderFlow.FLAG_WORLD_TRANSFORM; this._renderFlag |= RenderFlow.FLAG_WORLD_TRANSFORM; this._onHierarchyChangedBase(oldParent); if (cc._widgetManager) { From ace82ce5cf96e7aba2553c21c1c2660fd7114ca8 Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 26 Dec 2018 14:00:12 +0800 Subject: [PATCH 0344/1631] fix editBox updateMatrix for fireball (#3681) --- .../core/components/editbox/CCEditBoxImpl.js | 74 +++++++++++++------ 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index 3b1711ab086..7a71ef00eb2 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -41,8 +41,8 @@ let FOCUS_DELAY_UC = 400; let FOCUS_DELAY_FIREFOX = 0; let math = cc.vmath; -let _matrix = math.mat4.create(); -let _matrix_temp = math.mat4.create(); +let _worldMat = math.mat4.create(); +let _cameraMat = math.mat4.create(); let _vec3 = cc.v3(); let _currentEditBoxImpl = null; @@ -94,6 +94,16 @@ let EditBoxImpl = cc.Class({ this.__autoResize = false; this.__rotateScreen = false; this.__orientationChanged = null; + + // matrix cache + this._m00 = 0; + this._m01 = 0; + this._m04 = 0; + this._m05 = 0; + this._m12 = 0; + this._m13 = 0; + this._w = 0; + this._h = 0; }, onEnable () { @@ -350,43 +360,59 @@ let EditBoxImpl = cc.Class({ _updateMatrix () { if (!this._edTxt) return; + + let node = this._node; + node.getWorldMatrix(_worldMat); + + // check whether need to update + if (this._m00 === _worldMat.m00 && this._m01 === _worldMat.m01 && + this._m04 === _worldMat.m04 && this._m05 === _worldMat.m05 && + this._m12 === _worldMat.m12 && this._m13 === _worldMat.m13 && + this._w === node._contentSize.width && this._h === node._contentSize.height) { + return; + } + + // update matrix cache + this._m00 = _worldMat.m00; + this._m01 = _worldMat.m01; + this._m04 = _worldMat.m04; + this._m05 = _worldMat.m05; + this._m12 = _worldMat.m12; + this._m13 = _worldMat.m13; + this._w = node._contentSize.width; + this._h = node._contentSize.height; + + let scaleX = cc.view._scaleX, scaleY = cc.view._scaleY, + viewport = cc.view._viewportRect, + dpr = cc.view._devicePixelRatio; + + _vec3.x = -node._anchorPoint.x * this._w; + _vec3.y = -node._anchorPoint.y * this._h; + + math.mat4.translate(_worldMat, _worldMat, _vec3); - let camera; // can't find camera in editor if (CC_EDITOR) { - camera = cc.Camera.main; + _cameraMat = _worldMat; } else { - camera = cc.Camera.findCamera(this._node); + let camera = cc.Camera.findCamera(node); + camera.getWorldToCameraMatrix(_cameraMat); + math.mat4.mul(_cameraMat, _cameraMat, _worldMat); } - if (!camera) return; - - let node = this._node, - scaleX = cc.view._scaleX, scaleY = cc.view._scaleY, - viewport = cc.view._viewportRect, - dpr = cc.view._devicePixelRatio; - - node.getWorldMatrix(_matrix); - let contentSize = node._contentSize; - _vec3.x = -node._anchorPoint.x * contentSize.width; - _vec3.y = -node._anchorPoint.y * contentSize.height; - - math.mat4.translate(_matrix, _matrix, _vec3); - camera.getWorldToCameraMatrix(_matrix_temp); - math.mat4.mul(_matrix_temp, _matrix_temp, _matrix); scaleX /= dpr; scaleY /= dpr; let container = cc.game.container; - let a = _matrix_temp.m00 * scaleX, b = _matrix.m01, c = _matrix.m04, d = _matrix_temp.m05 * scaleY; + let a = _cameraMat.m00 * scaleX, b = _cameraMat.m01, c = _cameraMat.m04, d = _cameraMat.m05 * scaleY; let offsetX = container && container.style.paddingLeft && parseInt(container.style.paddingLeft); offsetX += viewport.x / dpr; let offsetY = container && container.style.paddingBottom && parseInt(container.style.paddingBottom); offsetY += viewport.y / dpr; - let tx = _matrix_temp.m12 * scaleX + offsetX, ty = _matrix_temp.m13 * scaleY + offsetY; + let tx = _cameraMat.m12 * scaleX + offsetX, ty = _cameraMat.m13 * scaleY + offsetY; if (polyfill.zoomInvalid) { this._updateSize(this._size.width * a, this._size.height * d); @@ -402,8 +428,8 @@ let EditBoxImpl = cc.Class({ }, _adjustEditBoxPosition () { - this._node.getWorldMatrix(_matrix); - let y = _matrix.m13; + this._node.getWorldMatrix(_worldMat); + let y = _worldMat.m13; let windowHeight = cc.visibleRect.height; let windowWidth = cc.visibleRect.width; let factor = 0.5; From fc3ebaae3c52d3526830cedbb22187362d83c587 Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 26 Dec 2018 15:28:54 +0800 Subject: [PATCH 0345/1631] fix editBox exitFullScreen bug (#3683) --- cocos2d/core/platform/CCScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCScreen.js b/cocos2d/core/platform/CCScreen.js index b919f494e50..99cc2d8eacc 100644 --- a/cocos2d/core/platform/CCScreen.js +++ b/cocos2d/core/platform/CCScreen.js @@ -150,7 +150,7 @@ cc.screen = /** @lends cc.screen# */{ * @return {Boolean} */ exitFullScreen: function (element) { - if (element.tagName.toLowerCase() === "video") { + if (element && element.tagName.toLowerCase() === "video") { if (cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser) { element.webkitExitFullscreen && element.webkitExitFullscreen(); return; From a4bfd7ab58c8984aaa0a2c9db413557cd881f3be Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 26 Dec 2018 17:50:11 +0800 Subject: [PATCH 0346/1631] Merge tag '2.1.0' into native-renderer --- cocos2d/actions/CCActionInterval.js | 161 ++------ cocos2d/animation/animation-animator.js | 8 +- cocos2d/audio/CCAudio.js | 4 +- cocos2d/core/3d/CCModel.js | 10 +- cocos2d/core/3d/CCSkeletonAnimationClip.js | 3 +- cocos2d/core/3d/actions.js | 215 +++++++++++ cocos2d/core/3d/index.js | 1 + cocos2d/core/3d/polyfill-3d.js | 11 +- cocos2d/core/CCGame.js | 16 +- cocos2d/core/CCNode.js | 71 +++- cocos2d/core/CCScene.js | 8 +- cocos2d/core/base-ui/CCWidgetManager.js | 2 +- cocos2d/core/camera/CCCamera.js | 2 + cocos2d/core/components/CCAudioSource.js | 9 +- cocos2d/core/components/CCButton.js | 72 ++-- cocos2d/core/components/CCLabel.js | 66 ++-- cocos2d/core/components/CCLabelOutline.js | 10 +- cocos2d/core/components/CCLayout.js | 50 ++- cocos2d/core/components/CCPageView.js | 18 +- cocos2d/core/components/CCRichText.js | 83 +++- cocos2d/core/components/CCSprite.js | 4 + cocos2d/core/components/CCToggle.js | 128 +++--- cocos2d/core/components/CCToggleContainer.js | 28 +- cocos2d/core/components/CCToggleGroup.js | 4 +- .../core/components/editbox/CCEditBoxImpl.js | 19 +- cocos2d/core/index.js | 1 + cocos2d/core/load-pipeline/CCLoader.js | 6 +- cocos2d/core/node-activator.js | 4 +- cocos2d/core/platform/CCInputManager.js | 8 +- cocos2d/core/platform/CCScreen.js | 21 +- cocos2d/core/platform/CCSys.js | 65 +--- cocos2d/core/platform/CCView.js | 11 +- cocos2d/core/platform/preprocess-class.js | 2 +- cocos2d/core/renderer/render-engine.canvas.js | 1 + cocos2d/core/renderer/render-engine.js | 17 +- cocos2d/core/renderer/render-engine.jsb.js | 17 +- cocos2d/core/renderer/render-flow.js | 12 +- cocos2d/core/renderer/utils/label/ttf.js | 1 + .../webgl/assemblers/label/{ => 2d}/bmfont.js | 72 ++-- .../webgl/assemblers/label/{ => 2d}/ttf.js | 31 +- .../webgl/assemblers/label/3d/bmfont.js | 35 ++ .../renderer/webgl/assemblers/label/3d/ttf.js | 36 ++ .../renderer/webgl/assemblers/label/index.js | 13 +- .../webgl/assemblers/mask-assembler.js | 2 +- .../webgl/assemblers/motion-streak.js | 2 +- .../assemblers/sprite/{ => 2d}/bar-filled.js | 68 ++-- .../webgl/assemblers/sprite/{ => 2d}/mesh.js | 55 +-- .../assemblers/sprite/2d/radial-filled.js | 337 ++++++++++++++++ .../assemblers/sprite/{ => 2d}/simple.js | 66 ++-- .../assemblers/sprite/{ => 2d}/sliced.js | 21 +- .../webgl/assemblers/sprite/{ => 2d}/tiled.js | 117 +++--- .../webgl/assemblers/sprite/3d/bar-filled.js | 67 ++++ .../webgl/assemblers/sprite/3d/mesh.js | 74 ++++ .../assemblers/sprite/3d/radial-filled.js | 47 +++ .../webgl/assemblers/sprite/3d/simple.js | 89 +++++ .../webgl/assemblers/sprite/3d/sliced.js | 100 +++++ .../webgl/assemblers/sprite/3d/tiled.js | 68 ++++ .../renderer/webgl/assemblers/sprite/index.js | 32 +- .../webgl/assemblers/sprite/radial-filled.js | 365 ------------------ .../core/renderer/webgl/assemblers/utils.js | 103 +++++ cocos2d/core/renderer/webgl/model-batcher.js | 6 +- cocos2d/core/utils/base-node.js | 2 +- cocos2d/core/utils/html-text-parser.js | 15 +- cocos2d/core/value-types/color.js | 4 + cocos2d/particle/CCParticleAsset.js | 6 +- cocos2d/particle/CCParticleSystem.js | 31 +- cocos2d/particle/particle-simulator.js | 4 +- cocos2d/videoplayer/video-player-impl.js | 116 +++--- editor/i18n/en/localization.js | 5 +- editor/i18n/zh/localization.js | 5 +- extensions/dragonbones/ArmatureDisplay.js | 1 + extensions/spine/spine-assembler.js | 2 +- gulpfile.js | 22 +- modules.json | 4 +- package.json | 2 +- test/qunit/lib/polyfill-for-phantom.js | 3 + .../unit-es5/test-component-scheduler.js | 6 +- test/qunit/unit-es5/test-node.js | 11 + 78 files changed, 2033 insertions(+), 1181 deletions(-) create mode 100644 cocos2d/core/3d/actions.js rename cocos2d/core/renderer/webgl/assemblers/label/{ => 2d}/bmfont.js (58%) rename cocos2d/core/renderer/webgl/assemblers/label/{ => 2d}/ttf.js (71%) create mode 100644 cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/bar-filled.js (82%) rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/mesh.js (84%) create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/simple.js (79%) rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/sliced.js (94%) rename cocos2d/core/renderer/webgl/assemblers/sprite/{ => 2d}/tiled.js (71%) create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/bar-filled.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/mesh.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/radial-filled.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/simple.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/sliced.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/3d/tiled.js delete mode 100644 cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/utils.js diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index ee5fdda61cc..e904b3b2cb8 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -25,10 +25,6 @@ THE SOFTWARE. ****************************************************************************/ -const quat = cc.vmath.quat; -let _quat_tmp = cc.quat(); -let _vec3_tmp = cc.v3(); - /** * @module cc @@ -871,13 +867,12 @@ cc.Spawn._actionOneTwo = function (action1, action2) { /* - * Rotates a Node object to a certain angle by modifying its rotation property.
+ * Rotates a Node object to a certain angle by modifying its angle property.
* The direction will be decided by the shortest angle. * @class RotateTo * @extends ActionInterval * @param {Number} duration duration in seconds - * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees. - * @param {Number} [deltaAngleY] deltaAngleY in degrees. + * @param {Number} dstAngle dstAngle in degrees. * @example * var rotateTo = new cc.RotateTo(2, 61.0); */ @@ -885,40 +880,22 @@ cc.RotateTo = cc.Class({ name: 'cc.RotateTo', extends: cc.ActionInterval, - ctor:function (duration, dstAngleX, dstAngleY) { - this._angle = cc.v3(); - this._startAngle = cc.v3(); - this._dstAngle = cc.v3(); - this._need3D = false; - dstAngleX !== undefined && this.initWithDuration(duration, dstAngleX, dstAngleY); + ctor:function (duration, dstAngle) { + this._startAngle = 0; + this._dstAngle = 0; + this._angle = 0; + dstAngle !== undefined && this.initWithDuration(duration, dstAngle); }, /* * Initializes the action. * @param {Number} duration - * @param {Number|Vec3} dstAngleX - * @param {Number} dstAngleY + * @param {Number} dstAngle * @return {Boolean} */ - initWithDuration:function (duration, dstAngleX, dstAngleY) { + initWithDuration:function (duration, dstAngle) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - let dstAngle = this._dstAngle; - if (dstAngleX instanceof cc.Vec3) { - dstAngle.set(dstAngleX); - if (dstAngleX.x || dstAngleX.y) { - this._need3D = true; - } - } - else if (dstAngleY !== undefined) { - dstAngle.x = dstAngleX; - dstAngle.y = dstAngleY; - dstAngle.z = 0; - this._need3D = true; - } - else { - dstAngle.x = dstAngle.y = 0; - dstAngle.z = dstAngleX; - } + this._dstAngle = dstAngle; return true; } return false; @@ -931,27 +908,14 @@ cc.RotateTo = cc.Class({ return action; }, - _formatAngle (angle) { - if (angle > 180) angle -= 360; - if (angle < -180) angle += 360; - return angle; - }, - startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - this._startAngle.set(target.eulerAngles); - - let angle = this._angle; - cc.vmath.vec3.sub(angle, this._dstAngle, this._startAngle); - - angle.x = this._formatAngle(angle.x); - angle.y = this._formatAngle(angle.y); - angle.z = this._formatAngle(angle.z); - - if (this._need3D) { - target.is3DNode = true; - } + this._startAngle = target.angle % 360; + let angle = this._dstAngle - this._startAngle; + if (angle > 180) angle -= 360; + if (angle < -180) angle += 360; + this._angle = angle; }, reverse:function () { @@ -961,49 +925,36 @@ cc.RotateTo = cc.Class({ update:function (dt) { dt = this._computeEaseTime(dt); if (this.target) { - let angle = this._angle; - let startAngle = this._startAngle; - let rotationZ = -(startAngle.z + angle.z * dt); - if (this._need3D) { - let rotationX = startAngle.x + angle.x * dt; - let rotationY = startAngle.y + angle.y * dt; - quat.fromEuler(_quat_tmp, rotationX, rotationY, rotationZ); - this.target.setRotation(_quat_tmp); - } - else { - this.target.angle = rotationZ; - } + this.target.angle = this._startAngle + this._angle * dt; } } }); /** * !#en - * Rotates a Node object to a certain angle by modifying its rotation property.
+ * Rotates a Node object to a certain angle by modifying its angle property.
* The direction will be decided by the shortest angle. - * !#zh 旋转到目标角度,通过逐帧修改它的 rotation 属性,旋转方向将由最短的角度决定。 + * !#zh 旋转到目标角度,通过逐帧修改它的 angle 属性,旋转方向将由最短的角度决定。 * @method rotateTo * @param {Number} duration duration in seconds - * @param {Number} deltaAngleX deltaAngleX in degrees. - * @param {Number} [deltaAngleY] deltaAngleY in degrees. + * @param {Number} dstAngle dstAngle in degrees. * @return {ActionInterval} * @example * // example * var rotateTo = cc.rotateTo(2, 61.0); */ -cc.rotateTo = function (duration, deltaAngleX, deltaAngleY) { - return new cc.RotateTo(duration, deltaAngleX, deltaAngleY); +cc.rotateTo = function (duration, dstAngle) { + return new cc.RotateTo(duration, dstAngle); }; /* - * Rotates a Node object clockwise a number of degrees by modifying its rotation property. + * Rotates a Node object clockwise a number of degrees by modifying its angle property. * Relative to its properties to modify. * @class RotateBy * @extends ActionInterval * @param {Number} duration duration in seconds - * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees - * @param {Number} [deltaAngleY] deltaAngleY in degrees + * @param {Number} deltaAngle deltaAngle in degrees * @example * var actionBy = new cc.RotateBy(2, 360); */ @@ -1011,38 +962,21 @@ cc.RotateBy = cc.Class({ name: 'cc.RotateBy', extends: cc.ActionInterval, - ctor: function (duration, deltaAngleX, deltaAngleY) { - this._angle = cc.v3(); - this._startAngle = cc.v3(); - this._need3D = false; - deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY); + ctor: function (duration, deltaAngle) { + this._deltaAngle = cc.v3(); + this._startAngle = 0; + deltaAngle !== undefined && this.initWithDuration(duration, deltaAngle); }, /* * Initializes the action. * @param {Number} duration duration in seconds - * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees - * @param {Number} [deltaAngleY=] deltaAngleY in degrees + * @param {Number} deltaAngle deltaAngle in degrees * @return {Boolean} */ - initWithDuration:function (duration, deltaAngleX, deltaAngleY) { + initWithDuration:function (duration, deltaAngle) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - if (deltaAngleX instanceof cc.Vec3) { - this._angle.set(deltaAngleX); - if (deltaAngleX.x || deltaAngleX.y) { - this._need3D = true; - } - } - else if (deltaAngleY !== undefined) { - this._angle.x = deltaAngleX; - this._angle.y = deltaAngleY; - this._angle.z = 0; - this._need3D = true; - } - else { - this._angle.x = this._angle.y = 0; - this._angle.z = deltaAngleX; - } + this._deltaAngle = deltaAngle; return true; } return false; @@ -1051,42 +985,24 @@ cc.RotateBy = cc.Class({ clone:function () { var action = new cc.RotateBy(); this._cloneDecoration(action); - action.initWithDuration(this._duration, this._angle); + action.initWithDuration(this._duration, this._deltaAngle); return action; }, startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - this._startAngle.set(target.eulerAngles); - if (this._need3D) { - target.is3DNode = true; - } + this._startAngle = target.angle; }, update:function (dt) { dt = this._computeEaseTime(dt); if (this.target) { - let angle = this._angle; - let startAngle = this._startAngle; - let rotationZ = -(startAngle.z + angle.z * dt); - if (this._need3D) { - let rotationX = startAngle.x + angle.x * dt; - let rotationY = startAngle.y + angle.y * dt; - quat.fromEuler(_quat_tmp, rotationX, rotationY, rotationZ); - this.target.setRotation(_quat_tmp); - } - else { - this.target.angle = rotationZ; - } + this.target.angle = this._startAngle + this._deltaAngle * dt; } }, reverse:function () { - let angle = this._angle; - _vec3_tmp.x = -angle.x; - _vec3_tmp.y = -angle.y; - _vec3_tmp.z = -angle.z; - var action = new cc.RotateBy(this._duration, _vec3_tmp); + var action = new cc.RotateBy(this._duration, -this._deltaAngle); this._cloneDecoration(action); this._reverseEaseList(action); return action; @@ -1095,20 +1011,19 @@ cc.RotateBy = cc.Class({ /** * !#en - * Rotates a Node object clockwise a number of degrees by modifying its rotation property. + * Rotates a Node object clockwise a number of degrees by modifying its angle property. * Relative to its properties to modify. * !#zh 旋转指定的角度。 * @method rotateBy * @param {Number} duration duration in seconds - * @param {Number} deltaAngleX deltaAngleX in degrees - * @param {Number} [deltaAngleY] deltaAngleY in degrees + * @param {Number} deltaAngle deltaAngle in degrees * @return {ActionInterval} * @example * // example * var actionBy = cc.rotateBy(2, 360); */ -cc.rotateBy = function (duration, deltaAngleX, deltaAngleY) { - return new cc.RotateBy(duration, deltaAngleX, deltaAngleY); +cc.rotateBy = function (duration, deltaAngle) { + return new cc.RotateBy(duration, deltaAngle); }; diff --git a/cocos2d/animation/animation-animator.js b/cocos2d/animation/animation-animator.js index 2780e546b34..77ebe24d837 100644 --- a/cocos2d/animation/animation-animator.js +++ b/cocos2d/animation/animation-animator.js @@ -226,10 +226,10 @@ function initClipData (root, state) { var curves = state.curves; curves.length = 0; - state.duration = clip.duration; - state.speed = clip.speed; - state.wrapMode = clip.wrapMode; - state.frameRate = clip.sample; + state.duration = Number.parseFloat(clip.duration); + state.speed = Number.parseFloat(clip.speed); + state.wrapMode = Number.parseInt(clip.wrapMode); + state.frameRate = Number.parseFloat(clip.sample); if ((state.wrapMode & WrapModeMask.Loop) === WrapModeMask.Loop) { state.repeatCount = Infinity; diff --git a/cocos2d/audio/CCAudio.js b/cocos2d/audio/CCAudio.js index 43d794fcd5a..68845a4a536 100644 --- a/cocos2d/audio/CCAudio.js +++ b/cocos2d/audio/CCAudio.js @@ -168,7 +168,7 @@ Audio.State = { }; proto.destroy = function () { - if (CC_WECHATGAME) { + if (CC_WECHATGAME || CC_QQPLAY) { this._element && this._element.destroy(); } this._element = null; @@ -264,7 +264,7 @@ Audio.State = { }; proto.getState = function () { - if (!CC_WECHATGAME) { + if (!CC_WECHATGAME && !CC_QQPLAY) { let elem = this._element; if (elem && Audio.State.PLAYING === this._state && elem.paused) { this._state = Audio.State.PAUSED; diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index 42156c1a84a..69f08710857 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -23,7 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const AnimationClip = require('../../animation/animation-clip'); const BufferAsset = require('../assets/CCBufferAsset'); const renderEngine = require('../renderer/render-engine'); @@ -237,6 +236,8 @@ let Model = cc.Class({ meshAsset._ibs.length = length; meshAsset._vbs.length = length; meshAsset._subMeshes.length = length; + vec3.set(meshAsset._minPos, Infinity, Infinity, Infinity); + vec3.set(meshAsset._maxPos, -Infinity, -Infinity, -Infinity); for (let i = 0; i < length; ++i) { let primitive = gltfMesh.primitives[i]; @@ -267,12 +268,8 @@ let Model = cc.Class({ this._initNodes(); let gltf = this._gltf; - let bin = this._bin; - - let accessors = gltf.accessors; let gltfAnimation = gltf.animations[clip._animationID]; - clip.name = gltfAnimation.name; clip.wrapMode = cc.WrapMode.Loop; let duration = 0; @@ -280,7 +277,6 @@ let Model = cc.Class({ let paths = curveData.paths = {}; let nodes = gltf.nodes; - let rootNode = nodes[0]; let samplers = gltfAnimation.samplers; let channels = gltfAnimation.channels; @@ -291,8 +287,6 @@ let Model = cc.Class({ let inputArray = this._createArray(gltf, sampler.input); let outputArray = this._createArray(gltf, sampler.output); - let interpolation = sampler.interpolation; - let target = gltfChannel.target; let node = nodes[target.node]; diff --git a/cocos2d/core/3d/CCSkeletonAnimationClip.js b/cocos2d/core/3d/CCSkeletonAnimationClip.js index ad1419bb5b0..f2df240637b 100644 --- a/cocos2d/core/3d/CCSkeletonAnimationClip.js +++ b/cocos2d/core/3d/CCSkeletonAnimationClip.js @@ -24,6 +24,7 @@ ****************************************************************************/ const Model = require('./CCModel'); +const AnimationClip = require('../../animation/animation-clip'); /** * @module cc @@ -36,7 +37,7 @@ const Model = require('./CCModel'); */ var SkeletonAnimationClip = cc.Class({ name: 'cc.SkeletonAnimationClip', - extends: cc.AnimationClip, + extends: AnimationClip, properties: { _modelSetter: { diff --git a/cocos2d/core/3d/actions.js b/cocos2d/core/3d/actions.js new file mode 100644 index 00000000000..687aa5daa83 --- /dev/null +++ b/cocos2d/core/3d/actions.js @@ -0,0 +1,215 @@ + +const quat = cc.vmath.quat; +let _quat_tmp = cc.quat(); +let _vec3_tmp = cc.v3(); + +/* + * Rotates a Node object to a certain angle by modifying its quaternion property.
+ * The direction will be decided by the shortest angle. + * @class Rotate3DTo + * @extends ActionInterval + * @param {Number} duration duration in seconds + * @param {Number|Vec3} dstAngleX dstAngleX in degrees. + * @param {Number} [dstAngleY] dstAngleY in degrees. + * @param {Number} [dstAngleZ] dstAngleZ in degrees. + * @example + * var rotate3DTo = new cc.Rotate3DTo(2, cc.v3(0, 180, 0)); + */ +cc.Rotate3DTo = cc.Class({ + name: 'cc.Rotate3DTo', + extends: cc.ActionInterval, + + ctor:function (duration, dstAngleX, dstAngleY, dstAngleZ) { + this._startQuat = cc.quat(); + this._dstQuat = cc.quat(); + + dstAngleX !== undefined && this.initWithDuration(duration, dstAngleX, dstAngleY, dstAngleZ); + }, + + /* + * Initializes the action. + * @param {Number} duration + * @param {Number|Vec3|Quat} dstAngleX + * @param {Number} dstAngleY + * @param {Number} dstAngleZ + * @return {Boolean} + */ + initWithDuration:function (duration, dstAngleX, dstAngleY, dstAngleZ) { + if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { + let dstQuat = this._dstQuat; + if (dstAngleX instanceof cc.Quat) { + dstQuat.set(dstAngleX); + } + else { + if (dstAngleX instanceof cc.Vec3) { + dstAngleY = dstAngleX.y; + dstAngleZ = dstAngleX.z; + dstAngleX = dstAngleX.x; + } + else { + dstAngleY = dstAngleY || 0; + dstAngleZ = dstAngleZ || 0; + } + cc.vmath.quat.fromEuler(dstQuat, dstAngleX, dstAngleY, dstAngleZ); + } + return true; + } + return false; + }, + + clone:function () { + var action = new cc.Rotate3DTo(); + this._cloneDecoration(action); + action.initWithDuration(this._duration, this._dstQuat); + return action; + }, + + startWithTarget:function (target) { + cc.ActionInterval.prototype.startWithTarget.call(this, target); + this._startQuat.set(target.quat); + }, + + reverse:function () { + cc.logID(1016); + }, + + update:function (dt) { + dt = this._computeEaseTime(dt); + if (this.target) { + quat.slerp(_quat_tmp, this._startQuat, this._dstQuat, dt); + this.target.setRotation(_quat_tmp); + } + } +}); + +/** + * !#en + * Rotates a Node object to a certain angle by modifying its quternion property.
+ * The direction will be decided by the shortest angle. + * !#zh 旋转到目标角度,通过逐帧修改它的 quternion 属性,旋转方向将由最短的角度决定。 + * @method rotate3DTo + * @param {Number} duration duration in seconds + * @param {Number|Vec3|Quat} dstAngleX dstAngleX in degrees. + * @param {Number} [dstAngleY] dstAngleY in degrees. + * @param {Number} [dstAngleZ] dstAngleZ in degrees. + * @return {ActionInterval} + * @example + * // example + * var rotate3DTo = cc.rotate3DTo(2, cc.v3(0, 180, 0)); + */ +cc.rotate3DTo = function (duration, dstAngleX, dstAngleY, dstAngleZ) { + return new cc.Rotate3DTo(duration, dstAngleX, dstAngleY, dstAngleZ); +}; + + +/* + * Rotates a Node object counter clockwise a number of degrees by modifying its quaternion property. + * Relative to its properties to modify. + * @class Rotate3DBy + * @extends ActionInterval + * @param {Number} duration duration in seconds + * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees + * @param {Number} [deltaAngleY] deltaAngleY in degrees + * @param {Number} [deltaAngleZ] deltaAngleZ in degrees + * @example + * var actionBy = new cc.Rotate3DBy(2, cc.v3(0, 360, 0)); + */ +cc.Rotate3DBy = cc.Class({ + name: 'cc.Rotate3DBy', + extends: cc.ActionInterval, + + ctor: function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { + this._angle = cc.v3(); + this._quat = cc.quat(); + this._lastDt = 0; + deltaAngleX !== undefined && this.initWithDuration(duration, deltaAngleX, deltaAngleY, deltaAngleZ); + }, + + /* + * Initializes the action. + * @param {Number} duration duration in seconds + * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees + * @param {Number} [deltaAngleY=] deltaAngleY in degrees + * @param {Number} [deltaAngleZ=] deltaAngleZ in degrees + * @return {Boolean} + */ + initWithDuration:function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { + if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { + if (deltaAngleX instanceof cc.Vec3) { + deltaAngleY = deltaAngleX.y; + deltaAngleZ = deltaAngleX.z; + deltaAngleX = deltaAngleX.x; + } + else { + deltaAngleY = deltaAngleY || 0; + deltaAngleZ = deltaAngleZ || 0; + } + cc.vmath.vec3.set(this._angle, deltaAngleX, deltaAngleY, deltaAngleZ); + return true; + } + return false; + }, + + clone:function () { + var action = new cc.Rotate3DBy(); + this._cloneDecoration(action); + action.initWithDuration(this._duration, this._angle); + return action; + }, + + startWithTarget:function (target) { + cc.ActionInterval.prototype.startWithTarget.call(this, target); + this._quat.set(target.quat); + this._lastDt = 0; + }, + + update: (function(){ + let RAD = Math.PI / 180; + return function (dt) { + dt = this._computeEaseTime(dt); + if (this.target) { + let angle = this._angle; + let dstQuat = this._quat; + let delta = dt - this._lastDt; + let angleX = angle.x, angleY = angle.y, angleZ = angle.z; + if (angleX) quat.rotateX(dstQuat, dstQuat, angleX * RAD * delta); + if (angleY) quat.rotateY(dstQuat, dstQuat, angleY * RAD * delta); + if (angleZ) quat.rotateZ(dstQuat, dstQuat, angleZ * RAD * delta); + this.target.setRotation(dstQuat); + + this._lastDt = dt; + } + } + })(), + + reverse:function () { + let angle = this._angle; + _vec3_tmp.x = -angle.x; + _vec3_tmp.y = -angle.y; + _vec3_tmp.z = -angle.z; + var action = new cc.Rotate3DBy(this._duration, _vec3_tmp); + this._cloneDecoration(action); + this._reverseEaseList(action); + return action; + } +}); + +/** + * !#en + * Rotates a Node object counter clockwise a number of degrees by modifying its quaternion property. + * Relative to its properties to modify. + * !#zh 旋转指定的 3D 角度。 + * @method rotate3DBy + * @param {Number} duration duration in seconds + * @param {Number|Vec3} deltaAngleX deltaAngleX in degrees + * @param {Number} [deltaAngleY] deltaAngleY in degrees + * @param {Number} [deltaAngleZ] deltaAngleZ in degrees + * @return {ActionInterval} + * @example + * // example + * var actionBy = cc.rotate3DBy(2, cc.v3(0, 360, 0)); + */ +cc.rotate3DBy = function (duration, deltaAngleX, deltaAngleY, deltaAngleZ) { + return new cc.Rotate3DBy(duration, deltaAngleX, deltaAngleY, deltaAngleZ); +}; + diff --git a/cocos2d/core/3d/index.js b/cocos2d/core/3d/index.js index c85054a8262..97cd062485f 100644 --- a/cocos2d/core/3d/index.js +++ b/cocos2d/core/3d/index.js @@ -8,6 +8,7 @@ require('./CCModel'); require('./CCSkeleton'); require('./CCSkeletonAnimationClip'); require('./CCModelMeshResource'); +require('./actions'); if (!CC_EDITOR || !Editor.isMainProcess) { require('./CCSkeletonAnimation'); diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index 52abd1d368f..83d5bfa4b8f 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -35,7 +35,7 @@ const ONE_DEGREE = Math.PI / 180; const POSITION_ON = 1 << 0; const SCALE_ON = 1 << 1; -const ROTATION_ON = 1 << 2; +const ERR_INVALID_NUMBER = CC_EDITOR && 'The %s is invalid'; let _quat = cc.quat(); @@ -158,7 +158,11 @@ function _update3DFunction () { this._calculWorldMatrix = _calculWorldMatrix2d; this._mulMat = _mulMat2d; } + if (this._renderComponent && this._renderComponent._on3DNodeChanged) { + this._renderComponent._on3DNodeChanged(); + } this._renderFlag |= RenderFlow.FLAG_TRANSFORM; + this._localMatDirty = DirtyFlag.ALL; } function _upgrade_1x_to_2x () { @@ -175,7 +179,6 @@ const _updateLocalMatrix2d = proto._updateLocalMatrix; const _calculWorldMatrix2d = proto._calculWorldMatrix; const _upgrade_1x_to_2x_2d = proto._upgrade_1x_to_2x; const _mulMat2d = proto._mulMat; -const _onBatchCreated2d = proto._onBatchCreated; proto.setPosition = setPosition; proto.setScale = setScale; @@ -233,14 +236,14 @@ cc.js.getset(proto, 'eulerAngles', function () { } else { _quat.fromRotation(this._trs); - return _quat.getEulerAngles(cc.v3()); + return _quat.toEuler(cc.v3()); } }, function (v) { if (CC_EDITOR) { this._eulerAngles.set(v); } - math.quat.fromEuler(_quat, v.x, v.y, v.z); + _quat.fromEuler(v); _quat.toRotation(this._trs); this.setLocalDirty(DirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 27b9770fc09..43d9fe38833 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -39,7 +39,6 @@ const dynamicAtlasManager = require('../core/renderer/utils/dynamic-atlas/manage * !#en An object to boot the game. * !#zh 包含游戏主体信息并负责驱动游戏的游戏对象。 * @class Game - * @static * @extends EventTarget */ var game = { @@ -704,11 +703,9 @@ var game = { let el = this.config.id, width, height, - localCanvas, localContainer, - isWeChatGame = cc.sys.platform === cc.sys.WECHAT_GAME, - isQQPlay = cc.sys.platform === cc.sys.QQ_PLAY; + localCanvas, localContainer; - if (isWeChatGame || CC_JSB) { + if (CC_WECHATGAME || CC_JSB) { this.container = localContainer = document.createElement("DIV"); this.frame = localContainer.parentNode === document.body ? document.documentElement : localContainer.parentNode; if (cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { @@ -722,7 +719,7 @@ var game = { } this.canvas = localCanvas; } - else if (isQQPlay) { + else if (CC_QQPLAY) { this.container = cc.container = document.createElement("DIV"); this.frame = document.documentElement; this.canvas = localCanvas = canvas; @@ -778,7 +775,7 @@ var game = { 'antialias': cc.macro.ENABLE_WEBGL_ANTIALIAS, 'alpha': cc.macro.ENABLE_TRANSPARENT_CANVAS }; - if (isWeChatGame || isQQPlay) { + if (CC_WECHATGAME || CC_QQPLAY) { opts['preserveDrawingBuffer'] = true; } renderer.initWebGL(localCanvas, opts); @@ -832,10 +829,11 @@ var game = { game.emit(game.EVENT_HIDE); } } - function onShown () { + // In order to adapt the most of platforms the onshow API. + function onShown (arg0, arg1, arg2, arg3, arg4) { if (hidden) { hidden = false; - game.emit(game.EVENT_SHOW); + game.emit(game.EVENT_SHOW, arg0, arg1, arg2, arg3, arg4); } } diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 2e3f4e3cdbd..265648c3a18 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -730,9 +730,8 @@ let NodeDefines = { return this._eulerAngles.z; }, set (value) { - this._eulerAngles.z = value; - math.quat.fromEuler(_quata, 0, 0, value); - _quata.toRotation(this._trs); + math.vec3.set(this._eulerAngles, 0, 0, value); + this._fromEuler(); this.setLocalDirty(LocalDirtyFlag.ROTATION); if (this._eventMask & ROTATION_ON) { @@ -1306,6 +1305,25 @@ let NodeDefines = { // INTERNAL + _toEuler () { + if (this.is3DNode) { + _quata.fromRotation(this._trs).toEuler(this._eulerAngles); + } + else { + let z = Math.asin(this._trs[6]) / ONE_DEGREE * 2; + math.vec3.set(this._eulerAngles, 0, 0, z); + } + }, + _fromEuler () { + if (this.is3DNode) { + _quata.fromRotation(this._trs).fromEuler(this._eulerAngles); + } + else { + math.quat.fromEuler(_quata, 0, 0, this._eulerAngles.z); + _quata.toRotation(this._trs); + } + }, + _upgrade_1x_to_2x () { if (!this._trs) { this._initTrs(); @@ -1331,6 +1349,23 @@ let NodeDefines = { } _quata.fromRotation(trs).toEuler(this._eulerAngles); + // TODO: remove _rotationX & _rotationY in future version, 3.0 ? + // Update quaternion from rotation, when upgrade from 1.x to 2.0 + // If rotation x & y is 0 in old version, then update rotation from default quaternion is ok too + // _quata.fromRotation(this._trs); + if ((this._rotationX || this._rotationY) && + (_quata.x === 0 && _quata.y === 0 && _quata.z === 0 && _quata.w === 1)) { + if (this._rotationX === this._rotationY) { + math.quat.fromEuler(_quata, 0, 0, -this._rotationX); + } + else { + math.quat.fromEuler(_quata, this._rotationX, this._rotationY, 0); + } + this._rotationX = this._rotationY = undefined; + } + + this._toEuler(); + // Upgrade _scale from v2 // TODO: remove in future version, 3.0 ? if (this._scale !== undefined) { @@ -2080,10 +2115,10 @@ let NodeDefines = { // TRANSFORM RELATED /** - * !#en + * !#en * Returns a copy of the position (x, y, z) of the node in its parent's coordinates. * You can pass a cc.Vec2 or cc.Vec3 as the argument to receive the return values. - * !#zh + * !#zh * 获取节点在父节点坐标系中的位置(x, y, z)。 * 你可以传一个 cc.Vec2 或者 cc.Vec3 作为参数来接收返回值。 * @method getPosition @@ -2182,10 +2217,10 @@ let NodeDefines = { }, /** - * !#en + * !#en * Sets the scale of axis in local coordinates of the node. * You can operate 2 axis in 2D node, and 3 axis in 3D node. - * !#zh + * !#zh * 设置节点在本地坐标系中坐标轴上的缩放比例。 * 2D 节点可以操作两个坐标轴,而 3D 节点可以操作三个坐标轴。 * @method setScale @@ -2218,10 +2253,10 @@ let NodeDefines = { }, /** - * !#en - * Get rotation of node (in quaternion). + * !#en + * Get rotation of node (in quaternion). * Need pass a cc.Quat as the argument to receive the return values. - * !#zh + * !#zh * 获取该节点的 quaternion 旋转角度,需要传一个 cc.Quat 作为参数来接收返回值。 * @method getRotation * @param {Quat} out @@ -2241,9 +2276,9 @@ let NodeDefines = { * !#en Set rotation of node (in quaternion). * !#zh 设置该节点的 quaternion 旋转角度。 * @method setRotation - * @param {cc.Quat|Number} quat Quaternion object represents the rotation or the x value of quaternion - * @param {Number} y y value of quternion - * @param {Number} z z value of quternion + * @param {cc.Quat|Number} quat Quaternion object represents the rotation or the x value of quaternion + * @param {Number} y y value of quternion + * @param {Number} z z value of quternion * @param {Number} w w value of quternion */ setRotation (quat, y, z, w) { @@ -2273,8 +2308,7 @@ let NodeDefines = { } if (CC_EDITOR) { - _quata.fromRotation(trs); - _quata.toEuler(this._eulerAngles); + this._toEuler(); } } } @@ -2528,8 +2562,7 @@ let NodeDefines = { else { math.quat.copy(_quata, quat); } - _quata.toEuler(this._eulerAngles); - _quata.toRotation(this._trs); + this._toEuler(); this.setLocalDirty(LocalDirtyFlag.ROTATION); }, @@ -3221,9 +3254,7 @@ let NodeDefines = { this._localMatDirty = LocalDirtyFlag.ALL; this._worldMatDirty = true; - let trs = this._trs; - _quata.fromRotation(trs); - _quata.toEuler(this._eulerAngles); + this._toEuler(); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._renderComponent) { diff --git a/cocos2d/core/CCScene.js b/cocos2d/core/CCScene.js index f5c4cbe2dff..1fd709917e2 100644 --- a/cocos2d/core/CCScene.js +++ b/cocos2d/core/CCScene.js @@ -74,7 +74,13 @@ cc.Scene = cc.Class({ }, destroy: function () { - this._super(); + if (cc.Object.prototype.destroy.call(this)) { + var children = this._children; + for (var i = 0; i < children.length; ++i) { + children[i].active = false; + } + } + this._active = false; this._activeInHierarchy = false; }, diff --git a/cocos2d/core/base-ui/CCWidgetManager.js b/cocos2d/core/base-ui/CCWidgetManager.js index 2c2a0a49d57..736e7d9d354 100644 --- a/cocos2d/core/base-ui/CCWidgetManager.js +++ b/cocos2d/core/base-ui/CCWidgetManager.js @@ -432,7 +432,7 @@ function updateAlignment (node) { } var widget = node._widget || node.getComponent(cc.Widget); // node._widget will be null when widget is disabled - if (widget) { + if (widget && parent) { align(node, widget); } } diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 42f8a7f8327..fac8df063b7 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -620,6 +620,8 @@ let Camera = cc.Class({ * @return {Ray} */ getRay (screenPos) { + if (!ray) return screenPos; + vec3.set(_v3_temp_3, screenPos.x, screenPos.y, 1); this._camera.screenToWorld(_v3_temp_2, _v3_temp_3, cc.visibleRect.width, cc.visibleRect.height); diff --git a/cocos2d/core/components/CCAudioSource.js b/cocos2d/core/components/CCAudioSource.js index 371c7aefec3..1337ac27918 100644 --- a/cocos2d/core/components/CCAudioSource.js +++ b/cocos2d/core/components/CCAudioSource.js @@ -208,10 +208,11 @@ var AudioSource = cc.Class({ }, _pausedCallback: function () { - var audio = this.audio; - if (audio.paused) return; - this.audio.pause(); - this._pausedFlag = true; + var state = this.audio.getState(); + if (state === cc.Audio.State.PLAYING) { + this.audio.pause(); + this._pausedFlag = true; + } }, _restoreCallback: function () { diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 96e2cb3961f..8afc509c016 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -207,6 +207,7 @@ let Button = cc.Class({ notify (oldValue) { this._updateTransition(oldValue); }, + formerlySerializedAs: 'transition' }, // color transition @@ -221,8 +222,8 @@ let Button = cc.Class({ displayName: 'Normal', tooltip: CC_DEV && 'i18n:COMPONENT.button.normal_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL && this.target) { - this.target.opacity = this.normalColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.NORMAL) { + this._getTarget().opacity = this.normalColor.a; } this._updateState(); } @@ -238,11 +239,12 @@ let Button = cc.Class({ displayName: 'Pressed', tooltip: CC_DEV && 'i18n:COMPONENT.button.pressed_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED && this.target) { - this.target.opacity = this.pressedColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.PRESSED) { + this._getTarget().opacity = this.pressedColor.a; } this._updateState(); - } + }, + formerlySerializedAs: 'pressedColor' }, /** @@ -255,11 +257,12 @@ let Button = cc.Class({ displayName: 'Hover', tooltip: CC_DEV && 'i18n:COMPONENT.button.hover_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.HOVER && this.target) { - this.target.opacity = this.hoverColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.HOVER) { + this._getTarget().opacity = this.hoverColor.a; } this._updateState(); - } + }, + formerlySerializedAs: 'hoverColor' }, /** @@ -272,8 +275,8 @@ let Button = cc.Class({ displayName: 'Disabled', tooltip: CC_DEV && 'i18n:COMPONENT.button.disabled_color', notify () { - if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED && this.target) { - this.target.opacity = this.disabledColor.a; + if (this.transition === Transition.Color && this._getButtonState() === State.DISABLED) { + this._getTarget().opacity = this.disabledColor.a; } this._updateState(); } @@ -405,9 +408,6 @@ let Button = cc.Class({ }, __preload () { - if (!this.target) { - this.target = this.node; - } this._applyTarget(); this._updateState(); }, @@ -416,10 +416,7 @@ let Button = cc.Class({ this._pressed = false; this._hovered = false; // // Restore button status - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); let transition = this.transition; if (transition === Transition.COLOR && this.interactable) { this._setTargetColor(this.normalColor); @@ -460,11 +457,12 @@ let Button = cc.Class({ } }, + _getTarget () { + return this.target ? this.target : this.node; + }, + _setTargetColor(color) { - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); target.color = color; target.opacity = color.a; }, @@ -546,10 +544,7 @@ let Button = cc.Class({ }, update (dt) { - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); if (this._transitionFinished) return; if (this.transition !== Transition.COLOR && this.transition !== Transition.SCALE) return; @@ -592,10 +587,9 @@ let Button = cc.Class({ }, _applyTarget () { - this._sprite = this._getTargetSprite(this.target); - if (this.target) { - this._originalScale = this.target.scale; - } + let target = this._getTarget(); + this._sprite = this._getTargetSprite(target); + this._originalScale = target.scale; }, // touch event handler @@ -613,8 +607,9 @@ let Button = cc.Class({ // so we have to do hit test when touch moving let touch = event.touch; let hit = this.node._hitTest(touch.getLocation()); + let target = this._getTarget(); - if (this.transition === Transition.SCALE && this.target) { + if (this.transition === Transition.SCALE) { if (hit) { this._fromScale = this._originalScale; this._toScale = this._originalScale * this.zoomScale; @@ -622,7 +617,7 @@ let Button = cc.Class({ } else { this.time = 0; this._transitionFinished = true; - this.target.scale = this._originalScale; + target.scale = this._originalScale; } } else { let state; @@ -706,10 +701,7 @@ let Button = cc.Class({ this._updateColorTransitionImmediately(state); } else { - let target = this.target; - if (!target) { - return; - } + let target = this._getTarget(); let color = this._getStateColor(state); this._fromColor = target.color.clone(); this._toColor = color; @@ -741,10 +733,8 @@ let Button = cc.Class({ }, _zoomBack () { - if (!this.target) { - return; - } - this._fromScale = this.target.scale; + let target = this._getTarget(); + this._fromScale = target.scale; this._toScale = this._originalScale; this.time = 0; this._transitionFinished = false; @@ -773,9 +763,7 @@ let Button = cc.Class({ }, _resizeNodeToTargetNode: CC_EDITOR && function () { - if (this.target) { - this.node.setContentSize(this.target.getContentSize()); - } + this.node.setContentSize(this._getTarget().getContentSize()); }, _updateDisabledState () { diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 74ca329b367..8d26fc1f75f 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -344,7 +344,6 @@ let Label = cc.Class({ } this._N$file = value; - this._bmFontOriginalSize = -1; if (value && this._isSystemFontUsed) this._isSystemFontUsed = false; @@ -352,17 +351,13 @@ let Label = cc.Class({ cc.warnID(4000); } - if (value instanceof cc.BitmapFont) { - this._bmFontOriginalSize = value.fontSize; - } - if (this._renderData) { this.destroyRenderData(this._renderData); this._renderData = null; } this._fontAtlas = null; this._updateAssembler(); - this._activateMaterial(true); + this._applyFontTexture(true); this._lazyUpdateRenderData(); }, type: cc.Font, @@ -413,9 +408,14 @@ let Label = cc.Class({ _bmFontOriginalSize: { displayName: 'BMFont Original Size', - default: -1, - serializable: false, - readonly: true, + get () { + if (this._N$file instanceof cc.BitmapFont) { + return this._N$file.fontSize; + } + else { + return -1; + } + }, visible: true, animatable: false }, @@ -494,6 +494,10 @@ let Label = cc.Class({ this.markForRender(!!this.string); }, + _on3DNodeChanged () { + this._updateAssembler(); + }, + _updateAssembler () { let assembler = Label._assembler.getAssembler(this); @@ -505,6 +509,7 @@ let Label = cc.Class({ if (!this._renderData) { this._renderData = this._assembler.createData(this); this._renderData.material = this._material; + this.markForUpdateRenderData(true); } if (CC_JSB && CC_NATIVERENDERER) { @@ -512,28 +517,32 @@ let Label = cc.Class({ } }, - _activateMaterial (force) { - let material = this._material; - if (material && !force) { - return; - } - + _applyFontTexture (force) { let font = this.font; if (font instanceof cc.BitmapFont) { let spriteFrame = font.spriteFrame; + let self = this; + let onBMFontTextureLoaded = function () { + // TODO: old texture in material have been released by loader + self._texture = spriteFrame._texture; + self._activateMaterial(force); + + if (force) { + this._assembler && this._assembler.updateRenderData(this); + } + }; // cannot be activated if texture not loaded yet - if (!spriteFrame || !spriteFrame.textureLoaded()) { + if (spriteFrame && spriteFrame.textureLoaded()) { + onBMFontTextureLoaded(); + } + else { this.disableRender(); if (spriteFrame) { - spriteFrame.once('load', this._activateMaterial, this); + spriteFrame.once('load', onBMFontTextureLoaded, this); spriteFrame.ensureLoadTexture(); } - return; } - - // TODO: old texture in material have been released by loader - this._texture = spriteFrame._texture; } else { if (!this._ttfTexture) { @@ -546,6 +555,18 @@ let Label = cc.Class({ this._ttfTexture.initWithElement(this._assemblerData.canvas); } this._texture = this._ttfTexture; + this._activateMaterial(force); + + if (force) { + this._assembler && this._assembler.updateRenderData(this); + } + } + }, + + _activateMaterial (force) { + let material = this._material; + if (material && !force) { + return; } // Canvas @@ -597,8 +618,7 @@ let Label = cc.Class({ this.setVertsDirty(); this.markForUpdateRenderData(true); this._updateAssembler(); - this._activateMaterial(true); - this._assembler.updateRenderData(this); + this._applyFontTexture(true); }, _enableBold (enabled) { diff --git a/cocos2d/core/components/CCLabelOutline.js b/cocos2d/core/components/CCLabelOutline.js index c5d69c3cf9b..7e2382a3a81 100644 --- a/cocos2d/core/components/CCLabelOutline.js +++ b/cocos2d/core/components/CCLabelOutline.js @@ -87,10 +87,18 @@ let LabelOutline = cc.Class({ } }, + onEnable () { + this._updateRenderData(); + }, + + onDisable () { + this._updateRenderData(); + }, + _updateRenderData () { let label = this.node.getComponent(cc.Label); if (label) { - label._forceUpdateRenderData(); + label._lazyUpdateRenderData(); } } diff --git a/cocos2d/core/components/CCLayout.js b/cocos2d/core/components/CCLayout.js index 435675eea94..2670dfd2eda 100644 --- a/cocos2d/core/components/CCLayout.js +++ b/cocos2d/core/components/CCLayout.js @@ -395,6 +395,23 @@ var Layout = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.layout.horizontal_direction', animatable: false }, + + /** + * !#en Adjust the layout if the children scaled. + * !#zh 子节点缩放比例是否影响布局。 + * @property affectedByScale + * @type {Boolean} + * @default false + */ + affectedByScale: { + default: false, + notify: function () { + // every time you switch this state, the layout will be calculated. + this._doLayoutDirty(); + }, + animatable: false, + tooltip: CC_DEV && 'i18n:COMPONENT.layout.affected_by_scale' + } }, statics: { @@ -435,6 +452,10 @@ var Layout = cc.Class({ this._layoutDirty = true; }, + _doScaleDirty: function () { + this._layoutDirty = this._layoutDirty || this.affectedByScale; + }, + _addEventListeners: function () { cc.director.on(cc.Director.EVENT_AFTER_UPDATE, this.updateLayout, this); this.node.on(NodeEvent.SIZE_CHANGED, this._resized, this); @@ -459,10 +480,10 @@ var Layout = cc.Class({ var children = this.node.children; for (var i = 0; i < children.length; ++i) { var child = children[i]; + child.on(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, @@ -471,29 +492,29 @@ var Layout = cc.Class({ var children = this.node.children; for (var i = 0; i < children.length; ++i) { var child = children[i]; + child.off(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); } }, _childAdded: function (child) { + child.on(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.on(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.on(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.on(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.on('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); }, _childRemoved: function (child) { + child.off(NodeEvent.SCALE_CHANGED, this._doScaleDirty, this); child.off(NodeEvent.SIZE_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.POSITION_CHANGED, this._doLayoutDirty, this); child.off(NodeEvent.ANCHOR_CHANGED, this._doLayoutDirty, this); - child.off(NodeEvent.SCALE_CHANGED, this._doLayoutDirty, this); child.off('active-in-hierarchy-changed', this._doLayoutDirty, this); this._doLayoutDirty(); @@ -541,8 +562,8 @@ var Layout = cc.Class({ for (var i = 0; i < children.length; ++i) { var child = children[i]; - let childScaleX = Math.abs(child.scaleX); - let childScaleY = Math.abs(child.scaleY); + let childScaleX = this._getUsedScaleValue(child.scaleX); + let childScaleY = this._getUsedScaleValue(child.scaleY); if (!child.activeInHierarchy) { continue; } @@ -639,7 +660,7 @@ var Layout = cc.Class({ var child = children[i]; if (child.activeInHierarchy) { activeChildCount++; - newHeight += child.height * Math.abs(child.scaleY); + newHeight += child.height * this._getUsedScaleValue(child.scaleY); } } @@ -687,8 +708,8 @@ var Layout = cc.Class({ for (var i = 0; i < children.length; ++i) { var child = children[i]; - let childScaleX = Math.abs(child.scaleX); - let childScaleY = Math.abs(child.scaleY); + let childScaleX = this._getUsedScaleValue(child.scaleX); + let childScaleY = this._getUsedScaleValue(child.scaleY); if (!child.activeInHierarchy) { continue; } @@ -829,7 +850,7 @@ var Layout = cc.Class({ } var fnPositionY = function (child, topOffset, row) { - return bottomBoundaryOfLayout + sign * (topOffset + child.anchorY * child.height * Math.abs(child.scaleY) + paddingY + row * this.spacingY); + return bottomBoundaryOfLayout + sign * (topOffset + child.anchorY * child.height * this._getUsedScaleValue(child.scaleY) + paddingY + row * this.spacingY); }.bind(this); @@ -870,7 +891,7 @@ var Layout = cc.Class({ } var fnPositionX = function (child, leftOffset, column) { - return leftBoundaryOfLayout + sign * (leftOffset + child.anchorX * child.width * Math.abs(child.scaleX) + paddingX + column * this.spacingX); + return leftBoundaryOfLayout + sign * (leftOffset + child.anchorX * child.width * this._getUsedScaleValue(child.scaleX) + paddingX + column * this.spacingX); }.bind(this); var newWidth = 0; @@ -918,7 +939,7 @@ var Layout = cc.Class({ var child = children[i]; if (child.activeInHierarchy) { activeChildCount++; - newWidth += child.width * Math.abs(child.scaleX); + newWidth += child.width * this._getUsedScaleValue(child.scaleX); } } newWidth += (activeChildCount - 1) * this.spacingX + this.paddingLeft + this.paddingRight; @@ -963,6 +984,10 @@ var Layout = cc.Class({ } }, + _getUsedScaleValue (value) { + return this.affectedByScale ? Math.abs(value) : 1; + }, + /** * !#en Perform the layout update * !#zh 立即执行更新布局 @@ -982,7 +1007,6 @@ var Layout = cc.Class({ this._layoutDirty = false; } } - }); /** diff --git a/cocos2d/core/components/CCPageView.js b/cocos2d/core/components/CCPageView.js index cfcbb37eb29..b7b7242d683 100644 --- a/cocos2d/core/components/CCPageView.js +++ b/cocos2d/core/components/CCPageView.js @@ -401,12 +401,12 @@ var PageView = cc.Class({ var lastPage = this._pages[this._pages.length - 1]; if (this.sizeMode === SizeMode.Free) { if (this.direction === Direction.Horizontal) { - layout.paddingLeft = (this.node.width - this._pages[0].width) / 2; - layout.paddingRight = (this.node.width - lastPage.width) / 2; + layout.paddingLeft = (this._view.width - this._pages[0].width) / 2; + layout.paddingRight = (this._view.width - lastPage.width) / 2; } else if (this.direction === Direction.Vertical) { - layout.paddingTop = (this.node.height - this._pages[0].height) / 2; - layout.paddingBottom = (this.node.height - lastPage.height) / 2; + layout.paddingTop = (this._view.height - this._pages[0].height) / 2; + layout.paddingBottom = (this._view.height - lastPage.height) / 2; } } } @@ -451,7 +451,7 @@ var PageView = cc.Class({ return; } var locPages = CC_EDITOR ? this.content.children : this._pages; - var selfSize = this.node.getContentSize(); + var selfSize = this._view.getContentSize(); for (var i = 0, len = locPages.length; i < len; i++) { locPages[i].setContentSize(selfSize); } @@ -495,10 +495,10 @@ var PageView = cc.Class({ } else { if (this.direction === Direction.Horizontal) { - return Math.abs(offset.x) >= this.node.width * this.scrollThreshold; + return Math.abs(offset.x) >= this._view.width * this.scrollThreshold; } else if (this.direction === Direction.Vertical) { - return Math.abs(offset.y) >= this.node.height * this.scrollThreshold; + return Math.abs(offset.y) >= this._view.height * this.scrollThreshold; } } }, @@ -531,10 +531,10 @@ var PageView = cc.Class({ } else { if (this.direction === Direction.Horizontal) { - offset.x = idx * this.node.width; + offset.x = idx * this._view.width; } else if (this.direction === Direction.Vertical) { - offset.y = idx * this.node.height; + offset.y = idx * this._view.height; } } return offset; diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index 9a557f6961b..c0dfb7f93ee 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -73,7 +73,7 @@ let pool = new js.Pool(function (node) { return true; }, 20); -pool.get = function (string, fontAsset, fontSize) { +pool.get = function (string, richtext) { let labelNode = this._get(); if (!labelNode) { labelNode = new cc.PrivateNode(RichTextChildName); @@ -91,23 +91,22 @@ pool.get = function (string, fontAsset, fontSize) { if (typeof string !== 'string') { string = '' + string; } - let isAsset = fontAsset instanceof cc.Font; + let isAsset = richtext.fontAsset instanceof cc.Font; if (isAsset) { - labelComponent.font = fontAsset; + labelComponent.font = richtext.fontAsset; } else { - labelComponent.fontFamily = "Arial"; + labelComponent.fontFamily = richtext.fontFamily; } labelComponent.string = string; labelComponent.horizontalAlign = HorizontalAlign.LEFT; labelComponent.verticalAlign = VerticalAlign.TOP; - labelComponent.fontSize = fontSize || 40; + labelComponent.fontSize = richtext.fontSize || 40; labelComponent.overflow = 0; labelComponent.enableWrapText = true; labelComponent.lineHeight = 40; labelComponent._enableBold(false); labelComponent._enableItalics(false); labelComponent._enableUnderline(false); - return labelNode; }; @@ -138,6 +137,7 @@ let RichText = cc.Class({ editor: CC_EDITOR && { menu: 'i18n:MAIN_MENU.component.renderers/RichText', help: 'i18n:COMPONENT.help_url.richtext', + inspector: 'packages://inspector/inspectors/comps/richtext.js', executeInEditMode: true }, @@ -190,6 +190,26 @@ let RichText = cc.Class({ } }, + /** + * !#en Custom System font of RichText + * !#zh 富文本定制系统字体 + * @property {String} fontFamily + */ + _fontFamily: "Arial", + fontFamily: { + tooltip: CC_DEV && 'i18n:COMPONENT.richtext.font_family', + get () { + return this._fontFamily; + }, + set (value) { + if (this._fontFamily === value) return; + this._fontFamily = value; + this._layoutDirty = true; + this._updateRichTextStatus(); + }, + animatable: false + }, + /** * !#en Custom TTF font of RichText * !#zh 富文本定制字体 @@ -204,12 +224,38 @@ let RichText = cc.Class({ this._layoutDirty = true; if (this.font) { + this.useSystemFont = false; this._onTTFLoaded(); } + else { + this.useSystemFont = true; + } this._updateRichTextStatus(); } }, + /** + * !#en Whether use system font name or not. + * !#zh 是否使用系统字体。 + * @property {Boolean} isSystemFontUsed + */ + _isSystemFontUsed: true, + useSystemFont: { + get () { + return this._isSystemFontUsed; + }, + set (value) { + if (!value && !this.font || (this._isSystemFontUsed === value)) { + return; + } + this._isSystemFontUsed = value; + this._layoutDirty = true; + this._updateRichTextStatus(); + }, + animatable: false, + tooltip: CC_DEV && 'i18n:COMPONENT.richtext.system_font', + }, + /** * !#en The maximize width of the RichText * !#zh 富文本的最大宽度 @@ -304,12 +350,21 @@ let RichText = cc.Class({ this._onTTFLoaded(); }, + _onColorChanged (parentColor) { + let children = this.node.children; + children.forEach(function (childNode) { + childNode.color = parentColor; + }); + }, + _addEventListeners () { this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); + this.node.on(cc.Node.EventType.COLOR_CHANGED, this._onColorChanged, this); }, _removeEventListeners () { this.node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); + this.node.off(cc.Node.EventType.COLOR_CHANGED, this._onColorChanged, this); }, _updateLabelSegmentTextAttributes () { @@ -319,7 +374,7 @@ let RichText = cc.Class({ }, _createFontLabel (string) { - return pool.get(string, this.font, this.fontSize); + return pool.get(string, this); }, _onTTFLoaded () { @@ -373,10 +428,11 @@ let RichText = cc.Class({ for (let i = 0; i < this._labelSegments.length; ++i) { let labelSegment = this._labelSegments[i]; let clickHandler = labelSegment._clickHandler; + let clickParam = labelSegment._clickParam; if (clickHandler && this._containsTouchLocation(labelSegment, event.touch.getLocation())) { components.forEach(function (component) { if (component.enabledInHierarchy && component[clickHandler]) { - component[clickHandler](event); + component[clickHandler](event, clickParam); } }); event.stopPropagation(); @@ -626,6 +682,9 @@ let RichText = cc.Class({ if (richTextElement.style.event.click) { spriteNode._clickHandler = richTextElement.style.event.click; } + if (richTextElement.style.event.param) { + spriteNode._clickParam = richTextElement.style.event.param; + } } } else { @@ -795,6 +854,11 @@ let RichText = cc.Class({ } let index = labelNode._styleIndex; + + if (this._isSystemFontUsed) { + labelComponent.fontFamily = this._fontFamily; + } + labelComponent.useSystemFont = this._isSystemFontUsed; labelComponent.lineHeight = this.lineHeight; labelComponent.horizontalAlign = HorizontalAlign.LEFT; labelComponent.verticalAlign = VerticalAlign.CENTER; @@ -842,6 +906,9 @@ let RichText = cc.Class({ if (textStyle.event.click) { labelNode._clickHandler = textStyle.event.click; } + if (textStyle.event.param) { + labelNode._clickParam = textStyle.event.param; + } } }, diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index dc29be937d6..1c97ae2137d 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -457,6 +457,10 @@ var Sprite = cc.Class({ this._activateMaterial(); }, + _on3DNodeChanged () { + this._updateAssembler(); + }, + _updateAssembler: function () { let assembler = Sprite._assembler.getAssembler(this); diff --git a/cocos2d/core/components/CCToggle.js b/cocos2d/core/components/CCToggle.js index 7a34233182d..4a808b84ed5 100644 --- a/cocos2d/core/components/CCToggle.js +++ b/cocos2d/core/components/CCToggle.js @@ -31,7 +31,7 @@ * @class Toggle * @extends Button */ -var Toggle = cc.Class({ +let Toggle = cc.Class({ name: 'cc.Toggle', extends: require('./CCButton'), editor: CC_EDITOR && { @@ -47,12 +47,34 @@ var Toggle = cc.Class({ * !#zh 如果这个设置为 true,则 check mark 组件会处于 enabled 状态,否则处于 disabled 状态。 * @property {Boolean} isChecked */ + _N$isChecked: true, isChecked: { - default: true, - tooltip: CC_DEV && 'i18n:COMPONENT.toggle.isChecked', - notify: function () { + get: function () { + return this._N$isChecked; + }, + set: function (value) { + if (value === this._N$isChecked) { + return; + } + + var group = this.toggleGroup || this._toggleContainer; + if (group && group.enabled && this._N$isChecked) { + if (!group.allowSwitchOff) { + return; + } + + } + + this._N$isChecked = value; this._updateCheckMark(); - } + + if (group && group.enabled) { + group.updateToggles(this); + } + + this._emitToggleEvents(); + }, + tooltip: CC_DEV && 'i18n:COMPONENT.toggle.isChecked', }, /** @@ -120,6 +142,33 @@ var Toggle = cc.Class({ } }, + _hideCheckMark () { + this._N$isChecked = false; + this._updateCheckMark(); + }, + + toggle: function (event) { + this.isChecked = !this.isChecked; + }, + + /** + * !#en Make the toggle button checked. + * !#zh 使 toggle 按钮处于选中状态 + * @method check + */ + check: function () { + this.isChecked = true; + }, + + /** + * !#en Make the toggle button unchecked. + * !#zh 使 toggle 按钮处于未选中状态 + * @method uncheck + */ + uncheck: function () { + this.isChecked = false; + }, + _updateCheckMark: function () { if (this.checkMark) { this.checkMark.node.active = !!this.isChecked; @@ -147,85 +196,22 @@ var Toggle = cc.Class({ this.node.off('click', this.toggle, this); }, - toggle: function (event) { - var group = this.toggleGroup || this._toggleContainer; - - if (group && group.enabled && this.isChecked) { - if (!group.allowSwitchOff) { - return; - } - } - - this.isChecked = !this.isChecked; - - this._updateCheckMark(); - - if (group && group.enabled) { - group.updateToggles(this); - } - - this._emitToggleEvents(); - }, - _emitToggleEvents: function () { - if (CC_EDITOR) { return; } this.node.emit('toggle', this); if (this.checkEvents) { cc.Component.EventHandler.emitEvents(this.checkEvents, this); } - }, - - /** - * !#en Make the toggle button checked. - * !#zh 使 toggle 按钮处于选中状态 - * @method check - */ - check: function () { - var group = this.toggleGroup || this._toggleContainer; - - if (group && group.enabled && this.isChecked) { - if (!group.allowSwitchOff) { - return; - } - } - - this.isChecked = true; - - if (group && group.enabled) { - group.updateToggles(this); - } - - this._emitToggleEvents(); - }, - - /** - * !#en Make the toggle button unchecked. - * !#zh 使 toggle 按钮处于未选中状态 - * @method uncheck - */ - uncheck: function () { - var group = this.toggleGroup || this._toggleContainer; - - if (group && group.enabled && this.isChecked) { - if (!group.allowSwitchOff) { - return; - } - } - - this.isChecked = false; - - this._emitToggleEvents(); } + }); cc.Toggle = module.exports = Toggle; - -var js = require('../platform/js'); +const js = require('../platform/js'); js.get(Toggle.prototype, '_toggleContainer', function () { - var parent = this.node.parent; + let parent = this.node.parent; if (cc.Node.isNode(parent)) { return parent.getComponent(cc.ToggleContainer); } diff --git a/cocos2d/core/components/CCToggleContainer.js b/cocos2d/core/components/CCToggleContainer.js index ad400d0e108..f7fb2560aaf 100644 --- a/cocos2d/core/components/CCToggleContainer.js +++ b/cocos2d/core/components/CCToggleContainer.js @@ -55,21 +55,39 @@ var ToggleContainer = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.toggle_group.allowSwitchOff', default: false }, + + /** + * !#en If Toggle is clicked, it will trigger event's handler + * !#zh Toggle 按钮的点击事件列表。 + * @property {Component.EventHandler[]} checkEvents + */ + checkEvents: { + default: [], + type: cc.Component.EventHandler + }, }, updateToggles: function (toggle) { - this.toggleItems.forEach(function (item) { - if (toggle.isChecked && item !== toggle) { - item.isChecked = false; + if(!this.enabledInHierarchy) return; + + if (toggle.isChecked) { + this.toggleItems.forEach(function (item) { + if (item !== toggle && item.isChecked && item.enabled) { + item._hideCheckMark(); + } + }); + + if (this.checkEvents) { + cc.Component.EventHandler.emitEvents(this.checkEvents, toggle); } - }); + } }, _allowOnlyOneToggleChecked: function () { var isChecked = false; this.toggleItems.forEach(function (item) { if (isChecked) { - item.isChecked = false; + item._hideCheckMark(); } else if (item.isChecked) { isChecked = true; diff --git a/cocos2d/core/components/CCToggleGroup.js b/cocos2d/core/components/CCToggleGroup.js index 81ffa4397d8..2443e20862e 100644 --- a/cocos2d/core/components/CCToggleGroup.js +++ b/cocos2d/core/components/CCToggleGroup.js @@ -74,7 +74,7 @@ var ToggleGroup = cc.Class({ this._toggleItems.forEach(function (item){ if(toggle.isChecked) { if (item !== toggle && item.isChecked && item.enabled) { - item.isChecked = false; + item._hideCheckMark(); } } }); @@ -100,7 +100,7 @@ var ToggleGroup = cc.Class({ var isChecked = false; this._toggleItems.forEach(function (item) { if(isChecked && item.enabled) { - item.isChecked = false; + item._hideCheckMark(); } if (item.isChecked && item.enabled) { diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index 2cc9d985a1d..b0cf5232f23 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -245,6 +245,10 @@ let EditBoxImpl = cc.Class({ this._node = null; this.setDelegate(null); this.removeDom(); + if (this.__orientationChanged) { + window.removeEventListener('orientationchange', this.__orientationChanged); + this.__orientationChanged = null; + } }, _onTouchBegan (touch) { @@ -434,10 +438,12 @@ _p.createInput = function() { // Called before editbox focus to register cc.view status _p._beginEditingOnMobile = function () { let self = this; - this.__orientationChanged = function () { - self._adjustEditBoxPosition(); - }; - window.addEventListener('orientationchange', this.__orientationChanged); + if (!this.__orientationChanged) { + this.__orientationChanged = function () { + self._adjustEditBoxPosition(); + }; + window.addEventListener('orientationchange', this.__orientationChanged); + } if (cc.view.isAutoFullScreenEnabled()) { this.__fullscreen = true; @@ -466,7 +472,10 @@ _p._endEditingOnMobile = function () { this.__rotateScreen = false; } - window.removeEventListener('orientationchange', this.__orientationChanged); + if (this.__orientationChanged) { + window.removeEventListener('orientationchange', this.__orientationChanged); + this.__orientationChanged = null; + } if(this.__fullscreen) { cc.view.enableAutoFullScreen(true); diff --git a/cocos2d/core/index.js b/cocos2d/core/index.js index 2ea06d0e34a..c5b9097f704 100644 --- a/cocos2d/core/index.js +++ b/cocos2d/core/index.js @@ -43,5 +43,6 @@ if (!CC_EDITOR || !Editor.isMainProcess) { require('./mesh'); require('./3d'); +require('./3d/polyfill-3d'); require('./base-ui/CCWidgetManager'); diff --git a/cocos2d/core/load-pipeline/CCLoader.js b/cocos2d/core/load-pipeline/CCLoader.js index af36508414c..85dbf6bcf21 100644 --- a/cocos2d/core/load-pipeline/CCLoader.js +++ b/cocos2d/core/load-pipeline/CCLoader.js @@ -713,13 +713,15 @@ proto.getResCount = function () { }; /** - * !#en Get all resource dependencies of the requested asset in an array, including itself. + * !#en + * Get all resource dependencies of the loaded asset in an array, including itself. * The owner parameter accept the following types: 1. The asset itself; 2. The resource url; 3. The asset's uuid.
* The returned array stores the dependencies with their uuids, after retrieve dependencies, * you can release them, access dependent assets by passing the uuid to {{#crossLink "loader/getRes:method"}}{{/crossLink}}, or other stuffs you want.
* For release all dependencies of an asset, please refer to {{#crossLink "loader/release:method"}}{{/crossLink}} * Here is some examples: - * !#zh 获取一个指定资源的所有依赖资源,包含它自身,并保存在数组中返回。owner 参数接收以下几种类型:1. 资源 asset 对象;2. 资源目录下的 url;3. 资源的 uuid。
+ * !#zh + * 获取某个已经加载好的资源的所有依赖资源,包含它自身,并保存在数组中返回。owner 参数接收以下几种类型:1. 资源 asset 对象;2. 资源目录下的 url;3. 资源的 uuid。
* 返回的数组将仅保存依赖资源的 uuid,获取这些 uuid 后,你可以从 loader 释放这些资源;通过 {{#crossLink "loader/getRes:method"}}{{/crossLink}} 获取某个资源或者进行其他你需要的操作。
* 想要释放一个资源及其依赖资源,可以参考 {{#crossLink "loader/release:method"}}{{/crossLink}}。下面是一些示例代码: * diff --git a/cocos2d/core/node-activator.js b/cocos2d/core/node-activator.js index 47afcaab5b8..77f171cb1c1 100644 --- a/cocos2d/core/node-activator.js +++ b/cocos2d/core/node-activator.js @@ -248,7 +248,7 @@ var NodeActivator = cc.Class({ activateComp: CC_EDITOR ? function (comp, preloadInvoker, onLoadInvoker, onEnableInvoker) { if (!cc.isValid(comp, true)) { - // destroied before activating + // destroyed before activating return; } if (cc.engine._isPlaying || comp.constructor._executeInEditMode) { @@ -288,7 +288,7 @@ var NodeActivator = cc.Class({ } } : function (comp, preloadInvoker, onLoadInvoker, onEnableInvoker) { if (!cc.isValid(comp, true)) { - // destroied before activating + // destroyed before activating return; } if (!(comp._objFlags & IsPreloadStarted)) { diff --git a/cocos2d/core/platform/CCInputManager.js b/cocos2d/core/platform/CCInputManager.js index c01fc498ca0..106d68dae5a 100644 --- a/cocos2d/core/platform/CCInputManager.js +++ b/cocos2d/core/platform/CCInputManager.js @@ -223,7 +223,7 @@ let inputManager = { * @return {Object} */ getHTMLElementPosition (element) { - if (sys.platform === sys.WECHAT_GAME) { + if (CC_WECHATGAME) { return { left: 0, top: 0, @@ -354,7 +354,7 @@ let inputManager = { if (event.pageX != null) //not avalable in <= IE8 return {x: event.pageX, y: event.pageY}; - if (sys.platform === sys.WECHAT_GAME) { + if (CC_WECHATGAME) { pos.left = 0; pos.top = 0; } @@ -417,7 +417,7 @@ let inputManager = { let supportMouse = ('mouse' in sys.capabilities); let supportTouches = ('touches' in sys.capabilities); - if (sys.platform === sys.WECHAT_GAME) { + if (CC_WECHATGAME) { prohibition = false; supportTouches = true; supportMouse = false; @@ -527,7 +527,7 @@ let inputManager = { let _touchEventsMap = { "touchstart": function (touchesToHandle) { selfPointer.handleTouchesBegin(touchesToHandle); - if (sys.platform !== sys.WECHAT_GAME) { + if (!CC_WECHATGAME) { element.focus(); } }, diff --git a/cocos2d/core/platform/CCScreen.js b/cocos2d/core/platform/CCScreen.js index 553c18bdf93..2247e57238e 100644 --- a/cocos2d/core/platform/CCScreen.js +++ b/cocos2d/core/platform/CCScreen.js @@ -116,6 +116,16 @@ cc.screen = /** @lends cc.screen# */{ * @param {Function} onFullScreenChange */ requestFullScreen: function (element, onFullScreenChange) { + if (element.tagName.toLowerCase() === "video") { + if (cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && element.readyState > 0) { + element.webkitEnterFullscreen && element.webkitEnterFullscreen(); + return; + } + else { + element.setAttribute("x5-video-player-fullscreen", "true"); + } + } + if (!this._supportsFullScreen) { return; } @@ -139,7 +149,16 @@ cc.screen = /** @lends cc.screen# */{ * @method exitFullScreen * @return {Boolean} */ - exitFullScreen: function () { + exitFullScreen: function (element) { + if (element.tagName.toLowerCase() === "video") { + if (cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser) { + element.webkitExitFullscreen && element.webkitExitFullscreen(); + return; + } + else { + element.setAttribute("x5-video-player-fullscreen", "false"); + } + } return this._supportsFullScreen ? document[this._fn.exitFullscreen]() : true; }, diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 7aa3c4fd4d3..6f8d03fa426 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -724,7 +724,7 @@ function initSys () { * Indicate the running platform * @property {Number} platform */ - if (typeof FbPlayableAd !== undefined) { + if (typeof FbPlayableAd !== "undefined") { sys.platform = sys.FB_PLAYABLE_ADS; } else { @@ -830,7 +830,7 @@ function initSys () { sys.browserVersion = ""; /* Determine the browser version number */ (function(){ - var versionReg1 = /(mqqbrowser|micromessenger|qq|sogou|qzone|liebao|maxthon|uc|ucbs|360 aphone|360|baiduboxapp|baidu|maxthon|mxbrowser|miui)(mobile)?(browser)?\/?([\d.]+)/i; + var versionReg1 = /(mqqbrowser|micromessenger|qq|sogou|qzone|liebao|maxthon|uc|ucbs|360 aphone|360|baiduboxapp|baidu|maxthon|mxbrowser|miui(?:.hybrid)?)(mobile)?(browser)?\/?([\d.]+)/i; var versionReg2 = /(qqbrowser|chrome|safari|firefox|trident|opera|opr\/|oupeng)(mobile)?(browser)?\/?([\d.]+)/i; var tmp = ua.match(versionReg1); if(!tmp) tmp = ua.match(versionReg2); @@ -898,53 +898,14 @@ function initSys () { var _supportWebp = _tmpCanvas1.toDataURL('image/webp').startsWith('data:image/webp'); var _supportCanvas = !!_tmpCanvas1.getContext("2d"); var _supportWebGL = false; - if (sys.browserType === sys.BROWSER_TYPE_WECHAT_GAME) { + if (CC_TEST) { + _supportWebGL = false; + } + else if (sys.browserType === sys.BROWSER_TYPE_WECHAT_GAME) { _supportWebGL = true; } else if (win.WebGLRenderingContext) { - if (create3DContext(document.createElement("CANVAS"))) { - _supportWebGL = true; - } - if (_supportWebGL && sys.os === sys.OS_ANDROID) { - var browserVer = parseFloat(sys.browserVersion); - switch (sys.browserType) { - case sys.BROWSER_TYPE_MOBILE_QQ: - case sys.BROWSER_TYPE_BAIDU: - case sys.BROWSER_TYPE_BAIDU_APP: - // QQ & Baidu Brwoser 6.2+ (using blink kernel) - if (browserVer >= 6.2) { - _supportWebGL = true; - } - else { - _supportWebGL = false; - } - break; - case sys.BROWSER_TYPE_ANDROID: - // Android 5+ default browser - if (sys.osMainVersion && sys.osMainVersion >= 5) { - _supportWebGL = true; - } - break; - case sys.BROWSER_TYPE_CHROME: - // Chrome on android supports WebGL from v. 30 - if (browserVer >= 30.0) { - _supportWebGL = true; - } else { - _supportWebGL = false; - } - break; - case sys.BROWSER_TYPE_UC: - if (browserVer > 11.0) { - _supportWebGL = true; - } else { - _supportWebGL = false; - } - break; - case sys.BROWSER_TYPE_360: - _supportWebGL = false; - break; - } - } + _supportWebGL = true; } /** @@ -1143,17 +1104,17 @@ function initSys () { }; /** - * !#en - * Return the safe area rect. only available on the iOS device.
- * when the safeArea rect is unavailable, it will return a rect with design resolution size. + * !#en + * Return the safe area rect.
+ * only available on the iOS native platform, otherwise it will return a rect with design resolution size. * !#zh - * 返回手机屏幕安全区域,目前仅在 iOS 设备上有效。其它平台将默认返回设计分辨率尺寸。 + * 返回手机屏幕安全区域,目前仅在 iOS 原生平台有效。其它平台将默认返回设计分辨率尺寸。 * @method getSafeAreaRect * @return {Rect} */ sys.getSafeAreaRect = function () { - let designSize = cc.view.getDesignResolutionSize(); - return cc.rect(0, 0, designSize.width, designSize.height); + let visibleSize = cc.view.getVisibleSize(); + return cc.rect(0, 0, visibleSize.width, visibleSize.height); }; /** diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 429b88be2d8..ac55e2fcbae 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -348,15 +348,6 @@ cc.js.mixin(View.prototype, { cc.game.container.style['-webkit-transform-origin'] = '0px 0px 0px'; cc.game.container.style.transformOrigin = '0px 0px 0px'; this._isRotated = true; - - // Fix for issue: https://github.com/cocos-creator/fireball/issues/8365 - // Reference: https://www.douban.com/note/343402554/ - // For Chrome, z-index not working after container transform rotate 90deg. - // Because 'transform' style adds canvas (the top-element of container) to a new stack context. - // That causes the DOM Input was hidden under canvas. - // This should be done after container rotated, instead of in style-mobile.css. - cc.game.canvas.style['-webkit-transform'] = 'translateZ(0px)'; - cc.game.canvas.style.transform = 'translateZ(0px)'; } if (this._orientationChanging) { setTimeout(function () { @@ -1069,7 +1060,7 @@ cc.ContainerStrategy = cc.Class({ _setupContainer: function (view, w, h) { var locCanvas = cc.game.canvas, locContainer = cc.game.container; - if (cc.sys.platform !== cc.sys.WECHAT_GAME) { + if (!CC_WECHATGAME) { if (cc.sys.os === cc.sys.OS_ANDROID) { document.body.style.width = (view._isRotated ? h : w) + 'px'; document.body.style.height = (view._isRotated ? w : h) + 'px'; diff --git a/cocos2d/core/platform/preprocess-class.js b/cocos2d/core/platform/preprocess-class.js index 16caa3039eb..a8ada68f7f4 100644 --- a/cocos2d/core/platform/preprocess-class.js +++ b/cocos2d/core/platform/preprocess-class.js @@ -159,7 +159,7 @@ function checkUrl (val, className, propName, url) { function parseType (val, type, className, propName) { if (Array.isArray(type)) { - if (CC_EDITOR) { + if (CC_EDITOR && 'default' in val) { var isArray = require('./CCClass').isArray; // require lazily to avoid circular require() calls if (!isArray(val.default)) { cc.warnID(5507, className, propName); diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js index f3c2d51af13..1c806215335 100644 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ b/cocos2d/core/renderer/render-engine.canvas.js @@ -1300,6 +1300,7 @@ var _vertsPool = new Pool(function () { return { x: 0.0, y: 0.0, + z: 0.0, u: 0.0, v: 0.0, color: 0 diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 13a6a24adb2..a9f9c66e3af 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -13795,13 +13795,12 @@ var templates = [ }, { name: 'sprite', - vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', + vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', defines: [ { name: 'useTexture', }, { name: 'useModel', }, { name: 'alphaTest', }, - { name: 'use2DPos', }, { name: 'useColor', } ], }]; @@ -13830,6 +13829,7 @@ var _vertsPool = new Pool(function () { return { x: 0.0, y: 0.0, + z: 0.0, u: 0.0, v: 0.0, color: 0 @@ -14213,7 +14213,6 @@ var SpriteMaterial = (function (Material$$1) { { name: 'useTexture', value: true }, { name: 'useModel', value: false }, { name: 'alphaTest', value: false }, - { name: 'use2DPos', value: true }, { name: 'useColor', value: true } ] ); @@ -14225,7 +14224,7 @@ var SpriteMaterial = (function (Material$$1) { SpriteMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); SpriteMaterial.prototype.constructor = SpriteMaterial; - var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },use2DPos: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; + var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; prototypeAccessors.effect.get = function () { return this._effect; @@ -14247,14 +14246,6 @@ var SpriteMaterial = (function (Material$$1) { this._effect.define('useModel', val); }; - prototypeAccessors.use2DPos.get = function () { - return this._effect.getDefine('use2DPos'); - }; - - prototypeAccessors.use2DPos.set = function (val) { - this._effect.define('use2DPos', val); - }; - prototypeAccessors.useColor.get = function () { return this._effect.getDefine('useColor'); }; @@ -14294,7 +14285,6 @@ var SpriteMaterial = (function (Material$$1) { copy.texture = this.texture; copy.useTexture = this.useTexture; copy.useModel = this.useModel; - copy.use2DPos = this.use2DPos; copy.useColor = this.useColor; copy.updateHash(); return copy; @@ -14431,7 +14421,6 @@ var StencilMaterial = (function (Material$$1) { { name: 'useTexture', value: true }, { name: 'useModel', value: false }, { name: 'alphaTest', value: true }, - { name: 'use2DPos', value: true }, { name: 'useColor', value: true } ] ); diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 10a33c224e0..b7b9a7c63ee 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -53,13 +53,12 @@ var templates = [ }, { name: 'sprite', - vert: '\n \nuniform mat4 viewProj;\n#ifdef use2DPos\nattribute vec2 a_position;\n#else\nattribute vec3 a_position;\n#endif\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', + vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', defines: [ { name: 'useTexture', }, { name: 'useModel', }, { name: 'alphaTest', }, - { name: 'use2DPos', }, { name: 'useColor', } ], }]; @@ -1340,6 +1339,7 @@ var _vertsPool = new Pool(function () { return { x: 0.0, y: 0.0, + z: 0.0, u: 0.0, v: 0.0, color: 0 @@ -1730,7 +1730,6 @@ var SpriteMaterial = (function (Material$$1) { { name: 'useTexture', value: true }, { name: 'useModel', value: false }, { name: 'alphaTest', value: false }, - { name: 'use2DPos', value: true }, { name: 'useColor', value: true } ] ); @@ -1742,7 +1741,7 @@ var SpriteMaterial = (function (Material$$1) { SpriteMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); SpriteMaterial.prototype.constructor = SpriteMaterial; - var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },use2DPos: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; + var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; prototypeAccessors.effect.get = function () { return this._effect; @@ -1764,14 +1763,6 @@ var SpriteMaterial = (function (Material$$1) { this._effect.define('useModel', val); }; - prototypeAccessors.use2DPos.get = function () { - return this._effect.getDefine('use2DPos'); - }; - - prototypeAccessors.use2DPos.set = function (val) { - this._effect.define('use2DPos', val); - }; - prototypeAccessors.useColor.get = function () { return this._effect.getDefine('useColor'); }; @@ -1811,7 +1802,6 @@ var SpriteMaterial = (function (Material$$1) { copy.texture = this.texture; copy.useTexture = this.useTexture; copy.useModel = this.useModel; - copy.use2DPos = this.use2DPos; copy.useColor = this.useColor; copy.updateHash(); return copy; @@ -1948,7 +1938,6 @@ var StencilMaterial = (function (Material$$1) { { name: 'useTexture', value: true }, { name: 'useModel', value: false }, { name: 'alphaTest', value: true }, - { name: 'use2DPos', value: true }, { name: 'useColor', value: true } ] ); diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index ae6a3fbaa0a..f0a745c9b6d 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -90,22 +90,26 @@ _proto._children = function (node) { let batcher = _batcher; let parentOpacity = batcher.parentOpacity; - batcher.parentOpacity *= (node._opacity / 255); + let opacity = (batcher.parentOpacity *= (node._opacity / 255)); let worldTransformFlag = batcher.worldMatDirty ? WORLD_TRANSFORM : 0; let worldOpacityFlag = batcher.parentOpacityDirty ? COLOR : 0; + let worldDirtyFlag = worldTransformFlag | worldOpacityFlag; let children = node._children; for (let i = 0, l = children.length; i < l; i++) { let c = children[i]; - c._renderFlag |= worldTransformFlag | worldOpacityFlag; + // Advance the modification of the flag to avoid node attribute modification is invalid when opacity === 0. + c._renderFlag |= worldDirtyFlag; if (!c._activeInHierarchy || c._opacity === 0) continue; _cullingMask = c._cullingMask = c.groupIndex === 0 ? cullingMask : 1 << c.groupIndex; + // TODO: Maybe has better way to implement cascade opacity - c._color.a = c._opacity * batcher.parentOpacity; + let colorVal = c._color._val; + c._color._fastSetA(c._opacity * opacity); flows[c._renderFlag]._func(c); - c._color.a = 255; + c._color._val = colorVal; } batcher.parentOpacity = parentOpacity; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index be64397b4e0..5ff11d030ab 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -149,6 +149,7 @@ textUtils.ttf = module.exports = { else { cc.loader.load(comp.font.nativeUrl, function (err, fontFamily) { _fontFamily = fontFamily || 'Arial'; + comp.font._nativeAsset = fontFamily; comp._forceUpdateRenderData(); }); } diff --git a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js similarity index 58% rename from cocos2d/core/renderer/webgl/assemblers/label/bmfont.js rename to cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js index 31253f08e04..0da83b6e86f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/bmfont.js @@ -23,8 +23,9 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('../../../../platform/js'); -const bmfontUtls = require('../../../utils/label/bmfont'); +const js = require('../../../../../platform/js'); +const bmfontUtls = require('../../../../utils/label/bmfont'); +const fillVertices = require('../../utils').fillVertices; module.exports = js.addon({ createData (comp) { @@ -32,39 +33,14 @@ module.exports = js.addon({ }, fillBuffers (comp, renderer) { - let node = comp.node, - renderData = comp._renderData, - verts = renderData.vertices, - color = node._color._val; - - let matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; - - let vertexCount = renderData.vertexCount; - buffer.request(vertexCount, renderData.indiceCount); - - // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - uintbuf = buffer._uintVData; - - for (let i = 0; i < vertexCount; i++) { - let vert = verts[i]; - vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; - vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; - vbuf[vertexOffset++] = vert.u; - vbuf[vertexOffset++] = vert.v; - uintbuf[vertexOffset++] = color; - } + let node = comp.node; + fillVertices(node, renderer._quadBuffer, comp._renderData, node._color._val); }, appendQuad (comp, texture, rect, rotated, x, y, scale) { let renderData = comp._renderData; let dataOffset = renderData.dataLength; - + renderData.dataLength += 4; renderData.vertexCount = renderData.dataLength; renderData.indiceCount = renderData.dataLength / 2 * 3; @@ -85,12 +61,12 @@ module.exports = js.addon({ verts[dataOffset].u = l; verts[dataOffset].v = b; - verts[dataOffset+1].u = r; - verts[dataOffset+1].v = b; - verts[dataOffset+2].u = l; - verts[dataOffset+2].v = t; - verts[dataOffset+3].u = r; - verts[dataOffset+3].v = t; + verts[dataOffset + 1].u = r; + verts[dataOffset + 1].v = b; + verts[dataOffset + 2].u = l; + verts[dataOffset + 2].v = t; + verts[dataOffset + 3].u = r; + verts[dataOffset + 3].v = t; } else { l = (rect.x) / texw; r = (rect.x + rectHeight) / texw; @@ -99,21 +75,21 @@ module.exports = js.addon({ verts[dataOffset].u = l; verts[dataOffset].v = t; - verts[dataOffset+1].u = l; - verts[dataOffset+1].v = b; - verts[dataOffset+2].u = r; - verts[dataOffset+2].v = t; - verts[dataOffset+3].u = r; - verts[dataOffset+3].v = b; + verts[dataOffset + 1].u = l; + verts[dataOffset + 1].v = b; + verts[dataOffset + 2].u = r; + verts[dataOffset + 2].v = t; + verts[dataOffset + 3].u = r; + verts[dataOffset + 3].v = b; } verts[dataOffset].x = x; verts[dataOffset].y = y - rectHeight * scale; - verts[dataOffset+1].x = x + rectWidth * scale; - verts[dataOffset+1].y = y - rectHeight * scale; - verts[dataOffset+2].x = x; - verts[dataOffset+2].y = y; - verts[dataOffset+3].x = x + rectWidth * scale; - verts[dataOffset+3].y = y; + verts[dataOffset + 1].x = x + rectWidth * scale; + verts[dataOffset + 1].y = y - rectHeight * scale; + verts[dataOffset + 2].x = x; + verts[dataOffset + 2].y = y; + verts[dataOffset + 3].x = x + rectWidth * scale; + verts[dataOffset + 3].y = y; }, }, bmfontUtls); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js similarity index 71% rename from cocos2d/core/renderer/webgl/assemblers/label/ttf.js rename to cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js index 237ebc7ce3e..952e5040c43 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js @@ -23,8 +23,9 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('../../../../platform/js'); -const ttfUtls = require('../../../utils/label/ttf'); +const js = require('../../../../../platform/js'); +const ttfUtls = require('../../../../utils/label/ttf'); +const fillVertices = require('../../utils').fillVertices; const WHITE = cc.color(255, 255, 255, 255); @@ -49,31 +50,7 @@ module.exports = js.addon({ }, fillBuffers (comp, renderer) { - let verts = comp._renderData.vertices, - node = comp.node, - color = WHITE._val, - matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; - - buffer.request(4, 6); - - // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - uintbuf = buffer._uintVData; - - // vertex - for (let i = 0; i < 4; i++) { - let vert = verts[i]; - vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; - vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; - vbuf[vertexOffset++] = vert.u; - vbuf[vertexOffset++] = vert.v; - uintbuf[vertexOffset++] = color; - } + fillVertices(comp.node, renderer._quadBuffer, comp._renderData, WHITE._val); }, _updateVerts (comp) { diff --git a/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js new file mode 100644 index 00000000000..35264daf92b --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/label/3d/bmfont.js @@ -0,0 +1,35 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/bmfont'); +const fillVertices3D = require('../../utils').fillVertices3D; + +module.exports = js.addon({ + fillBuffers (comp, renderer) { + let node = comp.node; + fillVertices3D(node, renderer._quadBuffer3D, comp._renderData, node._color._val); + }, +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js new file mode 100644 index 00000000000..5d7a2b07614 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js @@ -0,0 +1,36 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/ttf'); +const fillVertices3D = require('../../utils').fillVertices3D; + +const WHITE = cc.color(255, 255, 255, 255); + +module.exports = js.addon({ + fillBuffers (comp, renderer) { + fillVertices3D(comp.node, renderer._quadBuffer3D, comp._renderData, WHITE._val); + } +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/index.js b/cocos2d/core/renderer/webgl/assemblers/label/index.js index 7bac03a3f00..c4c47c55a03 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/index.js @@ -24,15 +24,20 @@ ****************************************************************************/ const Label = require('../../../../components/CCLabel'); -const ttfAssembler = require('./ttf'); -const bmfontAssembler = require('./bmfont'); + +const ttfAssembler = require('./2d/ttf'); +const bmfontAssembler = require('./2d/bmfont'); + +const ttfAssembler3D = require('./3d/ttf'); +const bmfontAssembler3D = require('./3d/bmfont'); var labelAssembler = { getAssembler (comp) { - let assembler = ttfAssembler; + let is3DNode = comp.node.is3DNode; + let assembler = is3DNode ? ttfAssembler3D : ttfAssembler; if (comp.font instanceof cc.BitmapFont) { - assembler = bmfontAssembler; + assembler = is3DNode ? bmfontAssembler3D : bmfontAssembler; } return assembler; diff --git a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js index 5a1be7222f3..9f882febaea 100644 --- a/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/mask-assembler.js @@ -26,7 +26,7 @@ const StencilManager = require('../stencil-manager'); const Mask = require('../../../components/CCMask'); const RenderFlow = require('../../render-flow'); -const spriteAssembler = require('./sprite/simple'); +const spriteAssembler = require('./sprite/2d/simple'); const graphicsAssembler = require('./graphics'); let _stencilMgr = StencilManager.sharedManager; diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index 72f425660ed..b9d4c57f6c8 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -183,7 +183,7 @@ var motionStreakAssembler = { } renderData.vertexCount = renderData.dataLength; - renderData.indiceCount = renderData.vertexCount === 0 ? 0 : (renderData.vertexCount - 2)*3; + renderData.indiceCount = renderData.vertexCount < 2 ? 0 : (renderData.vertexCount - 2)*3; }, fillBuffers (comp, renderer) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js similarity index 82% rename from cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js index d6bac15bf90..bce245d3134 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js @@ -23,16 +23,17 @@ THE SOFTWARE. ****************************************************************************/ -const Sprite = require('../../../../components/CCSprite'); +const Sprite = require('../../../../../components/CCSprite'); const FillType = Sprite.FillType; -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); +const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { useModel: false, updateRenderData (sprite) { let frame = sprite.spriteFrame; - + // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here if (frame) { @@ -67,7 +68,7 @@ module.exports = { fillRange = fillRange < 0.0 ? 0.0 : fillRange; fillRange = fillRange - fillStart; fillRange = fillRange < 0 ? 0 : fillRange; - + let fillEnd = fillStart + fillRange; fillEnd = fillEnd > 1 ? 1 : fillEnd; @@ -116,22 +117,22 @@ module.exports = { switch (sprite._fillType) { case FillType.HORIZONTAL: verts[0].u = quadUV0 + (quadUV2 - quadUV0) * fillStart; - verts[0].v = quadUV1; + verts[0].v = quadUV1 + (quadUV3 - quadUV1) * fillStart; verts[1].u = quadUV0 + (quadUV2 - quadUV0) * fillEnd; - verts[1].v = quadUV3; + verts[1].v = quadUV1 + (quadUV3 - quadUV1) * fillEnd; verts[2].u = quadUV4 + (quadUV6 - quadUV4) * fillStart; - verts[2].v = quadUV5; + verts[2].v = quadUV5 + (quadUV7 - quadUV5) * fillStart; verts[3].u = quadUV4 + (quadUV6 - quadUV4) * fillEnd; - verts[3].v = quadUV7; + verts[3].v = quadUV5 + (quadUV7 - quadUV5) * fillEnd; break; case FillType.VERTICAL: - verts[0].u = quadUV0; + verts[0].u = quadUV0 + (quadUV4 - quadUV0) * fillStart; verts[0].v = quadUV1 + (quadUV5 - quadUV1) * fillStart; - verts[1].u = quadUV2; + verts[1].u = quadUV2 + (quadUV6 - quadUV2) * fillStart; verts[1].v = quadUV3 + (quadUV7 - quadUV3) * fillStart; - verts[2].u = quadUV4; + verts[2].u = quadUV0 + (quadUV4 - quadUV0) * fillEnd; verts[2].v = quadUV1 + (quadUV5 - quadUV1) * fillEnd; - verts[3].u = quadUV6; + verts[3].u = quadUV2 + (quadUV6 - quadUV2) * fillEnd; verts[3].v = quadUV3 + (quadUV7 - quadUV3) * fillEnd; break; default: @@ -148,7 +149,7 @@ module.exports = { appx = node.anchorX * width, appy = node.anchorY * height; let l = -appx, b = -appy, - r = width-appx, t = height-appy; + r = width - appx, t = height - appy; let progressStart, progressEnd; switch (sprite._fillType) { @@ -188,6 +189,11 @@ module.exports = { renderData.dataLength = 8; renderData.vertexCount = 4; renderData.indiceCount = 6; + + let verts = renderData.vertices; + for (let i = 0; i < verts.length; i++) { + verts[i].z = 0; + } return renderData; }, @@ -198,9 +204,9 @@ module.exports = { let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - + for (let i = 0; i < 4; i++) { - let local = verts[i+4]; + let local = verts[i + 4]; let world = verts[i]; world.x = local.x * a + local.y * c + tx; world.y = local.x * b + local.y * d + ty; @@ -212,27 +218,21 @@ module.exports = { this.updateWorldVerts(sprite); } - let verts = sprite._renderData.vertices, - node = sprite.node, - color = node._color._val; - - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; + // buffer + let buffer = renderer._meshBuffer, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; - buffer.request(4, 6); + let node = sprite.node; + fillVerticesWithoutCalc(node, buffer, sprite._renderData, node._color._val); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - uintbuf = buffer._uintVData; - - // vertex - for (let i = 0; i < 4; i++) { - let vert = verts[i]; - vbuf[vertexOffset++] = vert.x; - vbuf[vertexOffset++] = vert.y; - vbuf[vertexOffset++] = vert.u; - vbuf[vertexOffset++] = vert.v; - uintbuf[vertexOffset++] = color; - } + let ibuf = buffer._iData; + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; } }; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js similarity index 84% rename from cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js index d9701bc097f..5a728d5e6da 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js @@ -23,7 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); +const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { useModel: false, @@ -34,7 +35,7 @@ module.exports = { updateRenderData (sprite) { let frame = sprite.spriteFrame; - + // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here if (frame) { @@ -53,7 +54,7 @@ module.exports = { if (renderData.vertexCount !== vertices.x.length) { renderData.vertexCount = vertices.x.length; renderData.indiceCount = vertices.triangles.length; - + // 1 for world vertices, 2 for local vertices renderData.dataLength = renderData.vertexCount * 2; @@ -107,8 +108,8 @@ module.exports = { offsetY = frame._offset.y, trimX = offsetX + (originalWidth - rectWidth) / 2, trimY = offsetY + (originalHeight - rectHeight) / 2; - - let scaleX = contentWidth / (sprite.trim ? rectWidth : originalWidth), + + let scaleX = contentWidth / (sprite.trim ? rectWidth : originalWidth), scaleY = contentHeight / (sprite.trim ? rectHeight : originalHeight); let renderData = sprite._renderData; @@ -116,14 +117,14 @@ module.exports = { if (!sprite.trim) { for (let i = 0, l = x.length; i < l; i++) { - let vertice = verts[i+l]; + let vertice = verts[i + l]; vertice.x = (x[i]) * scaleX - appx; vertice.y = (originalHeight - y[i]) * scaleY - appy; } } else { for (let i = 0, l = x.length; i < l; i++) { - let vertice = verts[i+l]; + let vertice = verts[i + l]; vertice.x = (x[i] - trimX) * scaleX - appx; vertice.y = (originalHeight - y[i] - trimY) * scaleY - appy; } @@ -135,11 +136,11 @@ module.exports = { renderData = sprite._renderData, verts = renderData.vertices; let matrix = node._worldMatrix; + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - for (let i = 0, l = renderData.vertexCount; i < l; i++) { - let local = verts[i+l]; + let local = verts[i + l]; let world = verts[i]; world.x = local.x * a + local.y * c + tx; world.y = local.x * b + local.y * d + ty; @@ -147,43 +148,29 @@ module.exports = { }, fillBuffers (sprite, renderer) { - let node = sprite.node, - color = node._color._val, - renderData = sprite._renderData, - verts = renderData.vertices; - let vertices = sprite.spriteFrame.vertices; if (!vertices) { return; } + // update world verts + if (renderer.worldMatDirty) { + this.updateWorldVerts(sprite); + } + // buffer - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2; - - let indiceOffset = buffer.indiceOffset, + let buffer = renderer._meshBuffer3D, + indiceOffset = buffer.indiceOffset, vertexId = buffer.vertexOffset; - buffer.request(renderData.vertexCount, renderData.indiceCount); + let node = sprite.node; + fillVerticesWithoutCalc(node, buffer, sprite._renderData, node._color._val); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - uintbuf = buffer._uintVData, - ibuf = buffer._iData; - - for (let i = 0, l = renderData.vertexCount; i < l; i++) { - let vertice = verts[i]; - vbuf[vertexOffset++] = vertice.x; - vbuf[vertexOffset++] = vertice.y; - vbuf[vertexOffset++] = vertice.u; - vbuf[vertexOffset++] = vertice.v; - uintbuf[vertexOffset++] = color; - } - + let ibuf = buffer._iData; let triangles = vertices.triangles; - for (let i = 0, l = triangles.length; i < l; i++) { ibuf[indiceOffset++] = vertexId + triangles[i]; } }, -}; \ No newline at end of file +}; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js new file mode 100644 index 00000000000..0c85bcd4ea2 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js @@ -0,0 +1,337 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); +const fillVertices = require('../../utils').fillVertices; + +const PI_2 = Math.PI * 2; + + +let _vertPos = [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)]; +let _vertices = [0, 0, 0, 0]; +let _uvs = [0, 0, 0, 0, 0, 0, 0, 0]; +let _intersectPoint_1 = [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)]; +let _intersectPoint_2 = [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)]; +let _center = cc.v2(0, 0); +let _triangles = []; + +function _calcInsectedPoints (left, right, bottom, top, center, angle, intersectPoints) { + //left bottom, right, top + let sinAngle = Math.sin(angle); + let cosAngle = Math.cos(angle); + let tanAngle, cotAngle; + if (Math.cos(angle) !== 0) { + tanAngle = sinAngle / cosAngle; + //calculate right and left + if ((left - center.x) * cosAngle > 0) { + let yleft = center.y + tanAngle * (left - center.x); + intersectPoints[0].x = left; + intersectPoints[0].y = yleft; + } + if ((right - center.x) * cosAngle > 0) { + let yright = center.y + tanAngle * (right - center.x); + + intersectPoints[2].x = right; + intersectPoints[2].y = yright; + } + + } + + if (Math.sin(angle) !== 0) { + cotAngle = cosAngle / sinAngle; + //calculate top and bottom + if ((top - center.y) * sinAngle > 0) { + let xtop = center.x + cotAngle * (top - center.y); + intersectPoints[3].x = xtop; + intersectPoints[3].y = top; + } + if ((bottom - center.y) * sinAngle > 0) { + let xbottom = center.x + cotAngle * (bottom - center.y); + intersectPoints[1].x = xbottom; + intersectPoints[1].y = bottom; + } + + } +} + +function _calculateVertices (sprite) { + let node = sprite.node, + width = node.width, height = node.height, + appx = node.anchorX * width, appy = node.anchorY * height; + + let l = -appx, b = -appy, + r = width - appx, t = height - appy; + + let vertices = _vertices; + vertices[0] = l; + vertices[1] = b; + vertices[2] = r; + vertices[3] = t; + + let fillCenter = sprite._fillCenter, + cx = _center.x = Math.min(Math.max(0, fillCenter.x), 1) * (r - l) + l, + cy = _center.y = Math.min(Math.max(0, fillCenter.y), 1) * (t - b) + b; + + _vertPos[0].x = _vertPos[3].x = l; + _vertPos[1].x = _vertPos[2].x = r; + _vertPos[0].y = _vertPos[1].y = b; + _vertPos[2].y = _vertPos[3].y = t; + + _triangles.length = 0; + if (cx !== vertices[0]) { + _triangles[0] = [3, 0]; + } + if (cx !== vertices[2]) { + _triangles[2] = [1, 2]; + } + if (cy !== vertices[1]) { + _triangles[1] = [0, 1]; + } + if (cy !== vertices[3]) { + _triangles[3] = [2, 3]; + } +} + +function _calculateUVs (spriteFrame) { + let atlasWidth = spriteFrame._texture.width; + let atlasHeight = spriteFrame._texture.height; + let textureRect = spriteFrame._rect; + + let u0, u1, v0, v1; + let uvs = _uvs; + + if (spriteFrame._rotated) { + u0 = (textureRect.x) / atlasWidth; + u1 = (textureRect.x + textureRect.height) / atlasWidth; + + v0 = (textureRect.y) / atlasHeight; + v1 = (textureRect.y + textureRect.width) / atlasHeight; + + uvs[0] = uvs[2] = u0; + uvs[4] = uvs[6] = u1; + uvs[3] = uvs[7] = v1; + uvs[1] = uvs[5] = v0; + } + else { + u0 = (textureRect.x) / atlasWidth; + u1 = (textureRect.x + textureRect.width) / atlasWidth; + + v0 = (textureRect.y) / atlasHeight; + v1 = (textureRect.y + textureRect.height) / atlasHeight; + + uvs[0] = uvs[4] = u0; + uvs[2] = uvs[6] = u1; + uvs[1] = uvs[3] = v1; + uvs[5] = uvs[7] = v0; + } +} + +function _getVertAngle (start, end) { + let placementX, placementY; + placementX = end.x - start.x; + placementY = end.y - start.y; + + if (placementX === 0 && placementY === 0) { + return undefined; + } else if (placementX === 0) { + if (placementY > 0) { + return Math.PI * 0.5; + } else { + return Math.PI * 1.5; + } + } else { + let angle = Math.atan(placementY / placementX); + if (placementX < 0) { + angle += Math.PI; + } + + return angle; + } +} + +function _generateTriangle (verts, offset, vert0, vert1, vert2) { + let vertices = _vertices; + let v0x = vertices[0]; + let v0y = vertices[1]; + let v1x = vertices[2]; + let v1y = vertices[3]; + + verts[offset].x = vert0.x; + verts[offset].y = vert0.y; + verts[offset + 1].x = vert1.x; + verts[offset + 1].y = vert1.y; + verts[offset + 2].x = vert2.x; + verts[offset + 2].y = vert2.y; + + let progressX, progressY; + progressX = (vert0.x - v0x) / (v1x - v0x); + progressY = (vert0.y - v0y) / (v1y - v0y); + _generateUV(progressX, progressY, verts, offset); + + progressX = (vert1.x - v0x) / (v1x - v0x); + progressY = (vert1.y - v0y) / (v1y - v0y); + _generateUV(progressX, progressY, verts, offset + 1); + + progressX = (vert2.x - v0x) / (v1x - v0x); + progressY = (vert2.y - v0y) / (v1y - v0y); + _generateUV(progressX, progressY, verts, offset + 2); +} + +function _generateUV (progressX, progressY, verts, offset) { + let uvs = _uvs; + let px1 = uvs[0] + (uvs[2] - uvs[0]) * progressX; + let px2 = uvs[4] + (uvs[6] - uvs[4]) * progressX; + let py1 = uvs[1] + (uvs[3] - uvs[1]) * progressX; + let py2 = uvs[5] + (uvs[7] - uvs[5]) * progressX; + let uv = verts[offset]; + uv.u = px1 + (px2 - px1) * progressY; + uv.v = py1 + (py2 - py1) * progressY; +} + +module.exports = { + useModel: false, + + createData (sprite) { + return sprite.requestRenderData(); + }, + + updateRenderData (sprite) { + let frame = sprite.spriteFrame; + + // TODO: Material API design and export from editor could affect the material activation process + // need to update the logic here + if (frame) { + if (!frame._original && dynamicAtlasManager) { + dynamicAtlasManager.insertSpriteFrame(frame); + } + if (sprite._material._texture !== frame._texture) { + sprite._activateMaterial(); + } + } + + let renderData = sprite._renderData; + if (renderData && frame && sprite._vertsDirty) { + let verts = renderData.vertices; + + let fillStart = sprite._fillStart; + let fillRange = sprite._fillRange; + if (fillRange < 0) { + fillStart += fillRange; + fillRange = -fillRange; + } + + //do round fill start [0,1), include 0, exclude 1 + while (fillStart >= 1.0) fillStart -= 1.0; + while (fillStart < 0.0) fillStart += 1.0; + + fillStart *= PI_2; + fillRange *= PI_2; + let fillEnd = fillStart + fillRange; + + //build vertices + _calculateVertices(sprite); + //build uvs + _calculateUVs(frame); + + _calcInsectedPoints(_vertices[0], _vertices[2], _vertices[1], _vertices[3], _center, fillStart, _intersectPoint_1); + _calcInsectedPoints(_vertices[0], _vertices[2], _vertices[1], _vertices[3], _center, fillStart + fillRange, _intersectPoint_2); + + let offset = 0; + for (let triangleIndex = 0; triangleIndex < 4; ++triangleIndex) { + let triangle = _triangles[triangleIndex]; + if (!triangle) { + continue; + } + //all in + if (fillRange >= PI_2) { + renderData.dataLength = offset + 3; + _generateTriangle(verts, offset, _center, _vertPos[triangle[0]], _vertPos[triangle[1]]); + offset += 3; + continue; + } + //test against + let startAngle = _getVertAngle(_center, _vertPos[triangle[0]]); + let endAngle = _getVertAngle(_center, _vertPos[triangle[1]]); + if (endAngle < startAngle) endAngle += PI_2; + startAngle -= PI_2; + endAngle -= PI_2; + //testing + for (let testIndex = 0; testIndex < 3; ++testIndex) { + if (startAngle >= fillEnd) { + //all out + } else if (startAngle >= fillStart) { + renderData.dataLength = offset + 3; + if (endAngle >= fillEnd) { + //startAngle to fillEnd + _generateTriangle(verts, offset, _center, _vertPos[triangle[0]], _intersectPoint_2[triangleIndex]); + } else { + //startAngle to endAngle + _generateTriangle(verts, offset, _center, _vertPos[triangle[0]], _vertPos[triangle[1]]); + } + offset += 3; + } else { + //startAngle < fillStart + if (endAngle <= fillStart) { + //all out + } else if (endAngle <= fillEnd) { + renderData.dataLength = offset + 3; + //fillStart to endAngle + _generateTriangle(verts, offset, _center, _intersectPoint_1[triangleIndex], _vertPos[triangle[1]]); + offset += 3; + } else { + renderData.dataLength = offset + 3; + //fillStart to fillEnd + _generateTriangle(verts, offset, _center, _intersectPoint_1[triangleIndex], _intersectPoint_2[triangleIndex]); + offset += 3; + } + } + //add 2 * PI + startAngle += PI_2; + endAngle += PI_2; + } + } + + renderData.indiceCount = renderData.vertexCount = offset; + sprite._vertsDirty = false; + } + }, + + fillBuffers (comp, renderer) { + let node = comp.node, + color = node._color._val, + buffer = renderer._meshBuffer, + renderData = comp._renderData; + + let indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + fillVertices(node, buffer, renderData, color); + + // buffer data may be realloc, need get reference after request. + let ibuf = buffer._iData; + for (let i = 0; i < renderData.dataLength; i++) { + ibuf[indiceOffset + i] = vertexId + i; + } + }, +}; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js similarity index 79% rename from cocos2d/core/renderer/webgl/assemblers/sprite/simple.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js index 7571d30cfc1..f48c263e5ad 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js @@ -23,14 +23,14 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { useModel: false, - + updateRenderData (sprite) { let frame = sprite._spriteFrame; - + // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here if (frame) { @@ -53,17 +53,15 @@ module.exports = { let verts = sprite._renderData.vertices, node = sprite.node, color = node._color._val, - matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - + matrix = node._worldMatrix; + let buffer = renderer._meshBuffer, vertexOffset = buffer.byteOffset >> 2, indiceOffset = buffer.indiceOffset, vertexId = buffer.vertexOffset; buffer.request(4, 6); - + // buffer data may be realloc, need get reference after request. let vbuf = buffer._vData, uintbuf = buffer._uintVData, @@ -71,19 +69,21 @@ module.exports = { // get uv from sprite frame directly let uv = sprite._spriteFrame.uv; - vbuf[vertexOffset+2] = uv[0]; - vbuf[vertexOffset+3] = uv[1]; - vbuf[vertexOffset+7] = uv[2]; - vbuf[vertexOffset+8] = uv[3]; - vbuf[vertexOffset+12] = uv[4]; - vbuf[vertexOffset+13] = uv[5]; - vbuf[vertexOffset+17] = uv[6]; - vbuf[vertexOffset+18] = uv[7]; + vbuf[vertexOffset + 2] = uv[0]; + vbuf[vertexOffset + 3] = uv[1]; + vbuf[vertexOffset + 7] = uv[2]; + vbuf[vertexOffset + 8] = uv[3]; + vbuf[vertexOffset + 12] = uv[4]; + vbuf[vertexOffset + 13] = uv[5]; + vbuf[vertexOffset + 17] = uv[6]; + vbuf[vertexOffset + 18] = uv[7]; let data0 = verts[0], data3 = verts[3], vl = data0.x, vr = data3.x, vb = data0.y, vt = data3.y; + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + tx = matrix.m12, ty = matrix.m13; let al = a * vl, ar = a * vr, bl = b * vl, br = b * vr, cb = c * vb, ct = c * vt, @@ -91,28 +91,30 @@ module.exports = { // left bottom vbuf[vertexOffset] = al + cb + tx; - vbuf[vertexOffset+1] = bl + db + ty; + vbuf[vertexOffset + 1] = bl + db + ty; // right bottom - vbuf[vertexOffset+5] = ar + cb + tx; - vbuf[vertexOffset+6] = br + db + ty; + vbuf[vertexOffset + 5] = ar + cb + tx; + vbuf[vertexOffset + 6] = br + db + ty; // left top - vbuf[vertexOffset+10] = al + ct + tx; - vbuf[vertexOffset+11] = bl + dt + ty; + vbuf[vertexOffset + 10] = al + ct + tx; + vbuf[vertexOffset + 11] = bl + dt + ty; // right top - vbuf[vertexOffset+15] = ar + ct + tx; - vbuf[vertexOffset+16] = br + dt + ty; + vbuf[vertexOffset + 15] = ar + ct + tx; + vbuf[vertexOffset + 16] = br + dt + ty; + // color - uintbuf[vertexOffset+4] = color; - uintbuf[vertexOffset+9] = color; - uintbuf[vertexOffset+14] = color; - uintbuf[vertexOffset+19] = color; + uintbuf[vertexOffset + 4] = color; + uintbuf[vertexOffset + 9] = color; + uintbuf[vertexOffset + 14] = color; + uintbuf[vertexOffset + 19] = color; + // fill indice data ibuf[indiceOffset++] = vertexId; - ibuf[indiceOffset++] = vertexId+1; - ibuf[indiceOffset++] = vertexId+2; - ibuf[indiceOffset++] = vertexId+1; - ibuf[indiceOffset++] = vertexId+3; - ibuf[indiceOffset++] = vertexId+2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; }, createData (sprite) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js similarity index 94% rename from cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js index dc3b05d8466..fa4f28a10d9 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { useModel: false, @@ -41,7 +41,7 @@ module.exports = { updateRenderData (sprite, batchData) { let frame = sprite.spriteFrame; - + // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here if (frame) { @@ -60,20 +60,20 @@ module.exports = { sprite._vertsDirty = false; } }, - + updateVerts (sprite) { let renderData = sprite._renderData, verts = renderData.vertices, node = sprite.node, width = node.width, height = node.height, appx = node.anchorX * width, appy = node.anchorY * height; - + let frame = sprite.spriteFrame; let leftWidth = frame.insetLeft; let rightWidth = frame.insetRight; let topHeight = frame.insetTop; let bottomHeight = frame.insetBottom; - + let sizableWidth = width - leftWidth - rightWidth; let sizableHeight = height - topHeight - bottomHeight; let xScale = width / (leftWidth + rightWidth); @@ -110,7 +110,7 @@ module.exports = { vertexId = buffer.vertexOffset; let uvSliced = sprite.spriteFrame.uvSliced; - + buffer.request(vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. @@ -131,7 +131,7 @@ module.exports = { for (let r = 0; r < 3; ++r) { for (let c = 0; c < 3; ++c) { - let start = vertexId + r*4 + c; + let start = vertexId + r * 4 + c; ibuf[indiceOffset++] = start; ibuf[indiceOffset++] = start + 1; ibuf[indiceOffset++] = start + 4; @@ -149,14 +149,13 @@ module.exports = { let matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - for (let row = 0; row < 4; ++row) { let rowD = verts[row]; for (let col = 0; col < 4; ++col) { let colD = verts[col]; - let world = verts[4 + row*4 + col]; - world.x = colD.x*a + rowD.y*c + tx; - world.y = colD.x*b + rowD.y*d + ty; + let world = verts[4 + row * 4 + col]; + world.x = colD.x * a + rowD.y * c + tx; + world.y = colD.x * b + rowD.y * d + ty; } } }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js similarity index 71% rename from cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js rename to cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js index bfed943e2cd..94786ea521a 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js @@ -23,10 +23,14 @@ THE SOFTWARE. ****************************************************************************/ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { useModel: false, + + vertexOffset: 5, + uvOffset: 2, + colorOffset: 4, createData (sprite) { return sprite.requestRenderData(); @@ -80,17 +84,48 @@ module.exports = { sprite._vertsDirty = false; }, + fillVertices (vbuf, vertexOffset, matrix, row, col, verts) { + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + tx = matrix.m12, ty = matrix.m13; + + let x, x1, y, y1; + for (let yindex = 0, ylength = row; yindex < ylength; ++yindex) { + y = verts[yindex].y; + y1 = verts[yindex+1].y; + for (let xindex = 0, xlength = col; xindex < xlength; ++xindex) { + x = verts[xindex].x; + x1 = verts[xindex+1].x; + + // Vertex + // lb + vbuf[vertexOffset] = x * a + y * c + tx; + vbuf[vertexOffset+1] = x * b + y * d + ty; + // rb + vbuf[vertexOffset+5] = x1 * a + y * c + tx; + vbuf[vertexOffset+6] = x1 * b + y * d + ty; + // lt + vbuf[vertexOffset+10] = x * a + y1 * c + tx; + vbuf[vertexOffset+11] = x * b + y1 * d + ty; + // rt + vbuf[vertexOffset+15] = x1 * a + y1 * c + tx; + vbuf[vertexOffset+16] = x1 * b + y1 * d + ty; + + vertexOffset += 20; + } + } + }, + fillBuffers (sprite, renderer) { let node = sprite.node, + is3DNode = node.is3DNode, color = node._color._val, renderData = sprite._renderData, verts = renderData.vertices; // buffer - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2; - - let indiceOffset = buffer.indiceOffset, + let buffer = is3DNode ? renderer._meshBuffer3D : renderer._meshBuffer, + vertexOffset = buffer.byteOffset >> 2, + indiceOffset = buffer.indiceOffset, vertexId = buffer.vertexOffset; buffer.request(renderData.vertexCount, renderData.indiceCount); @@ -111,68 +146,54 @@ module.exports = { col = Math.ceil(hRepeat); let matrix = node._worldMatrix; - let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; + + this.fillVertices(vbuf, vertexOffset, matrix, row, col, verts); - let x, x1, y, y1, coefu, coefv; + let offset = this.vertexOffset, uvOffset = this.uvOffset, colorOffset = this.colorOffset; + let offset1 = offset, offset2 = offset*2, offset3 = offset*3, offset4 = offset*4; + let coefu, coefv; for (let yindex = 0, ylength = row; yindex < ylength; ++yindex) { - y = verts[yindex].y; - y1 = verts[yindex+1].y; coefv = Math.min(1, vRepeat - yindex); for (let xindex = 0, xlength = col; xindex < xlength; ++xindex) { coefu = Math.min(1, hRepeat - xindex); - x = verts[xindex].x; - x1 = verts[xindex+1].x; - - // Vertex - // lb - vbuf[vertexOffset] = x * a + y * c + tx; - vbuf[vertexOffset+1] = x * b + y * d + ty; - // rb - vbuf[vertexOffset+5] = x1 * a + y * c + tx; - vbuf[vertexOffset+6] = x1 * b + y * d + ty; - // lt - vbuf[vertexOffset+10] = x * a + y1 * c + tx; - vbuf[vertexOffset+11] = x * b + y1 * d + ty; - // rt - vbuf[vertexOffset+15] = x1 * a + y1 * c + tx; - vbuf[vertexOffset+16] = x1 * b + y1 * d + ty; + let vertexOffsetU = vertexOffset + uvOffset; + let vertexOffsetV = vertexOffsetU + 1; // UV if (rotated) { // lb - vbuf[vertexOffset+2] = uv[0]; - vbuf[vertexOffset+3] = uv[1]; + vbuf[vertexOffsetU] = uv[0]; + vbuf[vertexOffsetV] = uv[1]; // rb - vbuf[vertexOffset+7] = uv[0]; - vbuf[vertexOffset+8] = uv[1] + (uv[7] - uv[1]) * coefu; + vbuf[vertexOffsetU+offset1] = uv[0]; + vbuf[vertexOffsetV+offset1] = uv[1] + (uv[7] - uv[1]) * coefu; // lt - vbuf[vertexOffset+12] = uv[0] + (uv[6] - uv[0]) * coefv; - vbuf[vertexOffset+13] = uv[1]; + vbuf[vertexOffsetU+offset2] = uv[0] + (uv[6] - uv[0]) * coefv; + vbuf[vertexOffsetV+offset2] = uv[1]; // rt - vbuf[vertexOffset+17] = vbuf[vertexOffset+12]; - vbuf[vertexOffset+18] = vbuf[vertexOffset+8]; + vbuf[vertexOffsetU+offset3] = vbuf[vertexOffsetU+offset2]; + vbuf[vertexOffsetV+offset3] = vbuf[vertexOffsetV+offset1]; } else { // lb - vbuf[vertexOffset+2] = uv[0]; - vbuf[vertexOffset+3] = uv[1]; + vbuf[vertexOffsetU] = uv[0]; + vbuf[vertexOffsetV] = uv[1]; // rb - vbuf[vertexOffset+7] = uv[0] + (uv[6] - uv[0]) * coefu; - vbuf[vertexOffset+8] = uv[1]; + vbuf[vertexOffsetU+offset1] = uv[0] + (uv[6] - uv[0]) * coefu; + vbuf[vertexOffsetV+offset1] = uv[1]; // lt - vbuf[vertexOffset+12] = uv[0]; - vbuf[vertexOffset+13] = uv[1] + (uv[7] - uv[1]) * coefv; + vbuf[vertexOffsetU+offset2] = uv[0]; + vbuf[vertexOffsetV+offset2] = uv[1] + (uv[7] - uv[1]) * coefv; // rt - vbuf[vertexOffset+17] = vbuf[vertexOffset+7]; - vbuf[vertexOffset+18] = vbuf[vertexOffset+13]; + vbuf[vertexOffsetU+offset3] = vbuf[vertexOffsetU+offset1]; + vbuf[vertexOffsetV+offset3] = vbuf[vertexOffsetV+offset2]; } // color - uintbuf[vertexOffset+4] = color; - uintbuf[vertexOffset+9] = color; - uintbuf[vertexOffset+14] = color; - uintbuf[vertexOffset+19] = color; - vertexOffset += 20; + uintbuf[vertexOffset+colorOffset] = color; + uintbuf[vertexOffset+colorOffset+offset1] = color; + uintbuf[vertexOffset+colorOffset+offset2] = color; + uintbuf[vertexOffset+colorOffset+offset3] = color; + vertexOffset += offset4; } } @@ -188,4 +209,4 @@ module.exports = { vertexId += 4; } }, -}; \ No newline at end of file +}; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/bar-filled.js new file mode 100644 index 00000000000..62c42d3d8fa --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/bar-filled.js @@ -0,0 +1,67 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/bar-filled'); +const fillVerticesWithoutCalc3D = require('../../utils').fillVerticesWithoutCalc3D; + +const vec3 = cc.vmath.vec3; + +module.exports = js.addon({ + updateWorldVerts (sprite) { + let node = sprite.node, + verts = sprite._renderData.vertices; + + let matrix = node._worldMatrix; + for (let i = 0; i < 4; i++) { + let local = verts[i + 4]; + let world = verts[i]; + vec3.transformMat4(world, local, matrix); + } + }, + + fillBuffers (sprite, renderer) { + if (renderer.worldMatDirty) { + this.updateWorldVerts(sprite); + } + + // buffer + let buffer = renderer._meshBuffer3D, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + let node = sprite.node; + fillVerticesWithoutCalc3D(node, buffer, sprite._renderData, node._color._val); + + // buffer data may be realloc, need get reference after request. + let ibuf = buffer._iData; + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; + } +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/mesh.js new file mode 100644 index 00000000000..9195c969979 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/mesh.js @@ -0,0 +1,74 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/mesh'); +const fillVerticesWithoutCalc3D = require('../../utils').fillVerticesWithoutCalc3D; + +const vec3 = cc.vmath.vec3; +let vec3_temp = vec3.create(); + +module.exports = js.addon({ + updateWorldVerts (sprite) { + let node = sprite.node, + renderData = sprite._renderData, + verts = renderData.vertices; + + let matrix = node._worldMatrix; + for (let i = 0, l = renderData.vertexCount; i < l; i++) { + let local = verts[i + l]; + let world = verts[i]; + vec3.set(vec3_temp, local.x, local.y, 0); + vec3.transformMat4(world, vec3_temp, matrix); + } + }, + + fillBuffers (sprite, renderer) { + let vertices = sprite.spriteFrame.vertices; + if (!vertices) { + return; + } + + // update world verts + if (renderer.worldMatDirty) { + this.updateWorldVerts(sprite); + } + + // buffer + let buffer = renderer._meshBuffer3D, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + let node = sprite.node; + fillVerticesWithoutCalc3D(node, buffer, sprite._renderData, node._color._val); + + // buffer data may be realloc, need get reference after request. + let ibuf = buffer._iData; + let triangles = vertices.triangles; + for (let i = 0, l = triangles.length; i < l; i++) { + ibuf[indiceOffset++] = vertexId + triangles[i]; + } + }, +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/radial-filled.js new file mode 100644 index 00000000000..666b2bc2735 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/radial-filled.js @@ -0,0 +1,47 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/radial-filled'); +const fillVertices3D = require('../../utils').fillVertices3D; + +module.exports = js.addon({ + fillBuffers (comp, renderer) { + let node = comp.node, + color = node._color._val, + buffer = renderer._meshBuffer3D, + renderData = comp._renderData; + + let indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + fillVertices3D(node, buffer, renderData, color); + + // buffer data may be realloc, need get reference after request. + let ibuf = buffer._iData; + for (let i = 0; i < renderData.dataLength; i++) { + ibuf[indiceOffset + i] = vertexId + i; + } + }, +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/simple.js new file mode 100644 index 00000000000..44344ff7f89 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/simple.js @@ -0,0 +1,89 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/simple'); +const vec3 = cc.vmath.vec3; + +module.exports = js.addon({ + fillBuffers: (function() { + let vec3_temps = []; + for (let i = 0; i < 4; i++) { + vec3_temps.push(vec3.create()); + } + return function (sprite, renderer) { + let verts = sprite._renderData.vertices, + node = sprite.node, + color = node._color._val, + matrix = node._worldMatrix; + + let buffer = renderer._meshBuffer3D, + vertexOffset = buffer.byteOffset >> 2, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + buffer.request(4, 6); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData, + ibuf = buffer._iData; + + let data0 = verts[0], data3 = verts[3]; + vec3.set(vec3_temps[0], data0.x, data0.y, 0); + vec3.set(vec3_temps[1], data3.x, data0.y, 0); + vec3.set(vec3_temps[2], data0.x, data3.y, 0); + vec3.set(vec3_temps[3], data3.x, data3.y, 0); + + // get uv from sprite frame directly + let uv = sprite._spriteFrame.uv; + for (let i = 0; i < 4; i++) { + // vertex + let vertex = vec3_temps[i]; + vec3.transformMat4(vertex, vertex, matrix); + + vbuf[vertexOffset++] = vertex.x; + vbuf[vertexOffset++] = vertex.y; + vbuf[vertexOffset++] = vertex.z; + + // uv + let uvOffset = i * 2; + vbuf[vertexOffset++] = uv[0 + uvOffset]; + vbuf[vertexOffset++] = uv[1 + uvOffset]; + + // color + uintbuf[vertexOffset++] = color; + } + + // fill indice data + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; + }; + })(), +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/sliced.js new file mode 100644 index 00000000000..1fc88bb97d1 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/sliced.js @@ -0,0 +1,100 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/sliced'); + +const vec3 = cc.vmath.vec3; +const vec3_temp = vec3.create(); + +module.exports = js.addon({ + fillBuffers (sprite, renderer) { + if (renderer.worldMatDirty) { + this.updateWorldVerts(sprite); + } + + let renderData = sprite._renderData, + node = sprite.node, + is3DNode = node.is3DNode, + color = node._color._val, + verts = renderData.vertices; + + let buffer = is3DNode ? renderer._meshBuffer3D : renderer._meshBuffer, + vertexOffset = buffer.byteOffset >> 2, + vertexCount = renderData.vertexCount, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; + + let uvSliced = sprite.spriteFrame.uvSliced; + + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData, + ibuf = buffer._iData; + + for (let i = 4; i < 20; ++i) { + let vert = verts[i]; + let uvs = uvSliced[i - 4]; + + vbuf[vertexOffset++] = vert.x; + vbuf[vertexOffset++] = vert.y; + vbuf[vertexOffset++] = vert.z; + vbuf[vertexOffset++] = uvs.u; + vbuf[vertexOffset++] = uvs.v; + uintbuf[vertexOffset++] = color; + } + + for (let r = 0; r < 3; ++r) { + for (let c = 0; c < 3; ++c) { + let start = vertexId + r * 4 + c; + ibuf[indiceOffset++] = start; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 4; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 5; + ibuf[indiceOffset++] = start + 4; + } + } + }, + + updateWorldVerts (sprite) { + let node = sprite.node, + verts = sprite._renderData.vertices; + + let matrix = node._worldMatrix; + for (let row = 0; row < 4; ++row) { + let rowD = verts[row]; + for (let col = 0; col < 4; ++col) { + let colD = verts[col]; + let world = verts[4 + row * 4 + col]; + + vec3.set(vec3_temp, colD.x, rowD.y, 0); + vec3.transformMat4(world, vec3_temp, matrix); + } + } + }, +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/3d/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/tiled.js new file mode 100644 index 00000000000..6d3859b2969 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/3d/tiled.js @@ -0,0 +1,68 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/tiled'); +const vec3 = cc.vmath.vec3; + +module.exports = js.addon({ + vertexOffset: 6, + uvOffset: 3, + colorOffset: 5, + + fillVertices: (function () { + let vec3_temps = []; + for (let i = 0; i < 4; i++) { + vec3_temps.push(vec3.create()); + } + return function (vbuf, vertexOffset, matrix, row, col, verts) { + let x, x1, y, y1; + for (let yindex = 0, ylength = row; yindex < ylength; ++yindex) { + y = verts[yindex].y; + y1 = verts[yindex+1].y; + for (let xindex = 0, xlength = col; xindex < xlength; ++xindex) { + x = verts[xindex].x; + x1 = verts[xindex+1].x; + + vec3.set(vec3_temps[0], x, y, 0); + vec3.set(vec3_temps[1], x1, y, 0); + vec3.set(vec3_temps[2], x, y1, 0); + vec3.set(vec3_temps[3], x1, y1, 0); + + for (let i = 0; i < 4; i ++) { + let vec3_temp = vec3_temps[i]; + vec3.transformMat4(vec3_temp, vec3_temp, matrix); + let offset = i * 6; + vbuf[vertexOffset + offset] = vec3_temp.x; + vbuf[vertexOffset + offset + 1] = vec3_temp.y; + vbuf[vertexOffset + offset + 2] = vec3_temp.z; + } + + vertexOffset += 24; + } + } + }; + })(), +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/index.js b/cocos2d/core/renderer/webgl/assemblers/sprite/index.js index ea4ddb592d3..367c6cf7452 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/index.js @@ -28,36 +28,44 @@ const Sprite = require('../../../../components/CCSprite'); const SpriteType = Sprite.Type; const FillType = Sprite.FillType; -const simpleRenderUtil = require('./simple'); -const slicedRenderUtil = require('./sliced'); -const tiledRenderUtil = require('./tiled'); -const radialFilledRenderUtil = require('./radial-filled'); -const barFilledRenderUtil = require('./bar-filled'); -const meshRenderUtil = require('./mesh'); +const simpleRenderUtil = require('./2d/simple'); +const slicedRenderUtil = require('./2d/sliced'); +const tiledRenderUtil = require('./2d/tiled'); +const radialFilledRenderUtil = require('./2d/radial-filled'); +const barFilledRenderUtil = require('./2d/bar-filled'); +const meshRenderUtil = require('./2d/mesh'); + +const simpleRenderUtil3D = require('./3d/simple'); +const slicedRenderUtil3D = require('./3d/sliced'); +const tiledRenderUtil3D = require('./3d/tiled'); +const radialFilledRenderUtil3D = require('./3d/radial-filled'); +const barFilledRenderUtil3D = require('./3d/bar-filled'); +const meshRenderUtil3D = require('./3d/mesh'); // Inline all type switch to avoid jit deoptimization during inlined function change let spriteAssembler = { getAssembler (sprite) { - let util = simpleRenderUtil; + let is3DNode = sprite.node.is3DNode; + let util = is3DNode ? simpleRenderUtil3D : simpleRenderUtil; switch (sprite.type) { case SpriteType.SLICED: - util = slicedRenderUtil; + util = is3DNode ? slicedRenderUtil3D : slicedRenderUtil; break; case SpriteType.TILED: - util = tiledRenderUtil; + util = is3DNode ? tiledRenderUtil3D : tiledRenderUtil; break; case SpriteType.FILLED: if (sprite._fillType === FillType.RADIAL) { - util = radialFilledRenderUtil; + util = is3DNode ? radialFilledRenderUtil3D : radialFilledRenderUtil; } else { - util = barFilledRenderUtil; + util = is3DNode ? barFilledRenderUtil3D : barFilledRenderUtil; } break; case SpriteType.MESH: - util = meshRenderUtil; + util = is3DNode ? meshRenderUtil3D : meshRenderUtil; break; } diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js deleted file mode 100644 index 17c1a72b87a..00000000000 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ /dev/null @@ -1,365 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 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 dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); - -const PI_2 = Math.PI * 2; - -module.exports = { - useModel: false, - - _vertPos: [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)], - _vertices: [0, 0, 0, 0], - _uvs: [0, 0, 0, 0, 0, 0, 0, 0], - _intersectPoint_1: [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)], - _intersectPoint_2: [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)], - _center: cc.v2(0, 0), - _triangles: [], - - createData (sprite) { - return sprite.requestRenderData(); - }, - - updateRenderData (sprite) { - let frame = sprite.spriteFrame; - - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - if (frame) { - if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); - } - if (sprite._material._texture !== frame._texture) { - sprite._activateMaterial(); - } - } - - let renderData = sprite._renderData; - if (renderData && frame && sprite._vertsDirty) { - let verts = renderData.vertices; - - let fillStart = sprite._fillStart; - let fillRange = sprite._fillRange; - if (fillRange < 0) { - fillStart += fillRange; - fillRange = -fillRange; - } - - //do round fill start [0,1), include 0, exclude 1 - while (fillStart >= 1.0) fillStart -= 1.0; - while (fillStart < 0.0) fillStart += 1.0; - - fillStart *= PI_2; - fillRange *= PI_2; - let fillEnd = fillStart + fillRange; - - //build vertices - this._calculateVertices(sprite); - //build uvs - this._calculateUVs(frame); - - let center = this._center; - - let vertPos = this._vertPos, - vertices = this._vertices; - - let triangles = this._triangles; - - this._calcInsectedPoints(vertices[0], vertices[2], vertices[1], vertices[3], center, fillStart, this._intersectPoint_1); - this._calcInsectedPoints(vertices[0], vertices[2], vertices[1], vertices[3], center, fillStart + fillRange, this._intersectPoint_2); - - let offset = 0; - for (let triangleIndex = 0; triangleIndex < 4; ++triangleIndex) { - let triangle = triangles[triangleIndex]; - if (!triangle) { - continue; - } - //all in - if (fillRange >= PI_2) { - renderData.dataLength = offset + 3; - this._generateTriangle(verts, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); - offset += 3; - continue; - } - //test against - let startAngle = this._getVertAngle(center, vertPos[triangle[0]]); - let endAngle = this._getVertAngle(center, vertPos[triangle[1]]); - if(endAngle < startAngle) endAngle += PI_2; - startAngle -= PI_2; - endAngle -= PI_2; - //testing - for(let testIndex = 0; testIndex < 3; ++testIndex) { - if(startAngle >= fillEnd) { - //all out - } else if (startAngle >= fillStart) { - renderData.dataLength = offset + 3; - if(endAngle >= fillEnd) { - //startAngle to fillEnd - this._generateTriangle(verts, offset, center, vertPos[triangle[0]], this._intersectPoint_2[triangleIndex]); - } else { - //startAngle to endAngle - this._generateTriangle(verts, offset, center, vertPos[triangle[0]], vertPos[triangle[1]]); - } - offset += 3; - } else { - //startAngle < fillStart - if(endAngle <= fillStart) { - //all out - } else if(endAngle <= fillEnd) { - renderData.dataLength = offset + 3; - //fillStart to endAngle - this._generateTriangle(verts, offset, center, this._intersectPoint_1[triangleIndex], vertPos[triangle[1]]); - offset += 3; - } else { - renderData.dataLength = offset + 3; - //fillStart to fillEnd - this._generateTriangle(verts, offset, center, this._intersectPoint_1[triangleIndex], this._intersectPoint_2[triangleIndex]); - offset += 3; - } - } - //add 2 * PI - startAngle += PI_2; - endAngle += PI_2; - } - } - - renderData.indiceCount = renderData.vertexCount = offset; - sprite._vertsDirty = false; - } - }, - - _getVertAngle: function(start, end) { - let placementX, placementY; - placementX = end.x - start.x; - placementY = end.y - start.y; - - if(placementX === 0 && placementY === 0) { - return undefined; - } else if(placementX === 0) { - if(placementY > 0) { - return Math.PI * 0.5; - } else { - return Math.PI * 1.5; - } - } else { - let angle = Math.atan(placementY / placementX); - if(placementX < 0) { - angle += Math.PI; - } - - return angle; - } - }, - - _generateTriangle: function(verts, offset, vert0, vert1, vert2) { - let vertices = this._vertices; - let v0x = vertices[0]; - let v0y = vertices[1]; - let v1x = vertices[2]; - let v1y = vertices[3]; - - verts[offset].x = vert0.x; - verts[offset].y = vert0.y; - verts[offset+1].x = vert1.x; - verts[offset+1].y = vert1.y; - verts[offset+2].x = vert2.x; - verts[offset+2].y = vert2.y; - - let progressX, progressY; - progressX = (vert0.x - v0x) / (v1x - v0x); - progressY = (vert0.y - v0y) / (v1y - v0y); - this._generateUV(progressX, progressY, verts, offset); - - progressX = (vert1.x - v0x) / (v1x - v0x); - progressY = (vert1.y - v0y) / (v1y - v0y); - this._generateUV(progressX, progressY, verts, offset + 1); - - progressX = (vert2.x - v0x) / (v1x - v0x); - progressY = (vert2.y - v0y) / (v1y - v0y); - this._generateUV(progressX, progressY, verts, offset + 2); - }, - - _generateUV : function(progressX, progressY, verts, offset) { - let uvs = this._uvs; - let px1 = uvs[0] + (uvs[2] - uvs[0]) * progressX; - let px2 = uvs[4] + (uvs[6] - uvs[4]) * progressX; - let py1 = uvs[1] + (uvs[3] - uvs[1]) * progressX; - let py2 = uvs[5] + (uvs[7] - uvs[5]) * progressX; - let uv = verts[offset]; - uv.u = px1 + (px2 - px1) * progressY; - uv.v = py1 + (py2 - py1) * progressY; - }, - - _calcInsectedPoints: function(left, right, bottom, top, center, angle, intersectPoints) { - //left bottom, right, top - let sinAngle = Math.sin(angle); - let cosAngle = Math.cos(angle); - let tanAngle,cotAngle; - if(Math.cos(angle) !== 0) { - tanAngle = sinAngle / cosAngle; - //calculate right and left - if((left - center.x) * cosAngle > 0) { - let yleft = center.y + tanAngle * (left - center.x); - intersectPoints[0].x = left; - intersectPoints[0].y = yleft; - } - if((right - center.x) * cosAngle > 0) { - let yright = center.y + tanAngle * (right - center.x); - - intersectPoints[2].x = right; - intersectPoints[2].y = yright; - } - - } - - if(Math.sin(angle) !== 0) { - cotAngle = cosAngle / sinAngle; - //calculate top and bottom - if((top - center.y) * sinAngle > 0) { - let xtop = center.x + cotAngle * (top-center.y); - intersectPoints[3].x = xtop; - intersectPoints[3].y = top; - } - if((bottom - center.y) * sinAngle > 0) { - let xbottom = center.x + cotAngle * (bottom-center.y); - intersectPoints[1].x = xbottom; - intersectPoints[1].y = bottom; - } - - } - }, - - _calculateVertices : function (sprite) { - let node = sprite.node, - width = node.width, height = node.height, - appx = node.anchorX * width, appy = node.anchorY * height; - - let l = -appx, b = -appy, - r = width-appx, t = height-appy; - - let vertices = this._vertices; - vertices[0] = l; - vertices[1] = b; - vertices[2] = r; - vertices[3] = t; - - let center = this._center, - fillCenter = sprite._fillCenter, - cx = center.x = Math.min(Math.max(0, fillCenter.x), 1) * (r-l) + l, - cy = center.y = Math.min(Math.max(0, fillCenter.y), 1) * (t-b) + b; - - let vertPos = this._vertPos; - vertPos[0].x = vertPos[3].x = l; - vertPos[1].x = vertPos[2].x = r; - vertPos[0].y = vertPos[1].y = b; - vertPos[2].y = vertPos[3].y = t; - - let triangles = this._triangles; - triangles.length = 0; - if(cx !== vertices[0]) { - triangles[0] = [3, 0]; - } - if(cx !== vertices[2]) { - triangles[2] = [1, 2]; - } - if(cy !== vertices[1]) { - triangles[1] = [0, 1]; - } - if(cy !== vertices[3]) { - triangles[3] = [2, 3]; - } - }, - - _calculateUVs : function (spriteFrame) { - let atlasWidth = spriteFrame._texture.width; - let atlasHeight = spriteFrame._texture.height; - let textureRect = spriteFrame._rect; - - let u0, u1, v0, v1; - let uvs = this._uvs; - - if (spriteFrame._rotated) { - u0 = (textureRect.x) / atlasWidth; - u1 = (textureRect.x + textureRect.height) / atlasWidth; - - v0 = (textureRect.y) / atlasHeight; - v1 = (textureRect.y + textureRect.width) / atlasHeight; - - uvs[0] = uvs[2] = u0; - uvs[4] = uvs[6] = u1; - uvs[3] = uvs[7] = v1; - uvs[1] = uvs[5] = v0; - } - else { - u0 = (textureRect.x) / atlasWidth; - u1 = (textureRect.x + textureRect.width) / atlasWidth; - - v0 = (textureRect.y) / atlasHeight; - v1 = (textureRect.y + textureRect.height) / atlasHeight; - - uvs[0] = uvs[4] = u0; - uvs[2] = uvs[6] = u1; - uvs[1] = uvs[3] = v1; - uvs[5] = uvs[7] = v0; - } - }, - - fillBuffers (sprite, renderer) { - let renderData = sprite._renderData, - verts = renderData.vertices, - node = sprite.node, - color = node._color._val; - - let matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - - // buffer - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, - vbuf = buffer._vData, - uintbuf = buffer._uintVData; - - let ibuf = buffer._iData, - indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; - - buffer.request(renderData.vertexCount, renderData.indiceCount); - - let count = verts.length; - for (let i = 0; i < count; i++) { - let vert = verts[i]; - vbuf[vertexOffset ++] = vert.x * a + vert.y * c + tx; - vbuf[vertexOffset ++] = vert.x * b + vert.y * d + ty; - vbuf[vertexOffset ++] = vert.u; - vbuf[vertexOffset ++] = vert.v; - uintbuf[vertexOffset ++] = color; - } - - for (let i = 0; i < count; i++) { - ibuf[indiceOffset+i] = vertexId+i; - } - }, -}; diff --git a/cocos2d/core/renderer/webgl/assemblers/utils.js b/cocos2d/core/renderer/webgl/assemblers/utils.js new file mode 100644 index 00000000000..53b0fc2337b --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/utils.js @@ -0,0 +1,103 @@ + +const vec3 = cc.vmath.vec3; +let vec3_temp = vec3.create(); + +function fillVertices (node, buffer, renderData, color) { + let verts = renderData.vertices, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount; + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; + + let matrix = node._worldMatrix; + let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + tx = matrix.m12, ty = matrix.m13; + for (let i = 0; i < vertexCount; i++) { + let vert = verts[i]; + vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; + vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } +} + +function fillVertices3D (node, buffer, renderData, color) { + let verts = renderData.vertices, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount; + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; + + let matrix = node._worldMatrix; + + for (let i = 0; i < vertexCount; i++) { + let vert = verts[i]; + vec3.set(vec3_temp, vert.x, vert.y, 0); + vec3.transformMat4(vec3_temp, vec3_temp, matrix); + vbuf[vertexOffset++] = vec3_temp.x; + vbuf[vertexOffset++] = vec3_temp.y; + vbuf[vertexOffset++] = vec3_temp.z; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } +} + +function fillVerticesWithoutCalc (node, buffer, renderData, color) { + let verts = renderData.vertices, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount; + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; + + for (let i = 0; i < vertexCount; i++) { + let vert = verts[i]; + vbuf[vertexOffset++] = vert.x; + vbuf[vertexOffset++] = vert.y; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } +} + +function fillVerticesWithoutCalc3D (node, buffer, renderData, color) { + let verts = renderData.vertices, + vertexOffset = buffer.byteOffset >> 2; + + let vertexCount = renderData.vertexCount; + buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let vbuf = buffer._vData, + uintbuf = buffer._uintVData; + + for (let i = 0; i < vertexCount; i++) { + let vert = verts[i]; + vbuf[vertexOffset++] = vert.x; + vbuf[vertexOffset++] = vert.y; + vbuf[vertexOffset++] = vert.z; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } +} + +module.exports = { + fillVertices: fillVertices, + fillVertices3D: fillVertices3D, + fillVerticesWithoutCalc: fillVerticesWithoutCalc, + fillVerticesWithoutCalc3D: fillVerticesWithoutCalc3D +}; diff --git a/cocos2d/core/renderer/webgl/model-batcher.js b/cocos2d/core/renderer/webgl/model-batcher.js index 04940bddf6f..0c5d141b558 100644 --- a/cocos2d/core/renderer/webgl/model-batcher.js +++ b/cocos2d/core/renderer/webgl/model-batcher.js @@ -24,7 +24,9 @@ ****************************************************************************/ const renderEngine = require('../render-engine'); -const defaultVertexFormat = require('./vertex-format').vfmtPosUvColor; +const vertexFormat = require('./vertex-format'); +const defaultVertexFormat = vertexFormat.vfmtPosUvColor; +const vfmt3D = vertexFormat.vfmt3D; const StencilManager = require('./stencil-manager'); const QuadBuffer = require('./quad-buffer'); const MeshBuffer = require('./mesh-buffer'); @@ -59,6 +61,8 @@ var ModelBatcher = function (device, renderScene) { // buffers this._quadBuffer = this.getBuffer('quad', defaultVertexFormat); this._meshBuffer = this.getBuffer('mesh', defaultVertexFormat); + this._quadBuffer3D = this.getBuffer('quad', vfmt3D); + this._meshBuffer3D = this.getBuffer('mesh', vfmt3D); this._buffer = this._quadBuffer; this._batchedModels = []; diff --git a/cocos2d/core/utils/base-node.js b/cocos2d/core/utils/base-node.js index 6b9b45e2c79..b39572d2ffe 100644 --- a/cocos2d/core/utils/base-node.js +++ b/cocos2d/core/utils/base-node.js @@ -1091,7 +1091,7 @@ var BaseNode = cc.Class({ destroy () { if (cc.Object.prototype.destroy.call(this)) { - this.parent = null; + this.active = false; } }, diff --git a/cocos2d/core/utils/html-text-parser.js b/cocos2d/core/utils/html-text-parser.js index b1e7fc7611d..479a78c14e3 100644 --- a/cocos2d/core/utils/html-text-parser.js +++ b/cocos2d/core/utils/html-text-parser.js @@ -25,7 +25,7 @@ ****************************************************************************/ var eventRegx = /^(click)(\s)*=/; -var imageAttrReg = /(\s)*src(\s)*=|(\s)*height(\s)*=|(\s)*width(\s)*=|(\s)*click(\s)*=/; +var imageAttrReg = /(\s)*src(\s)*=|(\s)*height(\s)*=|(\s)*width(\s)*=|(\s)*click(\s)*=|(\s)*param(\s)*=/; /** * A utils class for parsing HTML texts. The parsed results will be an object array. */ @@ -161,6 +161,11 @@ HtmlTextParser.prototype = { } else if (tagName === "click") { obj.event = this._processEventHandler(tagName + "=" + tagValue); } + + if (obj.event && tagName === 'param') { + obj.event.param = tagValue.replace(/^\"|\"$/g, ''); + } + header = attribute.match(imageAttrReg); } @@ -178,7 +183,7 @@ HtmlTextParser.prototype = { attribute = header[0].substring("outline".length).trim(); var defaultOutlineObject = {color: "#ffffff", width: 1}; if (attribute) { - var outlineAttrReg = /(\s)*color(\s)*=|(\s)*width(\s)*=|(\s)*click(\s)*=/; + var outlineAttrReg = /(\s)*color(\s)*=|(\s)*width(\s)*=|(\s)*click(\s)*=|(\s)*param(\s)*=/; header = attribute.match(outlineAttrReg); var tagValue; while (header) { @@ -204,6 +209,11 @@ HtmlTextParser.prototype = { } else if (tagName === "width") { defaultOutlineObject.width = parseInt(tagValue); } + + if (obj.event && tagName === 'param') { + obj.event.param = tagValue.replace(/^\"|\"$/g, ''); + } + header = attribute.match(outlineAttrReg); } } @@ -232,7 +242,6 @@ HtmlTextParser.prototype = { obj.event = eventObj; } - return obj; }, diff --git a/cocos2d/core/value-types/color.js b/cocos2d/core/value-types/color.js index f521c7654da..2b25ff83efd 100644 --- a/cocos2d/core/value-types/color.js +++ b/cocos2d/core/value-types/color.js @@ -340,6 +340,10 @@ var Color = (function () { return this; }; + proto._fastSetA = function (alpha) { + this._val = ((this._val & 0x00ffffff) | ((alpha << 24) >>> 0)) >>> 0; + }; + js.getset(proto, 'r', proto.getR, proto.setR, true); js.getset(proto, 'g', proto.getG, proto.setG, true); js.getset(proto, 'b', proto.getB, proto.setB, true); diff --git a/cocos2d/particle/CCParticleAsset.js b/cocos2d/particle/CCParticleAsset.js index 0731d96886a..0a8c20ade69 100644 --- a/cocos2d/particle/CCParticleAsset.js +++ b/cocos2d/particle/CCParticleAsset.js @@ -25,7 +25,7 @@ ****************************************************************************/ const Asset = require('../core/assets/CCAsset'); -const Texture2D = require('../core/assets/CCTexture2D'); +const CCSpriteFrame = require('../core/assets/CCSpriteFrame'); /** * Class for particle asset handling. @@ -37,9 +37,9 @@ var ParticleAsset = cc.Class({ extends: Asset, properties: { - texture: { + spriteFrame: { default: null, - type: Texture2D + type: CCSpriteFrame } } }); diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 9719e8ea34a..10d1b68e565 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -218,7 +218,7 @@ var properties = { return this._spriteFrame; }, set: function (value, force) { - var lastSprite = this._spriteFrame; + var lastSprite = this._renderSpriteFrame; if (CC_EDITOR) { if (!force && lastSprite === value) { return; @@ -229,7 +229,12 @@ var properties = { return; } } - this._spriteFrame = value; + this._renderSpriteFrame = value; + + if (!value || value._uuid) { + this._spriteFrame = value; + } + if ((lastSprite && lastSprite.getTexture()) !== (value && value.getTexture())) { this._texture = null; this._applySpriteFrame(lastSprite); @@ -254,7 +259,9 @@ var properties = { return this._texture; }, set: function (value) { - cc.warnID(6017); + if (value) { + cc.warnID(6017); + } }, type: cc.Texture2D, tooltip: CC_DEV && 'i18n:COMPONENT.particle_system.texture', @@ -722,6 +729,9 @@ var ParticleSystem = cc.Class({ this._startColorVar = cc.color(0, 0, 0, 0); this._endColor = cc.color(255, 255, 255, 0); this._endColorVar = cc.color(0, 0, 0, 0); + + // The temporary SpriteFrame object used for the renderer. Because there is no corresponding asset, it can't be serialized. + this._renderSpriteFrame = null; }, properties: properties, @@ -802,6 +812,9 @@ var ParticleSystem = cc.Class({ this._applyFile(); } } + else if (this._custom && this.spriteFrame && !this._renderSpriteFrame) { + this._applySpriteFrame(this.spriteFrame); + } // auto play if (!CC_EDITOR || cc.engine.isPlaying) { if (this.playOnLoad) { @@ -926,9 +939,9 @@ var ParticleSystem = cc.Class({ if (!self._custom) { self._initWithDictionary(content); } - if (!self.spriteFrame) { - if (file.texture) { - self.spriteFrame = new cc.SpriteFrame(file.texture); + if (!self.spriteFrame || !self._renderSpriteFrame) { + if (file.spriteFrame) { + self.spriteFrame = file.spriteFrame; } else if (self._custom) { self._initTextureWithDictionary(content); @@ -1102,7 +1115,7 @@ var ParticleSystem = cc.Class({ }, _onTextureLoaded: function () { - this._texture = this._spriteFrame.getTexture(); + this._texture = this._renderSpriteFrame.getTexture(); this._simulator.updateUVs(true); // Reactivate material this._activateMaterial(); @@ -1113,7 +1126,7 @@ var ParticleSystem = cc.Class({ oldFrame.off('load', this._onTextureLoaded, this); } - var spriteFrame = this._spriteFrame; + var spriteFrame = this._renderSpriteFrame = this._renderSpriteFrame || this._spriteFrame; if (spriteFrame) { if (spriteFrame.textureLoaded()) { this._onTextureLoaded(null); @@ -1135,7 +1148,7 @@ var ParticleSystem = cc.Class({ if (!this._texture || !this._texture.loaded) { this.markForCustomIARender(false); - if (this._spriteFrame) { + if (this._renderSpriteFrame) { this._applySpriteFrame(); } } diff --git a/cocos2d/particle/particle-simulator.js b/cocos2d/particle/particle-simulator.js index fc31d50d3a5..0c7bec0c526 100644 --- a/cocos2d/particle/particle-simulator.js +++ b/cocos2d/particle/particle-simulator.js @@ -193,10 +193,10 @@ Simulator.prototype.emitParticle = function (pos) { Simulator.prototype.updateUVs = function (force) { let particleCount = this.particles.length; - if (this.sys._buffer && this.sys._spriteFrame) { + if (this.sys._buffer && this.sys._renderSpriteFrame) { const FLOAT_PER_PARTICLE = 4 * this.sys._vertexFormat._bytes / 4; let vbuf = this.sys._buffer._vData; - let uv = this.sys._spriteFrame.uv; + let uv = this.sys._renderSpriteFrame.uv; let start = force ? 0 : this._uvFilled; for (let i = start; i < particleCount; i++) { diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index abf4b5fa653..7aca916fd3e 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -28,20 +28,16 @@ const sys = require('../core/platform/CCSys'); const renderEngine = require('../core/renderer/render-engine'); const math = renderEngine.math; -let _mat4_temp = math.mat4.create(); - -// ios brower need to wait until the video's loadedmetadata event -// has been fired before calling webkitEnterFullScreen() -function triggerFullScene (video, enable) { - if (!video) return; - if (enable) { - video.webkitEnterFullscreen && video.webkitEnterFullscreen(); - } - else { - video.webkitExitFullscreen && video.webkitExitFullscreen(); - } +const READY_STATE = { + HAVE_NOTHING: 0, + HAVE_METADATA: 1, + HAVE_CURRENT_DATA: 2, + HAVE_FUTURE_DATA: 3, + HAVE_ENOUGH_DATA: 4 } +let _mat4_temp = math.mat4.create(); + let VideoPlayerImpl = cc.Class({ name: 'VideoPlayerImpl', @@ -57,8 +53,6 @@ let VideoPlayerImpl = cc.Class({ this._loadedmeta = false; this._loaded = false; this._visible = false; - // 有一些浏览器第一次播放视频需要特殊处理,这个标记用来标识是否播放过 - this._played = false; this._playing = false; this._ignorePause = false; @@ -82,8 +76,11 @@ let VideoPlayerImpl = cc.Class({ let cbs = this.__eventListeners; cbs.loadedmetadata = function () { self._loadedmeta = true; - if (sys.os === sys.OS_IOS && sys.isBrowser) { - triggerFullScene(video, self._fullScreenEnabled); + if (self._fullScreenEnabled) { + cc.screen.requestFullScreen(video); + } + else { + cc.screen.exitFullScreen(video); } self._dispatchEvent(VideoPlayerImpl.EventType.META_LOADED); }; @@ -95,12 +92,21 @@ let VideoPlayerImpl = cc.Class({ cbs.play = function () { if (self._video !== video) return; self._playing = true; + self._updateVisibility(); self._dispatchEvent(VideoPlayerImpl.EventType.PLAYING); }; + // pause and stop callback cbs.pause = function () { - if (self._ignorePause || self._video !== video) return; + if (self._video !== video) { + return; + } self._playing = false; - self._dispatchEvent(VideoPlayerImpl.EventType.PAUSED); + if (self._ignorePause) { + return; + } + else { + self._dispatchEvent(VideoPlayerImpl.EventType.PAUSED); + } }; cbs.click = function () { self._dispatchEvent(VideoPlayerImpl.EventType.CLICKED); @@ -113,36 +119,37 @@ let VideoPlayerImpl = cc.Class({ video.addEventListener("click", cbs.click); function onCanPlay () { - if (this._loaded) + if (self._loaded || self._loadedmeta || self._playing) return; - let video = this._video; - if (video.readyState === 4) { - this._loaded = true; - // node.setContentSize(node._contentSize.width, node._contentSize.height); + let video = self._video; + if (video.readyState === READY_STATE.HAVE_ENOUGH_DATA) { video.currentTime = 0; - this._dispatchEvent(VideoPlayerImpl.EventType.READY_TO_PLAY); - this._updateVisibility(); + self._loaded = true; + self._dispatchEvent(VideoPlayerImpl.EventType.READY_TO_PLAY); + self._updateVisibility(); } } - cbs.onCanPlay = onCanPlay.bind(this); + cbs.onCanPlay = onCanPlay; video.addEventListener('canplay', cbs.onCanPlay); video.addEventListener('canplaythrough', cbs.onCanPlay); video.addEventListener('suspend', cbs.onCanPlay); }, _updateVisibility () { - if (!this._video) return; let video = this._video; + if (!video) return; + if (this._visible) { video.style.visibility = 'visible'; + this._forceUpdate = true; } else { video.style.visibility = 'hidden'; video.pause(); this._playing = false; + this._forceUpdate = false; } - this._forceUpdate = true; }, _updateSize (width, height) { @@ -164,10 +171,10 @@ let VideoPlayerImpl = cc.Class({ video.setAttribute('playsinline', ''); // Stupid tencent x5 adaptation - let orientation = cc.winSize.width > cc.winSize.height ? "landscape" : "portrait"; video.setAttribute("x5-playsinline", ""); video.setAttribute("x5-video-player-type", "h5"); - video.setAttribute("x5-video-player-fullscreen", "false"); + video.setAttribute("x5-video-player-fullscreen", this._fullScreenEnabled ? "true" : "false"); + let orientation = cc.winSize.width > cc.winSize.height ? "landscape" : "portrait"; video.setAttribute("x5-video-orientation", orientation); this._video = video; @@ -223,7 +230,6 @@ let VideoPlayerImpl = cc.Class({ let video = this._video; video.style["visibility"] = "hidden"; this._loaded = false; - this._played = false; this._playing = false; this._loadedmeta = false; @@ -248,34 +254,22 @@ let VideoPlayerImpl = cc.Class({ play: function () { let video = this._video; - if (!video || !this._visible) return; - - this._played = true; - if (this._playing) { - return; - } + if (!video || !this._visible || this._playing) return; if (VideoPlayerImpl._polyfill.autoplayAfterOperation) { let self = this; setTimeout(function () { video.play(); - self._playing = !video.paused; }, 20); } else { video.play(); - this._playing = !video.paused; } }, pause: function () { let video = this._video; - if (!this._playing) return; - - this._playing = false; - if (!video) { - return; - } + if (!this._playing || !video) return; video.pause(); }, @@ -287,15 +281,13 @@ let VideoPlayerImpl = cc.Class({ let video = this._video; if (!video || !this._visible) return; this._ignorePause = true; + video.currentTime = 0; video.pause(); - let self = this; setTimeout(function () { - self._dispatchEvent(VideoPlayerImpl.EventType.STOPPED); - self._ignorePause = false; - }, 0); - // 恢复到视频起始位置 - video.currentTime = 0; - this._playing = false; + this._dispatchEvent(VideoPlayerImpl.EventType.STOPPED); + this._ignorePause = false; + }.bind(this), 0); + }, setVolume: function (volume) { @@ -368,24 +360,16 @@ let VideoPlayerImpl = cc.Class({ }, setFullScreenEnabled: function (enable) { - let video = this._video; + let video = this._video; if (!video) { return; } this._fullScreenEnabled = enable; - if (sys.os === sys.OS_IOS && sys.isBrowser) { - if (this._loadedmeta) { - triggerFullScene(video, enable); - } + if (enable) { + cc.screen.requestFullScreen(video); } else { - if (enable) { - cc.screen.requestFullScreen(video); - } - else { - cc.screen.exitFullScreen(video); - } - video.setAttribute("x5-video-player-fullscreen", enable ? "true" : "false"); + cc.screen.exitFullScreen(video); } }, @@ -481,9 +465,9 @@ let VideoPlayerImpl = cc.Class({ h = this._h * scaleY; } else { - this._updateSize(this._w, this._h); w = this._w * scaleX; h = this._h * scaleY; + this._updateSize(this._w, this._h); } let appx = (w * _mat4_temp.m00) * node._anchorPoint.x; @@ -556,7 +540,7 @@ VideoPlayerImpl._polyfill = { * so it is best to provide mp4 and webm or ogv file */ let dom = document.createElement("video"); -if (sys.platform !== sys.WECHAT_GAME) { +if (!CC_WECHATGAME) { if (dom.canPlayType("video/ogg")) { VideoPlayerImpl._polyfill.canPlayType.push(".ogg"); VideoPlayerImpl._polyfill.canPlayType.push(".ogv"); diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 83440e218b4..c97971f99f4 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -197,7 +197,8 @@ module.exports = { "vertical_direction": "Vertically align in the direction of the child Nodes: \n 1. TOP_TO_BOTTOM, \n 2. BOTTOM_TO_TOP", "horizontal_direction": "Horizontally align in the direction of the child Nodes: \n 1. LEFT_TO_RIGHT \n 2. RIGHT_TO_LEFT", "cell_size": "In Grid layout, the size of each child element.", - "start_axis": "In Grid layout, the arrangement direction of children elements." + "start_axis": "In Grid layout, the arrangement direction of children elements.", + "affected_by_scale": "Whether the scaling of the child node affects the layout." }, "particle": { "export_title": "Export custom particle data to plist file.", @@ -240,6 +241,8 @@ module.exports = { "horizontal_align": "Horizontal alignment", "font_size": "Font size, in points", "font": "Custom TTF font of RichText", + "font_family": "Custom System font of RichText", + "system_font": "Whether to use the system default font", "line_height": "Line height, in points", "max_width": "The maximize width of RichText, pass 0 means not limit the maximize width.", "image_atlas": "The image atlas for the img tag. For each src value in the img tag, there should be a valid spriteFrame in the image atlas.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 87f41105add..b7c66052ae5 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -201,7 +201,8 @@ module.exports = { 'vertical_direction': '垂直排列子节点的方向,包括:\n 1. TOP_TO_BOTTOM, 从上到下排列 \n 2. BOTTOM_TO_TOP, 从下到上排列', 'horizontal_direction': '水平排列子节点的方向,包括:\n 1. LEFT_TO_RIGHT, 从左到右排列 \n 2. RIGHT_TO_LEFT, 从右到左排列', 'cell_size': '网格布局中,规定每一个网格的大小', - 'start_axis': '网格布局中,子物体排版时的起始方向轴,支持水平和垂直两个方向。', + 'start_axis': '网格布局中,子物体排版时的起始方向轴,支持水平和垂直两个方向', + "affected_by_scale": "子节点的缩放是否影响布局" }, 'particle': { 'export_title': "将自定义的粒子数据导出成 plist 文件", @@ -244,6 +245,8 @@ module.exports = { "horizontal_align": "水平对齐方式", "font_size": "字体大小, 单位是 point", "font": "富文本定制字体", + "font_family": "富文本定制系统字体", + 'system_font': "是否使用系统默认字体", "line_height": "字体行高, 单位是 point", "max_width": "富文本的最大宽度, 传 0 的话意味着必须手动换行.", "image_atlas": "对于 img 标签里面的 src 属性名称,都需要在 imageAtlas 里面找到一个有效的 spriteFrame,否则 img tag 会判定为无效。", diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 00f9b4b41b0..6bc9aceba22 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -239,6 +239,7 @@ let ArmatureDisplay = cc.Class({ type: DefaultAnimsEnum, visible: true, editorOnly: true, + animatable: false, displayName: 'Animation', tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.animation_name' }, diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index b1811c50d75..1a38234221a 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -75,7 +75,6 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { let materialCache = comp._materialCache; let material = materialCache[key]; if (!material) { - var baseKey = baseMaterial._hash; if (!materialCache[baseKey]) { material = baseMaterial; @@ -176,6 +175,7 @@ var spineAssembler = { let material = null, currMaterial = null; let vertexCount = 0, vertexOffset = 0; let indiceCount = 0, indiceOffset = 0; + let materials = comp._materials; for (let i = 0, n = locSkeleton.drawOrder.length; i < n; i++) { slot = locSkeleton.drawOrder[i]; if (!slot.attachment) diff --git a/gulpfile.js b/gulpfile.js index dbd088bde9b..dbb628a1b81 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -97,15 +97,15 @@ gulp.task('build-jsb', ['build-jsb-preview', 'build-jsb-dev', 'build-jsb-min']); // test // ///////// -gulp.task('clean-test', ['clean-test-cases'], function (done) { - Del([ +gulp.task('clean-test', ['clean-test-cases'], function () { + return Del([ './bin/cocos2d-js-extends-for-test.js', './bin/cocos2d-js-for-test.js', - ], done); + ]); }); -gulp.task('clean-test-cases', function (done) { - Del('./bin/test/**/*', done); +gulp.task('clean-test-cases', function () { + return Del('./bin/test/**/*'); }); gulp.task('build-test-cases', ['clean-test-cases'], function (done) { @@ -145,13 +145,13 @@ gulp.task('test-no-build', function (done) { // global // //////////// -gulp.task('clean-cache', function (done) { - Del(['./bin/.cache/*', '!./bin/.cache/dev/**'], done); +gulp.task('clean-cache', function () { + return Del(['./bin/.cache/*', '!./bin/.cache/dev/**']); }); // fast build, only for develop -gulp.task('build-dev', ['clean-cache', 'build-html5-preview', 'build-jsb-preview'], function (done) { - Del(['./bin/cocos2d-jsb-min.js', './bin/cocos2d-jsb.js'], done); +gulp.task('build-dev', ['clean-cache', 'build-html5-preview', 'build-jsb-preview'], function () { + return Del(['./bin/cocos2d-jsb-min.js', './bin/cocos2d-jsb.js']); }); // only build preview for html5 since it will built by editor @@ -160,8 +160,8 @@ gulp.task('build', ['clean-cache', 'build-html5-preview', 'build-jsb']); // default task gulp.task('default', ['build']); -gulp.task('clean', function (done) { - Del('./bin/**/*', done); +gulp.task('clean', function () { + return Del('./bin/**/*'); }); //////////// diff --git a/modules.json b/modules.json index 112c57e31fa..3612085ba40 100644 --- a/modules.json +++ b/modules.json @@ -266,7 +266,9 @@ { "name": "3D", "entries": [ - "./cocos2d/core/3d/index.js" + "./cocos2d/core/3d/index.js", + "./cocos2d/core/3d/geom-utils/aabb.js", + "./cocos2d/core/3d/geom-utils/ray.js" ], "dependencies": ["Mesh", "WebGL Renderer"] }, diff --git a/package.json b/package.json index 765eb8b4e6d..a0e8966c879 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "babelify": "7.3.0", "browserify": "13.0.0", "chalk": "1.1.0", - "del": "1.2.0", + "del": "3.0.0", "event-stream": "3.3.2", "fire-fs": "0.2.1", "gulp": "^3.9.1", diff --git a/test/qunit/lib/polyfill-for-phantom.js b/test/qunit/lib/polyfill-for-phantom.js index f9946938d95..057a1030a7b 100644 --- a/test/qunit/lib/polyfill-for-phantom.js +++ b/test/qunit/lib/polyfill-for-phantom.js @@ -176,3 +176,6 @@ if (!Object.getOwnPropertySymbols) { return []; }; } + +Number.parseFloat = Number.parseFloat || parseFloat; +Number.parseInt = Number.parseInt || parseInt; diff --git a/test/qunit/unit-es5/test-component-scheduler.js b/test/qunit/unit-es5/test-component-scheduler.js index a1fab6658a6..5ec0d7d464e 100644 --- a/test/qunit/unit-es5/test-component-scheduler.js +++ b/test/qunit/unit-es5/test-component-scheduler.js @@ -544,16 +544,16 @@ test('set sibling index during onDisable', function () { compOfChild.onEnable.once('child component should be re-enabled'); }); - test('component might be destroied when destroy() called before node activating', function () { + test('component might be destroyed when destroy() called before node activating', function () { var node = new cc.Node(); - var comp = createDisabledComp(node, 'destroied'); + var comp = createDisabledComp(node, 'destroyed'); comp.onDestroy = new Callback().disable('onDestroy should not be called'); comp.destroy(); cc.director.getScene().addChild(node); cc.game.step(); - strictEqual(comp.isValid, false, 'component should be destroied'); + strictEqual(comp.isValid, false, 'component should be destroyed'); }); // test('could deactivate parent in onLoad', function () { diff --git a/test/qunit/unit-es5/test-node.js b/test/qunit/unit-es5/test-node.js index f842c983ef6..a9657f1e84b 100644 --- a/test/qunit/unit-es5/test-node.js +++ b/test/qunit/unit-es5/test-node.js @@ -137,6 +137,17 @@ test('activeInHierarchy should be false after destroy', function () { strictEqual(child.activeInHierarchy, false, 'child should not activeInHierarchy after destroy'); }); +test('nodes should be destroyed with the scene', function () { + var child = new cc.Node(); + var scene = cc.director.getScene(); + child.parent = scene; + + cc.director.runSceneImmediate(new cc.Scene()); + + strictEqual(child.activeInHierarchy, false, 'nodes should not activeInHierarchy after destroy'); + strictEqual(child.isValid, false, 'nodes should be destroyed with the scene'); +}); + test('activation logic for component', function () { // 这里主要测试node,不是测试component From 99a2f28bbb4aa38c42317148473d2c13b2ea64fe Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Wed, 26 Dec 2018 21:48:51 +0800 Subject: [PATCH 0347/1631] Update README.md --- README.md | 52 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 96f8c0828d0..291e3ca353c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,38 @@ -# Cocos Creator Engine Framework - -This repo is the engine framework for Cocos Creator, Cocos Creator is a game development tool focused on content creation, which has realized features like thorough scriptability, componentization and data driven, etc. on the basis of Cocos2d-x. - -Cocos Creator's in-editor scene view and web runtime share the same framework, which is the content of this repo. It's originally forked from [Cocos2d-html5](https://github.com/cocos2d/cocos2d-html5/), we build up an Entity Component architecture on it to meet the needs of Cocos Creator. - -This framework is a cross-platform game engine written in Javascript and licensed under MIT. It supports major desktop and mobile browsers, it's also compatible with [Cocos2d Javascript Binding engine](https://github.com/cocos-creator/cocos2d-x-lite) to support native platforms like iOS, Android, Win32, Mac OS X. +

+ +

+

+ + stars + + + forks + + + version + + + license + + + twitter + +

+ +# Cocos Creator + +![image](https://user-images.githubusercontent.com/1503156/50446041-a95bac80-094d-11e9-8292-012b56b21103.png) + +Cocos Creator is a complete package of game development tools and workflow, including a game engine, resource management, scene editing, game preview, debug and publish one project to multiple platforms. Cocos Creator focused on content creation, which has realized features like thorough scriptability, componentization and data driven, etc. on the basis of Cocos2d-x. With JavaScript, you can scripting your component in no time. The editor and engine extension is also made with JavaScript so you can make games and refine your tool in a single programming language. Cocos Creator is an provides an innovative, easy to use toolset such as the UI system and Animation editor. The toolset will be expanding continuously and quickly, thanks to the open editor extension system. + +This repo is the engine framework for Cocos Creator. Cocos Creator's in-editor scene view and web runtime share the same framework, which is the content of this repo. It's originally forked from [Cocos2d-html5](https://github.com/cocos2d/cocos2d-html5/), we build up an Entity Component architecture on it to meet the needs of Cocos Creator. + +This framework is a cross-platform game engine written in JavaScript and licensed under MIT. It supports major desktop and mobile browsers, it's also compatible with [Cocos2d Javascript Binding engine](https://github.com/cocos-creator/cocos2d-x-lite) to support native platforms like iOS, Android, Win32, macOS. The framework is naturally integrated with Cocos Creator, so it's not designed to be used independently. @@ -94,12 +122,10 @@ For details below: ``` - -## Links +## Useful links * [Official site](http://cocos2d-x.org/creator) * [Download](http://cocos2d-x.org/download) -* [Documentation](http://www.cocos2d-x.org/docs/creator/manual/en/) -* [API References](http://www.cocos2d-x.org/docs/creator/api/en/) -* [Forum](http://discuss.cocos2d-x.org/c/editors-and-tools/cocos-creator) -* [Road Map](https://trello.com/b/JWVRRxMG/cocos-creator-roadmap) +* [Documentation](https://docs.cocos2d-x.org/creator/manual/en/) +* [API References](https://docs.cocos2d-x.org/creator/api/en/) +* [Forum](https://discuss.cocos2d-x.org/c/creator) From cdcd664eaa9c5903ff2f541a5520b977e82414b0 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 27 Dec 2018 00:48:14 +0800 Subject: [PATCH 0348/1631] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 291e3ca353c..593063641b5 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,19 @@

- stars - forks - version - license @@ -26,7 +26,7 @@ # Cocos Creator -![image](https://user-images.githubusercontent.com/1503156/50446041-a95bac80-094d-11e9-8292-012b56b21103.png) +![image](https://user-images.githubusercontent.com/1503156/50451713-97d7cc00-0970-11e9-89f8-ccdd8b2cc5cb.png) Cocos Creator is a complete package of game development tools and workflow, including a game engine, resource management, scene editing, game preview, debug and publish one project to multiple platforms. Cocos Creator focused on content creation, which has realized features like thorough scriptability, componentization and data driven, etc. on the basis of Cocos2d-x. With JavaScript, you can scripting your component in no time. The editor and engine extension is also made with JavaScript so you can make games and refine your tool in a single programming language. Cocos Creator is an provides an innovative, easy to use toolset such as the UI system and Animation editor. The toolset will be expanding continuously and quickly, thanks to the open editor extension system. From ffbd246d48a99bb15585ed596f2c84a85239473f Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 27 Dec 2018 01:03:43 +0800 Subject: [PATCH 0349/1631] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 593063641b5..78d53d4667c 100644 --- a/README.md +++ b/README.md @@ -3,23 +3,23 @@

- stars - forks - version - license - twitter

From e6d74d3eb3f10db8f6b1a810ba9db4cc206b65ef Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 27 Dec 2018 11:04:11 +0800 Subject: [PATCH 0350/1631] distinguish CC_RUNTIME and CC_JSB && implement buildRuntime && fix __getCurrentLanguageCode (#3668) * distinguish CC_RUNTIME and CC_JSB * implement buildRuntime * fix __getCurrentLanguageCode on runtime --- cocos2d/core/CCDebug.js | 8 +-- cocos2d/core/CCGame.js | 8 +-- cocos2d/core/components/CCLabel.js | 2 +- cocos2d/core/components/CCScrollView.js | 2 +- cocos2d/core/load-pipeline/uuid-loader.js | 2 +- cocos2d/core/platform/CCInputExtension.js | 4 +- cocos2d/core/platform/CCSys.js | 13 ++-- cocos2d/core/platform/CCView.js | 4 +- cocos2d/core/platform/deserialize.js | 4 +- gulp/tasks/engine.js | 75 +++++++++++++++++++++++ polyfill/misc.js | 2 +- predefine.js | 4 +- 12 files changed, 103 insertions(+), 25 deletions(-) diff --git a/cocos2d/core/CCDebug.js b/cocos2d/core/CCDebug.js index 11febe776a7..7e52f0348ec 100644 --- a/cocos2d/core/CCDebug.js +++ b/cocos2d/core/CCDebug.js @@ -129,7 +129,7 @@ let resetDebugSetting = function (mode) { cc.error = console.error.bind(console); } else { - cc.error = CC_JSB ? console.error : function () { + cc.error = CC_JSB || CC_RUNTIME ? console.error : function () { return console.error.apply(console, arguments); }; } @@ -172,7 +172,7 @@ let resetDebugSetting = function (mode) { cc.warn = console.warn.bind(console); } else { - cc.warn = CC_JSB ? console.warn : function () { + cc.warn = CC_JSB || CC_RUNTIME ? console.warn : function () { return console.warn.apply(console, arguments); }; } @@ -188,7 +188,7 @@ let resetDebugSetting = function (mode) { * @param {String|any} msg - A JavaScript string containing zero or more substitution strings. * @param {any} ...subst - JavaScript objects with which to replace substitution strings within msg. This gives you additional control over the format of the output. */ - if (CC_JSB) { + if (CC_JSB || CC_RUNTIME) { if (scriptEngineType === "JavaScriptCore") { // console.log has to use `console` as its context for iOS 8~9. Therefore, apply it. cc.log = function () { @@ -213,7 +213,7 @@ let resetDebugSetting = function (mode) { cc._throw = CC_EDITOR ? Editor.error : function (error) { var stack = error.stack; if (stack) { - cc.error(CC_JSB ? (error + '\n' + stack) : stack); + cc.error(CC_JSB || CC_RUNTIME ? (error + '\n' + stack) : stack); } else { cc.error(error); diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 1afdc004695..7e33ff1e98b 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -571,7 +571,7 @@ var game = { var frameRate = game.config.frameRate; this._frameTime = 1000 / frameRate; - if (CC_JSB) { + if (CC_JSB || CC_RUNTIME) { jsb.setPreferredFramesPerSecond(frameRate); window.requestAnimFrame = window.requestAnimationFrame; window.cancelAnimFrame = window.cancelAnimationFrame; @@ -624,7 +624,7 @@ var game = { callback = function () { if (!self._paused) { self._intervalId = window.requestAnimFrame(callback); - if (!CC_JSB && frameRate === 30) { + if (!CC_JSB && !CC_RUNTIME && frameRate === 30) { if (skip = !skip) { return; } @@ -709,13 +709,13 @@ var game = { width, height, localCanvas, localContainer; - if (CC_WECHATGAME || CC_JSB) { + if (CC_WECHATGAME || CC_JSB || CC_RUNTIME) { this.container = localContainer = document.createElement("DIV"); this.frame = localContainer.parentNode === document.body ? document.documentElement : localContainer.parentNode; if (cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { localCanvas = window.sharedCanvas || wx.getSharedCanvas(); } - else if (CC_JSB) { + else if (CC_JSB || CC_RUNTIME) { localCanvas = window.__canvas; } else { diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index ae85451e296..a58301cf66b 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -576,7 +576,7 @@ let Label = cc.Class({ if (!this._ttfTexture) { this._ttfTexture = new cc.Texture2D(); // TTF texture in web will blend with canvas or body background color - if (!CC_JSB) { + if (!CC_JSB && !CC_RUNTIME) { this._ttfTexture.setPremultiplyAlpha(true); } this._assemblerData = this._assembler._getAssemblerData(); diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index 48041b6f7b0..ab963ac5274 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -777,7 +777,7 @@ let ScrollView = cc.Class({ let deltaMove = cc.v2(0, 0); let wheelPrecision = -0.1; - if(CC_JSB) { + if(CC_JSB || CC_RUNTIME) { wheelPrecision = -7; } if(this.vertical) { diff --git a/cocos2d/core/load-pipeline/uuid-loader.js b/cocos2d/core/load-pipeline/uuid-loader.js index df7b7f2186c..289f5d2078d 100644 --- a/cocos2d/core/load-pipeline/uuid-loader.js +++ b/cocos2d/core/load-pipeline/uuid-loader.js @@ -269,7 +269,7 @@ function loadUuid (item, callback) { } catch (e) { cc.deserialize.Details.pool.put(tdInfo); - var err = CC_JSB ? (e + '\n' + e.stack) : e.stack; + var err = CC_JSB || CC_RUNTIME ? (e + '\n' + e.stack) : e.stack; return new Error(debug.getError(4925, item.id, err)); } diff --git a/cocos2d/core/platform/CCInputExtension.js b/cocos2d/core/platform/CCInputExtension.js index 1c71067ca77..73d24fb454b 100644 --- a/cocos2d/core/platform/CCInputExtension.js +++ b/cocos2d/core/platform/CCInputExtension.js @@ -74,7 +74,7 @@ inputManager.setAccelerometerEnabled = function (isEnable) { scheduler.unscheduleUpdate(_t); } - if (CC_JSB) { + if (CC_JSB || CC_RUNTIME) { jsb.device.setMotionEnabled(isEnable); } }; @@ -88,7 +88,7 @@ inputManager.setAccelerometerInterval = function (interval) { if (this._accelInterval !== interval) { this._accelInterval = interval; - if (CC_JSB) { + if (CC_JSB || CC_RUNTIME) { jsb.device.setMotionInterval(interval); } } diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index c2bb0178811..152e87964dc 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -566,14 +566,14 @@ function initSys () { * Is native ? This is set to be true in jsb auto. * @property {Boolean} isNative */ - sys.isNative = CC_JSB; + sys.isNative = CC_JSB || CC_RUNTIME; /** * Is web browser ? * @property {Boolean} isBrowser */ - sys.isBrowser = typeof window === 'object' && typeof document === 'object' && !CC_WECHATGAME && !CC_QQPLAY && !CC_JSB && !isBaiduGame; + sys.isBrowser = typeof window === 'object' && typeof document === 'object' && !CC_WECHATGAME && !CC_QQPLAY && !CC_JSB && !CC_RUNTIME && !isBaiduGame; if (CC_EDITOR && Editor.isMainProcess) { sys.isMobile = false; @@ -593,7 +593,7 @@ function initSys () { }; sys.__audioSupport = {}; } - else if (CC_JSB) { + else if (CC_JSB || CC_RUNTIME) { let platform; if (isVivoGame) { platform = sys.VIVO_GAME; @@ -616,7 +616,10 @@ function initSys () { sys.os = __getOS(); sys.language = __getCurrentLanguage(); - var languageCode = __getCurrentLanguageCode(); + var languageCode; + if (CC_JSB) { + languageCode = __getCurrentLanguageCode(); + } sys.languageCode = languageCode ? languageCode.toLowerCase() : undefined; sys.osVersion = __getOSVersion(); sys.osMainVersion = parseInt(sys.osVersion); @@ -1239,7 +1242,7 @@ function initSys () { * @param {String} url */ sys.openURL = function (url) { - if (CC_JSB) { + if (CC_JSB || CC_RUNTIME) { jsb.openURL(url); } else { diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 37b23b2fe1d..86fe571b176 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -412,7 +412,7 @@ cc.js.mixin(View.prototype, { }, _adjustViewportMeta: function () { - if (this._isAdjustViewport && !CC_JSB && !CC_WECHATGAME && !CC_QQPLAY && !isBaiduGame) { + if (this._isAdjustViewport && !CC_JSB && !CC_RUNTIME && !CC_WECHATGAME && !CC_QQPLAY && !isBaiduGame) { this._setViewportMeta(__BrowserGetter.meta, false); this._isAdjustViewport = false; } @@ -813,7 +813,7 @@ cc.js.mixin(View.prototype, { * @param {ResolutionPolicy|Number} resolutionPolicy The resolution policy desired */ setRealPixelResolution: function (width, height, resolutionPolicy) { - if (!CC_JSB && !CC_WECHATGAME && !CC_QQPLAY && !isBaiduGame) { + if (!CC_JSB && !CC_RUNTIME && !CC_WECHATGAME && !CC_QQPLAY && !isBaiduGame) { // Set viewport's width this._setViewportMeta({"width": width}, true); diff --git a/cocos2d/core/platform/deserialize.js b/cocos2d/core/platform/deserialize.js index a3f90a403b1..ec62b32a68e 100644 --- a/cocos2d/core/platform/deserialize.js +++ b/cocos2d/core/platform/deserialize.js @@ -497,7 +497,7 @@ var _Deserializer = (function () { } sources.push('prop=d' + accessorToGet + ';'); - sources.push(`if(typeof ${CC_JSB ? '(prop)' : 'prop'}!=="undefined"){`); + sources.push(`if(typeof ${CC_JSB || CC_RUNTIME ? '(prop)' : 'prop'}!=="undefined"){`); var stillUseUrl = attrs[propName + SAVE_URL_AS_ASSET]; // function undefined object(null) string boolean number @@ -526,7 +526,7 @@ var _Deserializer = (function () { } } else { - sources.push(`if(typeof ${CC_JSB ? '(prop)' : 'prop'}!=="object"){` + + sources.push(`if(typeof ${CC_JSB || CC_RUNTIME ? '(prop)' : 'prop'}!=="object"){` + 'o' + accessorToSet + '=prop;' + '}else{'); compileObjectTypeJit(sources, defaultValue, accessorToSet, propNameLiteralToSet, false, stillUseUrl); diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index 0836bfccad1..25c938bacc7 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -311,4 +311,79 @@ exports.buildJsbMin = function (sourceFile, outputFile, excludes, opt_macroFlags .on('end', callback); }; +exports.buildRuntime = function (sourceFile, outputFile, excludes, opt_macroFlags, callback, createMap) { + if (typeof opt_macroFlags === 'function') { + callback = opt_macroFlags; + opt_macroFlags = null; + } + + var opts = { + sourcemaps: createMap !== false + }; + if (opt_macroFlags && opt_macroFlags.nativeRenderer) { + opts.aliasifyConfig = jsbAliasify; + } + + var FixJavaScriptCore = require('../util/fix-jsb-javascriptcore'); + + var outFile = Path.basename(outputFile); + var outDir = Path.dirname(outputFile); + + var bundler = createBundler(sourceFile, opts); + excludes.forEach(function (module) { + bundler.exclude(require.resolve(module)); + }); + bundler.bundle() + .on('error', HandleErrors.handler) + .pipe(HandleErrors()) + .pipe(Source(outFile)) + .pipe(Buffer()) + .pipe(FixJavaScriptCore()) + .pipe(Utils.uglify('build', Object.assign({ jsb: false, runtime: true, debug: true }, opt_macroFlags))) + .pipe(Optimizejs({ + sourceMap: false + })) + .pipe(Gulp.dest(outDir)) + .on('end', callback); +}; + +exports.buildRuntimeMin = function (sourceFile, outputFile, excludes, opt_macroFlags, callback, createMap) { + if (typeof opt_macroFlags === 'function') { + callback = opt_macroFlags; + opt_macroFlags = null; + } + + var opts = { + sourcemaps: createMap !== false + }; + if (opt_macroFlags && opt_macroFlags.nativeRenderer) { + opts.aliasifyConfig = jsbAliasify; + } + + var FixJavaScriptCore = require('../util/fix-jsb-javascriptcore'); + + var outFile = Path.basename(outputFile); + var outDir = Path.dirname(outputFile); + + var bundler = createBundler(sourceFile, opts); + excludes.forEach(function (module) { + bundler.exclude(require.resolve(module)); + }); + + bundler.exclude(Path.resolve(__dirname, '../../DebugInfos.json')); + + bundler.bundle() + .on('error', HandleErrors.handler) + .pipe(HandleErrors()) + .pipe(Source(outFile)) + .pipe(Buffer()) + .pipe(FixJavaScriptCore()) + .pipe(Utils.uglify('build', Object.assign({ jsb: false, runtime: true }, opt_macroFlags))) + .pipe(Optimizejs({ + sourceMap: false + })) + .pipe(Gulp.dest(outDir)) + .on('end', callback); +}; + exports.jsbSkipModules = jsbSkipModules; diff --git a/polyfill/misc.js b/polyfill/misc.js index 6072ba33e5f..f801fee8fbf 100644 --- a/polyfill/misc.js +++ b/polyfill/misc.js @@ -14,7 +14,7 @@ if (!Number.isInteger) { }; } -if (CC_JSB || !console.time) { +if (CC_JSB || CC_RUNTIME || !console.time) { var Timer = window.performance || Date; var _timerTable = Object.create(null); console.time = function (label) { diff --git a/predefine.js b/predefine.js index 842db989e2c..970ec54f507 100644 --- a/predefine.js +++ b/predefine.js @@ -160,11 +160,11 @@ else { defineMacro('CC_PREVIEW', !CC_EDITOR); defineMacro('CC_DEV', true); // (CC_EDITOR && !CC_BUILD) || CC_PREVIEW || CC_TEST defineMacro('CC_DEBUG', true); // CC_DEV || Debug Build - defineMacro('CC_JSB', defined('jsb')); + defineMacro('CC_RUNTIME', 'function' === typeof loadRuntime); + defineMacro('CC_JSB', defined('jsb') && !CC_RUNTIME); defineMacro('CC_WECHATGAMESUB', !!(defined('wx') && wx.getSharedCanvas)); defineMacro('CC_WECHATGAME', !!(defined('wx') && (wx.getSystemInfoSync || wx.getSharedCanvas))); defineMacro('CC_QQPLAY', defined('bk')); - defineMacro('CC_RUNTIME', 'function' === typeof loadRuntime); defineMacro('CC_SUPPORT_JIT', !(CC_WECHATGAME || CC_QQPLAY || CC_RUNTIME)); } From af4c92b4bb9c45f13fb59fe6fb8501b92c9407cb Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 27 Dec 2018 15:30:43 +0800 Subject: [PATCH 0351/1631] Revert "Support switch 2D/3D edit mode (#3266)" This reverts commit fdd1590d69abcd4bb1eacc120a7d29f788c3f64c. --- cocos2d/core/CCNode.js | 5 --- cocos2d/core/CCPrivateNode.js | 5 --- cocos2d/core/renderer/index.js | 42 +++++++++++++++++++- cocos2d/core/renderer/webgl/model-batcher.js | 4 +- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 265648c3a18..28597a60ce5 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1126,11 +1126,6 @@ let NodeDefines = { } } }, - - showInEditor: { - default: true, - editorOnly: true - } }, /** diff --git a/cocos2d/core/CCPrivateNode.js b/cocos2d/core/CCPrivateNode.js index db9705c1b8b..c69ebabd85b 100644 --- a/cocos2d/core/CCPrivateNode.js +++ b/cocos2d/core/CCPrivateNode.js @@ -98,11 +98,6 @@ let PrivateNode = cc.Class({ }, override: true }, - showInEditor: { - default: false, - editorOnly: true, - override: true - } }, /** diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 3088adba78c..340a526d39b 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -25,6 +25,8 @@ const renderEngine = require('./render-engine'); +let _pos = math.vec3.create(); + function _initBuiltins(device) { let defaultTexture = new renderEngine.Texture2D(device, { images: [], @@ -115,7 +117,31 @@ cc.renderer = module.exports = { else { this.device = new renderEngine.Device(canvas, opts); this.scene = new renderEngine.Scene(); - + + + if (CC_EDITOR) { + this._cameraNode = new cc.Node(); + + this._camera = new renderEngine.Camera(); + this._camera.setColor(0, 0, 0, 1); + this._camera.setFov(Math.PI * 60 / 180); + this._camera.setNear(0.1); + this._camera.setFar(1024); + this._camera.setNode(this._cameraNode); + + let view = new renderEngine.View(); + this._camera.view = view; + this._camera.dirty = true; + + if (CC_EDITOR) { + this._camera.setColor(0, 0, 0, 0); + } + this._camera.setStages([ + 'transparent' + ]); + this.scene.addCamera(this._camera); + } + let builtins = _initBuiltins(this.device); this._forward = new renderEngine.ForwardRenderer(this.device, builtins); this._handle = new ModelBatcher(this.device, this.scene); @@ -160,6 +186,20 @@ cc.renderer = module.exports = { this._camera.tx = vp.x; this._camera.ty = vp.y + vp.height; } + else if (CC_EDITOR && this.canvas) { + let canvas = this.canvas; + let scaleX = cc.view.getScaleX(); + let scaleY = cc.view.getScaleY(); + + let node = this._cameraNode; + _pos.x = node.x = canvas.width / scaleX / 2; + _pos.y = node.y = canvas.height / scaleY / 2; + _pos.z = 0; + + node.z = canvas.height / scaleY / 1.1566; + node.lookAt(_pos); + this._camera.dirty = true; + } }, render (ecScene) { diff --git a/cocos2d/core/renderer/webgl/model-batcher.js b/cocos2d/core/renderer/webgl/model-batcher.js index 0c5d141b558..c9e035fdcb5 100644 --- a/cocos2d/core/renderer/webgl/model-batcher.js +++ b/cocos2d/core/renderer/webgl/model-batcher.js @@ -140,7 +140,7 @@ ModelBatcher.prototype = { let model = this._modelPool.add(); this._batchedModels.push(model); model.sortKey = this._sortKey++; - model._cullingMask = this.cullingMask; + model._cullingMask = CC_EDITOR ? 1 : this.cullingMask; model.setNode(this.node); model.addEffect(effect); model.addInputAssembler(ia); @@ -168,7 +168,7 @@ ModelBatcher.prototype = { let model = this._modelPool.add(); this._batchedModels.push(model); model.sortKey = this._sortKey++; - model._cullingMask = this.cullingMask; + model._cullingMask = CC_EDITOR ? 1 : this.cullingMask; model.setNode(this.node); model.addEffect(effect); model.addInputAssembler(iaRenderData.ia); From 6543c160bbfcf7f3542e152d26ee48b76bccfdaf Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 27 Dec 2018 15:45:21 +0800 Subject: [PATCH 0352/1631] Fix issues on v2.1.0 --- cocos2d/core/CCNode.js | 8 ++++---- cocos2d/core/renderer/index.js | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 28597a60ce5..7aac500579a 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -2633,10 +2633,10 @@ let NodeDefines = { * @param {Vec3} [up] - default is (0,1,0) */ lookAt (pos, up) { - this.getWorldPosition(_vec3_temp); - math.vec3.sub(_vec3_temp, _vec3_temp, pos); // NOTE: we use -z for view-dir - math.vec3.normalize(_vec3_temp, _vec3_temp); - math.quat.fromViewUp(_quat_temp, _vec3_temp, up); + this.getWorldPosition(_v3a); + math.vec3.sub(_v3a, _v3a, pos); // NOTE: we use -z for view-dir + math.vec3.normalize(_v3a, _v3a); + math.quat.fromViewUp(_quat_temp, _v3a, up); this.setWorldRotation(_quat_temp); }, diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 340a526d39b..ede21deeb06 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -24,6 +24,7 @@ ****************************************************************************/ const renderEngine = require('./render-engine'); +const math = renderEngine.math; let _pos = math.vec3.create(); @@ -133,9 +134,7 @@ cc.renderer = module.exports = { this._camera.view = view; this._camera.dirty = true; - if (CC_EDITOR) { - this._camera.setColor(0, 0, 0, 0); - } + this._camera.setColor(0, 0, 0, 0); this._camera.setStages([ 'transparent' ]); From 32ed23b5e3892bf34b8373f96c09c769c6664c29 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 27 Dec 2018 16:54:34 +0800 Subject: [PATCH 0353/1631] Fix sharing _trs between prefab instance issue --- cocos2d/core/platform/instantiate.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cocos2d/core/platform/instantiate.js b/cocos2d/core/platform/instantiate.js index 5fbe719c262..851882e5cc5 100644 --- a/cocos2d/core/platform/instantiate.js +++ b/cocos2d/core/platform/instantiate.js @@ -228,6 +228,15 @@ function instantiateObj (obj, parent) { return obj; } var clone; + if (ArrayBuffer.isView(obj)) { + clone = new (obj.constructor)(obj.length); + obj._iN$t = clone; + for (var i = 0; i < len; ++i) { + clone[i] = obj[i]; + } + objsToClearTmpVar.push(obj); + return clone; + } if (Array.isArray(obj)) { var len = obj.length; clone = new Array(len); From 2c94ef0eeab06bb5000cd9550bcae396f55381b9 Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 27 Dec 2018 16:57:44 +0800 Subject: [PATCH 0354/1631] update audio state onEnded (#3686) --- cocos2d/audio/CCAudio.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cocos2d/audio/CCAudio.js b/cocos2d/audio/CCAudio.js index 68845a4a536..734086efcbc 100644 --- a/cocos2d/audio/CCAudio.js +++ b/cocos2d/audio/CCAudio.js @@ -48,6 +48,7 @@ let Audio = function (src) { this._state = Audio.State.INITIALZING; this._onended = function () { + this._state = Audio.State.STOPPED; this.emit('ended'); }.bind(this); }; @@ -236,6 +237,8 @@ Audio.State = { } if (!(CC_QQPLAY || CC_WECHATGAME)) { + // setCurrentTime would fire 'ended' event + // so we need to change the callback to rebind ended callback after setCurrentTime this._unbindEnded(); this._bindEnded(function () { this._bindEnded(); @@ -265,9 +268,11 @@ Audio.State = { proto.getState = function () { if (!CC_WECHATGAME && !CC_QQPLAY) { + // HACK: in some browser, audio may not fire 'ended' event + // so we need to force updating the Audio state let elem = this._element; if (elem && Audio.State.PLAYING === this._state && elem.paused) { - this._state = Audio.State.PAUSED; + this._state = Audio.State.STOPPED; } } return this._state; From c7fcb1787a4bc2f1894ec1fa3d34795cbc20c0a4 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 27 Dec 2018 19:50:07 +0800 Subject: [PATCH 0355/1631] Fix instantiateObj for TypedArray --- cocos2d/core/platform/instantiate.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/platform/instantiate.js b/cocos2d/core/platform/instantiate.js index 851882e5cc5..0a910486165 100644 --- a/cocos2d/core/platform/instantiate.js +++ b/cocos2d/core/platform/instantiate.js @@ -229,7 +229,8 @@ function instantiateObj (obj, parent) { } var clone; if (ArrayBuffer.isView(obj)) { - clone = new (obj.constructor)(obj.length); + var len = obj.length; + clone = new (obj.constructor)(len); obj._iN$t = clone; for (var i = 0; i < len; ++i) { clone[i] = obj[i]; From 847eb0cd2ad0a0318673d642470ccde0fdbc4061 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 27 Dec 2018 20:46:53 +0800 Subject: [PATCH 0356/1631] Fix destroyed _renderData still kept by Label issue in Editor --- cocos2d/core/components/CCRenderComponent.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index a5ec5728013..03fb8529cb8 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -148,6 +148,7 @@ let RenderComponent = cc.Class({ RenderData.free(this.__allocedDatas[i]); } this.__allocedDatas.length = 0; + this._renderData = null; this._material = null; }, From 0049be8e7f8eaae2beb7afd0fc7a31498b17917c Mon Sep 17 00:00:00 2001 From: caryliu Date: Fri, 28 Dec 2018 00:14:52 +0800 Subject: [PATCH 0357/1631] Add node opacity processing. --- cocos2d/core/CCNode.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 7aac500579a..cdcce549316 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -942,6 +942,9 @@ let NodeDefines = { set (value) { if (this._opacity !== value) { this._opacity = value; + if (CC_JSB && CC_NATIVERENDERER) { + this._proxy.updateOpacity(); + }; this._renderFlag |= RenderFlow.FLAG_OPACITY | RenderFlow.FLAG_COLOR; } }, @@ -1163,6 +1166,7 @@ let NodeDefines = { if (CC_JSB && CC_NATIVERENDERER) { this._proxy = new renderer.NodeProxy(); this._proxy.bind(this); + this._proxy.updateOpacity(); } }, @@ -1421,6 +1425,7 @@ let NodeDefines = { this._proxy.setName(this._name); this._parent && this._proxy.updateParent(this._parent._proxy); this._proxy.updateJSTRS(this._trs); + this._proxy.updateOpacity(); } }, From 2bedef162dd146ab13eff5cc780ae1edffa654cf Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 28 Dec 2018 12:08:40 +0800 Subject: [PATCH 0358/1631] Tiny improvements --- cocos2d/core/components/CCLabel.js | 4 ++-- cocos2d/core/components/CCSprite.js | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 8d26fc1f75f..81475a83a3d 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -496,6 +496,7 @@ let Label = cc.Class({ _on3DNodeChanged () { this._updateAssembler(); + this.markForUpdateRenderData(true); }, _updateAssembler () { @@ -509,7 +510,6 @@ let Label = cc.Class({ if (!this._renderData) { this._renderData = this._assembler.createData(this); this._renderData.material = this._material; - this.markForUpdateRenderData(true); } if (CC_JSB && CC_NATIVERENDERER) { @@ -616,9 +616,9 @@ let Label = cc.Class({ _forceUpdateRenderData () { this.setVertsDirty(); - this.markForUpdateRenderData(true); this._updateAssembler(); this._applyFontTexture(true); + this.markForUpdateRenderData(true); }, _enableBold (enabled) { diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 5bb83bd5eca..1c97ae2137d 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -461,10 +461,6 @@ var Sprite = cc.Class({ this._updateAssembler(); }, - _on3DNodeChanged () { - this._updateAssembler(); - }, - _updateAssembler: function () { let assembler = Sprite._assembler.getAssembler(this); From 8295f20c394c339b1c83f531faf14f4741cc6863 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 28 Dec 2018 17:06:05 +0800 Subject: [PATCH 0359/1631] fix mask no spriteframe alway reprot error (#3691) --- cocos2d/core/components/CCMask.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index d215e221ff6..4e7c0425686 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -265,6 +265,9 @@ let Mask = cc.Class({ if (this._type !== MaskType.IMAGE_STENCIL) { this._updateGraphics(); } + else { + this._applySpriteFrame(); + } }, onEnable () { @@ -345,6 +348,9 @@ let Mask = cc.Class({ spriteFrame.ensureLoadTexture(); } } + else { + this.disableRender(); + } }, _activateMaterial () { From a944f4df27d402923f17277d353f50e447954348 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 28 Dec 2018 23:50:31 +0800 Subject: [PATCH 0360/1631] Fix sprite frame not changing issue --- cocos2d/core/components/CCSprite.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 1c97ae2137d..d84af4b5bc7 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -567,6 +567,7 @@ var Sprite = cc.Class({ this.node.setContentSize(rect.width, rect.height); } + this.setVertsDirty(); this._activateMaterial(); } }, From 7806d7aa5c78296342b869dd421c59565fc5b9a0 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Sat, 29 Dec 2018 13:54:06 +0800 Subject: [PATCH 0361/1631] Fix Matrix issue for 2d node --- cocos2d/core/CCNode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index cdcce549316..27a45de9a66 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1333,7 +1333,7 @@ let NodeDefines = { if (this._position !== undefined) { trs[1] = this._position.x; trs[2] = this._position.y; - trs[3] = this._position.z; + trs[3] = this._position.z || 0; this._position = undefined; } From 5af2d48cdcd6e43fd71907e5300749a341af8a32 Mon Sep 17 00:00:00 2001 From: Knox Date: Sat, 29 Dec 2018 16:01:24 +0800 Subject: [PATCH 0362/1631] refine fullScreen code and fix videoPlayer exitFullScreen error (#3695) --- cocos2d/core/platform/CCScreen.js | 8 +++++--- cocos2d/videoplayer/video-player-impl.js | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/platform/CCScreen.js b/cocos2d/core/platform/CCScreen.js index 99cc2d8eacc..610c9ee71d9 100644 --- a/cocos2d/core/platform/CCScreen.js +++ b/cocos2d/core/platform/CCScreen.js @@ -102,11 +102,13 @@ cc.screen = /** @lends cc.screen# */{ * @returns {Boolean} */ fullScreen: function () { - if(!this._supportsFullScreen) return false; - else if( document[this._fn.fullscreenElement] === undefined || document[this._fn.fullscreenElement] === null ) + if (!this._supportsFullScreen) return false; + else if (!document[this._fn.fullscreenElement] && !document[this._fn.webkitFullscreenElement] && !document[this._fn.mozFullScreenElement]) { return false; - else + } + else { return true; + } }, /** diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 58e8b320310..437c5820559 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -79,7 +79,7 @@ let VideoPlayerImpl = cc.Class({ if (self._fullScreenEnabled) { cc.screen.requestFullScreen(video); } - else { + else if (cc.screen.fullScreen()) { cc.screen.exitFullScreen(video); } self._dispatchEvent(VideoPlayerImpl.EventType.META_LOADED); @@ -368,7 +368,7 @@ let VideoPlayerImpl = cc.Class({ if (enable) { cc.screen.requestFullScreen(video); } - else { + else if (cc.screen.fullScreen()) { cc.screen.exitFullScreen(video); } }, From e1fc76632f698ecafc55c4633b142fc4dc7e2ef7 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 2 Jan 2019 00:22:29 +0800 Subject: [PATCH 0363/1631] Fix unsuitable textures being packed into atlas manager issue (#3698) * fixed the atlas texture make premultiply effect error in the native problem * Improve code --- cocos2d/core/assets/CCTexture2D.js | 24 ++++++++++++++++++- .../renderer/utils/dynamic-atlas/atlas.js | 6 ++++- .../renderer/utils/dynamic-atlas/manager.js | 7 +++--- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 606853006b6..a9409d8cce3 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -228,7 +228,7 @@ var Texture2D = cc.Class({ _minFilter: Filter.LINEAR, _magFilter: Filter.LINEAR, _wrapS: WrapMode.CLAMP_TO_EDGE, - _wrapT: WrapMode.CLAMP_TO_EDGE + _wrapT: WrapMode.CLAMP_TO_EDGE, }, statics: { @@ -285,6 +285,8 @@ var Texture2D = cc.Class({ */ this.height = 0; + this._hashDirty = true; + this._hash = 0; this._texture = null; }, @@ -378,6 +380,8 @@ var Texture2D = cc.Class({ if (options.images && options.images.length > 0) { this._texture.update(options); } + + this._hashDirty = true; } }, @@ -713,6 +717,24 @@ var Texture2D = cc.Class({ // decode premultiply alpha this._premultiplyAlpha = fields[5].charCodeAt(0) === CHAR_CODE_1; } + }, + + _getHash () { + if (!this._hashDirty) { + return this._hash; + } + let hasMipmap = this._hasMipmap ? 1 : 0; + let premultiplyAlpha = this._premultiplyAlpha ? 1 : 0; + let flipY = this._flipY ? 1 : 0; + let minFilter = this._minFilter === Filter.LINEAR ? 1 : 2; + let magFilter = this._magFilter === Filter.LINEAR ? 1 : 2; + let wrapS = this._wrapS === WrapMode.REPEAT ? 1 : (this._wrapS === WrapMode.CLAMP_TO_EDGE ? 2 : 3); + let wrapT = this._wrapT === WrapMode.REPEAT ? 1 : (this._wrapT === WrapMode.CLAMP_TO_EDGE ? 2 : 3); + let pixelFormat = this._format; + + this._hash = parseInt(`${minFilter}${magFilter}${pixelFormat}${wrapS}${wrapT}${hasMipmap}${premultiplyAlpha}${flipY}`); + this._hashDirty = false; + return this._hash; } }); diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js b/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js index 8c93a3b67f7..84369f14606 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/atlas.js @@ -1,7 +1,9 @@ +const RenderTexture = require('../../../assets/CCRenderTexture'); + const space = 2; function Atlas (width, height) { - let texture = new cc.RenderTexture(); + let texture = new RenderTexture(); texture.initWithSize(width, height); texture.update(); @@ -18,6 +20,8 @@ function Atlas (width, height) { this._innerSpriteFrames = []; } +Atlas.DEFAULT_HASH = (new RenderTexture())._getHash(); + cc.js.mixin(Atlas.prototype, { insertSpriteFrame (spriteFrame) { let rect = spriteFrame._rect, diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js index 34531252796..2d8e90b9b0d 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js @@ -106,14 +106,13 @@ let dynamicAtlasManager = { if (CC_EDITOR) return null; if (!_enabled || _atlasIndex === _maxAtlasCount || !spriteFrame || spriteFrame._original) return null; - + let texture = spriteFrame._texture; if (texture instanceof cc.RenderTexture) return null; let w = texture.width, h = texture.height; - let min = texture._minFilter, mag = texture._magFilter; - let LINEAR = cc.Texture2D.Filter.LINEAR; - if (w > _maxFrameSize || h > _maxFrameSize || w <= _minFrameSize || h <= _minFrameSize || (min & mag) !== LINEAR) { + if (w > _maxFrameSize || h > _maxFrameSize || w <= _minFrameSize || h <= _minFrameSize + || texture._getHash() !== Atlas.DEFAULT_HASH) { return null; } From b4a4fe8585e800aae36ad1913ad52d3528464025 Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 2 Jan 2019 16:17:03 +0800 Subject: [PATCH 0364/1631] move __modular run to CCGame _prepareFinished for 2d-tasks/issues/981 (#3699) --- cocos2d/core/CCGame.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 7e33ff1e98b..79074ea13dd 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -385,6 +385,11 @@ var game = { }, _prepareFinished (cb) { + + if (CC_PREVIEW && window.__modular) { + window.__modular.run(); + } + this._prepared = true; // Init engine @@ -425,8 +430,9 @@ var game = { * on(type: string, callback: T, target?: any, useCapture?: boolean): T */ on (type, callback, target) { - // Make sure EVENT_ENGINE_INITED callbacks to be invoked - if (this._prepared && type === this.EVENT_ENGINE_INITED) { + // Make sure EVENT_ENGINE_INITED and EVENT_GAME_INITED callbacks to be invoked + if ((this._prepared && type === this.EVENT_ENGINE_INITED) || + (!this._pause && type === this.EVENT_GAME_INITED)) { callback.call(target); } else { @@ -452,8 +458,9 @@ var game = { * @param {Object} [target] - The target (this object) to invoke the callback, can be null */ once (type, callback, target) { - // Make sure EVENT_ENGINE_INITED callbacks to be invoked - if (this._prepared && type === this.EVENT_ENGINE_INITED) { + // Make sure EVENT_ENGINE_INITED and EVENT_GAME_INITED callbacks to be invoked + if ((this._prepared && type === this.EVENT_ENGINE_INITED) || + (!this._pause && type === this.EVENT_GAME_INITED)) { callback.call(target); } else { From b2bd1208ec22a984c327924d0a00d7d925c765ec Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 2 Jan 2019 16:34:10 +0800 Subject: [PATCH 0365/1631] Master move renderer.js (#3616) * remove render-engine.js * add renderer.js stuff * add build shader logic * add vmath * fixed renderEngine dependency * fixed setImage * fixed issues * add light component * refine render pipeline * refine render pipeline * optimize forward-renderer for when has no lights * update chunks * small fix * add chunks * fixed test * fixed init render texture * refine cc.MeshRenderer.ShadowCastingMode define * add modules * should not only copy value to the color of the out value * execute camera in editor but not add to scene * refine code * add shader-config for MeshRenderer * compute hash for shader config * add render engine to deprecated * fixed label color * refine code * fixed rendertexture * extract uniforms in model * add custom properties * support resize render texture * refine code * should update material when mesh change vertex format * fixed quat usage * upgrade shdc-lib * refine Effect.parseForInspector * parse default stages * sync 3d engine effect * disable tiled map culling in editor * remove useModel in assemblers * fixed some issues * add renderStages for camera --- cocos2d/core/3d/CCLightComponent.js | 449 + cocos2d/core/3d/CCModel.js | 12 +- cocos2d/core/3d/CCSkeletonAnimation.js | 1 - cocos2d/core/3d/CCSkinnedMeshRenderer.js | 25 +- cocos2d/core/3d/geom-utils/intersect.js | 9 +- cocos2d/core/3d/geom-utils/ray.js | 4 +- cocos2d/core/3d/index.js | 1 + cocos2d/core/3d/polyfill-3d.js | 11 +- cocos2d/core/CCNode.js | 137 +- cocos2d/core/CCPrivateNode.js | 3 - cocos2d/core/assets/CCEffectAsset.js | 5 +- cocos2d/core/assets/CCRenderTexture.js | 56 +- cocos2d/core/assets/CCTexture2D.js | 38 +- cocos2d/core/assets/index.js | 2 +- .../core/assets/{ => material}/CCMaterial.js | 79 +- .../core/assets/material/custom-properties.js | 62 + .../{utils => material}/murmurhash2_gc.js | 0 cocos2d/core/assets/material/utils.js | 113 + cocos2d/core/assets/utils/compute-hash.js | 111 - cocos2d/core/camera/CCCamera.js | 62 +- cocos2d/core/components/CCLabel.js | 25 +- cocos2d/core/components/CCMask.js | 27 +- cocos2d/core/components/CCMotionStreak.js | 4 +- cocos2d/core/components/CCRenderComponent.js | 58 +- cocos2d/core/components/CCSprite.js | 8 +- cocos2d/core/graphics/graphics.js | 4 +- cocos2d/core/mesh/CCMesh.js | 13 +- cocos2d/core/mesh/CCMeshRenderer.js | 163 +- cocos2d/core/mesh/mesh-renderer.js | 26 +- cocos2d/core/renderer/canvas/Device.js | 86 + cocos2d/core/renderer/canvas/Texture2D.js | 41 + cocos2d/core/renderer/index.js | 50 +- cocos2d/core/renderer/render-engine.canvas.js | 8874 --------- cocos2d/core/renderer/render-engine.js | 14878 ---------------- cocos2d/core/renderer/render-engine.jsb.js | 10700 ----------- cocos2d/core/renderer/render-flow.js | 33 +- .../renderer/webgl/assemblers/assembler.js | 1 - .../webgl/assemblers/graphics/impl.js | 30 +- .../webgl/assemblers/graphics/index.js | 1 - .../webgl/assemblers/sprite/2d/bar-filled.js | 2 - .../webgl/assemblers/sprite/2d/mesh.js | 3 - .../assemblers/sprite/2d/radial-filled.js | 3 - .../webgl/assemblers/sprite/2d/simple.js | 4 - .../webgl/assemblers/sprite/2d/sliced.js | 3 - .../webgl/assemblers/sprite/2d/tiled.js | 3 - cocos2d/core/renderer/webgl/mesh-buffer.js | 28 +- cocos2d/core/renderer/webgl/model-batcher.js | 39 +- cocos2d/core/renderer/webgl/quad-buffer.js | 25 + .../core/renderer/webgl/stencil-manager.js | 11 +- cocos2d/core/renderer/webgl/vertex-format.js | 3 +- cocos2d/core/utils/math-pools.js | 20 +- cocos2d/core/utils/prefab-helper.js | 4 +- cocos2d/core/value-types/index.js | 3 +- cocos2d/core/value-types/mat4.js | 4 +- cocos2d/core/value-types/quat.js | 21 +- cocos2d/core/value-types/vec2.js | 5 +- cocos2d/core/value-types/vec3.js | 13 +- cocos2d/core/value-types/vec4.js | 504 + cocos2d/core/vmath/bits.js | 307 + cocos2d/core/vmath/color3.js | 283 + cocos2d/core/vmath/color4.js | 306 + cocos2d/core/vmath/index.js | 22 + cocos2d/core/vmath/mat2.js | 443 + cocos2d/core/vmath/mat23.js | 547 + cocos2d/core/vmath/mat3.js | 851 + cocos2d/core/vmath/mat4.js | 1729 ++ cocos2d/core/vmath/quat.js | 822 + cocos2d/core/vmath/utils.js | 217 + cocos2d/core/vmath/vec2.js | 691 + cocos2d/core/vmath/vec3.js | 927 + cocos2d/core/vmath/vec4.js | 715 + cocos2d/deprecated.js | 16 + cocos2d/particle/CCParticleSystem.js | 6 +- cocos2d/particle/particle-system-assembler.js | 11 +- cocos2d/renderer/build/build-chunks.js | 20 + cocos2d/renderer/build/build-mapping.js | 8 +- cocos2d/renderer/build/build-shader.js | 4 +- cocos2d/renderer/build/chunks/common.inc | 12 + .../build/chunks/gamma-correction.inc | 45 + cocos2d/renderer/build/chunks/index.js | 17 + cocos2d/renderer/build/chunks/packing.inc | 12 + cocos2d/renderer/build/chunks/pbr-fs.inc | 366 + cocos2d/renderer/build/chunks/pbr-vs.inc | 49 + cocos2d/renderer/build/chunks/phong-fs.inc | 305 + cocos2d/renderer/build/chunks/phong-vs.inc | 50 + .../renderer/build/chunks/rect-area-light.inc | 175 + .../renderer/build/chunks/shadow-depth-fs.inc | 14 + .../renderer/build/chunks/shadow-depth-vs.inc | 27 + .../renderer/build/chunks/shadow-mapping.inc | 85 + .../renderer/build/chunks/shadow-prepare.inc | 20 + cocos2d/renderer/build/chunks/skinning.inc | 61 + cocos2d/renderer/build/chunks/unlit-fs.inc | 29 + cocos2d/renderer/build/chunks/unlit-vs.inc | 40 + cocos2d/renderer/build/chunks/unpack.inc | 9 + .../renderer/{ => build}/mappings/index.js | 99 +- .../{ => build}/mappings/offline-mappings.js | 6 +- cocos2d/renderer/build/shdc-lib.js | 269 +- cocos2d/renderer/chunks/index.js | 3 - cocos2d/renderer/chunks/skinning.inc | 43 - cocos2d/renderer/config.js | 37 + cocos2d/renderer/core/base-renderer.js | 645 + cocos2d/renderer/core/constants.js | 13 + cocos2d/renderer/{ => core}/effect.js | 134 +- cocos2d/renderer/core/input-assembler.js | 31 + cocos2d/renderer/core/pass.js | 120 + cocos2d/renderer/core/program-lib.js | 210 + cocos2d/renderer/core/technique.js | 32 + cocos2d/renderer/core/view.js | 78 + cocos2d/renderer/enums.js | 49 + cocos2d/renderer/gfx/device.js | 1318 ++ cocos2d/renderer/{mappings => }/gfx/enums.js | 0 cocos2d/renderer/gfx/frame-buffer.js | 41 + cocos2d/renderer/gfx/index-buffer.js | 95 + cocos2d/renderer/gfx/index.js | 40 + cocos2d/renderer/gfx/misc.js | 3 + cocos2d/renderer/gfx/program.js | 176 + cocos2d/renderer/gfx/render-buffer.js | 43 + cocos2d/renderer/gfx/state.js | 133 + cocos2d/renderer/gfx/texture-2d.js | 327 + cocos2d/renderer/gfx/texture-cube.js | 338 + cocos2d/renderer/gfx/texture.js | 56 + cocos2d/renderer/gfx/vertex-buffer.js | 86 + cocos2d/renderer/gfx/vertex-format.js | 56 + cocos2d/renderer/mappings/enums.js | 50 - cocos2d/renderer/mappings/index.js.map | 1 - cocos2d/renderer/memop/circular-pool.js | 17 + cocos2d/renderer/memop/fixed-array.js | 73 + cocos2d/renderer/memop/index.js | 6 + cocos2d/renderer/memop/linked-array.js | 82 + cocos2d/renderer/memop/optimized-array.js | 187 + cocos2d/renderer/memop/pool.js | 45 + cocos2d/renderer/memop/recycle-pool.js | 57 + cocos2d/renderer/memop/sort.js | 166 + cocos2d/renderer/memop/timsort.js | 967 + cocos2d/renderer/memop/typed-array-pool.js | 129 + .../renderer/render-data/base-render-data.js | 14 + .../renderer/render-data/ia-render-data.js | 21 + cocos2d/renderer/render-data/render-data.js | 102 + .../renderer/renderers/forward-renderer.js | 255 + cocos2d/renderer/scene/camera.js | 466 + cocos2d/renderer/scene/light.js | 492 + cocos2d/renderer/scene/model.js | 104 + cocos2d/renderer/scene/scene.js | 192 + cocos2d/renderer/types.js | 60 + cocos2d/tilemap/CCTiledLayer.js | 6 +- cocos2d/tilemap/tmx-layer-assembler.js | 7 +- cocos2d/videoplayer/video-player-impl.js | 6 +- cocos2d/webview/webview-impl.js | 6 +- extensions/dragonbones/ArmatureDisplay.js | 5 +- extensions/dragonbones/CCSlot.js | 9 +- extensions/dragonbones/canvas-assembler.js | 9 +- extensions/dragonbones/webgl-assembler.js | 14 +- extensions/spine/Skeleton.js | 2 +- extensions/spine/spine-assembler.js | 20 +- gulp/tasks/engine.js | 4 +- gulp/util/create-bundler.js | 10 +- package.json | 5 +- 157 files changed, 18850 insertions(+), 35361 deletions(-) create mode 100644 cocos2d/core/3d/CCLightComponent.js rename cocos2d/core/assets/{ => material}/CCMaterial.js (68%) create mode 100644 cocos2d/core/assets/material/custom-properties.js rename cocos2d/core/assets/{utils => material}/murmurhash2_gc.js (100%) create mode 100644 cocos2d/core/assets/material/utils.js delete mode 100644 cocos2d/core/assets/utils/compute-hash.js create mode 100644 cocos2d/core/renderer/canvas/Device.js create mode 100644 cocos2d/core/renderer/canvas/Texture2D.js delete mode 100644 cocos2d/core/renderer/render-engine.canvas.js delete mode 100644 cocos2d/core/renderer/render-engine.js delete mode 100644 cocos2d/core/renderer/render-engine.jsb.js create mode 100644 cocos2d/core/value-types/vec4.js create mode 100644 cocos2d/core/vmath/bits.js create mode 100644 cocos2d/core/vmath/color3.js create mode 100644 cocos2d/core/vmath/color4.js create mode 100644 cocos2d/core/vmath/index.js create mode 100644 cocos2d/core/vmath/mat2.js create mode 100644 cocos2d/core/vmath/mat23.js create mode 100644 cocos2d/core/vmath/mat3.js create mode 100644 cocos2d/core/vmath/mat4.js create mode 100644 cocos2d/core/vmath/quat.js create mode 100644 cocos2d/core/vmath/utils.js create mode 100644 cocos2d/core/vmath/vec2.js create mode 100644 cocos2d/core/vmath/vec3.js create mode 100644 cocos2d/core/vmath/vec4.js create mode 100644 cocos2d/renderer/build/build-chunks.js create mode 100644 cocos2d/renderer/build/chunks/common.inc create mode 100644 cocos2d/renderer/build/chunks/gamma-correction.inc create mode 100644 cocos2d/renderer/build/chunks/index.js create mode 100644 cocos2d/renderer/build/chunks/packing.inc create mode 100644 cocos2d/renderer/build/chunks/pbr-fs.inc create mode 100644 cocos2d/renderer/build/chunks/pbr-vs.inc create mode 100644 cocos2d/renderer/build/chunks/phong-fs.inc create mode 100644 cocos2d/renderer/build/chunks/phong-vs.inc create mode 100644 cocos2d/renderer/build/chunks/rect-area-light.inc create mode 100644 cocos2d/renderer/build/chunks/shadow-depth-fs.inc create mode 100644 cocos2d/renderer/build/chunks/shadow-depth-vs.inc create mode 100644 cocos2d/renderer/build/chunks/shadow-mapping.inc create mode 100644 cocos2d/renderer/build/chunks/shadow-prepare.inc create mode 100644 cocos2d/renderer/build/chunks/skinning.inc create mode 100644 cocos2d/renderer/build/chunks/unlit-fs.inc create mode 100644 cocos2d/renderer/build/chunks/unlit-vs.inc create mode 100644 cocos2d/renderer/build/chunks/unpack.inc rename cocos2d/renderer/{ => build}/mappings/index.js (87%) rename cocos2d/renderer/{ => build}/mappings/offline-mappings.js (93%) delete mode 100644 cocos2d/renderer/chunks/index.js delete mode 100644 cocos2d/renderer/chunks/skinning.inc create mode 100644 cocos2d/renderer/config.js create mode 100644 cocos2d/renderer/core/base-renderer.js create mode 100644 cocos2d/renderer/core/constants.js rename cocos2d/renderer/{ => core}/effect.js (68%) create mode 100644 cocos2d/renderer/core/input-assembler.js create mode 100644 cocos2d/renderer/core/pass.js create mode 100644 cocos2d/renderer/core/program-lib.js create mode 100644 cocos2d/renderer/core/technique.js create mode 100644 cocos2d/renderer/core/view.js create mode 100644 cocos2d/renderer/enums.js create mode 100644 cocos2d/renderer/gfx/device.js rename cocos2d/renderer/{mappings => }/gfx/enums.js (100%) create mode 100644 cocos2d/renderer/gfx/frame-buffer.js create mode 100644 cocos2d/renderer/gfx/index-buffer.js create mode 100644 cocos2d/renderer/gfx/index.js create mode 100644 cocos2d/renderer/gfx/misc.js create mode 100644 cocos2d/renderer/gfx/program.js create mode 100644 cocos2d/renderer/gfx/render-buffer.js create mode 100644 cocos2d/renderer/gfx/state.js create mode 100644 cocos2d/renderer/gfx/texture-2d.js create mode 100644 cocos2d/renderer/gfx/texture-cube.js create mode 100644 cocos2d/renderer/gfx/texture.js create mode 100644 cocos2d/renderer/gfx/vertex-buffer.js create mode 100644 cocos2d/renderer/gfx/vertex-format.js delete mode 100644 cocos2d/renderer/mappings/enums.js delete mode 100644 cocos2d/renderer/mappings/index.js.map create mode 100644 cocos2d/renderer/memop/circular-pool.js create mode 100644 cocos2d/renderer/memop/fixed-array.js create mode 100644 cocos2d/renderer/memop/index.js create mode 100644 cocos2d/renderer/memop/linked-array.js create mode 100644 cocos2d/renderer/memop/optimized-array.js create mode 100644 cocos2d/renderer/memop/pool.js create mode 100644 cocos2d/renderer/memop/recycle-pool.js create mode 100644 cocos2d/renderer/memop/sort.js create mode 100644 cocos2d/renderer/memop/timsort.js create mode 100644 cocos2d/renderer/memop/typed-array-pool.js create mode 100644 cocos2d/renderer/render-data/base-render-data.js create mode 100644 cocos2d/renderer/render-data/ia-render-data.js create mode 100644 cocos2d/renderer/render-data/render-data.js create mode 100644 cocos2d/renderer/renderers/forward-renderer.js create mode 100644 cocos2d/renderer/scene/camera.js create mode 100644 cocos2d/renderer/scene/light.js create mode 100644 cocos2d/renderer/scene/model.js create mode 100644 cocos2d/renderer/scene/scene.js create mode 100644 cocos2d/renderer/types.js diff --git a/cocos2d/core/3d/CCLightComponent.js b/cocos2d/core/3d/CCLightComponent.js new file mode 100644 index 00000000000..e933ce3997d --- /dev/null +++ b/cocos2d/core/3d/CCLightComponent.js @@ -0,0 +1,449 @@ +/**************************************************************************** + Copyright (c) 2013-2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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. + ****************************************************************************/ +// @ts-check +import enums from '../../renderer/enums'; +import Light from '../../renderer/scene/light'; +import { Color } from '../value-types'; +import { toRadian } from '../vmath'; + +const renderer = require('../renderer/index'); +const Enum = require('../platform/CCEnum'); +const CCComponent = require('../components/CCComponent'); +const { ccclass, menu, property, executeInEditMode } = require('../platform/CCClassDecorator'); + +/** + * !#en The light source type + * + * !#ch 光源类型 + * @static + * @enum LightComponent.Type + */ +const LightType = Enum({ + /** + * !#en The direction of light + * + * !#ch 平行光 + * @property DIRECTIONAL + * @readonly + * @type {Number} + */ + DIRECTIONAL: 0, + /** + * !#en The point of light + * + * !#ch 点光源 + * @property POINT + * @readonly + * @type {Number} + */ + POINT: 1, + /** + * !#en The spot of light + * + * !#ch 聚光灯 + * @property SPOT + * @readonly + * @type {Number} + */ + SPOT: 2, +}); + +/** + * !#en The shadow type + * + * !#ch 阴影类型 + * @static + * @enum LightComponent.ShadowType + */ +const LightShadowType = Enum({ + /** + * !#en No shadows + * + * !#ch 阴影关闭 + * @property NONE + * @readonly + * @type {Number} + */ + NONE: 0, + /** + * !#en Soft shadows + * + * !#ch 软阴影 + * @property SOFT + * @readonly + * @type {Number} + */ + SOFT: 1, + /** + * !#en Hard shadows + * + * !#ch 阴硬影 + * @property HARD + * @readonly + * @type {Number} + */ + HARD: 2, +}); + +/** + * !#en The Light Component + * + * !#ch 光源组件 + * @class LightComponent + * @extends CCComponent + */ +@ccclass('cc.LightComponent') +@menu('i18n:MAIN_MENU.component.renderers/LightComponent') +@executeInEditMode +export default class LightComponent extends CCComponent { + @property + _type = LightType.DIRECTIONAL; + + @property + _color = Color.WHITE; + + @property + _intensity = 1; + + @property + _range = 1; + + @property + _spotAngle = 60; + + @property + _spotExp = 1; + + @property + _shadowType = LightShadowType.NONE; + + @property + _shadowResolution = 1024; + + @property + _shadowDarkness = 0.5; + + @property + _shadowMinDepth = 1; + + @property + _shadowMaxDepth = 1000; + + @property + _shadowDepthScale = 250; + + @property + _shadowFrustumSize = 50; + + @property + _shadowBias = 0.0005; + + /** + * !#en The light source type + * + * !#ch 光源类型 + * + * @type {Number} + */ + @property({ + type: LightType + }) + get type() { + return this._type; + } + + set type(val) { + this._type = val; + + let type = enums.LIGHT_DIRECTIONAL; + if (this._type === LightType.POINT) { + type = enums.LIGHT_POINT; + } else if (this._type === LightType.SPOT) { + type = enums.LIGHT_SPOT; + } + this._light.setType(type); + } + + /** + * !#en The light source color + * + * !#ch 光源颜色 + * @type {Color} + */ + @property + get color() { + return this._color; + } + + set color(val) { + this._color = val; + this._light.setColor(val.r / 255, val.g / 255, val.b / 255); + } + + /** + * !#en The light source intensity + * + * !#ch 光源强度 + * @type {Number} + */ + @property + get intensity() { + return this._intensity; + } + + set intensity(val) { + this._intensity = val; + this._light.setIntensity(val); + } + + /** + * !#en The light range, used for spot and point light + * + * !#ch 针对聚光灯和点光源设置光源范围 + * @type {Number} + */ + @property + get range() { + return this._range; + } + + set range(val) { + this._range = val; + this._light.setRange(val); + } + + /** + * !#en The spot light cone angle + * + * !#ch 聚光灯锥角 + * @type {Number} + */ + @property + get spotAngle() { + return this._spotAngle; + } + + set spotAngle(val) { + this._spotAngle = val; + this._light.setSpotAngle(toRadian(val)); + } + + /** + * !#en The spot light exponential + * + * !#ch 聚光灯指数 + * @type {Number} + */ + @property + get spotExp() { + return this._spotExp; + } + + set spotExp(val) { + this._spotExp = val; + this._light.setSpotExp(val); + } + + /** + * !#en The shadow type + * + * !#ch 阴影类型 + * @type {Number} shadowType + */ + @property({ + type: LightShadowType + }) + get shadowType() { + return this._shadowType; + } + + set shadowType(val) { + this._shadowType = val; + + let type = enums.SHADOW_NONE; + if (val === LightShadowType.HARD) { + type = enums.SHADOW_HARD; + } else if (val === LightShadowType.SOFT) { + type = enums.SHADOW_SOFT; + } + this._light.setShadowType(type); + } + + /** + * !#en The shadow resolution + * + * !#ch 阴影分辨率 + * + * @type {Number} + */ + @property + get shadowResolution() { + return this._shadowResolution; + } + + set shadowResolution(val) { + this._shadowResolution = val; + this._light.setShadowResolution(val); + } + + /** + * !#en The shadow darkness + * + * !#ch 阴影灰度值 + * + * @type {Number} + */ + @property + get shadowDarkness() { + return this._shadowDarkness; + } + + set shadowDarkness(val) { + this._shadowDarkness = val; + this._light.setShadowDarkness(val); + } + + /** + * !#en The shadow min depth + * + * !#ch 阴影最小深度 + * + * @type {Number} + */ + @property + get shadowMinDepth() { + return this._shadowMinDepth; + } + + set shadowMinDepth(val) { + this._shadowMinDepth = val; + this._light.setShadowMinDepth(val); + } + + /** + * !#en The shadow max depth + * + * !#ch 阴影最大深度 + * + * @type {Number} + */ + @property + get shadowMaxDepth() { + return this._shadowMaxDepth; + } + + set shadowMaxDepth(val) { + this._shadowMaxDepth = val; + this._light.setShadowMaxDepth(val); + } + + /** + * !#en The shadow depth scale + * + * !#ch 阴影深度比例 + * + * @type {Number} + */ + @property + get shadowDepthScale() { + return this._shadowDepthScale; + } + + set shadowDepthScale(val) { + this._shadowDepthScale = val; + this._light.setShadowDepthScale(val); + } + + /** + * !#en The shadow frustum size + * + * !#ch 阴影截锥体大小 + * + * @type {Number} + */ + @property + get shadowFrustumSize() { + return this._shadowFrustumSize; + } + + set shadowFrustumSize(val) { + this._shadowFrustumSize = val; + this._light.setShadowFrustumSize(val); + } + + /** + * !#en The shadow bias + * + * !#ch 阴影偏移量 + * + * @type {Number} + */ + @property + get shadowBias() { + return this._shadowBias; + } + + set shadowBias(val) { + this._shadowBias = val; + this._light.setShadowBias(val); + } + + static Type = LightType; + + static ShadowType = LightShadowType; + + constructor() { + super(); + + this._light = new Light(); + } + + onLoad() { + this._light.setNode(this.node); + this.type = this._type; + this.color = this._color; + this.intensity = this._intensity; + this.range = this._range; + this.spotAngle = this._spotAngle; + this.spotExp = this._spotExp; + this.shadowType = this._shadowType; + this.shadowResolution = this._shadowResolution; + this.shadowDarkness = this._shadowDarkness; + this.shadowMaxDepth = this._shadowMaxDepth; + this.shadowDepthScale = this._shadowDepthScale; + this.shadowFrustumSize = this._shadowFrustumSize; + this.shadowBias = this._shadowBias; + } + + onEnable() { + renderer.scene.addLight(this._light); + } + + onDisable() { + renderer.scene.removeLight(this._light); + } +} + +cc.LightComponent = LightComponent; diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index 0b827277d33..49616ffa788 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -24,11 +24,11 @@ ****************************************************************************/ const BufferAsset = require('../assets/CCBufferAsset'); - -const renderEngine = require('../renderer/render-engine'); const renderer = require('../renderer'); -const gfx = renderEngine.gfx; -const vec3 = cc.vmath.vec3; + +import gfx from '../../renderer/gfx'; +import InputAssembler from '../../renderer/core/input-assembler'; +import { vec3, mat4 } from '../../core/vmath'; const _type2size = { SCALAR: 1, @@ -119,7 +119,7 @@ let Model = cc.Class({ let bindposes = new Array(accessor.count); for (let i = 0; i < accessor.count; ++i) { - bindposes[i] = cc.vmath.mat4.new( + bindposes[i] = mat4.create( data[16 * i + 0], data[16 * i + 1], data[16 * i + 2], data[16 * i + 3], data[16 * i + 4], data[16 * i + 5], data[16 * i + 6], data[16 * i + 7], data[16 * i + 8], data[16 * i + 9], data[16 * i + 10], data[16 * i + 11], @@ -258,7 +258,7 @@ let Model = cc.Class({ maxPos.z = Math.max(maxPos.z, max[2]); } - meshAsset._subMeshes[i] = new renderEngine.InputAssembler(vb.buffer, ib.buffer); + meshAsset._subMeshes[i] = new InputAssembler(vb.buffer, ib.buffer); meshAsset._vbs[i] = vb; meshAsset._ibs[i] = ib; } diff --git a/cocos2d/core/3d/CCSkeletonAnimation.js b/cocos2d/core/3d/CCSkeletonAnimation.js index fed2e01fa0f..77ec7156618 100644 --- a/cocos2d/core/3d/CCSkeletonAnimation.js +++ b/cocos2d/core/3d/CCSkeletonAnimation.js @@ -26,7 +26,6 @@ const Animation = require('../components/CCAnimation'); const Model = require('./CCModel'); const SkeletonAnimationClip = require('./CCSkeletonAnimationClip'); -const AnimationClip = require('../../animation/animation-clip'); /** * @module cc diff --git a/cocos2d/core/3d/CCSkinnedMeshRenderer.js b/cocos2d/core/3d/CCSkinnedMeshRenderer.js index 7755806f8fa..5a911badcc5 100644 --- a/cocos2d/core/3d/CCSkinnedMeshRenderer.js +++ b/cocos2d/core/3d/CCSkinnedMeshRenderer.js @@ -25,7 +25,6 @@ const Skeleton = require('./CCSkeleton'); const MeshRenderer = require('../mesh/CCMeshRenderer'); -const renderEngine = require('../renderer/render-engine'); const mat4 = cc.vmath.mat4; let _m4_tmp = mat4.create(); @@ -76,22 +75,6 @@ let SkinnedMeshRenderer = cc.Class({ } }, - _activateSubMaterial (material) { - material.setProperty('color', cc.Color.WHITE); - material.define('useSkinning', true); - material.define('useTexture', true); - - if (this._jointsTexture) { - material.define('useJointsTexture', true); - material.setProperty('jointsTexture', this._jointsTexture); - material.setProperty('jointsTextureSize', this._jointsTexture.width); - } - else { - material.define('useJointsTexture', false); - material.setProperty('jointMatrices', this._jointsTextureData); - } - }, - _activateMaterial (force) { if (!this._jointsTextureData) { this.disableRender(); @@ -132,6 +115,7 @@ let SkinnedMeshRenderer = cc.Class({ if (!this._skeleton) return; let jointCount = this._joints.length; + let customProperties = this._customProperties; let ALLOW_FLOAT_TEXTURE = !!cc.renderer.device.ext('OES_texture_float'); if (ALLOW_FLOAT_TEXTURE) { @@ -153,10 +137,17 @@ let SkinnedMeshRenderer = cc.Class({ texture.initWithData(this._jointsTextureData, cc.Texture2D.PixelFormat.RGBA32F, size, size); this._jointsTexture = texture; + + customProperties.setProperty('_jointsTexture', texture.getImpl()); + customProperties.setProperty('_jointsTextureSize', this._jointsTexture.width); } else { this._jointsTextureData = new Float32Array(jointCount * 16); + customProperties.setProperty('_jointMatrices', this._jointsTextureData); } + + customProperties.define('_USE_SKINNING', true); + customProperties.define('_USE_JOINTS_TEXTRUE', ALLOW_FLOAT_TEXTURE); }, _setJointsTextureData (iMatrix, matrix) { diff --git a/cocos2d/core/3d/geom-utils/intersect.js b/cocos2d/core/3d/geom-utils/intersect.js index 2a0c6cbcac6..d809fd61b88 100644 --- a/cocos2d/core/3d/geom-utils/intersect.js +++ b/cocos2d/core/3d/geom-utils/intersect.js @@ -1,10 +1,11 @@ -const renderEngine = require('../../renderer/render-engine'); -const RecyclePool = renderEngine.RecyclePool; const aabb = require('./aabb'); const ray = require('./ray'); const triangle = require('./triangle'); +import gfx from '../../../renderer/gfx'; +import RecyclePool from '../../../renderer/memop/recycle-pool'; + const mat4 = cc.vmath.mat4; const vec3 = cc.vmath.vec3; @@ -94,8 +95,6 @@ intersect.rayTriangle = (function () { intersect.rayMesh = (function () { - const gfx = renderEngine.gfx; - let tri = triangle.create(); let minDist = Infinity; @@ -249,7 +248,7 @@ intersect.raycast = (function () { transformMat4Normal(d, d, m4_1); let res = resultsPool.add(); res.node = node; - res.distance = cc.vmath.vec3.length(d); + res.distance = cc.vmath.vec3.mag(d); results.push(res); } }); diff --git a/cocos2d/core/3d/geom-utils/ray.js b/cocos2d/core/3d/geom-utils/ray.js index d007d094122..e7fb4c627d3 100644 --- a/cocos2d/core/3d/geom-utils/ray.js +++ b/cocos2d/core/3d/geom-utils/ray.js @@ -10,8 +10,8 @@ const vec3 = cc.vmath.vec3; * @param {Number} dz */ function ray(ox, oy, oz, dx, dy, dz) { - this.o = vec3.new(ox, oy, oz); - this.d = vec3.new(dx, dy, dz); + this.o = vec3.create(ox, oy, oz); + this.d = vec3.create(dx, dy, dz); } /** diff --git a/cocos2d/core/3d/index.js b/cocos2d/core/3d/index.js index c85054a8262..4663f6ebe94 100644 --- a/cocos2d/core/3d/index.js +++ b/cocos2d/core/3d/index.js @@ -12,4 +12,5 @@ require('./CCModelMeshResource'); if (!CC_EDITOR || !Editor.isMainProcess) { require('./CCSkeletonAnimation'); require('./CCSkinnedMeshRenderer'); + require('./CCLightComponent'); } diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index b6cc00b8cd0..24fcaa5544e 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -27,9 +27,10 @@ const Node = require('../CCNode'); const EventType = Node.EventType; const DirtyFlag = Node._LocalDirtyFlag; -const math = require('../renderer/render-engine').math; const RenderFlow = require('../renderer/render-flow'); +import { mat4 } from '../vmath'; + // ====== Node transform polyfills ====== const ONE_DEGREE = Math.PI / 180; @@ -41,7 +42,7 @@ function _updateLocalMatrix3d () { if (this._localMatDirty) { // Update transform let t = this._matrix; - math.mat4.fromRTS(t, this._quat, this._position, this._scale); + mat4.fromRTS(t, this._quat, this._position, this._scale); // skew if (this._skewX || this._skewY) { @@ -71,10 +72,10 @@ function _calculWorldMatrix3d () { if (this._parent) { let parentMat = this._parent._worldMatrix; - math.mat4.mul(this._worldMatrix, parentMat, this._matrix); + mat4.mul(this._worldMatrix, parentMat, this._matrix); } else { - math.mat4.copy(this._worldMatrix, this._matrix); + mat4.copy(this._worldMatrix, this._matrix); } this._worldMatDirty = false; } @@ -148,7 +149,7 @@ function _update3DFunction () { if (this._is3DNode) { this._updateLocalMatrix = _updateLocalMatrix3d; this._calculWorldMatrix = _calculWorldMatrix3d; - this._mulMat = cc.vmath.mat4.mul; + this._mulMat = mat4.mul; } else { this._updateLocalMatrix = _updateLocalMatrix2d; diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 44d0aaaf015..9963d3d7de1 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -25,14 +25,14 @@ 'use strict'; +import { mat4, vec2, vec3, quat } from './vmath'; + const BaseNode = require('./utils/base-node'); const PrefabHelper = require('./utils/prefab-helper'); const mathPools = require('./utils/math-pools'); -const math = require('./renderer/render-engine').math; const AffineTrans = require('./utils/affine-transform'); const eventManager = require('./event-manager'); const macro = require('./platform/CCMacro'); -const misc = require('./utils/misc'); const js = require('./platform/js'); const Event = require('./event/event'); const EventTarget = require('./event/event-target'); @@ -48,9 +48,9 @@ var ActionManagerExist = !!cc.ActionManager; var emptyFunc = function () {}; var _vec2a = cc.v2(); var _vec2b = cc.v2(); -var _mat4_temp = math.mat4.create(); -var _vec3_temp = math.vec3.create(); -var _quat_temp = math.quat.create(); +var _mat4_temp = mat4.create(); +var _vec3_temp = vec3.create(); +var _quat_temp = quat.create(); var _globalOrderOfArrival = 1; var _cachedArray = new Array(16); _cachedArray.length = 0; @@ -721,7 +721,7 @@ let NodeDefines = { return this._eulerAngles.z; }, set (value) { - math.vec3.set(this._eulerAngles, 0, 0, value); + vec3.set(this._eulerAngles, 0, 0, value); this._fromEuler(); this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -758,10 +758,10 @@ let NodeDefines = { this._eulerAngles.x = value; // Update quaternion from rotation if (this._eulerAngles.x === this._eulerAngles.y) { - math.quat.fromEuler(this._quat, 0, 0, -value); + quat.fromEuler(this._quat, 0, 0, -value); } else { - math.quat.fromEuler(this._quat, value, this._eulerAngles.y, 0); + quat.fromEuler(this._quat, value, this._eulerAngles.y, 0); } this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -792,10 +792,10 @@ let NodeDefines = { this._eulerAngles.y = value; // Update quaternion from rotation if (this._eulerAngles.x === this._eulerAngles.y) { - math.quat.fromEuler(this._quat, 0, 0, -value); + quat.fromEuler(this._quat, 0, 0, -value); } else { - math.quat.fromEuler(this._quat, this._eulerAngles.x, value, 0); + quat.fromEuler(this._quat, this._eulerAngles.x, value, 0); } this.setLocalDirty(LocalDirtyFlag.ROTATION); this._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -938,7 +938,7 @@ let NodeDefines = { set (value) { if (this._opacity !== value) { this._opacity = value; - this._renderFlag |= RenderFlow.FLAG_OPACITY | RenderFlow.FLAG_COLOR; + this._renderFlag |= RenderFlow.FLAG_OPACITY; } }, range: [0, 255] @@ -962,10 +962,6 @@ let NodeDefines = { if (CC_DEV && value.a !== 255) { cc.warnID(1626); } - - if (this._renderComponent) { - this._renderFlag |= RenderFlow.FLAG_COLOR; - } if (this._eventMask & COLOR_ON) { this.emit(EventType.COLOR_CHANGED, value); @@ -1275,7 +1271,7 @@ let NodeDefines = { } else { let z = Math.asin(this._quat.z) / ONE_DEGREE * 2; - math.vec3.set(this._eulerAngles, 0, 0, z); + vec3.set(this._eulerAngles, 0, 0, z); } }, _fromEuler () { @@ -1283,7 +1279,7 @@ let NodeDefines = { this._quat.fromEuler(this._eulerAngles); } else { - math.quat.fromEuler(this._quat, 0, 0, this._eulerAngles.z); + quat.fromEuler(this._quat, 0, 0, this._eulerAngles.z); } }, @@ -1310,10 +1306,10 @@ let NodeDefines = { if ((this._rotationX || this._rotationY) && (quat.x === 0 && quat.y === 0 && quat.z === 0 && quat.w === 1)) { if (this._rotationX === this._rotationY) { - math.quat.fromEuler(quat, 0, 0, -this._rotationX); + quat.fromEuler(quat, 0, 0, -this._rotationX); } else { - math.quat.fromEuler(quat, this._rotationX, this._rotationY, 0); + quat.fromEuler(quat, this._rotationX, this._rotationY, 0); } this._rotationX = this._rotationY = undefined; } @@ -1830,8 +1826,8 @@ let NodeDefines = { } this._updateWorldMatrix(); - math.mat4.invert(_mat4_temp, this._worldMatrix); - math.vec2.transformMat4(testPt, cameraPt, _mat4_temp); + mat4.invert(_mat4_temp, this._worldMatrix); + vec2.transformMat4(testPt, cameraPt, _mat4_temp); testPt.x += this._anchorPoint.x * w; testPt.y += this._anchorPoint.y * h; @@ -2377,19 +2373,19 @@ let NodeDefines = { if (this._parent) { this._parent._invTransformPoint(out, pos); } else { - math.vec3.copy(out, pos); + vec3.copy(out, pos); } // out = parent_inv_pos - pos - math.vec3.sub(out, out, this._position); + vec3.sub(out, out, this._position); // out = inv(rot) * out - math.quat.conjugate(_quat_temp, this._quat); - math.vec3.transformQuat(out, out, _quat_temp); + quat.conjugate(_quat_temp, this._quat); + vec3.transformQuat(out, out, _quat_temp); // out = (1/scale) * out - math.vec3.inverseSafe(_vec3_temp, this._scale); - math.vec3.mul(out, out, _vec3_temp); + vec3.inverseSafe(_vec3_temp, this._scale); + vec3.mul(out, out, _vec3_temp); return out; }, @@ -2402,15 +2398,15 @@ let NodeDefines = { * @return {Vec3} */ getWorldPosition (out) { - math.vec3.copy(out, this._position); + vec3.copy(out, this._position); let curr = this._parent; while (curr) { // out = parent_scale * pos - math.vec3.mul(out, out, curr._scale); + vec3.mul(out, out, curr._scale); // out = parent_quat * out - math.vec3.transformQuat(out, out, curr._quat); + vec3.transformQuat(out, out, curr._quat); // out = out + pos - math.vec3.add(out, out, curr._position); + vec3.add(out, out, curr._position); curr = curr._parent; } return out; @@ -2431,7 +2427,7 @@ let NodeDefines = { this._parent._invTransformPoint(this._position, pos); } else { - math.vec3.copy(this._position, pos); + vec3.copy(this._position, pos); } this.setLocalDirty(LocalDirtyFlag.POSITION); @@ -2455,10 +2451,10 @@ let NodeDefines = { * @return {Quat} */ getWorldRotation (out) { - math.quat.copy(out, this._quat); + quat.copy(out, this._quat); let curr = this._parent; while (curr) { - math.quat.mul(out, curr._quat, out); + quat.mul(out, curr._quat, out); curr = curr._parent; } return out; @@ -2468,16 +2464,16 @@ let NodeDefines = { * Set world rotation with quaternion * This is not a public API yet, its usage could be updated * @method setWorldRotation - * @param {Quat} rot + * @param {Quat} val */ - setWorldRotation (quat) { + setWorldRotation (val) { if (this._parent) { this._parent.getWorldRotation(this._quat); - math.quat.conjugate(this._quat, this._quat); - math.quat.mul(this._quat, this._quat, quat); + quat.conjugate(this._quat, this._quat); + quat.mul(this._quat, this._quat, val); } else { - math.quat.copy(this._quat, quat); + quat.copy(this._quat, quat); } this._toEuler(); this.setLocalDirty(LocalDirtyFlag.ROTATION); @@ -2491,10 +2487,10 @@ let NodeDefines = { * @return {Vec3} */ getWorldScale (out) { - math.vec3.copy(out, this._scale); + vec3.copy(out, this._scale); let curr = this._parent; while (curr) { - math.vec3.mul(out, out, curr._scale); + vec3.mul(out, out, curr._scale); curr = curr._parent; } return out; @@ -2509,10 +2505,10 @@ let NodeDefines = { setWorldScale (scale) { if (this._parent) { this._parent.getWorldScale(this._scale); - math.vec3.div(this._scale, scale, this._scale); + vec3.div(this._scale, scale, this._scale); } else { - math.vec3.copy(this._scale, scale); + vec3.copy(this._scale, scale); } this.setLocalDirty(LocalDirtyFlag.SCALE); }, @@ -2520,22 +2516,22 @@ let NodeDefines = { getWorldRT (out) { let opos = _vec3_temp; let orot = _quat_temp; - math.vec3.copy(opos, this._position); - math.quat.copy(orot, this._quat); + vec3.copy(opos, this._position); + quat.copy(orot, this._quat); let curr = this._parent; while (curr) { // opos = parent_lscale * lpos - math.vec3.mul(opos, opos, curr._scale); + vec3.mul(opos, opos, curr._scale); // opos = parent_lrot * opos - math.vec3.transformQuat(opos, opos, curr._quat); + vec3.transformQuat(opos, opos, curr._quat); // opos = opos + lpos - math.vec3.add(opos, opos, curr._position); + vec3.add(opos, opos, curr._position); // orot = lrot * orot - math.quat.mul(orot, curr._quat, orot); + quat.mul(orot, curr._quat, orot); curr = curr._parent; } - math.mat4.fromRT(out, orot, opos); + mat4.fromRT(out, orot, opos); return out; }, @@ -2548,9 +2544,9 @@ let NodeDefines = { */ lookAt (pos, up) { this.getWorldPosition(_vec3_temp); - math.vec3.sub(_vec3_temp, _vec3_temp, pos); // NOTE: we use -z for view-dir - math.vec3.normalize(_vec3_temp, _vec3_temp); - math.quat.fromViewUp(_quat_temp, _vec3_temp, up); + vec3.sub(_vec3_temp, _vec3_temp, pos); // NOTE: we use -z for view-dir + vec3.normalize(_vec3_temp, _vec3_temp); + quat.fromViewUp(_quat_temp, _vec3_temp, up); this.setWorldRotation(_quat_temp); }, @@ -2561,7 +2557,7 @@ let NodeDefines = { // Update transform let t = this._matrix; - //math.mat4.fromRTS(t, this._quat, this._position, this._scale); + //mat4.fromRTS(t, this._quat, this._position, this._scale); if (dirtyFlag & (LocalDirtyFlag.RT | LocalDirtyFlag.SKEW)) { let rotation = -this._eulerAngles.z; @@ -2627,7 +2623,7 @@ let NodeDefines = { this._mulMat(this._worldMatrix, parent._worldMatrix, this._matrix); } else { - math.mat4.copy(this._worldMatrix, this._matrix); + mat4.copy(this._worldMatrix, this._matrix); } this._worldMatDirty = false; }, @@ -2689,7 +2685,7 @@ let NodeDefines = { */ getLocalMatrix (out) { this._updateLocalMatrix(); - return math.mat4.copy(out, this._matrix); + return mat4.copy(out, this._matrix); }, /** @@ -2705,7 +2701,7 @@ let NodeDefines = { */ getWorldMatrix (out) { this._updateWorldMatrix(); - return math.mat4.copy(out, this._worldMatrix); + return mat4.copy(out, this._worldMatrix); }, /** @@ -2723,9 +2719,9 @@ let NodeDefines = { */ convertToNodeSpace (worldPoint) { this._updateWorldMatrix(); - math.mat4.invert(_mat4_temp, this._worldMatrix); + mat4.invert(_mat4_temp, this._worldMatrix); let out = new cc.Vec2(); - math.vec2.transformMat4(out, worldPoint, _mat4_temp); + vec2.transformMat4(out, worldPoint, _mat4_temp); out.x += this._anchorPoint.x * this._contentSize.width; out.y += this._anchorPoint.y * this._contentSize.height; return out; @@ -2748,7 +2744,7 @@ let NodeDefines = { nodePoint.x - this._anchorPoint.x * this._contentSize.width, nodePoint.y - this._anchorPoint.y * this._contentSize.height ); - return math.vec2.transformMat4(out, out, this._worldMatrix); + return vec2.transformMat4(out, out, this._worldMatrix); }, /** @@ -2764,9 +2760,9 @@ let NodeDefines = { */ convertToNodeSpaceAR (worldPoint) { this._updateWorldMatrix(); - math.mat4.invert(_mat4_temp, this._worldMatrix); + mat4.invert(_mat4_temp, this._worldMatrix); let out = new cc.Vec2(); - return math.vec2.transformMat4(out, worldPoint, _mat4_temp); + return vec2.transformMat4(out, worldPoint, _mat4_temp); }, /** @@ -2783,7 +2779,7 @@ let NodeDefines = { convertToWorldSpaceAR (nodePoint) { this._updateWorldMatrix(); let out = new cc.Vec2(); - return math.vec2.transformMat4(out, nodePoint, this._worldMatrix); + return vec2.transformMat4(out, nodePoint, this._worldMatrix); }, // OLD TRANSFORM ACCESS APIs @@ -2810,8 +2806,8 @@ let NodeDefines = { _vec3_temp.x = -this._anchorPoint.x * contentSize.width; _vec3_temp.y = -this._anchorPoint.y * contentSize.height; - math.mat4.copy(_mat4_temp, this._matrix); - math.mat4.translate(_mat4_temp, _mat4_temp, _vec3_temp); + mat4.copy(_mat4_temp, this._matrix); + mat4.translate(_mat4_temp, _mat4_temp, _vec3_temp); return AffineTrans.fromMat4(out, _mat4_temp); }, @@ -2861,8 +2857,8 @@ let NodeDefines = { _vec3_temp.x = -this._anchorPoint.x * contentSize.width; _vec3_temp.y = -this._anchorPoint.y * contentSize.height; - math.mat4.copy(_mat4_temp, this._worldMatrix); - math.mat4.translate(_mat4_temp, _mat4_temp, _vec3_temp); + mat4.copy(_mat4_temp, this._worldMatrix); + mat4.translate(_mat4_temp, _mat4_temp, _vec3_temp); return AffineTrans.fromMat4(out, _mat4_temp); }, @@ -2910,7 +2906,7 @@ let NodeDefines = { out = AffineTrans.identity(); } this._updateLocalMatrix(); - math.mat4.invert(_mat4_temp, this._matrix); + mat4.invert(_mat4_temp, this._matrix); return AffineTrans.fromMat4(out, _mat4_temp); }, @@ -2930,7 +2926,7 @@ let NodeDefines = { out = AffineTrans.identity(); } this._updateWorldMatrix(); - math.mat4.invert(_mat4_temp, this._worldMatrix); + mat4.invert(_mat4_temp, this._worldMatrix); return AffineTrans.fromMat4(out, _mat4_temp); }, @@ -3016,7 +3012,7 @@ let NodeDefines = { width, height); - var parentMat = math.mat4.mul(this._worldMatrix, parentMat, this._matrix); + var parentMat = mat4.mul(this._worldMatrix, parentMat, this._matrix); rect.transformMat4(rect, parentMat); //query child's BoundingBox @@ -3155,7 +3151,6 @@ let NodeDefines = { this._renderFlag |= RenderFlow.FLAG_TRANSFORM; if (this._renderComponent) { if (this._renderComponent.enabled) { - this._renderFlag |= RenderFlow.FLAG_COLOR; this._renderComponent.markForUpdateRenderData(true); } else { diff --git a/cocos2d/core/CCPrivateNode.js b/cocos2d/core/CCPrivateNode.js index e1a0e7bf701..9a5ed3f49ea 100644 --- a/cocos2d/core/CCPrivateNode.js +++ b/cocos2d/core/CCPrivateNode.js @@ -27,14 +27,11 @@ const Node = require('./CCNode'); const RenderFlow = require('./renderer/render-flow'); -const math = require('./renderer/render-engine').math; const HideInHierarchy = cc.Object.Flags.HideInHierarchy; const LocalDirtyFlag = Node._LocalDirtyFlag; const POSITION_ON = 1 << 0; -let _vec3_temp = math.vec3.create(); - /** * !#en * Class of private entities in Cocos Creator scenes.
diff --git a/cocos2d/core/assets/CCEffectAsset.js b/cocos2d/core/assets/CCEffectAsset.js index e6f513d8ef4..72ea91a397a 100644 --- a/cocos2d/core/assets/CCEffectAsset.js +++ b/cocos2d/core/assets/CCEffectAsset.js @@ -5,8 +5,9 @@ let EffectAsset = cc.Class({ extends: Asset, properties: { - shaders: Object, - effect: Object + properties: Object, + techniques: [], + shaders: [] }, onLoad () { diff --git a/cocos2d/core/assets/CCRenderTexture.js b/cocos2d/core/assets/CCRenderTexture.js index ee5fea48947..9d9e2a2cc6e 100644 --- a/cocos2d/core/assets/CCRenderTexture.js +++ b/cocos2d/core/assets/CCRenderTexture.js @@ -1,8 +1,8 @@ const renderer = require('../renderer'); -const renderEngine = require('../renderer/render-engine'); -const gfx = renderEngine.gfx; const Texture2D = require('./CCTexture2D'); +import gfx from '../../renderer/gfx'; + /** * Render textures are textures that can be rendered to. * @class RenderTexture @@ -29,50 +29,45 @@ let RenderTexture = cc.Class({ initWithSize (width, height, depthStencilFormat) { this.width = Math.floor(width || cc.visibleRect.width); this.height = Math.floor(height || cc.visibleRect.height); - - let opts = {}; - opts.format = this._format; - opts.width = width; - opts.height = height; - opts.images = undefined; - opts.wrapS = this._wrapS; - opts.wrapT = this._wrapT; - opts.premultiplyAlpha = this._premultiplyAlpha; - opts.minFilter = Texture2D._FilterIndex[this._minFilter]; - opts.magFilter = Texture2D._FilterIndex[this._magFilter]; - - if (!this._texture) { - this._texture = new renderer.Texture2D(renderer.device, opts); - } - else { - this._texture.update(opts); - } - - opts = { + this._resetUnderlyingMipmaps(); + + let opts = { colors: [ this._texture ], }; + + if (this._depthStencilBuffer) this._depthStencilBuffer.destroy(); + let depthStencilBuffer; if (depthStencilFormat) { - let depthStencilBuffer = new gfx.RenderBuffer(renderer.device, depthStencilFormat, width, height); + depthStencilBuffer = new gfx.RenderBuffer(renderer.device, depthStencilFormat, width, height); if (depthStencilFormat === gfx.RB_FMT_D24S8) { - opts.depth = opts.stencil = depthStencilBuffer; + opts.depthStencil = depthStencilBuffer; } else if (depthStencilFormat === gfx.RB_FMT_S8) { opts.stencil = depthStencilBuffer; } - else if (depthStencilFormat === gl.RB_FMT_D16) { + else if (depthStencilFormat === gfx.RB_FMT_D16) { opts.depth = depthStencilBuffer; } } - - if (this._framebuffer) { - this._framebuffer.destroy(); - } - this._framebuffer = new renderEngine.gfx.FrameBuffer(renderer.device, width, height, opts); + this._depthStencilBuffer = depthStencilBuffer; + if (this._framebuffer) this._framebuffer.destroy(); + this._framebuffer = new gfx.FrameBuffer(renderer.device, width, height, opts); this.loaded = true; this.emit("load"); }, + updateSize(width, height) { + this.width = Math.floor(width || cc.visibleRect.width); + this.height = Math.floor(height || cc.visibleRect.height); + this._resetUnderlyingMipmaps(); + + let rbo = this._depthStencilBuffer; + if (rbo) rbo.update(this.width, this.height); + this._framebuffer._width = width; + this._framebuffer._height = height; + }, + /** * !#en Draw a texture to the specified position * !#zh 将指定的图片渲染到指定的位置上 @@ -124,7 +119,6 @@ let RenderTexture = cc.Class({ let gl = renderer._forward._device._gl; let oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING); gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebuffer._glID); - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._texture._glID, 0); gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data); gl.bindFramebuffer(gl.FRAMEBUFFER, oldFBO); diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 8dfc87fd48f..ffd52871372 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -25,10 +25,10 @@ ****************************************************************************/ const EventTarget = require('../event/event-target'); -const renderEngine = require('../renderer/render-engine'); const renderer = require('../renderer'); require('../platform/CCClass'); -const gfx = renderEngine.gfx; + +import gfx from '../../renderer/gfx'; const GL_NEAREST = 9728; // gl.NEAREST const GL_LINEAR = 9729; // gl.LINEAR @@ -268,6 +268,7 @@ var Texture2D = cc.Class({ _flipY: false, _minFilter: Filter.LINEAR, _magFilter: Filter.LINEAR, + _mipFilter: Filter.LINEAR, _wrapS: WrapMode.CLAMP_TO_EDGE, _wrapT: WrapMode.CLAMP_TO_EDGE }, @@ -340,7 +341,7 @@ var Texture2D = cc.Class({ /** * !#en * Get renderer texture implementation object - * extended from renderEngine.TextureAsset + * extended from render.Texture2D * !#zh 返回渲染器内部贴图对象 * @method getImpl */ @@ -387,6 +388,10 @@ var Texture2D = cc.Class({ this._magFilter = options.magFilter; options.magFilter = FilterIndex[options.magFilter]; } + if (options.mipFilter !== undefined) { + this._mipFilter = options.mipFilter; + options.mipFilter = FilterIndex[options.mipFilter]; + } if (options.wrapS !== undefined) { this._wrapS = options.wrapS; } @@ -713,6 +718,33 @@ var Texture2D = cc.Class({ } }, + _getOpts() { + let opts = _getSharedOptions(); + opts.width = this.width; + opts.height = this.height; + opts.mipmap = this._genMipmap; + opts.format = this._format; + opts.premultiplyAlpha = this._premultiplyAlpha; + opts.anisotropy = this._anisotropy; + opts.flipY = this._flipY; + opts.minFilter = FilterIndex[this._minFilter]; + opts.magFilter = FilterIndex[this._magFilter]; + opts.mipFilter = FilterIndex[this._mipFilter]; + opts.wrapS = this._wrapS; + opts.wrapT = this._wrapT; + return opts; + }, + + _resetUnderlyingMipmaps(mipmapSources) { + const opts = this._getOpts(); + opts.images = mipmapSources || [null]; + if (!this._texture) { + this._texture = new renderer.Texture2D(renderer.device, opts); + } else { + this._texture.update(opts); + } + }, + // SERIALIZATION _serialize: (CC_EDITOR || CC_TEST) && function () { diff --git a/cocos2d/core/assets/index.js b/cocos2d/core/assets/index.js index 5c855b1a8d7..1afd23bb31b 100644 --- a/cocos2d/core/assets/index.js +++ b/cocos2d/core/assets/index.js @@ -42,4 +42,4 @@ require('./CCTextAsset'); require('./CCJsonAsset'); require('./CCBufferAsset'); require('./CCEffectAsset'); -require('./CCMaterial'); +require('./material/CCMaterial'); diff --git a/cocos2d/core/assets/CCMaterial.js b/cocos2d/core/assets/material/CCMaterial.js similarity index 68% rename from cocos2d/core/assets/CCMaterial.js rename to cocos2d/core/assets/material/CCMaterial.js index 1c338aceb26..12b0710c773 100644 --- a/cocos2d/core/assets/CCMaterial.js +++ b/cocos2d/core/assets/material/CCMaterial.js @@ -24,18 +24,20 @@ ****************************************************************************/ // @ts-check -const Asset = require('./CCAsset'); -const Texture = require('./CCTexture2D'); -const EffectAsset = require('./CCEffectAsset'); +const Asset = require('../CCAsset'); +const Texture = require('../CCTexture2D'); +const EffectAsset = require('../CCEffectAsset'); -import computeHash from './utils/compute-hash'; -import Effect from '../../renderer/effect'; +import Effect from '../../../renderer/core/effect'; +import murmurhash2 from './murmurhash2_gc'; +import utils from './utils'; let Material = cc.Class({ name: 'cc.Material', extends: Asset, ctor () { + this._dirty = true; this._effect = null; }, @@ -77,7 +79,7 @@ let Material = cc.Class({ cc.error('Can not set an empty effect asset.'); return; } - this._effect = Effect.parseEffect(asset.effect); + this._effect = Effect.parseEffect(asset); } }, @@ -89,19 +91,23 @@ let Material = cc.Class({ }, statics: { - getInstantiatedBuiltinMaterial(name) { - let builtinMaterial = cc.AssetLibrary.getBuiltin('material', 'builtin-' + name); - return Material.getInstantiatedMaterial(builtinMaterial, this); + getBuiltinMaterial (name) { + return cc.AssetLibrary.getBuiltin('material', 'builtin-' + name); }, - getInstantiatedMaterial(mat, renderComponent) { + getInstantiatedBuiltinMaterial (name, renderComponent) { + let builtinMaterial = this.getBuiltinMaterial(name); + return Material.getInstantiatedMaterial(builtinMaterial, renderComponent); + }, + getInstantiatedMaterial (mat, renderComponent) { if (mat._owner === renderComponent) { return mat; } else { let instance = new Material(); instance.copy(mat); - instance._native = mat._native + ' (Instance)'; + instance._name = mat._name + ' (Instance)'; instance._owner = renderComponent; + instance._objFlags |= cc.Object.Flags.DontSave; return instance; } } @@ -111,7 +117,7 @@ let Material = cc.Class({ * * @param {Material} mat */ - copy(mat) { + copy (mat) { this.effectAsset = mat.effectAsset; for (let name in mat._defines) { @@ -126,14 +132,16 @@ let Material = cc.Class({ /** * * @param {string} name - * @param {*} val + * @param {Object} val */ - setProperty(name, val) { + setProperty (name, val, force) { + if (this._props[name] === val && !force) return; this._props[name] = val; + this._dirty = true; if (this._effect) { if (val instanceof Texture) { - this._effect.setProperty(name, val._texture); + this._effect.setProperty(name, val.getImpl()); } else { this._effect.setProperty(name, val); @@ -141,39 +149,62 @@ let Material = cc.Class({ } }, - getProperty(name) { + getProperty (name) { return this._props[name]; }, /** * * @param {string} name - * @param {*} val + * @param {Boolean|Number} val */ - define(name, val) { + define (name, val, force) { + if (this._defines[name] === val && !force) return; this._defines[name] = val; + this._dirty = true; + if (this._effect) { this._effect.define(name, val); } }, - getDefine(name) { + getDefine (name) { return this._defines[name]; }, - updateHash (val) { - this._hash = val || computeHash(this); + setDirty (dirty) { + this._dirty = dirty; + }, + + updateHash (hash) { + this._dirty = false; + this._hash = hash; + }, + + getHash () { + if (!this._dirty) return this._hash; + this._dirty = false; + let effect = this._effect; + + let hashStr = ''; + if (effect) { + hashStr += utils.serializeDefines(effect._defines); + hashStr += utils.serializeTechniques(effect._techniques); + hashStr += utils.serializeUniforms(effect._properties); + } + + return this._hash = murmurhash2(hashStr, 666); }, onLoad () { this.effectAsset = this._effectAsset; if (!this._effect) return; - + for (let def in this._defines) { - this._effect.define(def, this._defines[def]); + this.define(def, this._defines[def], true); } for (let prop in this._props) { - this._effect.setProperty(prop, this._props[prop]); + this.setProperty(prop, this._props[prop], true); } }, }); diff --git a/cocos2d/core/assets/material/custom-properties.js b/cocos2d/core/assets/material/custom-properties.js new file mode 100644 index 00000000000..0906775cec6 --- /dev/null +++ b/cocos2d/core/assets/material/custom-properties.js @@ -0,0 +1,62 @@ +import { ctor2enums } from '../../../renderer/types'; +import murmurhash2 from './murmurhash2_gc'; +import utils from './utils'; + +export default class CustomProperties { + constructor () { + this._properties = {}; + this._defines = {}; + this._dirty = false; + } + + setProperty (name, value) { + let uniform = this._properties[name]; + if (!uniform) { + uniform = Object.create(null); + uniform.name = name; + uniform.type = ctor2enums[value.constructor]; + this._properties[name] = uniform; + } + else if (uniform.value === value) return; + + this._dirty = true; + uniform.value = value; + } + + getProperty(name) { + let prop = this._properties[name]; + if (prop) return prop.value; + return null; + } + + define (name, value) { + if (this._defines[name] === value) return; + this._dirty = true; + this._defines[name] = value; + } + + getDefine (name) { + return this._defines[name]; + } + + extractProperties(out = {}) { + Object.assign(out, this._properties); + return out; + } + + extractDefines(out = {}) { + Object.assign(out, this._defines); + return out; + } + + getHash () { + if (!this._dirty) return this._hash; + this._dirty = false; + + let hash = ''; + hash += utils.serializeDefines(this._defines); + hash += utils.serializeUniforms(this._properties); + + return this._hash = murmurhash2(hash, 666); + } +} diff --git a/cocos2d/core/assets/utils/murmurhash2_gc.js b/cocos2d/core/assets/material/murmurhash2_gc.js similarity index 100% rename from cocos2d/core/assets/utils/murmurhash2_gc.js rename to cocos2d/core/assets/material/murmurhash2_gc.js diff --git a/cocos2d/core/assets/material/utils.js b/cocos2d/core/assets/material/utils.js new file mode 100644 index 00000000000..3a80795aa30 --- /dev/null +++ b/cocos2d/core/assets/material/utils.js @@ -0,0 +1,113 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import enums from '../../../renderer/enums'; + +// function genHashCode (str) { +// var hash = 0; +// if (str.length == 0) { +// return hash; +// } +// for (var i = 0; i < str.length; i++) { +// var char = str.charCodeAt(i); +// hash = ((hash<<5)-hash)+char; +// hash = hash & hash; // Convert to 32bit integer +// } +// return hash; +// } + +function serializeDefines (defines) { + let str = ''; + for (let name in defines) { + str += name + defines[name]; + } + return str; +} + +function serializePass (pass) { + let str = pass._programName + pass._cullMode; + if (pass._blend) { + str += pass._blendEq + pass._blendAlphaEq + pass._blendSrc + pass._blendDst + + pass._blendSrcAlpha + pass._blendDstAlpha + pass._blendColor; + } + if (pass._depthTest) { + str += pass._depthWrite + pass._depthFunc; + } + if (pass._stencilTest) { + str += pass._stencilFuncFront + pass._stencilRefFront + pass._stencilMaskFront + + pass._stencilFailOpFront + pass._stencilZFailOpFront + pass._stencilZPassOpFront + + pass._stencilWriteMaskFront + + pass._stencilFuncBack + pass._stencilRefBack + pass._stencilMaskBack + + pass._stencilFailOpBack + pass._stencilZFailOpBack + pass._stencilZPassOpBack + + pass._stencilWriteMaskBack; + } + return str; +} + +function serializeTechniques (techniques) { + let hashData = ''; + for (let i = 0; i < techniques.length; i++) { + let techData = techniques[i]; + // technique.stageIDs + hashData += techData.stageIDs; + // technique._layer + // hashData += + techData._layer + "_"; + // technique.passes + for (let j = 0; j < techData.passes.length; j++) { + hashData += serializePass(techData.passes[j]); + } + } + return hashData; +} + +function serializeUniforms (uniforms) { + let hashData = ''; + for (let name in uniforms) { + let param = uniforms[name]; + let prop = param.value; + + if (!prop) { + continue; + } + switch (param.type) { + case enums.PARAM_INT: + case enums.PARAM_FLOAT: + hashData += prop + ';'; + break; + case enums.PARAM_INT2: + case enums.PARAM_FLOAT2: + hashData += prop.x + ',' + prop.y + ';'; + break; + case enums.PARAM_INT4: + case enums.PARAM_FLOAT4: + hashData += prop.x + ',' + prop.y + ',' + prop.z + ',' + prop.w + ';'; + break; + case enums.PARAM_COLOR4: + hashData += prop.r + ',' + prop.g + ',' + prop.b + ',' + prop.a + ';'; + break; + case enums.PARAM_MAT2: + hashData += prop.m00 + ',' + prop.m01 + ',' + prop.m02 + ',' + prop.m03 + ';'; + break; + case enums.PARAM_TEXTURE_2D: + case enums.PARAM_TEXTURE_CUBE: + hashData += prop._id + ';'; + break; + case enums.PARAM_INT3: + case enums.PARAM_FLOAT3: + case enums.PARAM_COLOR3: + case enums.PARAM_MAT3: + case enums.PARAM_MAT4: + hashData += JSON.stringify(prop) + ';'; + break; + default: + break; + } + } + + return hashData; +} + +export default { + serializeDefines, + serializeTechniques, + serializeUniforms +}; \ No newline at end of file diff --git a/cocos2d/core/assets/utils/compute-hash.js b/cocos2d/core/assets/utils/compute-hash.js deleted file mode 100644 index a39bc6cfeb4..00000000000 --- a/cocos2d/core/assets/utils/compute-hash.js +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -import murmurhash2 from './murmurhash2_gc'; -import enums from '../../../renderer/mappings/enums'; - -// function genHashCode (str) { -// var hash = 0; -// if (str.length == 0) { -// return hash; -// } -// for (var i = 0; i < str.length; i++) { -// var char = str.charCodeAt(i); -// hash = ((hash<<5)-hash)+char; -// hash = hash & hash; // Convert to 32bit integer -// } -// return hash; -// } - -function serializeDefines (defines) { - let str = ''; - for (let i = 0; i < defines.length; i++) { - str += defines[i].name + defines[i].value; - } - return str; -} - -function serializePass (pass) { - let str = pass._programName + pass._cullMode; - if (pass._blend) { - str += pass._blendEq + pass._blendAlphaEq + pass._blendSrc + pass._blendDst - + pass._blendSrcAlpha + pass._blendDstAlpha + pass._blendColor; - } - if (pass._depthTest) { - str += pass._depthWrite + pass._depthFunc; - } - if (pass._stencilTest) { - str += pass._stencilFuncFront + pass._stencilRefFront + pass._stencilMaskFront - + pass._stencilFailOpFront + pass._stencilZFailOpFront + pass._stencilZPassOpFront - + pass._stencilWriteMaskFront - + pass._stencilFuncBack + pass._stencilRefBack + pass._stencilMaskBack - + pass._stencilFailOpBack + pass._stencilZFailOpBack + pass._stencilZPassOpBack - + pass._stencilWriteMaskBack; - } - return str; -} - -export default function computeHash(material) { - let effect = material._effect; - let hashData = ''; - if (effect) { - let i, j, techData, param, prop, propKey; - - // effect._defines - hashData += serializeDefines(effect._defines); - // effect._techniques - for (i = 0; i < effect._techniques.length; i++) { - techData = effect._techniques[i]; - // technique.stageIDs - hashData += techData.stageIDs; - // technique._layer - // hashData += + techData._layer + "_"; - // technique.passes - for (j = 0; j < techData.passes.length; j++) { - hashData += serializePass(techData.passes[j]); - } - } - - for (let name in effect._properties) { - let param = effect._properties[name]; - let prop = param.value; - - if (!prop) { - continue; - } - switch(param.type) { - case enums.PARAM_INT: - case enums.PARAM_FLOAT: - hashData += prop + ';'; - break; - case enums.PARAM_INT2: - case enums.PARAM_FLOAT2: - hashData += prop.x + ',' + prop.y + ';'; - break; - case enums.PARAM_INT4: - case enums.PARAM_FLOAT4: - hashData += prop.x + ',' + prop.y + ',' + prop.z + ',' + prop.w + ';'; - break; - case enums.PARAM_COLOR4: - hashData += prop.r + ',' + prop.g + ',' + prop.b + ',' + prop.a + ';'; - break; - case enums.PARAM_MAT2: - hashData += prop.m00 + ',' + prop.m01 + ',' + prop.m02 + ',' + prop.m03 + ';'; - break; - case enums.PARAM_TEXTURE_2D: - case enums.PARAM_TEXTURE_CUBE: - hashData += prop._id + ';'; - break; - case enums.PARAM_INT3: - case enums.PARAM_FLOAT3: - case enums.PARAM_COLOR3: - case enums.PARAM_MAT3: - case enums.PARAM_MAT4: - hashData += JSON.stringify(prop) + ';'; - break; - default: - break; - } - } - } - return hashData ? murmurhash2(hashData, 666) : hashData; -}; \ No newline at end of file diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index e942131c34f..5ca1d7fab6b 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -25,12 +25,14 @@ ****************************************************************************/ const AffineTrans = require('../utils/affine-transform'); -const renderEngine = require('../renderer/render-engine'); const renderer = require('../renderer/index'); const RenderFlow = require('../renderer/render-flow'); const game = require('../CCGame'); const ray = require('../3d/geom-utils/ray'); +import RendererCamera from '../../renderer/scene/camera'; +import View from '../../renderer/core/view'; + const mat4 = cc.vmath.mat4; const vec2 = cc.vmath.vec2; const vec3 = cc.vmath.vec3; @@ -76,6 +78,11 @@ let ClearFlags = cc.Enum({ STENCIL: 4, }); +let StageFlags = cc.Enum({ + OPAQUE: 1, + TRANSPARENT: 2 +}); + /** * !#en * Camera is usefull when making reel game or other games which need scroll screen. @@ -92,13 +99,13 @@ let Camera = cc.Class({ ctor () { if (game.renderType !== game.RENDER_TYPE_CANVAS) { - let camera = new renderEngine.Camera(); + let camera = new RendererCamera(); camera.setStages([ - 'transparent' + 'opaque', ]); - let view = new renderEngine.View(); + let view = new View(); camera.view = view; camera.dirty = true; @@ -113,7 +120,7 @@ let Camera = cc.Class({ editor: CC_EDITOR && { menu: 'i18n:MAIN_MENU.component.others/Camera', inspector: 'packages://inspector/inspectors/comps/camera.js', - executeInEditMode: false + executeInEditMode: true }, properties: { @@ -129,6 +136,7 @@ let Camera = cc.Class({ _farClip: 4096, _ortho: true, _rect: cc.rect(0, 0, 1, 1), + _renderStages: 1, /** * !#en @@ -319,7 +327,7 @@ let Camera = cc.Class({ set (value) { this._depth = value; if (this._camera) { - this._camera._sortDepth = value; + this._camera._priority = value; } } }, @@ -343,6 +351,16 @@ let Camera = cc.Class({ } }, + renderStages: { + get () { + return this._renderStages; + }, + set (val) { + this._renderStages = val; + this._updateStages(); + } + }, + _is3D: { get () { return this.node._is3DNode; @@ -397,23 +415,19 @@ let Camera = cc.Class({ _setupDebugCamera () { if (_debugCamera) return; if (game.renderType === game.RENDER_TYPE_CANVAS) return; - let camera = new renderEngine.Camera(); + let camera = new RendererCamera(); _debugCamera = camera; - camera.setStages([ - 'transparent' - ]); - camera.setFov(Math.PI * 60 / 180); camera.setNear(0.1); camera.setFar(4096); - let view = new renderEngine.View(); + let view = new View(); camera.view = view; camera.dirty = true; - camera._cullingMask = camera.view._cullingMask = 1 << cc.Node.BuiltinGroupIndex.DEBUG; - camera._sortDepth = cc.macro.MAX_ZINDEX; + camera._cullingMask = 1 << cc.Node.BuiltinGroupIndex.DEBUG; + camera._priority = cc.macro.MAX_ZINDEX; camera.setClearFlags(0); camera.setColor(0, 0, 0, 0); @@ -431,7 +445,6 @@ let Camera = cc.Class({ if (this._camera) { let mask = this._cullingMask & (~(1 << cc.Node.BuiltinGroupIndex.DEBUG)); this._camera._cullingMask = mask; - this._camera.view._cullingMask = mask; } }, @@ -471,6 +484,18 @@ let Camera = cc.Class({ this._camera.setRect(this._rect); }, + _updateStages () { + let flags = this._renderStages; + let stages = this._camera._stages; + stages.length = 0; + if (flags & StageFlags.OPAQUE) { + stages.push('opaque'); + } + if (flags & StageFlags.TRANSPARENT) { + stages.push('transparent'); + } + }, + _init () { if (this._inited) return; this._inited = true; @@ -479,12 +504,13 @@ let Camera = cc.Class({ if (!camera) return; camera.setNode(this.node); camera.setClearFlags(this._clearFlags); - camera._sortDepth = this._depth; + camera._priority = this._depth; this._updateBackgroundColor(); this._updateCameraMask(); this._updateTargetTexture(); this._updateClippingpPlanes(); this._updateProjection(); + this._updateStages(); }, onLoad () { @@ -492,7 +518,7 @@ let Camera = cc.Class({ }, onEnable () { - if (game.renderType !== game.RENDER_TYPE_CANVAS) { + if (!CC_EDITOR && game.renderType !== game.RENDER_TYPE_CANVAS) { cc.director.on(cc.Director.EVENT_BEFORE_DRAW, this.beforeDraw, this); renderer.scene.addCamera(this._camera); } @@ -500,7 +526,7 @@ let Camera = cc.Class({ }, onDisable () { - if (game.renderType !== game.RENDER_TYPE_CANVAS) { + if (!CC_EDITOR && game.renderType !== game.RENDER_TYPE_CANVAS) { cc.director.off(cc.Director.EVENT_BEFORE_DRAW, this.beforeDraw, this); renderer.scene.removeCamera(this._camera); } diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 1acc37d5382..8669819821e 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -26,8 +26,7 @@ const macro = require('../platform/CCMacro'); const RenderComponent = require('./CCRenderComponent'); -const RenderFlow = require('../renderer/render-flow'); -const Material = require('../assets/CCMaterial'); +const Material = require('../assets/material/CCMaterial'); /** * !#en Enum for text alignment. @@ -464,6 +463,7 @@ let Label = cc.Class({ // Keep track of Node size this.node.on(cc.Node.EventType.SIZE_CHANGED, this._updateRenderData, this); this.node.on(cc.Node.EventType.ANCHOR_CHANGED, this._updateRenderData, this); + this.node.on(cc.Node.EventType.COLOR_CHANGED, this._updateColor, this); this._checkStringEmpty(); this._updateRenderData(true); @@ -485,6 +485,12 @@ let Label = cc.Class({ this._super(); }, + _updateColor () { + if (!(this.font instanceof cc.BitmapFont)) { + this._updateRenderData(); + } + }, + _canRender () { let result = this._super(); let font = this.font; @@ -531,7 +537,7 @@ let Label = cc.Class({ self._activateMaterial(force); if (CC_EDITOR || force) { - this._assembler && this._assembler.updateRenderData(this); + self._assembler && self._assembler.updateRenderData(self); } }; // cannot be activated if texture not loaded yet @@ -580,7 +586,7 @@ let Label = cc.Class({ else { if (!material) { material = Material.getInstantiatedBuiltinMaterial('sprite', this); - material.define('useTexture', true); + material.define('USE_TEXTURE', true); } // Setup blend function for premultiplied ttf label texture if (this._texture === this._ttfTexture) { @@ -597,17 +603,6 @@ let Label = cc.Class({ this.markForRender(true); }, - _updateColor () { - let font = this.font; - if (font instanceof cc.BitmapFont) { - this._super(); - } - else { - this._updateRenderData(); - this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; - } - }, - _updateRenderData (force) { let renderData = this._renderData; if (renderData) { diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 1cd0fc08edd..4aae3dcd331 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -25,16 +25,16 @@ ****************************************************************************/ const misc = require('../utils/misc'); -const renderEngine = require('../renderer/render-engine'); -const math = renderEngine.math; -const Material = require('../assets/CCMaterial'); +const Material = require('../assets/material/CCMaterial'); const RenderComponent = require('./CCRenderComponent'); const RenderFlow = require('../renderer/render-flow'); const Graphics = require('../graphics/graphics'); const Node = require('../CCNode'); +import { mat4, vec2 } from '../vmath'; + let _vec2_temp = cc.v2(); -let _mat4_temp = math.mat4.create(); +let _mat4_temp = mat4.create(); let _circlepoints =[]; function _calculateCircle (center, radius, segements) { @@ -196,8 +196,7 @@ let Mask = cc.Class({ } let material = this.sharedMaterials[0]; if (material) { - material.alphaThreshold = this.alphaThreshold; - material.updateHash(); + material.setProperty('alphaThreshold', this.alphaThreshold); } } }, @@ -359,23 +358,21 @@ let Mask = cc.Class({ let material = this.sharedMaterials[0]; if (!material) { material = Material.getInstantiatedBuiltinMaterial('sprite', this); - material.define('alphaTest', true); + material.define('ALPHA_TEST', true); } // Reset material if (this._type === MaskType.IMAGE_STENCIL) { let texture = this.spriteFrame.getTexture(); - material.define('useModel', false); - material.define('useTexture', true); - material.define('useColor', true); + material.define('_USE_MODEL', false); + material.define('USE_TEXTURE', true); material.setProperty('texture', texture); material.setProperty('alphaThreshold', this.alphaThreshold); } else { - material.define('useModel', true); - material.define('useTexture', false); - material.define('useColor', false); + material.define('_USE_MODEL', true); + material.define('USE_TEXTURE', false); } this.setMaterial(0, material); @@ -458,8 +455,8 @@ let Mask = cc.Class({ testPt = _vec2_temp; node._updateWorldMatrix(); - math.mat4.invert(_mat4_temp, node._worldMatrix); - math.vec2.transformMat4(testPt, cameraPt, _mat4_temp); + mat4.invert(_mat4_temp, node._worldMatrix); + vec2.transformMat4(testPt, cameraPt, _mat4_temp); testPt.x += node._anchorPoint.x * w; testPt.y += node._anchorPoint.y * h; diff --git a/cocos2d/core/components/CCMotionStreak.js b/cocos2d/core/components/CCMotionStreak.js index 32bed00bf89..338b09bc664 100644 --- a/cocos2d/core/components/CCMotionStreak.js +++ b/cocos2d/core/components/CCMotionStreak.js @@ -25,7 +25,7 @@ ****************************************************************************/ const RenderComponent = require('../components/CCRenderComponent'); -const Material = require('../assets/CCMaterial'); +const Material = require('../assets/material/CCMaterial'); const textureUtil = require('../utils/texture-util'); /** @@ -243,7 +243,7 @@ var MotionStreak = cc.Class({ let material = this.sharedMaterials[0]; if (!material) { material = Material.getInstantiatedBuiltinMaterial('sprite', this); - material.define('useTexture', true); + material.define('USE_TEXTURE', true); } if (this._texture && this._texture.loaded) { diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index c4e976fb9ef..b229d070d16 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -23,13 +23,13 @@ THE SOFTWARE. ****************************************************************************/ +import gfx from '../../renderer/gfx'; +import RenderData from '../../renderer/render-data/render-data'; + const Component = require('./CCComponent'); -const renderEngine = require('../renderer/render-engine'); const RenderFlow = require('../renderer/render-flow'); const BlendFactor = require('../platform/CCMacro').BlendFactor; -const RenderData = renderEngine.RenderData; -const gfx = renderEngine.gfx; -const Material = require('../assets/CCMaterial'); +const Material = require('../assets/material/CCMaterial'); /** * !#en @@ -68,7 +68,7 @@ let RenderComponent = cc.Class({ set: function(value) { if (this._srcBlendFactor === value) return; this._srcBlendFactor = value; - this._updateBlendFunc(true); + this._updateBlendFunc(); }, animatable: false, type:BlendFactor, @@ -90,7 +90,7 @@ let RenderComponent = cc.Class({ set: function(value) { if (this._dstBlendFactor === value) return; this._dstBlendFactor = value; - this._updateBlendFunc(true); + this._updateBlendFunc(); }, animatable: false, type: BlendFactor, @@ -129,7 +129,7 @@ let RenderComponent = cc.Class({ this.node._renderComponent.enabled = false; } this.node._renderComponent = this; - this.node._renderFlag |= RenderFlow.FLAG_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_COLOR; + this.node._renderFlag |= RenderFlow.FLAG_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA; }, onDisable () { @@ -144,6 +144,13 @@ let RenderComponent = cc.Class({ this.__allocedDatas.length = 0; this._materials.length = 0; this._renderData = null; + + let uniforms = this._uniforms; + for (let name in uniforms) { + _uniformPool.remove(_uniformPool._data.indexOf(uniforms[name])); + } + this._uniforms = null; + this._defines = null; }, _canRender () { @@ -179,7 +186,7 @@ let RenderComponent = cc.Class({ }, disableRender () { - this.node._renderFlag &= ~(RenderFlow.FLAG_RENDER | RenderFlow.FLAG_CUSTOM_IA_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_COLOR); + this.node._renderFlag &= ~(RenderFlow.FLAG_RENDER | RenderFlow.FLAG_CUSTOM_IA_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA); }, requestRenderData () { @@ -196,23 +203,6 @@ let RenderComponent = cc.Class({ } }, - _updateColor () { - let materials = this._materials; - for (let i = 0; i < materials.length; i++) { - let material = materials[i]; - // For batch rendering, update the color only when useColor is set to true. - if (material.getDefine('useColor')) { - material.setProperty('color', this.node.color); - material.updateHash(); - } - } - // reset flag when set color to material successfully - this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; - }, - - getMaterials () { - return this._materials; - }, getMaterial (index) { if (index < 0 || index >= this._materials.length) { return null; @@ -231,21 +221,21 @@ let RenderComponent = cc.Class({ setMaterial (index, material) { this._materials[index] = material; if (material) { - this._updateMaterialBlendFunc(true, material); + this._updateMaterialBlendFunc(material); + this.markForUpdateRenderData(true); } - this.markForUpdateRenderData(true); }, - _updateBlendFunc: function (updateHash) { + _updateBlendFunc: function () { let materials = this._materials; for (let i = 0; i < materials.length; i++) { let material = materials[i]; - this._updateMaterialBlendFunc(updateHash, material); + this._updateMaterialBlendFunc(material); } }, - _updateMaterialBlendFunc (updateHash, material) { - let passes = material._effect.getTechnique('transparent').passes; + _updateMaterialBlendFunc (material) { + let passes = material._effect.getDefaultTechnique().passes; for (let j = 0; j < passes.length; j++) { let pass = passes[j]; pass.setBlend( @@ -256,14 +246,10 @@ let RenderComponent = cc.Class({ this._srcBlendFactor, this._dstBlendFactor ); } - - if (updateHash) { - material.updateHash(); - } }, _activateMaterial (force) { - } + }, }); RenderComponent._assembler = null; RenderComponent._postAssembler = null; diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 27a5aaf7404..7675a2a638c 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -29,7 +29,7 @@ const NodeEvent = require('../CCNode').EventType; const RenderComponent = require('./CCRenderComponent'); const RenderFlow = require('../renderer/render-flow'); -const Material = require('../assets/CCMaterial'); +const Material = require('../assets/material/CCMaterial'); /** * !#en Enum for sprite type. @@ -502,17 +502,13 @@ var Sprite = cc.Class({ if (!material) { material = this._graySpriteMaterial = Material.getInstantiatedBuiltinMaterial('gray-sprite', this); } - - this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; } else { material = this._spriteMaterial; if (!material) { material = this._spriteMaterial = Material.getInstantiatedBuiltinMaterial('sprite', this); - material.define('useColor', true); - material.define('useTexture', true); + material.define('USE_TEXTURE', true); } - this.node._renderFlag |= RenderFlow.FLAG_COLOR; } // Set texture diff --git a/cocos2d/core/graphics/graphics.js b/cocos2d/core/graphics/graphics.js index 92bc0190715..48207ab8e00 100644 --- a/cocos2d/core/graphics/graphics.js +++ b/cocos2d/core/graphics/graphics.js @@ -25,7 +25,7 @@ ****************************************************************************/ const RenderComponent = require('../components/CCRenderComponent'); -const Material = require('../assets/CCMaterial'); +const Material = require('../assets/material/CCMaterial'); const Types = require('./types'); const LineCap = Types.LineCap; @@ -200,7 +200,7 @@ let Graphics = cc.Class({ } let material = Material.getInstantiatedBuiltinMaterial('sprite', this); - material.define('useModel', true); + material.define('_USE_MODEL', true); this.setMaterial(0, material); }, diff --git a/cocos2d/core/mesh/CCMesh.js b/cocos2d/core/mesh/CCMesh.js index 3b12d85b893..5bee7ca80b3 100644 --- a/cocos2d/core/mesh/CCMesh.js +++ b/cocos2d/core/mesh/CCMesh.js @@ -25,8 +25,10 @@ const MeshResource = require('./CCMeshResource'); const renderer = require('../renderer'); -const renderEngine = require('../renderer/render-engine'); -const gfx = renderEngine.gfx; +const EventTarget = require('../event/event-target'); + +import InputAssembler from '../../renderer/core/input-assembler'; +import gfx from '../../renderer/gfx'; function applyColor (data, offset, value) { data[offset] = value._val; @@ -55,6 +57,7 @@ function applyVec3 (data, offset, value) { let Mesh = cc.Class({ name: 'cc.Mesh', extends: cc.Asset, + mixins: [EventTarget], properties: { _resource: { @@ -65,7 +68,7 @@ let Mesh = cc.Class({ /** * !#en Get ir set the sub meshes. * !#zh 设置或者获取子网格。 - * @property {[renderEngine.InputAssembler]} subMeshes + * @property {[InputAssembler]} subMeshes */ subMeshes: { get () { @@ -123,6 +126,8 @@ let Mesh = cc.Class({ data: data, dirty: true }; + + this.emit('init-format'); }, /** @@ -235,7 +240,7 @@ let Mesh = cc.Class({ }; let vb = this._vbs[0]; - this._subMeshes[index] = new renderEngine.InputAssembler(vb.buffer, buffer); + this._subMeshes[index] = new InputAssembler(vb.buffer, buffer); } else { ib.data = data; diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index 5f2a1b111c6..f5769377d29 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -25,11 +25,58 @@ const RenderComponent = require('../components/CCRenderComponent'); const Mesh = require('./CCMesh'); -const renderEngine = require('../renderer/render-engine'); -const gfx = renderEngine.gfx; const RenderFlow = require('../renderer/render-flow'); const aabb = require('../3d/geom-utils/aabb'); -const Material = require('../assets/CCMaterial'); +const Material = require('../assets/material/CCMaterial'); + +import gfx from '../../renderer/gfx'; +import CustomProperties from '../assets/material/custom-properties'; + +/** + * !#en Shadow projection mode + * + * !#ch 阴影投射方式 + * @static + * @enum MeshRenderer.ShadowCastingMode + */ +let ShadowCastingMode = cc.Enum({ + /** + * !#en + * + * !#ch 关闭阴影投射 + * @property OFF + * @readonly + * @type {Number} + */ + OFF: 0, + /** + * !#en + * + * !#ch 开启阴影投射,当阴影光产生的时候 + * @property ON + * @readonly + * @type {Number} + */ + ON: 1, + // /** + // * !#en + // * + // * !#ch 可以从网格的任意一遍投射出阴影 + // * @property TWO_SIDED + // * @readonly + // * @type {Number} + // */ + // TWO_SIDED: 2, + // /** + // * !#en + // * + // * !#ch 只显示阴影 + // * @property SHADOWS_ONLY + // * @readonly + // * @type {Number} + // */ + // SHADOWS_ONLY: 3, +}); let MeshRenderer = cc.Class({ name: 'cc.MeshRenderer', @@ -45,13 +92,16 @@ let MeshRenderer = cc.Class({ type: Mesh }, + _receiveShadows: false, + _shadowCastingMode: ShadowCastingMode.OFF, + mesh: { get () { return this._mesh; }, set (v) { if (this._mesh === v) return; - this._mesh = v; + this._setMesh(v); this._activateMaterial(true); this.markForUpdateRenderData(true); this.node._renderFlag |= RenderFlow.FLAG_TRANSFORM; @@ -61,44 +111,64 @@ let MeshRenderer = cc.Class({ textures: { default: [], - type: cc.Texture2D + type: cc.Texture2D, + visible: false + }, + + receiveShadows: { + get () { + return this._receiveShadows; + }, + set (val) { + this._receiveShadows = val; + this._updateReceiveShadow(); + } + }, + + shadowCastingMode: { + get () { + return this._shadowCastingMode; + }, + set (val) { + this._shadowCastingMode = val; + this._updateCastShadow(); + }, + type: ShadowCastingMode } }, + statics: { + ShadowCastingMode: ShadowCastingMode + }, + ctor () { this._renderDatas = []; - this._materials = []; this._boundingBox = null; + this._customProperties = new CustomProperties(); }, onEnable () { this._super(); + this._setMesh(this._mesh); this._activateMaterial(); }, - _activateSubMaterial (material, subMesh) { - material.define('useTexture', true); - material.define('useModel', true); - - material.setProperty('color', this.node.color); - if (subMesh._vertexBuffer._format._attr2el[gfx.ATTR_COLOR]) { - material.define('useAttributeColor', true); - } + onDestroy () { + this._setMesh(null); }, - _updateColor () { - let materials = this._materials; - for (let i = 0; i < materials.length; i++) { - let material = materials[i]; - material.setProperty('color', this.node.color); - material.updateHash(); + _setMesh (mesh) { + if (this._mesh) { + this._mesh.off('init-format', this._updateMeshAttribute, this); } - - this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; + if (mesh) { + mesh.on('init-format', this._updateMeshAttribute, this); + } + this._mesh = mesh; }, - _reset () { - this._materials.length = 0; + _getDefaultMaterial () { + return Material.getBuiltinMaterial('unlit'); }, _activateMaterial (force) { @@ -116,25 +186,48 @@ let MeshRenderer = cc.Class({ if (aabb) { this._boundingBox = aabb.fromPoints(aabb.create(), mesh._minPos, mesh._maxPos); } - - this._reset(); - let subMeshes = mesh._subMeshes; - let materials = this.sharedMaterials; + // TODO: used to upgrade from 2.1, should be removed + let textures = this.textures; + if (textures && textures.length > 0) { + for (let i = 0; i < textures.length; i++) { + let material = this.sharedMaterials[i]; + if (material) continue; + material = cc.Material.getInstantiatedMaterial(this._getDefaultMaterial(), this); + material.setProperty('texture', textures[i]); + this.setMaterial(i, material); + } + } + let materials = this.sharedMaterials; if (!materials[0]) { - materials[0] = Material.getInstantiatedBuiltinMaterial('mesh', this); + let material = this._getDefaultMaterial(); + materials[0] = material; } - for (let i = 0; i < materials.length; i++) { - let subMesh = subMeshes[i]; - if (!subMesh) continue; - let material = materials[i]; - this._activateSubMaterial(material, subMesh); - } + this._updateMeshAttribute(); + this._updateReceiveShadow(); + this._updateCastShadow(); this.markForUpdateRenderData(true); this.markForRender(true); + }, + + _updateReceiveShadow () { + this._customProperties.define('_USE_SHADOW_MAP', this._receiveShadows); + }, + + _updateCastShadow () { + this._customProperties.define('_SHADOW_CASTING', this._shadowCastingMode === ShadowCastingMode.ON); + }, + + _updateMeshAttribute () { + let subMeshes = this._mesh && this._mesh.subMeshes; + if (!subMeshes) return; + + let attr2el = subMeshes[0]._vertexBuffer._format._attr2el; + this._customProperties.define('_USE_ATTRIBUTE_COLOR', !!attr2el[gfx.ATTR_COLOR]); + this._customProperties.define('_USE_ATTRIBUTE_UV0', !!attr2el[gfx.ATTR_UV0]); } }); diff --git a/cocos2d/core/mesh/mesh-renderer.js b/cocos2d/core/mesh/mesh-renderer.js index 45cc9dce76f..b39570a5fdc 100644 --- a/cocos2d/core/mesh/mesh-renderer.js +++ b/cocos2d/core/mesh/mesh-renderer.js @@ -23,17 +23,15 @@ THE SOFTWARE. ****************************************************************************/ -const MeshRenderer = require('./CCMeshRenderer'); +import gfx from '../../renderer/gfx'; +import InputAssembler from '../../renderer/core/input-assembler'; +import IARenderData from '../../renderer/render-data/ia-render-data'; -const renderEngine = require('../renderer/render-engine'); -const IARenderData = renderEngine.IARenderData; -const gfx = renderEngine.gfx; -const InputAssembler = renderEngine.InputAssembler; +const MeshRenderer = require('./CCMeshRenderer'); const BLACK_COLOR = cc.Color.BLACK; let meshRendererAssembler = { - useModel: true, updateRenderData (comp) { let renderDatas = comp._renderDatas; renderDatas.length = 0; @@ -50,9 +48,8 @@ let meshRendererAssembler = { createWireFrameData (ia, oldIbData, material, renderer) { let data = new IARenderData(); let m = material.clone(); - m.color = BLACK_COLOR; - m.useTexture = false; - m._mainTech._passes[0].setDepth(true, true); + m.setProperty('color', BLACK_COLOR); + m.define('USE_TEXTURE', false); data.material = m; let indices = []; @@ -101,23 +98,20 @@ let meshRendererAssembler = { let tmpNode = renderer.node; renderer.node = comp instanceof cc.SkinnedMeshRenderer ? renderer._dummyNode : comp.node; + renderer.customProperties = comp._customProperties; + let tmpCustomProperties = renderer.customProperties; + comp.mesh._uploadData(); - let textures = comp.textures; for (let i = 0; i < renderDatas.length; i++) { let renderData = renderDatas[i]; let material = renderData.material; - if (textures[i]) { - material.setProperty('texture', textures[i]); - } - else { - material.define('useTexture', false); - } renderer.material = material; renderer._flushIA(renderData); } + renderer.customProperties = tmpCustomProperties; renderer.node = tmpNode; renderer.material = tmpMaterial; } diff --git a/cocos2d/core/renderer/canvas/Device.js b/cocos2d/core/renderer/canvas/Device.js new file mode 100644 index 00000000000..f9860f1e8d1 --- /dev/null +++ b/cocos2d/core/renderer/canvas/Device.js @@ -0,0 +1,86 @@ + +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +var Device = function Device(canvasEL) { + var ctx; + + try { + ctx = canvasEL.getContext('2d'); + } catch (err) { + console.error(err); + return; + } + + // statics + this._canvas = canvasEL; + this._ctx = ctx; + this._caps = {}; // capability + this._stats = { + drawcalls: 0, + }; + + // runtime + this._vx = this._vy = this._vw = this._vh = 0; + this._sx = this._sy = this._sw = this._sh = 0; +}; + +Device.prototype._restoreTexture = function _restoreTexture (unit) { +}; + +// =============================== +// Immediate Settings +// =============================== + +/** + * @method setViewport + * @param {Number} x + * @param {Number} y + * @param {Number} w + * @param {Number} h + */ +Device.prototype.setViewport = function setViewport (x, y, w, h) { + if ( + this._vx !== x || + this._vy !== y || + this._vw !== w || + this._vh !== h + ) { + this._vx = x; + this._vy = y; + this._vw = w; + this._vh = h; + } +}; + +/** + * @method setScissor + * @param {Number} x + * @param {Number} y + * @param {Number} w + * @param {Number} h + */ +Device.prototype.setScissor = function setScissor (x, y, w, h) { + if ( + this._sx !== x || + this._sy !== y || + this._sw !== w || + this._sh !== h + ) { + this._sx = x; + this._sy = y; + this._sw = w; + this._sh = h; + } +}; + +Device.prototype.clear = function clear (color) { + var ctx = this._ctx; + ctx.clearRect(this._vx, this._vy, this._vw, this._vh); + if (color && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { + ctx.fillStyle = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] +')'; + ctx.globalAlpha = color[3]; + ctx.fillRect(this._vx, this._vy, this._vw, this._vh); + } +}; + +module.exports = Device; diff --git a/cocos2d/core/renderer/canvas/Texture2D.js b/cocos2d/core/renderer/canvas/Texture2D.js new file mode 100644 index 00000000000..8bda7d7f6a7 --- /dev/null +++ b/cocos2d/core/renderer/canvas/Texture2D.js @@ -0,0 +1,41 @@ + +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +var Texture2D = function Texture2D(device, options) { + this._device = device; + + this._width = 4; + this._height = 4; + + this._image = null; + + if (options) { + if (options.width !== undefined) { + this._width = options.width; + } + if (options.height !== undefined) { + this._height = options.height; + } + + this.updateImage(options); + } +}; + +Texture2D.prototype.update = function update (options) { + this.updateImage(options); +}; + +Texture2D.prototype.updateImage = function updateImage (options) { + if (options.images && options.images[0]) { + var image = options.images[0]; + if (image && image !== this._image) { + this._image = image; + } + } +}; + +Texture2D.prototype.destroy = function destroy () { + this._image = null; +}; + +module.exports = Texture2D; diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 6d71accf9ef..8cb8233df86 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -23,17 +23,25 @@ THE SOFTWARE. ****************************************************************************/ -const renderEngine = require('./render-engine'); +import ForwardRenderer from '../../renderer/renderers/forward-renderer'; +import config from '../../renderer/config'; +import gfx from '../../renderer/gfx'; +import Scene from '../../renderer/scene/scene'; + +import InputAssembler from '../../renderer/core/input-assembler'; +import IARenderData from '../../renderer/render-data/ia-render-data'; +import Pass from '../../renderer/core/pass'; + const RenderFlow = require('./render-flow'); function _initBuiltins(device) { - let defaultTexture = new renderEngine.Texture2D(device, { + let defaultTexture = new gfx.Texture2D(device, { images: [], width: 128, height: 128, - wrapS: renderEngine.gfx.WRAP_REPEAT, - wrapT: renderEngine.gfx.WRAP_REPEAT, - format: renderEngine.gfx.TEXTURE_FMT_RGB8, + wrapS: gfx.WRAP_REPEAT, + wrapT: gfx.WRAP_REPEAT, + format: gfx.TEXTURE_FMT_RGB8, mipmap: false, }); @@ -56,6 +64,12 @@ function _initBuiltins(device) { * @static */ cc.renderer = module.exports = { + Texture2D: null, + + InputAssembler: InputAssembler, + IARenderData: IARenderData, + Pass: Pass, + /** * !#en The render engine is available only after cc.game.EVENT_ENGINE_INITED event.
* Normally it will be inited as the webgl render engine, but in wechat open context domain, @@ -63,10 +77,10 @@ cc.renderer = module.exports = { * !#zh 基础渲染引擎对象只在 cc.game.EVENT_ENGINE_INITED 事件触发后才可获取。
* 大多数情况下,它都会是 WebGL 渲染引擎实例,但是在微信开放数据域当中,它会是 Canvas 渲染引擎实例。请注意,从 2.0 开始,我们在其他平台和环境下都废弃了 Canvas 渲染器。 * @property renderEngine + * @deprecated * @type {Object} */ - renderEngine: renderEngine, - Texture2D: null, + renderEngine: null, /* * !#en The canvas object which provides the rendering context @@ -79,7 +93,7 @@ cc.renderer = module.exports = { * !#en The device object which provides device related rendering functionality, it divers for different render engine type. * !#zh 提供设备渲染能力的对象,它对于不同的渲染环境功能也不相同。 * @property device - * @type {renderer.renderEngine.Device} + * @type {renderer.Device} */ device: null, scene: null, @@ -100,7 +114,7 @@ cc.renderer = module.exports = { require('./webgl/assemblers'); const ModelBatcher = require('./webgl/model-batcher'); - this.Texture2D = renderEngine.Texture2D; + this.Texture2D = gfx.Texture2D; this.canvas = canvas; if (CC_JSB && CC_NATIVERENDERER) { @@ -108,30 +122,34 @@ cc.renderer = module.exports = { this.device = window.device; } else { - this.device = new renderEngine.Device(canvas, opts); + this.device = new gfx.Device(canvas, opts); } - this.scene = new renderEngine.Scene(); + this.scene = new Scene(); this._handle = new ModelBatcher(this.device, this.scene); RenderFlow.init(this._handle); let builtins = _initBuiltins(this.device); - this._forward = new renderEngine.ForwardRenderer(this.device, builtins); + this._forward = new ForwardRenderer(this.device, builtins); + config.addStage('shadowcast'); + config.addStage('opaque'); + config.addStage('transparent'); }, initCanvas (canvas) { let canvasRenderer = require('./canvas'); + const Texture2D = require('./canvas/Texture2D'); + const Device = require('./canvas/Device'); if (CC_TEST) { // It's actually running with original render engine - renderEngine.Texture2D = renderEngine.canvas.Texture2D; - renderEngine.Device = renderEngine.canvas.Device; + this.Device = Device; } - this.Texture2D = renderEngine.Texture2D; + this.Texture2D = Texture2D; this.canvas = canvas; - this.device = new renderEngine.Device(canvas); + this.device = new Device(canvas); this._camera = { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }; diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js deleted file mode 100644 index 75b5f40ba3e..00000000000 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ /dev/null @@ -1,8874 +0,0 @@ - -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - render-engine v1.2.0 - 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. - ****************************************************************************/ - - -'use strict'; - -// reference: https://github.com/mziccard/node-timsort - -/** - * Default minimum size of a run. - */ -var DEFAULT_MIN_MERGE = 32; - -/** - * Minimum ordered subsequece required to do galloping. - */ -var DEFAULT_MIN_GALLOPING = 7; - -/** - * Default tmp storage length. Can increase depending on the size of the - * smallest run to merge. - */ -var DEFAULT_TMP_STORAGE_LENGTH = 256; - -/** - * Pre-computed powers of 10 for efficient lexicographic comparison of - * small integers. - */ -var POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9]; - -/** - * Estimate the logarithm base 10 of a small integer. - * - * @param {number} x - The integer to estimate the logarithm of. - * @return {number} - The estimated logarithm of the integer. - */ -function log10(x) { - if (x < 1e5) { - if (x < 1e2) { - return x < 1e1 ? 0 : 1; - } - - if (x < 1e4) { - return x < 1e3 ? 2 : 3; - } - - return 4; - } - - if (x < 1e7) { - return x < 1e6 ? 5 : 6; - } - - if (x < 1e9) { - return x < 1e8 ? 7 : 8; - } - - return 9; -} - -/** - * Default alphabetical comparison of items. - * - * @param {string|object|number} a - First element to compare. - * @param {string|object|number} b - Second element to compare. - * @return {number} - A positive number if a.toString() > b.toString(), a - * negative number if .toString() < b.toString(), 0 otherwise. - */ -function alphabeticalCompare(a, b) { - if (a === b) { - return 0; - } - - if (~~a === a && ~~b === b) { - if (a === 0 || b === 0) { - return a < b ? -1 : 1; - } - - if (a < 0 || b < 0) { - if (b >= 0) { - return -1; - } - - if (a >= 0) { - return 1; - } - - a = -a; - b = -b; - } - - var al = log10(a); - var bl = log10(b); - - var t = 0; - - if (al < bl) { - a *= POWERS_OF_TEN[bl - al - 1]; - b /= 10; - t = -1; - } else if (al > bl) { - b *= POWERS_OF_TEN[al - bl - 1]; - a /= 10; - t = 1; - } - - if (a === b) { - return t; - } - - return a < b ? -1 : 1; - } - - var aStr = String(a); - var bStr = String(b); - - if (aStr === bStr) { - return 0; - } - - return aStr < bStr ? -1 : 1; -} - -/** - * Compute minimum run length for TimSort - * - * @param {number} n - The size of the array to sort. - */ -function minRunLength(n) { - var r = 0; - - while (n >= DEFAULT_MIN_MERGE) { - r |= (n & 1); - n >>= 1; - } - - return n + r; -} - -/** - * Counts the length of a monotonically ascending or strictly monotonically - * descending sequence (run) starting at array[lo] in the range [lo, hi). If - * the run is descending it is made ascending. - * - * @param {array} array - The array to reverse. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {function} compare - Item comparison function. - * @return {number} - The length of the run. - */ -function makeAscendingRun(array, lo, hi, compare) { - var runHi = lo + 1; - - if (runHi === hi) { - return 1; - } - - // Descending - if (compare(array[runHi++], array[lo]) < 0) { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { - runHi++; - } - - reverseRun(array, lo, runHi); - // Ascending - } else { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { - runHi++; - } - } - - return runHi - lo; -} - -/** - * Reverse an array in the range [lo, hi). - * - * @param {array} array - The array to reverse. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - */ -function reverseRun(array, lo, hi) { - hi--; - - while (lo < hi) { - var t = array[lo]; - array[lo++] = array[hi]; - array[hi--] = t; - } -} - -/** - * Perform the binary sort of the array in the range [lo, hi) where start is - * the first element possibly out of order. - * - * @param {array} array - The array to sort. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {number} start - First element possibly out of order. - * @param {function} compare - Item comparison function. - */ -function binaryInsertionSort(array, lo, hi, start, compare) { - if (start === lo) { - start++; - } - - for (; start < hi; start++) { - var pivot = array[start]; - - // Ranges of the array where pivot belongs - var left = lo; - var right = start; - - /* - * pivot >= array[i] for i in [lo, left) - * pivot < array[i] for i in in [right, start) - */ - while (left < right) { - var mid = (left + right) >>> 1; - - if (compare(pivot, array[mid]) < 0) { - right = mid; - } else { - left = mid + 1; - } - } - - /* - * Move elements right to make room for the pivot. If there are elements - * equal to pivot, left points to the first slot after them: this is also - * a reason for which TimSort is stable - */ - var n = start - left; - // Switch is just an optimization for small arrays - switch (n) { - case 3: - array[left + 3] = array[left + 2]; - /* falls through */ - case 2: - array[left + 2] = array[left + 1]; - /* falls through */ - case 1: - array[left + 1] = array[left]; - break; - default: - while (n > 0) { - array[left + n] = array[left + n - 1]; - n--; - } - } - - array[left] = pivot; - } -} - -/** - * Find the position at which to insert a value in a sorted range. If the range - * contains elements equal to the value the leftmost element index is returned - * (for stability). - * - * @param {number} value - Value to insert. - * @param {array} array - The array in which to insert value. - * @param {number} start - First element in the range. - * @param {number} length - Length of the range. - * @param {number} hint - The index at which to begin the search. - * @param {function} compare - Item comparison function. - * @return {number} - The index where to insert value. - */ -function gallopLeft(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) > 0) { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - lastOffset += hint; - offset += hint; - - // value <= array[start + hint] - } else { - maxOffset = hint + 1; - while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - } - - /* - * Now array[start+lastOffset] < value <= array[start+offset], so value - * belongs somewhere in the range (start + lastOffset, start + offset]. Do a - * binary search, with invariant array[start + lastOffset - 1] < value <= - * array[start + offset]. - */ - lastOffset++; - while (lastOffset < offset) { - var m = lastOffset + ((offset - lastOffset) >>> 1); - - if (compare(value, array[start + m]) > 0) { - lastOffset = m + 1; - - } else { - offset = m; - } - } - return offset; -} - -/** - * Find the position at which to insert a value in a sorted range. If the range - * contains elements equal to the value the rightmost element index is returned - * (for stability). - * - * @param {number} value - Value to insert. - * @param {array} array - The array in which to insert value. - * @param {number} start - First element in the range. - * @param {number} length - Length of the range. - * @param {number} hint - The index at which to begin the search. - * @param {function} compare - Item comparison function. - * @return {number} - The index where to insert value. - */ -function gallopRight(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) < 0) { - maxOffset = hint + 1; - - while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - - // value >= array[start + hint] - } else { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - lastOffset += hint; - offset += hint; - } - - /* - * Now array[start+lastOffset] < value <= array[start+offset], so value - * belongs somewhere in the range (start + lastOffset, start + offset]. Do a - * binary search, with invariant array[start + lastOffset - 1] < value <= - * array[start + offset]. - */ - lastOffset++; - - while (lastOffset < offset) { - var m = lastOffset + ((offset - lastOffset) >>> 1); - - if (compare(value, array[start + m]) < 0) { - offset = m; - - } else { - lastOffset = m + 1; - } - } - - return offset; -} - -var TimSort = function TimSort(array, compare) { - this.array = array; - this.compare = compare; - this.minGallop = DEFAULT_MIN_GALLOPING; - this.length = array.length; - - this.tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH; - if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) { - this.tmpStorageLength = this.length >>> 1; - } - - this.tmp = new Array(this.tmpStorageLength); - - this.stackLength = - (this.length < 120 ? 5 : - this.length < 1542 ? 10 : - this.length < 119151 ? 19 : 40); - - this.runStart = new Array(this.stackLength); - this.runLength = new Array(this.stackLength); - this.stackSize = 0; -}; - -/** - * Push a new run on TimSort's stack. - * - * @param {number} runStart - Start index of the run in the original array. - * @param {number} runLength - Length of the run; - */ -TimSort.prototype.pushRun = function pushRun (runStart, runLength) { - this.runStart[this.stackSize] = runStart; - this.runLength[this.stackSize] = runLength; - this.stackSize += 1; -}; - -/** - * Merge runs on TimSort's stack so that the following holds for all i: - * 1) runLength[i - 3] > runLength[i - 2] + runLength[i - 1] - * 2) runLength[i - 2] > runLength[i - 1] - */ -TimSort.prototype.mergeRuns = function mergeRuns () { - var this$1 = this; - - while (this.stackSize > 1) { - var n = this$1.stackSize - 2; - - if ((n >= 1 && - this$1.runLength[n - 1] <= this$1.runLength[n] + this$1.runLength[n + 1]) || - (n >= 2 && - this$1.runLength[n - 2] <= this$1.runLength[n] + this$1.runLength[n - 1])) { - - if (this$1.runLength[n - 1] < this$1.runLength[n + 1]) { - n--; - } - - } else if (this$1.runLength[n] > this$1.runLength[n + 1]) { - break; - } - this$1.mergeAt(n); - } -}; - -/** - * Merge all runs on TimSort's stack until only one remains. - */ -TimSort.prototype.forceMergeRuns = function forceMergeRuns () { - var this$1 = this; - - while (this.stackSize > 1) { - var n = this$1.stackSize - 2; - - if (n > 0 && this$1.runLength[n - 1] < this$1.runLength[n + 1]) { - n--; - } - - this$1.mergeAt(n); - } -}; - -/** - * Merge the runs on the stack at positions i and i+1. Must be always be called - * with i=stackSize-2 or i=stackSize-3 (that is, we merge on top of the stack). - * - * @param {number} i - Index of the run to merge in TimSort's stack. - */ -TimSort.prototype.mergeAt = function mergeAt (i) { - var compare = this.compare; - var array = this.array; - - var start1 = this.runStart[i]; - var length1 = this.runLength[i]; - var start2 = this.runStart[i + 1]; - var length2 = this.runLength[i + 1]; - - this.runLength[i] = length1 + length2; - - if (i === this.stackSize - 3) { - this.runStart[i + 1] = this.runStart[i + 2]; - this.runLength[i + 1] = this.runLength[i + 2]; - } - - this.stackSize--; - - /* - * Find where the first element in the second run goes in run1. Previous - * elements in run1 are already in place - */ - var k = gallopRight(array[start2], array, start1, length1, 0, compare); - start1 += k; - length1 -= k; - - if (length1 === 0) { - return; - } - - /* - * Find where the last element in the first run goes in run2. Next elements - * in run2 are already in place - */ - length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); - - if (length2 === 0) { - return; - } - - /* - * Merge remaining runs. A tmp array with length = min(length1, length2) is - * used - */ - if (length1 <= length2) { - this.mergeLow(start1, length1, start2, length2); - - } else { - this.mergeHigh(start1, length1, start2, length2); - } -}; - -/** - * Merge two adjacent runs in a stable way. The runs must be such that the - * first element of run1 is bigger than the first element in run2 and the - * last element of run1 is greater than all the elements in run2. - * The method should be called when run1.length <= run2.length as it uses - * TimSort temporary array to store run1. Use mergeHigh if run1.length > - * run2.length. - * - * @param {number} start1 - First element in run1. - * @param {number} length1 - Length of run1. - * @param {number} start2 - First element in run2. - * @param {number} length2 - Length of run2. - */ -TimSort.prototype.mergeLow = function mergeLow (start1, length1, start2, length2) { - - var compare = this.compare; - var array = this.array; - var tmp = this.tmp; - var i = 0; - - for (i = 0; i < length1; i++) { - tmp[i] = array[start1 + i]; - } - - var cursor1 = 0; - var cursor2 = start2; - var dest = start1; - - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - return; - } - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - array[dest + length2] = tmp[cursor1]; - return; - } - - var minGallop = this.minGallop; - - while (true) { - var count1 = 0; - var count2 = 0; - var exit = false; - - do { - if (compare(array[cursor2], tmp[cursor1]) < 0) { - array[dest++] = array[cursor2++]; - count2++; - count1 = 0; - - if (--length2 === 0) { - exit = true; - break; - } - - } else { - array[dest++] = tmp[cursor1++]; - count1++; - count2 = 0; - if (--length1 === 1) { - exit = true; - break; - } - } - } while ((count1 | count2) < minGallop); - - if (exit) { - break; - } - - do { - count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); - - if (count1 !== 0) { - for (i = 0; i < count1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - - dest += count1; - cursor1 += count1; - length1 -= count1; - if (length1 <= 1) { - exit = true; - break; - } - } - - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - exit = true; - break; - } - - count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); - - if (count2 !== 0) { - for (i = 0; i < count2; i++) { - array[dest + i] = array[cursor2 + i]; - } - - dest += count2; - cursor2 += count2; - length2 -= count2; - - if (length2 === 0) { - exit = true; - break; - } - } - array[dest++] = tmp[cursor1++]; - - if (--length1 === 1) { - exit = true; - break; - } - - minGallop--; - - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (minGallop < 0) { - minGallop = 0; - } - - minGallop += 2; - } - - this.minGallop = minGallop; - - if (minGallop < 1) { - this.minGallop = 1; - } - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - array[dest + length2] = tmp[cursor1]; - - } else if (length1 === 0) { - throw new Error('mergeLow preconditions were not respected'); - - } else { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - } -}; - -/** - * Merge two adjacent runs in a stable way. The runs must be such that the - * first element of run1 is bigger than the first element in run2 and the - * last element of run1 is greater than all the elements in run2. - * The method should be called when run1.length > run2.length as it uses - * TimSort temporary array to store run2. Use mergeLow if run1.length <= - * run2.length. - * - * @param {number} start1 - First element in run1. - * @param {number} length1 - Length of run1. - * @param {number} start2 - First element in run2. - * @param {number} length2 - Length of run2. - */ -TimSort.prototype.mergeHigh = function mergeHigh (start1, length1, start2, length2) { - var compare = this.compare; - var array = this.array; - var tmp = this.tmp; - var i = 0; - - for (i = 0; i < length2; i++) { - tmp[i] = array[start2 + i]; - } - - var cursor1 = start1 + length1 - 1; - var cursor2 = length2 - 1; - var dest = start2 + length2 - 1; - var customCursor = 0; - var customDest = 0; - - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - customCursor = dest - (length2 - 1); - - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - - return; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - return; - } - - var minGallop = this.minGallop; - - while (true) { - var count1 = 0; - var count2 = 0; - var exit = false; - - do { - if (compare(tmp[cursor2], array[cursor1]) < 0) { - array[dest--] = array[cursor1--]; - count1++; - count2 = 0; - if (--length1 === 0) { - exit = true; - break; - } - - } else { - array[dest--] = tmp[cursor2--]; - count2++; - count1 = 0; - if (--length2 === 1) { - exit = true; - break; - } - } - - } while ((count1 | count2) < minGallop); - - if (exit) { - break; - } - - do { - count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); - - if (count1 !== 0) { - dest -= count1; - cursor1 -= count1; - length1 -= count1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = count1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - if (length1 === 0) { - exit = true; - break; - } - } - - array[dest--] = tmp[cursor2--]; - - if (--length2 === 1) { - exit = true; - break; - } - - count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); - - if (count2 !== 0) { - dest -= count2; - cursor2 -= count2; - length2 -= count2; - customDest = dest + 1; - customCursor = cursor2 + 1; - - for (i = 0; i < count2; i++) { - array[customDest + i] = tmp[customCursor + i]; - } - - if (length2 <= 1) { - exit = true; - break; - } - } - - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - exit = true; - break; - } - - minGallop--; - - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (minGallop < 0) { - minGallop = 0; - } - - minGallop += 2; - } - - this.minGallop = minGallop; - - if (minGallop < 1) { - this.minGallop = 1; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - - } else if (length2 === 0) { - throw new Error('mergeHigh preconditions were not respected'); - - } else { - customCursor = dest - (length2 - 1); - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - } -}; - -/** - * Sort an array in the range [lo, hi) using TimSort. - * - * @param {array} array - The array to sort. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {function=} compare - Item comparison function. Default is alphabetical. - */ -function sort (array, lo, hi, compare) { - if (!Array.isArray(array)) { - throw new TypeError('Can only sort arrays'); - } - - /* - * Handle the case where a comparison function is not provided. We do - * lexicographic sorting - */ - - if (lo === undefined) { - lo = 0; - } - - if (hi === undefined) { - hi = array.length; - } - - if (compare === undefined) { - compare = alphabeticalCompare; - } - - var remaining = hi - lo; - - // The array is already sorted - if (remaining < 2) { - return; - } - - var runLength = 0; - // On small arrays binary sort can be used directly - if (remaining < DEFAULT_MIN_MERGE) { - runLength = makeAscendingRun(array, lo, hi, compare); - binaryInsertionSort(array, lo, hi, lo + runLength, compare); - return; - } - - var ts = new TimSort(array, compare); - - var minRun = minRunLength(remaining); - - do { - runLength = makeAscendingRun(array, lo, hi, compare); - if (runLength < minRun) { - var force = remaining; - if (force > minRun) { - force = minRun; - } - - binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); - runLength = force; - } - // Push new run and merge if necessary - ts.pushRun(lo, runLength); - ts.mergeRuns(); - - // Go find next run - remaining -= runLength; - lo += runLength; - - } while (remaining !== 0); - - // Force merging of remaining runs - ts.forceMergeRuns(); -} - -var FixedArray = function FixedArray(size) { - this._count = 0; - this._data = new Array(size); -}; - -var prototypeAccessors = { length: { configurable: true },data: { configurable: true } }; - -FixedArray.prototype._resize = function _resize (size) { - var this$1 = this; - - if (size > this._data.length) { - for (var i = this._data.length; i < size; ++i) { - this$1._data[i] = undefined; - } - } -}; - -prototypeAccessors.length.get = function () { - return this._count; -}; - -prototypeAccessors.data.get = function () { - return this._data; -}; - -FixedArray.prototype.reset = function reset () { - var this$1 = this; - - for (var i = 0; i < this._count; ++i) { - this$1._data[i] = undefined; - } - - this._count = 0; -}; - -FixedArray.prototype.push = function push (val) { - if (this._count >= this._data.length) { - this._resize(this._data.length * 2); - } - - this._data[this._count] = val; - ++this._count; -}; - -FixedArray.prototype.pop = function pop () { - --this._count; - - if (this._count < 0) { - this._count = 0; - } - - var ret = this._data[this._count]; - this._data[this._count] = undefined; - - return ret; -}; - -FixedArray.prototype.fastRemove = function fastRemove (idx) { - if (idx >= this._count) { - return; - } - - var last = this._count - 1; - this._data[idx] = this._data[last]; - this._data[last] = undefined; - this._count -= 1; -}; - -FixedArray.prototype.indexOf = function indexOf (val) { - var idx = this._data.indexOf(val); - if (idx >= this._count) { - return -1; - } - - return idx; -}; - -FixedArray.prototype.sort = function sort$1 (cmp) { - return sort(this._data, 0, this._count, cmp); -}; - -Object.defineProperties( FixedArray.prototype, prototypeAccessors ); - -var Pool = function Pool(fn, size) { - var this$1 = this; - - this._fn = fn; - this._idx = size - 1; - this._frees = new Array(size); - - for (var i = 0; i < size; ++i) { - this$1._frees[i] = fn(); - } -}; - -Pool.prototype._expand = function _expand (size) { - var this$1 = this; - - var old = this._frees; - this._frees = new Array(size); - - var len = size - old.length; - for (var i = 0; i < len; ++i) { - this$1._frees[i] = this$1._fn(); - } - - for (var i$1 = len, j = 0; i$1 < size; ++i$1, ++j) { - this$1._frees[i$1] = old[j]; - } - - this._idx += len; -}; - -Pool.prototype.alloc = function alloc () { - // create some more space (expand by 20%, minimum 1) - if (this._idx < 0) { - this._expand(Math.round(this._frees.length * 1.2) + 1); - } - - var ret = this._frees[this._idx]; - this._frees[this._idx] = null; - --this._idx; - - return ret; -}; - -Pool.prototype.free = function free (obj) { - ++this._idx; - this._frees[this._idx] = obj; -}; - -// NOTE: you must have `_prev` and `_next` field in the object returns by `fn` - -var LinkedArray = function LinkedArray(fn, size) { - this._fn = fn; - this._count = 0; - this._head = null; - this._tail = null; - - this._pool = new Pool(fn, size); -}; - -var prototypeAccessors$1 = { head: { configurable: true },tail: { configurable: true },length: { configurable: true } }; - -prototypeAccessors$1.head.get = function () { - return this._head; -}; - -prototypeAccessors$1.tail.get = function () { - return this._tail; -}; - -prototypeAccessors$1.length.get = function () { - return this._count; -}; - -LinkedArray.prototype.add = function add () { - var node = this._pool.alloc(); - - if (!this._tail) { - this._head = node; - } else { - this._tail._next = node; - node._prev = this._tail; - } - this._tail = node; - this._count += 1; - - return node; -}; - -LinkedArray.prototype.remove = function remove (node) { - if (node._prev) { - node._prev._next = node._next; - } else { - this._head = node._next; - } - - if (node._next) { - node._next._prev = node._prev; - } else { - this._tail = node._prev; - } - - node._next = null; - node._prev = null; - this._pool.free(node); - this._count -= 1; -}; - -LinkedArray.prototype.forEach = function forEach (fn, binder) { - var this$1 = this; - - var cursor = this._head; - if (!cursor) { - return; - } - - if (binder) { - fn = fn.bind(binder); - } - - var idx = 0; - var next = cursor; - - while (cursor) { - next = cursor._next; - fn(cursor, idx, this$1); - - cursor = next; - ++idx; - } -}; - -Object.defineProperties( LinkedArray.prototype, prototypeAccessors$1 ); - -var RecyclePool = function RecyclePool(fn, size) { - var this$1 = this; - - this._fn = fn; - this._count = 0; - this._data = new Array(size); - - for (var i = 0; i < size; ++i) { - this$1._data[i] = fn(); - } -}; - -var prototypeAccessors$2 = { length: { configurable: true },data: { configurable: true } }; - -prototypeAccessors$2.length.get = function () { - return this._count; -}; - -prototypeAccessors$2.data.get = function () { - return this._data; -}; - -RecyclePool.prototype.reset = function reset () { - this._count = 0; -}; - -RecyclePool.prototype.resize = function resize (size) { - var this$1 = this; - - if (size > this._data.length) { - for (var i = this._data.length; i < size; ++i) { - this$1._data[i] = this$1._fn(); - } - } -}; - -RecyclePool.prototype.add = function add () { - if (this._count >= this._data.length) { - this.resize(this._data.length * 2); - } - - return this._data[this._count++]; -}; - -RecyclePool.prototype.remove = function remove (idx) { - if (idx >= this._count) { - return; - } - - var last = this._count - 1; - var tmp = this._data[idx]; - this._data[idx] = this._data[last]; - this._data[last] = tmp; - this._count -= 1; -}; - -RecyclePool.prototype.sort = function sort$1 (cmp) { - return sort(this._data, 0, this._count, cmp); -}; - -Object.defineProperties( RecyclePool.prototype, prototypeAccessors$2 ); - -var _bufferPools = Array(8); -for (var i = 0; i < 8; ++i) { - _bufferPools[i] = []; -} - -// Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - -/** - * BaseRenderData is a core data abstraction for renderer, this is a abstract class. - * An inherited render data type should define raw vertex datas. - * User should also define the effect, vertex count and index count. - */ -var BaseRenderData = function BaseRenderData () { - this.material = null; - this.vertexCount = 0; - this.indiceCount = 0; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _pool; -var _dataPool = new Pool(function () { - return { - x: 0.0, - y: 0.0, - z: 0.0, - u: 0.0, - v: 0.0, - color: 0 - }; -}, 128); - -/** - * RenderData is most widely used render data type. - * It describes raw vertex data with a fixed data layout. - * Each vertex is described by five property: x, y, u, v, color. The data layout might be extended in the future. - * Vertex data objects are managed automatically by RenderData, user only need to set the dataLength property. - * User can also define rendering index orders for the vertex list. - */ -var RenderData = (function (BaseRenderData$$1) { - function RenderData () { - BaseRenderData$$1.call(this); - this._data = []; - this._indices = []; - - this._pivotX = 0; - this._pivotY = 0; - this._width = 0; - this._height = 0; - - this.uvDirty = true; - this.vertDirty = true; - } - - if ( BaseRenderData$$1 ) RenderData.__proto__ = BaseRenderData$$1; - RenderData.prototype = Object.create( BaseRenderData$$1 && BaseRenderData$$1.prototype ); - RenderData.prototype.constructor = RenderData; - - var prototypeAccessors = { type: { configurable: true },dataLength: { configurable: true } }; - - prototypeAccessors.type.get = function () { - return RenderData.type; - }; - - prototypeAccessors.dataLength.get = function () { - return this._data.length; - }; - - prototypeAccessors.dataLength.set = function (length) { - var data = this._data; - if (data.length !== length) { - // Free extra data - for (var i = length; i < data.length; i++) { - _dataPool.free(data[i]); - } - // Alloc needed data - for (var i$1 = data.length; i$1 < length; i$1++) { - data[i$1] = _dataPool.alloc(); - } - data.length = length; - } - }; - - RenderData.prototype.updateSizeNPivot = function updateSizeNPivot (width, height, pivotX, pivotY) { - if (width !== this._width || - height !== this._height || - pivotX !== this._pivotX || - pivotY !== this._pivotY) - { - this._width = width; - this._height = height; - this._pivotX = pivotX; - this._pivotY = pivotY; - this.vertDirty = true; - } - }; - - RenderData.alloc = function alloc () { - return _pool.alloc(); - }; - - RenderData.free = function free (data) { - if (data instanceof RenderData) { - for (var i = data.length-1; i > 0; i--) { - _dataPool.free(data._data[i]); - } - data._data.length = 0; - data._indices.length = 0; - data.material = null; - data.uvDirty = true; - data.vertDirty = true; - data.vertexCount = 0; - data.indiceCount = 0; - _pool.free(data); - } - }; - - Object.defineProperties( RenderData.prototype, prototypeAccessors ); - - return RenderData; -}(BaseRenderData)); - -RenderData.type = 'RenderData'; - -_pool = new Pool(function () { - return new RenderData(); -}, 32); - -var _d2r = Math.PI / 180.0; -var _r2d = 180.0 / Math.PI; - -/** - * @property {number} EPSILON - */ -var EPSILON = 0.000001; - -/** - * Tests whether or not the arguments have approximately the same value, within an absolute - * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less - * than or equal to 1.0, and a relative tolerance is used for larger values) - * - * @param {Number} a The first number to test. - * @param {Number} b The second number to test. - * @returns {Boolean} True if the numbers are approximately equal, false otherwise. - */ -function equals(a, b) { - return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b)); -} - -/** - * Tests whether or not the arguments have approximately the same value by given maxDiff - * - * @param {Number} a The first number to test. - * @param {Number} b The second number to test. - * @param {Number} maxDiff Maximum difference. - * @returns {Boolean} True if the numbers are approximately equal, false otherwise. - */ -function approx(a, b, maxDiff) { - maxDiff = maxDiff || EPSILON; - return Math.abs(a - b) <= maxDiff; -} - -/** - * Clamps a value between a minimum float and maximum float value. - * - * @method clamp - * @param {number} val - * @param {number} min - * @param {number} max - * @return {number} - */ -function clamp(val, min, max) { - return val < min ? min : val > max ? max : val; -} - -/** - * Clamps a value between 0 and 1. - * - * @method clamp01 - * @param {number} val - * @return {number} - */ -function clamp01(val) { - return val < 0 ? 0 : val > 1 ? 1 : val; -} - -/** - * @method lerp - * @param {number} from - * @param {number} to - * @param {number} ratio - the interpolation coefficient - * @return {number} - */ -function lerp(from, to, ratio) { - return from + (to - from) * ratio; -} - -/** -* Convert Degree To Radian -* -* @param {Number} a Angle in Degrees -*/ -function toRadian(a) { - return a * _d2r; -} - -/** -* Convert Radian To Degree -* -* @param {Number} a Angle in Radian -*/ -function toDegree(a) { - return a * _r2d; -} - -/** -* @method random -*/ -var random = Math.random; - -/** - * Returns a floating-point random number between min (inclusive) and max (exclusive). - * - * @method randomRange - * @param {number} min - * @param {number} max - * @return {number} the random number - */ -function randomRange(min, max) { - return Math.random() * (max - min) + min; -} - -/** - * Returns a random integer between min (inclusive) and max (exclusive). - * - * @method randomRangeInt - * @param {number} min - * @param {number} max - * @return {number} the random integer - */ -function randomRangeInt(min, max) { - return Math.floor(randomRange(min, max)); -} - -/** - * Returns the next power of two for the value - * - * @method nextPow2 - * @param {number} val - * @return {number} the the next power of two - */ -function nextPow2(val) { - --val; - val = (val >> 1) | val; - val = (val >> 2) | val; - val = (val >> 4) | val; - val = (val >> 8) | val; - val = (val >> 16) | val; - ++val; - - return val; -} - -/** - * Bit twiddling hacks for JavaScript. - * - * Author: Mikola Lysenko - * - * Ported from Stanford bit twiddling hack library: - * http://graphics.stanford.edu/~seander/bithacks.html - */ - -// Number of bits in an integer -var INT_BITS = 32; -var INT_MAX = 0x7fffffff; -var INT_MIN = -1<<(INT_BITS-1); - -/** - * Returns -1, 0, +1 depending on sign of x - * - * @param {number} v - * @returns {number} - */ -function sign(v) { - return (v > 0) - (v < 0); -} - -/** - * Computes absolute value of integer - * - * @param {number} v - * @returns {number} - */ -function abs(v) { - var mask = v >> (INT_BITS-1); - return (v ^ mask) - mask; -} - -/** - * Computes minimum of integers x and y - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function min(x, y) { - return y ^ ((x ^ y) & -(x < y)); -} - -/** - * Computes maximum of integers x and y - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function max(x, y) { - return x ^ ((x ^ y) & -(x < y)); -} - -/** - * Checks if a number is a power of two - * - * @param {number} v - * @returns {boolean} - */ -function isPow2(v) { - return !(v & (v-1)) && (!!v); -} - -/** - * Computes log base 2 of v - * - * @param {number} v - * @returns {number} - */ -function log2(v) { - var r, shift; - r = (v > 0xFFFF) << 4; v >>>= r; - shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; - return r | (v >> 1); -} - -/** - * Computes log base 10 of v - * - * @param {number} v - * @returns {number} - */ -function log10$1(v) { - return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : - (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : - (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; -} - -/** - * Counts number of bits - * - * @param {number} v - * @returns {number} - */ -function popCount(v) { - v = v - ((v >>> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); - return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; -} - -/** - * Counts number of trailing zeros - * - * @param {number} v - * @returns {number} - */ -function countTrailingZeros(v) { - var c = 32; - v &= -v; - if (v) { c--; } - if (v & 0x0000FFFF) { c -= 16; } - if (v & 0x00FF00FF) { c -= 8; } - if (v & 0x0F0F0F0F) { c -= 4; } - if (v & 0x33333333) { c -= 2; } - if (v & 0x55555555) { c -= 1; } - return c; -} - -/** - * Rounds to next power of 2 - * - * @param {number} v - * @returns {number} - */ -function nextPow2$1(v) { - v += v === 0; - --v; - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v + 1; -} - -/** - * Rounds down to previous power of 2 - * - * @param {number} v - * @returns {number} - */ -function prevPow2(v) { - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v - (v>>>1); -} - -/** - * Computes parity of word - * - * @param {number} v - * @returns {number} - */ -function parity(v) { - v ^= v >>> 16; - v ^= v >>> 8; - v ^= v >>> 4; - v &= 0xf; - return (0x6996 >>> v) & 1; -} - -var REVERSE_TABLE = new Array(256); - -(function(tab) { - for(var i=0; i<256; ++i) { - var v = i, r = i, s = 7; - for (v >>>= 1; v; v >>>= 1) { - r <<= 1; - r |= v & 1; - --s; - } - tab[i] = (r << s) & 0xff; - } -})(REVERSE_TABLE); - -/** - * Reverse bits in a 32 bit word - * - * @param {number} v - * @returns {number} - */ -function reverse(v) { - return (REVERSE_TABLE[v & 0xff] << 24) | - (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | - (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | - REVERSE_TABLE[(v >>> 24) & 0xff]; -} - -/** - * Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function interleave2(x, y) { - x &= 0xFFFF; - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y &= 0xFFFF; - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -/** - * Extracts the nth interleaved component - * - * @param {number} v - * @param {number} n - * @returns {number} - */ -function deinterleave2(v, n) { - v = (v >>> n) & 0x55555555; - v = (v | (v >>> 1)) & 0x33333333; - v = (v | (v >>> 2)) & 0x0F0F0F0F; - v = (v | (v >>> 4)) & 0x00FF00FF; - v = (v | (v >>> 16)) & 0x000FFFF; - return (v << 16) >> 16; -} - -/** - * Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes - * - * @param {number} x - * @param {number} y - * @param {number} z - * @returns {number} - */ -function interleave3(x, y, z) { - x &= 0x3FF; - x = (x | (x<<16)) & 4278190335; - x = (x | (x<<8)) & 251719695; - x = (x | (x<<4)) & 3272356035; - x = (x | (x<<2)) & 1227133513; - - y &= 0x3FF; - y = (y | (y<<16)) & 4278190335; - y = (y | (y<<8)) & 251719695; - y = (y | (y<<4)) & 3272356035; - y = (y | (y<<2)) & 1227133513; - x |= (y << 1); - - z &= 0x3FF; - z = (z | (z<<16)) & 4278190335; - z = (z | (z<<8)) & 251719695; - z = (z | (z<<4)) & 3272356035; - z = (z | (z<<2)) & 1227133513; - - return x | (z << 2); -} - -/** - * Extracts nth interleaved component of a 3-tuple - * - * @param {number} v - * @param {number} n - * @returns {number} - */ -function deinterleave3(v, n) { - v = (v >>> n) & 1227133513; - v = (v | (v>>>2)) & 3272356035; - v = (v | (v>>>4)) & 251719695; - v = (v | (v>>>8)) & 4278190335; - v = (v | (v>>>16)) & 0x3FF; - return (v<<22)>>22; -} - -/** - * Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) - * - * @param {number} v - * @returns {number} - */ -function nextCombination(v) { - var t = v | (v - 1); - return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); -} - -var bits_ = Object.freeze({ - INT_BITS: INT_BITS, - INT_MAX: INT_MAX, - INT_MIN: INT_MIN, - sign: sign, - abs: abs, - min: min, - max: max, - isPow2: isPow2, - log2: log2, - log10: log10$1, - popCount: popCount, - countTrailingZeros: countTrailingZeros, - nextPow2: nextPow2$1, - prevPow2: prevPow2, - parity: parity, - reverse: reverse, - interleave2: interleave2, - deinterleave2: deinterleave2, - interleave3: interleave3, - deinterleave3: deinterleave3, - nextCombination: nextCombination -}); - -var _tmp = new Array(2); - -var _vec2 = function _vec2(x, y) { - this.x = x; - this.y = y; -}; - -_vec2.prototype.toJSON = function toJSON () { - _tmp[0] = this.x; - _tmp[1] = this.y; - - return _tmp; -}; - -/** - * @class 2 Dimensional Vector - * @name vec2 - */ -var vec2 = {}; - -/** - * Creates a new, empty vec2 - * - * @returns {vec2} a new 2D vector - */ -vec2.create = function () { - return new _vec2(0, 0); -}; - -/** - * Creates a new vec2 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @returns {vec2} a new 2D vector - */ -vec2.new = function (x, y) { - return new _vec2(x, y); -}; - -/** - * Creates a new vec2 initialized with values from an existing vector - * - * @param {vec2} a vector to clone - * @returns {vec2} a new 2D vector - */ -vec2.clone = function (a) { - return new _vec2(a.x, a.y); -}; - -/** - * Copy the values from one vec2 to another - * - * @param {vec2} out the receiving vector - * @param {vec2} a the source vector - * @returns {vec2} out - */ -vec2.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - return out; -}; - -/** - * Set the components of a vec2 to the given values - * - * @param {vec2} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @returns {vec2} out - */ -vec2.set = function (out, x, y) { - out.x = x; - out.y = y; - return out; -}; - -/** - * Adds two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - return out; -}; - -/** - * Alias for {@link vec2.subtract} - * @function - */ -vec2.sub = vec2.subtract; - -/** - * Multiplies two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - return out; -}; - -/** - * Alias for {@link vec2.multiply} - * @function - */ -vec2.mul = vec2.multiply; - -/** - * Divides two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - return out; -}; - -/** - * Alias for {@link vec2.divide} - * @function - */ -vec2.div = vec2.divide; - -/** - * Math.ceil the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to ceil - * @returns {vec2} out - */ -vec2.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - return out; -}; - -/** - * Math.floor the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to floor - * @returns {vec2} out - */ -vec2.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - return out; -}; - -/** - * Returns the minimum of two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - return out; -}; - -/** - * Returns the maximum of two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - return out; -}; - -/** - * Math.round the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to round - * @returns {vec2} out - */ -vec2.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - return out; -}; - -/** - * Scales a vec2 by a scalar number - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec2} out - */ -vec2.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - return out; -}; - -/** - * Adds two vec2's after scaling the second operand by a scalar value - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec2} out - */ -vec2.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} distance between a and b - */ -vec2.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y; - return Math.sqrt(x * x + y * y); -}; - -/** - * Alias for {@link vec2.distance} - * @function - */ -vec2.dist = vec2.distance; - -/** - * Calculates the squared euclidian distance between two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} squared distance between a and b - */ -vec2.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y; - return x * x + y * y; -}; - -/** - * Alias for {@link vec2.squaredDistance} - * @function - */ -vec2.sqrDist = vec2.squaredDistance; - -/** - * Calculates the length of a vec2 - * - * @param {vec2} a vector to calculate length of - * @returns {Number} length of a - */ -vec2.length = function (a) { - var x = a.x, - y = a.y; - return Math.sqrt(x * x + y * y); -}; - -/** - * Alias for {@link vec2.length} - * @function - */ -vec2.len = vec2.length; - -/** - * Calculates the squared length of a vec2 - * - * @param {vec2} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec2.squaredLength = function (a) { - var x = a.x, - y = a.y; - return x * x + y * y; -}; - -/** - * Alias for {@link vec2.squaredLength} - * @function - */ -vec2.sqrLen = vec2.squaredLength; - -/** - * Negates the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to negate - * @returns {vec2} out - */ -vec2.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - return out; -}; - -/** - * Returns the inverse of the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to invert - * @returns {vec2} out - */ -vec2.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - return out; -}; - -/** - * Returns the inverse of the components of a vec2 safely - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to invert - * @returns {vec2} out - */ -vec2.inverseSafe = function (out, a) { - var x = a.x, - y = a.y; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / a.y; - } - - return out; -}; - -/** - * Normalize a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to normalize - * @returns {vec2} out - */ -vec2.normalize = function (out, a) { - var x = a.x, - y = a.y; - var len = x * x + y * y; - if (len > 0) { - //TODO: evaluate use of glm_invsqrt here? - len = 1 / Math.sqrt(len); - out.x = a.x * len; - out.y = a.y * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} dot product of a and b - */ -vec2.dot = function (a, b) { - return a.x * b.x + a.y * b.y; -}; - -/** - * Computes the cross product of two vec2's - * Note that the cross product must by definition produce a 3D vector - * - * @param {vec3} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec3} out - */ -vec2.cross = function (out, a, b) { - var z = a.x * b.y - a.y * b.x; - out.x = out.y = 0; - out.z = z; - return out; -}; - -/** - * Performs a linear interpolation between two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec2} out - */ -vec2.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec2} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec2} out - */ -vec2.random = function (out, scale) { - scale = scale || 1.0; - var r = random() * 2.0 * Math.PI; - out.x = Math.cos(r) * scale; - out.y = Math.sin(r) * scale; - return out; -}; - -/** - * Transforms the vec2 with a mat2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat2} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat2 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m02 * y; - out.y = m.m01 * x + m.m03 * y; - return out; -}; - -/** - * Transforms the vec2 with a mat23 - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat23} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat23 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m02 * y + m.m04; - out.y = m.m01 * x + m.m03 * y + m.m05; - return out; -}; - -/** - * Transforms the vec2 with a mat3 - * 3rd vector component is implicitly '1' - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat3} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat3 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m03 * y + m.m06; - out.y = m.m01 * x + m.m04 * y + m.m07; - return out; -}; - -/** - * Transforms the vec2 with a mat4 - * 3rd vector component is implicitly '0' - * 4th vector component is implicitly '1' - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat4 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m04 * y + m.m12; - out.y = m.m01 * x + m.m05 * y + m.m13; - return out; -}; - -/** - * Perform some operation over an array of vec2s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec2.forEach = (function () { - var vec = vec2.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 2; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; - } - - return a; - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec2} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec2.str = function (a) { - return ("vec2(" + (a.x) + ", " + (a.y) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec2} v - * @returns {array} - */ -vec2.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - - return out; -}; - -/** - * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===) - * - * @param {vec2} a The first vector. - * @param {vec2} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec2.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec2} a The first vector. - * @param {vec2} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec2.equals = function (a, b) { - var a0 = a.x, a1 = a.y; - var b0 = b.x, b1 = b.y; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1))); -}; - -var _tmp$1 = new Array(3); - -var _vec3 = function _vec3(x, y, z) { - this.x = x; - this.y = y; - this.z = z; -}; - -_vec3.prototype.toJSON = function toJSON () { - _tmp$1[0] = this.x; - _tmp$1[1] = this.y; - _tmp$1[2] = this.z; - - return _tmp$1; -}; - -/** - * @class 3 Dimensional Vector - * @name vec3 - */ -var vec3 = {}; - -/** - * Creates a new, empty vec3 - * - * @returns {vec3} a new 3D vector - */ -vec3.create = function () { - return new _vec3(0, 0, 0); -}; - -/** - * Creates a new vec3 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} a new 3D vector - */ -vec3.new = function (x, y, z) { - return new _vec3(x, y, z); -}; - -/** - * Creates a new vec3 initialized with values from an existing vector - * - * @param {vec3} a vector to clone - * @returns {vec3} a new 3D vector - */ -vec3.clone = function (a) { - return new _vec3(a.x, a.y, a.z); -}; - -/** - * Copy the values from one vec3 to another - * - * @param {vec3} out the receiving vector - * @param {vec3} a the source vector - * @returns {vec3} out - */ -vec3.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - out.z = a.z; - return out; -}; - -/** - * Set the components of a vec3 to the given values - * - * @param {vec3} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} out - */ -vec3.set = function (out, x, y, z) { - out.x = x; - out.y = y; - out.z = z; - return out; -}; - -/** - * Adds two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - out.z = a.z + b.z; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; - return out; -}; - -/** - * Alias for {@link vec3.subtract} - * @function - */ -vec3.sub = vec3.subtract; - -/** - * Multiplies two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - out.z = a.z * b.z; - return out; -}; - -/** - * Alias for {@link vec3.multiply} - * @function - */ -vec3.mul = vec3.multiply; - -/** - * Divides two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - out.z = a.z / b.z; - return out; -}; - -/** - * Alias for {@link vec3.divide} - * @function - */ -vec3.div = vec3.divide; - -/** - * Math.ceil the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to ceil - * @returns {vec3} out - */ -vec3.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - out.z = Math.ceil(a.z); - return out; -}; - -/** - * Math.floor the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to floor - * @returns {vec3} out - */ -vec3.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - out.z = Math.floor(a.z); - return out; -}; - -/** - * Returns the minimum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - out.z = Math.min(a.z, b.z); - return out; -}; - -/** - * Returns the maximum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - out.z = Math.max(a.z, b.z); - return out; -}; - -/** - * Math.round the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to round - * @returns {vec3} out - */ -vec3.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - out.z = Math.round(a.z); - return out; -}; - -/** - * Scales a vec3 by a scalar number - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec3} out - */ -vec3.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - out.z = a.z * b; - return out; -}; - -/** - * Adds two vec3's after scaling the second operand by a scalar value - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec3} out - */ -vec3.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - out.z = a.z + (b.z * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} distance between a and b - */ -vec3.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z; - return Math.sqrt(x * x + y * y + z * z); -}; - -/** - * Alias for {@link vec3.distance} - * @function - */ -vec3.dist = vec3.distance; - -/** - * Calculates the squared euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} squared distance between a and b - */ -vec3.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z; - return x * x + y * y + z * z; -}; - -/** - * Alias for {@link vec3.squaredDistance} - * @function - */ -vec3.sqrDist = vec3.squaredDistance; - -/** - * Calculates the length of a vec3 - * - * @param {vec3} a vector to calculate length of - * @returns {Number} length of a - */ -vec3.length = function (a) { - var x = a.x, - y = a.y, - z = a.z; - return Math.sqrt(x * x + y * y + z * z); -}; - -/** - * Alias for {@link vec3.length} - * @function - */ -vec3.len = vec3.length; - -/** - * Calculates the squared length of a vec3 - * - * @param {vec3} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec3.squaredLength = function (a) { - var x = a.x, - y = a.y, - z = a.z; - return x * x + y * y + z * z; -}; - -/** - * Alias for {@link vec3.squaredLength} - * @function - */ -vec3.sqrLen = vec3.squaredLength; - -/** - * Negates the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to negate - * @returns {vec3} out - */ -vec3.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - return out; -}; - -/** - * Returns the inverse of the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to invert - * @returns {vec3} out - */ -vec3.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - out.z = 1.0 / a.z; - return out; -}; - -/** - * Returns the inverse of the components of a vec3 safely - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to invert - * @returns {vec3} out - */ -vec3.inverseSafe = function (out, a) { - var x = a.x, - y = a.y, - z = a.z; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / y; - } - - if (Math.abs(z) < EPSILON) { - out.z = 0; - } else { - out.z = 1.0 / z; - } - - return out; -}; - -/** - * Normalize a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to normalize - * @returns {vec3} out - */ -vec3.normalize = function (out, a) { - var x = a.x, - y = a.y, - z = a.z; - - var len = x * x + y * y + z * z; - if (len > 0) { - //TODO: evaluate use of glm_invsqrt here? - len = 1 / Math.sqrt(len); - out.x = x * len; - out.y = y * len; - out.z = z * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} dot product of a and b - */ -vec3.dot = function (a, b) { - return a.x * b.x + a.y * b.y + a.z * b.z; -}; - -/** - * Computes the cross product of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.cross = function (out, a, b) { - var ax = a.x, ay = a.y, az = a.z, - bx = b.x, by = b.y, bz = b.z; - - out.x = ay * bz - az * by; - out.y = az * bx - ax * bz; - out.z = ax * by - ay * bx; - return out; -}; - -/** - * Performs a linear interpolation between two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y, - az = a.z; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - out.z = az + t * (b.z - az); - return out; -}; - -/** - * Performs a hermite interpolation with two control points - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {vec3} c the third operand - * @param {vec3} d the fourth operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.hermite = function (out, a, b, c, d, t) { - var factorTimes2 = t * t, - factor1 = factorTimes2 * (2 * t - 3) + 1, - factor2 = factorTimes2 * (t - 2) + t, - factor3 = factorTimes2 * (t - 1), - factor4 = factorTimes2 * (3 - 2 * t); - - out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; - out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; - out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; - - return out; -}; - -/** - * Performs a bezier interpolation with two control points - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {vec3} c the third operand - * @param {vec3} d the fourth operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.bezier = function (out, a, b, c, d, t) { - var inverseFactor = 1 - t, - inverseFactorTimesTwo = inverseFactor * inverseFactor, - factorTimes2 = t * t, - factor1 = inverseFactorTimesTwo * inverseFactor, - factor2 = 3 * t * inverseFactorTimesTwo, - factor3 = 3 * factorTimes2 * inverseFactor, - factor4 = factorTimes2 * t; - - out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; - out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; - out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; - - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec3} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec3} out - */ -vec3.random = function (out, scale) { - scale = scale || 1.0; - - var r = random() * 2.0 * Math.PI; - var z = (random() * 2.0) - 1.0; - var zScale = Math.sqrt(1.0 - z * z) * scale; - - out.x = Math.cos(r) * zScale; - out.y = Math.sin(r) * zScale; - out.z = z * scale; - return out; -}; - -/** - * Transforms the vec3 with a mat4. - * 4th vector component is implicitly '1' - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec3} out - */ -vec3.transformMat4 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z, - w = m.m03 * x + m.m07 * y + m.m11 * z + m.m15; - w = w || 1.0; - out.x = (m.m00 * x + m.m04 * y + m.m08 * z + m.m12) / w; - out.y = (m.m01 * x + m.m05 * y + m.m09 * z + m.m13) / w; - out.z = (m.m02 * x + m.m06 * y + m.m10 * z + m.m14) / w; - return out; -}; - -/** - * Transforms the vec3 with a mat3. - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m the 3x3 matrix to transform with - * @returns {vec3} out - */ -vec3.transformMat3 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z; - out.x = x * m.m00 + y * m.m03 + z * m.m06; - out.y = x * m.m01 + y * m.m04 + z * m.m07; - out.z = x * m.m02 + y * m.m05 + z * m.m08; - return out; -}; - -/** - * Transforms the vec3 with a quat - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec3} out - */ -vec3.transformQuat = function (out, a, q) { - // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations - - var x = a.x, y = a.y, z = a.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vec - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - - // calculate result * inverse quat - out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - return out; -}; - -/** - * Rotate a 3D vector around the x-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateX = function (out, a, b, c) { - var p = [], r = []; - // Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.x; - r.y = p.y * Math.cos(c) - p.z * Math.sin(c); - r.z = p.y * Math.sin(c) + p.z * Math.cos(c); - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Rotate a 3D vector around the y-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateY = function (out, a, b, c) { - var p = [], r = []; - //Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.z * Math.sin(c) + p.x * Math.cos(c); - r.y = p.y; - r.z = p.z * Math.cos(c) - p.x * Math.sin(c); - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Rotate a 3D vector around the z-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateZ = function (out, a, b, c) { - var p = [], r = []; - //Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.x * Math.cos(c) - p.y * Math.sin(c); - r.y = p.x * Math.sin(c) + p.y * Math.cos(c); - r.z = p.z; - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Perform some operation over an array of vec3s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec3.forEach = (function () { - var vec = vec3.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 3; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; vec.z = a[i + 2]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; a[i + 2] = vec.z; - } - - return a; - }; -})(); - -/** - * Get the angle between two 3D vectors - * @param {vec3} a The first operand - * @param {vec3} b The second operand - * @returns {Number} The angle in radians - */ -vec3.angle = (function () { - var tempA = vec3.create(); - var tempB = vec3.create(); - - return function (a, b) { - vec3.copy(tempA, a); - vec3.copy(tempB, b); - - vec3.normalize(tempA, tempA); - vec3.normalize(tempB, tempB); - - var cosine = vec3.dot(tempA, tempB); - - if (cosine > 1.0) { - return 0; - } - - if (cosine < -1.0) { - return Math.PI; - } - - return Math.acos(cosine); - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec3} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec3.str = function (a) { - return ("vec3(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec3} v - * @returns {array} - */ -vec3.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - out[2] = v.z; - - return out; -}; - -/** - * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec3.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y && a.z === b.z; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec3.equals = function (a, b) { - var a0 = a.x, a1 = a.y, a2 = a.z; - var b0 = b.x, b1 = b.y, b2 = b.z; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); -}; - -var _tmp$2 = new Array(4); - -var _vec4 = function _vec4(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; -}; - -_vec4.prototype.toJSON = function toJSON () { - _tmp$2[0] = this.x; - _tmp$2[1] = this.y; - _tmp$2[2] = this.z; - _tmp$2[3] = this.w; - - return _tmp$2; -}; - -/** - * @class 4 Dimensional Vector - * @name vec4 - */ -var vec4 = {}; - -/** - * Creates a new, empty vec4 - * - * @returns {vec4} a new 4D vector - */ -vec4.create = function () { - return new _vec4(0, 0, 0, 0); -}; - -/** - * Creates a new vec4 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} a new 4D vector - */ -vec4.new = function (x, y, z, w) { - return new _vec4(x, y, z, w); -}; - -/** - * Creates a new vec4 initialized with values from an existing vector - * - * @param {vec4} a vector to clone - * @returns {vec4} a new 4D vector - */ -vec4.clone = function (a) { - return new _vec4(a.x, a.y, a.z, a.w); -}; - -/** - * Copy the values from one vec4 to another - * - * @param {vec4} out the receiving vector - * @param {vec4} a the source vector - * @returns {vec4} out - */ -vec4.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - out.z = a.z; - out.w = a.w; - return out; -}; - -/** - * Set the components of a vec4 to the given values - * - * @param {vec4} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} out - */ -vec4.set = function (out, x, y, z, w) { - out.x = x; - out.y = y; - out.z = z; - out.w = w; - return out; -}; - -/** - * Adds two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - out.z = a.z + b.z; - out.w = a.w + b.w; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; - out.w = a.w - b.w; - return out; -}; - -/** - * Alias for {@link vec4.subtract} - * @function - */ -vec4.sub = vec4.subtract; - -/** - * Multiplies two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - out.z = a.z * b.z; - out.w = a.w * b.w; - return out; -}; - -/** - * Alias for {@link vec4.multiply} - * @function - */ -vec4.mul = vec4.multiply; - -/** - * Divides two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - out.z = a.z / b.z; - out.w = a.w / b.w; - return out; -}; - -/** - * Alias for {@link vec4.divide} - * @function - */ -vec4.div = vec4.divide; - -/** - * Math.ceil the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to ceil - * @returns {vec4} out - */ -vec4.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - out.z = Math.ceil(a.z); - out.w = Math.ceil(a.w); - return out; -}; - -/** - * Math.floor the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to floor - * @returns {vec4} out - */ -vec4.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - out.z = Math.floor(a.z); - out.w = Math.floor(a.w); - return out; -}; - -/** - * Returns the minimum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - out.z = Math.min(a.z, b.z); - out.w = Math.min(a.w, b.w); - return out; -}; - -/** - * Returns the maximum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - out.z = Math.max(a.z, b.z); - out.w = Math.max(a.w, b.w); - return out; -}; - -/** - * Math.round the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to round - * @returns {vec4} out - */ -vec4.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - out.z = Math.round(a.z); - out.w = Math.round(a.w); - return out; -}; - -/** - * Scales a vec4 by a scalar number - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec4} out - */ -vec4.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - out.z = a.z * b; - out.w = a.w * b; - return out; -}; - -/** - * Adds two vec4's after scaling the second operand by a scalar value - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec4} out - */ -vec4.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - out.z = a.z + (b.z * scale); - out.w = a.w + (b.w * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} distance between a and b - */ -vec4.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z, - w = b.w - a.w; - return Math.sqrt(x * x + y * y + z * z + w * w); -}; - -/** - * Alias for {@link vec4.distance} - * @function - */ -vec4.dist = vec4.distance; - -/** - * Calculates the squared euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} squared distance between a and b - */ -vec4.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z, - w = b.w - a.w; - return x * x + y * y + z * z + w * w; -}; - -/** - * Alias for {@link vec4.squaredDistance} - * @function - */ -vec4.sqrDist = vec4.squaredDistance; - -/** - * Calculates the length of a vec4 - * - * @param {vec4} a vector to calculate length of - * @returns {Number} length of a - */ -vec4.length = function (a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - return Math.sqrt(x * x + y * y + z * z + w * w); -}; - -/** - * Alias for {@link vec4.length} - * @function - */ -vec4.len = vec4.length; - -/** - * Calculates the squared length of a vec4 - * - * @param {vec4} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec4.squaredLength = function (a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - return x * x + y * y + z * z + w * w; -}; - -/** - * Alias for {@link vec4.squaredLength} - * @function - */ -vec4.sqrLen = vec4.squaredLength; - -/** - * Negates the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to negate - * @returns {vec4} out - */ -vec4.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - out.w = -a.w; - return out; -}; - -/** - * Returns the inverse of the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to invert - * @returns {vec4} out - */ -vec4.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - out.z = 1.0 / a.z; - out.w = 1.0 / a.w; - return out; -}; - -/** - * Returns the inverse of the components of a vec4 safely - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to invert - * @returns {vec4} out - */ -vec4.inverseSafe = function (out, a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / y; - } - - if (Math.abs(z) < EPSILON) { - out.z = 0; - } else { - out.z = 1.0 / z; - } - - if (Math.abs(w) < EPSILON) { - out.w = 0; - } else { - out.w = 1.0 / w; - } - - return out; -}; - -/** - * Normalize a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to normalize - * @returns {vec4} out - */ -vec4.normalize = function (out, a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - var len = x * x + y * y + z * z + w * w; - if (len > 0) { - len = 1 / Math.sqrt(len); - out.x = x * len; - out.y = y * len; - out.z = z * len; - out.w = w * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} dot product of a and b - */ -vec4.dot = function (a, b) { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -}; - -/** - * Performs a linear interpolation between two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec4} out - */ -vec4.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y, - az = a.z, - aw = a.w; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - out.z = az + t * (b.z - az); - out.w = aw + t * (b.w - aw); - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec4} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec4} out - */ -vec4.random = function (out, scale) { - scale = scale || 1.0; - - //TODO: This is a pretty awful way of doing this. Find something better. - out.x = random(); - out.y = random(); - out.z = random(); - out.w = random(); - vec4.normalize(out, out); - vec4.scale(out, out, scale); - return out; -}; - -/** - * Transforms the vec4 with a mat4. - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec4} out - */ -vec4.transformMat4 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z, w = a.w; - out.x = m.m00 * x + m.m04 * y + m.m08 * z + m.m12 * w; - out.y = m.m01 * x + m.m05 * y + m.m09 * z + m.m13 * w; - out.z = m.m02 * x + m.m06 * y + m.m10 * z + m.m14 * w; - out.w = m.m03 * x + m.m07 * y + m.m11 * z + m.m15 * w; - return out; -}; - -/** - * Transforms the vec4 with a quat - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec4} out - */ -vec4.transformQuat = function (out, a, q) { - var x = a.x, y = a.y, z = a.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vec - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - - // calculate result * inverse quat - out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - out.w = a.w; - return out; -}; - -/** - * Perform some operation over an array of vec4s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec4.forEach = (function () { - var vec = vec4.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 4; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; vec.z = a[i + 2]; vec.w = a[i + 3]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; a[i + 2] = vec.z; a[i + 3] = vec.w; - } - - return a; - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec4} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec4.str = function (a) { - return ("vec4(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ", " + (a.w) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec4} v - * @returns {array} - */ -vec4.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - out[2] = v.z; - out[3] = v.w; - - return out; -}; - -/** - * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) - * - * @param {vec4} a The first vector. - * @param {vec4} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec4.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y && a.z === b.z && a.w === b.w; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec4} a The first vector. - * @param {vec4} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec4.equals = function (a, b) { - var a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; - var b0 = b.x, b1 = b.y, b2 = b.z, b3 = b.w; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); -}; - -var _tmp$3 = new Array(9); - -var _mat3 = function _mat3(m00, m01, m02, m03, m04, m05, m06, m07, m08) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; - this.m06 = m06; - this.m07 = m07; - this.m08 = m08; -}; - -_mat3.prototype.toJSON = function toJSON () { - _tmp$3[0] = this.m00; - _tmp$3[1] = this.m01; - _tmp$3[2] = this.m02; - _tmp$3[3] = this.m03; - _tmp$3[4] = this.m04; - _tmp$3[5] = this.m05; - _tmp$3[6] = this.m06; - _tmp$3[7] = this.m07; - _tmp$3[8] = this.m08; - - return _tmp$3; -}; - -/** - * @class 3x3 Matrix - * @name mat3 - * - * NOTE: we use column-major matrix for all matrix calculation. - * - * This may lead to some confusion when referencing OpenGL documentation, - * however, which represents out all matricies in column-major format. - * This means that while in code a matrix may be typed out as: - * - * [1, 0, 0, 0, - * 0, 1, 0, 0, - * 0, 0, 1, 0, - * x, y, z, 0] - * - * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) - * is written as: - * - * 1 0 0 x - * 0 1 0 y - * 0 0 1 z - * 0 0 0 0 - * - * Please rest assured, however, that they are the same thing! - * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the - * apparent lack of consistency between the memory layout and the documentation. - */ -var mat3 = {}; - -/** - * Creates a new identity mat3 - * - * @returns {mat3} a new 3x3 matrix - */ -mat3.create = function () { - return new _mat3( - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - ); -}; - -/** - * Create a new mat3 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m10 Component in column 1, row 0 position (index 3) - * @param {Number} m11 Component in column 1, row 1 position (index 4) - * @param {Number} m12 Component in column 1, row 2 position (index 5) - * @param {Number} m20 Component in column 2, row 0 position (index 6) - * @param {Number} m21 Component in column 2, row 1 position (index 7) - * @param {Number} m22 Component in column 2, row 2 position (index 8) - * @returns {mat3} A new mat3 - */ -mat3.new = function (m00, m01, m02, m10, m11, m12, m20, m21, m22) { - return new _mat3( - m00, m01, m02, - m10, m11, m12, - m20, m21, m22 - ); -}; - -/** - * Creates a new mat3 initialized with values from an existing matrix - * - * @param {mat3} a matrix to clone - * @returns {mat3} a new 3x3 matrix - */ -mat3.clone = function (a) { - return new _mat3( - a.m00, a.m01, a.m02, - a.m03, a.m04, a.m05, - a.m06, a.m07, a.m08 - ); -}; - -/** - * Copy the values from one mat3 to another - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - return out; -}; - -/** - * Set the components of a mat3 to the given values - * - * @param {mat3} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m10 Component in column 1, row 0 position (index 3) - * @param {Number} m11 Component in column 1, row 1 position (index 4) - * @param {Number} m12 Component in column 1, row 2 position (index 5) - * @param {Number} m20 Component in column 2, row 0 position (index 6) - * @param {Number} m21 Component in column 2, row 1 position (index 7) - * @param {Number} m22 Component in column 2, row 2 position (index 8) - * @returns {mat3} out - */ -mat3.set = function (out, m00, m01, m02, m10, m11, m12, m20, m21, m22) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m02; - out.m03 = m10; - out.m04 = m11; - out.m05 = m12; - out.m06 = m20; - out.m07 = m21; - out.m08 = m22; - return out; -}; - -/** - * Set a mat3 to the identity matrix - * - * @param {mat3} out the receiving matrix - * @returns {mat3} out - */ -mat3.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 1; - out.m05 = 0; - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Transpose the values of a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a01 = a.m01, a02 = a.m02, a12 = a.m05; - out.m01 = a.m03; - out.m02 = a.m06; - out.m03 = a01; - out.m05 = a.m07; - out.m06 = a02; - out.m07 = a12; - } else { - out.m00 = a.m00; - out.m01 = a.m03; - out.m02 = a.m06; - out.m03 = a.m01; - out.m04 = a.m04; - out.m05 = a.m07; - out.m06 = a.m02; - out.m07 = a.m05; - out.m08 = a.m08; - } - - return out; -}; - -/** - * Inverts a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.invert = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var b01 = a22 * a11 - a12 * a21; - var b11 = -a22 * a10 + a12 * a20; - var b21 = a21 * a10 - a11 * a20; - - // Calculate the determinant - var det = a00 * b01 + a01 * b11 + a02 * b21; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = b01 * det; - out.m01 = (-a22 * a01 + a02 * a21) * det; - out.m02 = (a12 * a01 - a02 * a11) * det; - out.m03 = b11 * det; - out.m04 = (a22 * a00 - a02 * a20) * det; - out.m05 = (-a12 * a00 + a02 * a10) * det; - out.m06 = b21 * det; - out.m07 = (-a21 * a00 + a01 * a20) * det; - out.m08 = (a11 * a00 - a01 * a10) * det; - return out; -}; - -/** - * Calculates the adjugate of a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.adjoint = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - out.m00 = (a11 * a22 - a12 * a21); - out.m01 = (a02 * a21 - a01 * a22); - out.m02 = (a01 * a12 - a02 * a11); - out.m03 = (a12 * a20 - a10 * a22); - out.m04 = (a00 * a22 - a02 * a20); - out.m05 = (a02 * a10 - a00 * a12); - out.m06 = (a10 * a21 - a11 * a20); - out.m07 = (a01 * a20 - a00 * a21); - out.m08 = (a00 * a11 - a01 * a10); - return out; -}; - -/** - * Calculates the determinant of a mat3 - * - * @param {mat3} a the source matrix - * @returns {Number} determinant of a - */ -mat3.determinant = function (a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); -}; - -/** - * Multiplies two mat3's - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.multiply = function (out, a, b) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var b00 = b.m00, b01 = b.m01, b02 = b.m02; - var b10 = b.m03, b11 = b.m04, b12 = b.m05; - var b20 = b.m06, b21 = b.m07, b22 = b.m08; - - out.m00 = b00 * a00 + b01 * a10 + b02 * a20; - out.m01 = b00 * a01 + b01 * a11 + b02 * a21; - out.m02 = b00 * a02 + b01 * a12 + b02 * a22; - - out.m03 = b10 * a00 + b11 * a10 + b12 * a20; - out.m04 = b10 * a01 + b11 * a11 + b12 * a21; - out.m05 = b10 * a02 + b11 * a12 + b12 * a22; - - out.m06 = b20 * a00 + b21 * a10 + b22 * a20; - out.m07 = b20 * a01 + b21 * a11 + b22 * a21; - out.m08 = b20 * a02 + b21 * a12 + b22 * a22; - return out; -}; - -/** - * Alias for {@link mat3.multiply} - * @function - */ -mat3.mul = mat3.multiply; - -/** - * Translate a mat3 by the given vector - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to translate - * @param {vec2} v vector to translate by - * @returns {mat3} out - */ -mat3.translate = function (out, a, v) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - var x = v.x, y = v.y; - - out.m00 = a00; - out.m01 = a01; - out.m02 = a02; - - out.m03 = a10; - out.m04 = a11; - out.m05 = a12; - - out.m06 = x * a00 + y * a10 + a20; - out.m07 = x * a01 + y * a11 + a21; - out.m08 = x * a02 + y * a12 + a22; - return out; -}; - -/** - * Rotates a mat3 by the given angle - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat3} out - */ -mat3.rotate = function (out, a, rad) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var s = Math.sin(rad); - var c = Math.cos(rad); - - out.m00 = c * a00 + s * a10; - out.m01 = c * a01 + s * a11; - out.m02 = c * a02 + s * a12; - - out.m03 = c * a10 - s * a00; - out.m04 = c * a11 - s * a01; - out.m05 = c * a12 - s * a02; - - out.m06 = a20; - out.m07 = a21; - out.m08 = a22; - return out; -}; - -/** - * Scales the mat3 by the dimensions in the given vec2 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to rotate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat3} out - **/ -mat3.scale = function (out, a, v) { - var x = v.x, y = v.y; - - out.m00 = x * a.m00; - out.m01 = x * a.m01; - out.m02 = x * a.m02; - - out.m03 = y * a.m03; - out.m04 = y * a.m04; - out.m05 = y * a.m05; - - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - return out; -}; - -/** - * Copies the upper-left 3x3 values into the given mat3. - * - * @param {mat3} out the receiving 3x3 matrix - * @param {mat4} a the source 4x4 matrix - * @returns {mat3} out - */ -mat3.fromMat4 = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m04; - out.m04 = a.m05; - out.m05 = a.m06; - out.m06 = a.m08; - out.m07 = a.m09; - out.m08 = a.m10; - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.translate(dest, dest, vec); - * - * @param {mat3} out mat3 receiving operation result - * @param {vec2} v Translation vector - * @returns {mat3} out - */ -mat3.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 1; - out.m05 = 0; - out.m06 = v.x; - out.m07 = v.y; - out.m08 = 1; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.rotate(dest, dest, rad); - * - * @param {mat3} out mat3 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat3} out - */ -mat3.fromRotation = function (out, rad) { - var s = Math.sin(rad), c = Math.cos(rad); - - out.m00 = c; - out.m01 = s; - out.m02 = 0; - - out.m03 = -s; - out.m04 = c; - out.m05 = 0; - - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.scale(dest, dest, vec); - * - * @param {mat3} out mat3 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat3} out - */ -mat3.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - - out.m03 = 0; - out.m04 = v.y; - out.m05 = 0; - - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Copies the values from a mat2d into a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat2d} a the matrix to copy - * @returns {mat3} out - **/ -mat3.fromMat2d = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = 0; - - out.m03 = a.m02; - out.m04 = a.m03; - out.m05 = 0; - - out.m06 = a.m04; - out.m07 = a.m05; - out.m08 = 1; - return out; -}; - -/** -* Calculates a 3x3 matrix from the given quaternion -* -* @param {mat3} out mat3 receiving operation result -* @param {quat} q Quaternion to create matrix from -* -* @returns {mat3} out -*/ -mat3.fromQuat = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var yx = y * x2; - var yy = y * y2; - var zx = z * x2; - var zy = z * y2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - yy - zz; - out.m03 = yx - wz; - out.m06 = zx + wy; - - out.m01 = yx + wz; - out.m04 = 1 - xx - zz; - out.m07 = zy - wx; - - out.m02 = zx - wy; - out.m05 = zy + wx; - out.m08 = 1 - xx - yy; - - return out; -}; - -/** -* Calculates a 3x3 matrix from view direction and up direction -* -* @param {mat3} out mat3 receiving operation result -* @param {vec3} view view direction (must be normalized) -* @param {vec3} [up] up direction, default is (0,1,0) (must be normalized) -* -* @returns {mat3} out -*/ -mat3.fromViewUp = (function () { - var default_up = vec3.new(0, 1, 0); - var x = vec3.create(); - var y = vec3.create(); - - return function (out, view, up) { - if (vec3.sqrLen(view) < EPSILON * EPSILON) { - mat3.identity(out); - return out; - } - - up = up || default_up; - vec3.cross(x, up, view); - - if (vec3.sqrLen(x) < EPSILON * EPSILON) { - mat3.identity(out); - return out; - } - - vec3.cross(y, view, x); - mat3.set(out, - x.x, x.y, x.z, - y.x, y.y, y.z, - view.x, view.y, view.z - ); - - return out; - }; -})(); - -/** -* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix -* -* @param {mat3} out mat3 receiving operation result -* @param {mat4} a Mat4 to derive the normal matrix from -* -* @returns {mat3} out -*/ -mat3.normalFromMat4 = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out.m01 = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out.m02 = (a10 * b10 - a11 * b08 + a13 * b06) * det; - - out.m03 = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out.m04 = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out.m05 = (a01 * b08 - a00 * b10 - a03 * b06) * det; - - out.m06 = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out.m07 = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out.m08 = (a30 * b04 - a31 * b02 + a33 * b00) * det; - - return out; -}; - -/** - * Returns a string representation of a mat3 - * - * @param {mat3} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat3.str = function (a) { - return ("mat3(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ", " + (a.m06) + ", " + (a.m07) + ", " + (a.m08) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat3} m - * @returns {array} - */ -mat3.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - out[6] = m.m06; - out[7] = m.m07; - out[8] = m.m08; - - return out; -}; - -/** - * Returns Frobenius norm of a mat3 - * - * @param {mat3} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat3.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2))); -}; - -/** - * Adds two mat3's - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - out.m06 = a.m06 + b.m06; - out.m07 = a.m07 + b.m07; - out.m08 = a.m08 + b.m08; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - out.m06 = a.m06 - b.m06; - out.m07 = a.m07 - b.m07; - out.m08 = a.m08 - b.m08; - return out; -}; - -/** - * Alias for {@link mat3.subtract} - * @function - */ -mat3.sub = mat3.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat3} out - */ -mat3.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - out.m06 = a.m06 * b; - out.m07 = a.m07 * b; - out.m08 = a.m08 * b; - return out; -}; - -/** - * Adds two mat3's after multiplying each element of the second operand by a scalar value. - * - * @param {mat3} out the receiving vector - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat3} out - */ -mat3.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - out.m06 = a.m06 + (b.m06 * scale); - out.m07 = a.m07 + (b.m07 * scale); - out.m08 = a.m08 + (b.m08 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat3} a The first matrix. - * @param {mat3} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat3.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && - a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05 && - a.m06 === b.m06 && a.m07 === b.m07 && a.m08 === b.m08; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat3} a The first matrix. - * @param {mat3} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat3.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, a8 = a.m08; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, b8 = b.m08; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && - Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && - Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && - Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) - ); -}; - -var _tmp$4 = new Array(4); - -var _quat = function _quat(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; -}; - -_quat.prototype.toJSON = function toJSON () { - _tmp$4[0] = this.x; - _tmp$4[1] = this.y; - _tmp$4[2] = this.z; - _tmp$4[3] = this.w; - - return _tmp$4; -}; - -/** - * @class Quaternion - * @name quat - */ -var quat = {}; - -/** - * Creates a new identity quat - * - * @returns {quat} a new quaternion - */ -quat.create = function () { - return new _quat(0, 0, 0, 1); -}; - -/** - * Creates a new quat initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {quat} a new quaternion - * @function - */ -quat.new = function (x, y, z, w) { - return new _quat(x, y, z, w); -}; - -/** - * Creates a new quat initialized with values from an existing quaternion - * - * @param {quat} a quaternion to clone - * @returns {quat} a new quaternion - * @function - */ -quat.clone = function (a) { - return new _quat(a.x, a.y, a.z, a.w); -}; - -/** - * Copy the values from one quat to another - * - * @param {quat} out the receiving quaternion - * @param {quat} a the source quaternion - * @returns {quat} out - * @function - */ -quat.copy = vec4.copy; - -/** - * Set the components of a quat to the given values - * - * @param {quat} out the receiving quaternion - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {quat} out - * @function - */ -quat.set = vec4.set; - -/** - * Set a quat to the identity quaternion - * - * @param {quat} out the receiving quaternion - * @returns {quat} out - */ -quat.identity = function (out) { - out.x = 0; - out.y = 0; - out.z = 0; - out.w = 1; - return out; -}; - -/** - * Sets a quaternion to represent the shortest rotation from one - * vector to another. - * - * Both vectors are assumed to be unit length. - * - * @param {quat} out the receiving quaternion. - * @param {vec3} a the initial vector - * @param {vec3} b the destination vector - * @returns {quat} out - */ -quat.rotationTo = (function () { - var tmpvec3 = vec3.create(); - var xUnitVec3 = vec3.new(1, 0, 0); - var yUnitVec3 = vec3.new(0, 1, 0); - - return function (out, a, b) { - var dot = vec3.dot(a, b); - if (dot < -0.999999) { - vec3.cross(tmpvec3, xUnitVec3, a); - if (vec3.length(tmpvec3) < 0.000001) { - vec3.cross(tmpvec3, yUnitVec3, a); - } - vec3.normalize(tmpvec3, tmpvec3); - quat.fromAxisAngle(out, tmpvec3, Math.PI); - return out; - } else if (dot > 0.999999) { - out.x = 0; - out.y = 0; - out.z = 0; - out.w = 1; - return out; - } else { - vec3.cross(tmpvec3, a, b); - out.x = tmpvec3.x; - out.y = tmpvec3.y; - out.z = tmpvec3.z; - out.w = 1 + dot; - return quat.normalize(out, out); - } - }; -})(); - -/** - * Gets the rotation axis and angle for a given - * quaternion. If a quaternion is created with - * fromAxisAngle, this method will return the same - * values as providied in the original parameter list - * OR functionally equivalent values. - * Example: The quaternion formed by axis [0, 0, 1] and - * angle -90 is the same as the quaternion formed by - * [0, 0, 1] and 270. This method favors the latter. - * @param {vec3} out_axis Vector receiving the axis of rotation - * @param {quat} q Quaternion to be decomposed - * @return {Number} Angle, in radians, of the rotation - */ -quat.getAxisAngle = function (out_axis, q) { - var rad = Math.acos(q.w) * 2.0; - var s = Math.sin(rad / 2.0); - if (s != 0.0) { - out_axis.x = q.x / s; - out_axis.y = q.y / s; - out_axis.z = q.z / s; - } else { - // If s is zero, return any axis (no rotation - axis does not matter) - out_axis.x = 1; - out_axis.y = 0; - out_axis.z = 0; - } - return rad; -}; - -/** - * Multiplies two quat's - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @returns {quat} out - */ -quat.multiply = function (out, a, b) { - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = b.x, by = b.y, bz = b.z, bw = b.w; - - out.x = ax * bw + aw * bx + ay * bz - az * by; - out.y = ay * bw + aw * by + az * bx - ax * bz; - out.z = az * bw + aw * bz + ax * by - ay * bx; - out.w = aw * bw - ax * bx - ay * by - az * bz; - return out; -}; - -/** - * Alias for {@link quat.multiply} - * @function - */ -quat.mul = quat.multiply; - -/** - * Scales a quat by a scalar number - * - * @param {quat} out the receiving vector - * @param {quat} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {quat} out - * @function - */ -quat.scale = vec4.scale; - -/** - * Rotates a quaternion by the given angle about the X axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateX = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw + aw * bx; - out.y = ay * bw + az * bx; - out.z = az * bw - ay * bx; - out.w = aw * bw - ax * bx; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the Y axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateY = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - by = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw - az * by; - out.y = ay * bw + aw * by; - out.z = az * bw + ax * by; - out.w = aw * bw - ay * by; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the Z axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateZ = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bz = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw + ay * bz; - out.y = ay * bw - ax * bz; - out.z = az * bw + aw * bz; - out.w = aw * bw - az * bz; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the axis in world space - * - * @param {quat} out quat receiving operation result - * @param {quat} rot quat to rotate - * @param {vec3} axis the axis around which to rotate in world space - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateAround = (function () { - var v3_tmp = vec3.create(); - var q_tmp = quat.create(); - - return function (out, rot, axis, rad) { - // get inv-axis (local to rot) - quat.invert(q_tmp, rot); - vec3.transformQuat(v3_tmp, axis, q_tmp); - // rotate by inv-axis - quat.fromAxisAngle(q_tmp, v3_tmp, rad); - quat.mul(out, rot, q_tmp); - - return out; - }; -})(); - -/** - * Rotates a quaternion by the given angle about the axis in local space - * - * @param {quat} out quat receiving operation result - * @param {quat} rot quat to rotate - * @param {vec3} axis the axis around which to rotate in local space - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateAroundLocal = (function () { - var q_tmp = quat.create(); - - return function (out, rot, axis, rad) { - quat.fromAxisAngle(q_tmp, axis, rad); - quat.mul(out, rot, q_tmp); - - return out; - }; -})(); - -/** - * Calculates the W component of a quat from the X, Y, and Z components. - * Assumes that quaternion is 1 unit in length. - * Any existing W component will be ignored. - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate W component of - * @returns {quat} out - */ -quat.calculateW = function (out, a) { - var x = a.x, y = a.y, z = a.z; - - out.x = x; - out.y = y; - out.z = z; - out.w = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); - return out; -}; - -/** - * Calculates the dot product of two quat's - * - * @param {quat} a the first operand - * @param {quat} b the second operand - * @returns {Number} dot product of a and b - * @function - */ -quat.dot = vec4.dot; - -/** - * Performs a linear interpolation between two quat's - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {quat} out - * @function - */ -quat.lerp = vec4.lerp; - -/** - * Performs a spherical linear interpolation between two quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {quat} out - */ -quat.slerp = function (out, a, b, t) { - // benchmarks: - // http://jsperf.com/quaternion-slerp-implementations - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = b.x, by = b.y, bz = b.z, bw = b.w; - - var omega, cosom, sinom, scale0, scale1; - - // calc cosine - cosom = ax * bx + ay * by + az * bz + aw * bw; - // adjust signs (if necessary) - if (cosom < 0.0) { - cosom = -cosom; - bx = - bx; - by = - by; - bz = - bz; - bw = - bw; - } - // calculate coefficients - if ((1.0 - cosom) > 0.000001) { - // standard case (slerp) - omega = Math.acos(cosom); - sinom = Math.sin(omega); - scale0 = Math.sin((1.0 - t) * omega) / sinom; - scale1 = Math.sin(t * omega) / sinom; - } else { - // "from" and "to" quaternions are very close - // ... so we can do a linear interpolation - scale0 = 1.0 - t; - scale1 = t; - } - // calculate final values - out.x = scale0 * ax + scale1 * bx; - out.y = scale0 * ay + scale1 * by; - out.z = scale0 * az + scale1 * bz; - out.w = scale0 * aw + scale1 * bw; - - return out; -}; - -/** - * Performs a spherical linear interpolation with two control points - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {quat} c the third operand - * @param {quat} d the fourth operand - * @param {Number} t interpolation amount - * @returns {quat} out - */ -quat.sqlerp = (function () { - var temp1 = quat.create(); - var temp2 = quat.create(); - - return function (out, a, b, c, d, t) { - quat.slerp(temp1, a, d, t); - quat.slerp(temp2, b, c, t); - quat.slerp(out, temp1, temp2, 2 * t * (1 - t)); - - return out; - }; -}()); - -/** - * Calculates the inverse of a quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate inverse of - * @returns {quat} out - */ -quat.invert = function (out, a) { - var a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; - var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3; - var invDot = dot ? 1.0 / dot : 0; - - // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 - - out.x = -a0 * invDot; - out.y = -a1 * invDot; - out.z = -a2 * invDot; - out.w = a3 * invDot; - return out; -}; - -/** - * Calculates the conjugate of a quat - * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate conjugate of - * @returns {quat} out - */ -quat.conjugate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - out.w = a.w; - return out; -}; - -/** - * Calculates the length of a quat - * - * @param {quat} a vector to calculate length of - * @returns {Number} length of a - * @function - */ -quat.length = vec4.length; - -/** - * Alias for {@link quat.length} - * @function - */ -quat.len = quat.length; - -/** - * Calculates the squared length of a quat - * - * @param {quat} a vector to calculate squared length of - * @returns {Number} squared length of a - * @function - */ -quat.squaredLength = vec4.squaredLength; - -/** - * Alias for {@link quat.squaredLength} - * @function - */ -quat.sqrLen = quat.squaredLength; - -/** - * Normalize a quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a quaternion to normalize - * @returns {quat} out - * @function - */ -quat.normalize = vec4.normalize; - -/** - * Sets the specified quaternion with values corresponding to the given - * axes. Each axis is a vec3 and is expected to be unit length and - * perpendicular to all other specified axes. - * - * @param {vec3} xAxis the vector representing the local "right" direction - * @param {vec3} yAxis the vector representing the local "up" direction - * @param {vec3} zAxis the vector representing the viewing direction - * @returns {quat} out - */ -quat.fromAxes = (function () { - var matr = mat3.create(); - - return function (out, xAxis, yAxis, zAxis) { - mat3.set( - matr, - xAxis.x, xAxis.y, xAxis.z, - yAxis.x, yAxis.y, yAxis.z, - zAxis.x, zAxis.y, zAxis.z - ); - return quat.normalize(out, quat.fromMat3(out, matr)); - }; -})(); - -/** -* Calculates a quaternion from view direction and up direction -* -* @param {quat} out mat3 receiving operation result -* @param {vec3} view view direction (must be normalized) -* @param {vec3} [up] up direction, default is (0,1,0) (must be normalized) -* -* @returns {quat} out -*/ -quat.fromViewUp = (function () { - var matr = mat3.create(); - - return function (out, view, up) { - mat3.fromViewUp(matr, view, up); - if (!matr) { - return null; - } - - return quat.normalize(out, quat.fromMat3(out, matr)); - }; -})(); - -/** - * Sets a quat from the given angle and rotation axis, - * then returns it. - * - * @param {quat} out the receiving quaternion - * @param {vec3} axis the axis around which to rotate - * @param {Number} rad the angle in radians - * @returns {quat} out - **/ -quat.fromAxisAngle = function (out, axis, rad) { - rad = rad * 0.5; - var s = Math.sin(rad); - out.x = s * axis.x; - out.y = s * axis.y; - out.z = s * axis.z; - out.w = Math.cos(rad); - return out; -}; - -/** - * Creates a quaternion from the given 3x3 rotation matrix. - * - * NOTE: The resultant quaternion is not normalized, so you should be sure - * to renormalize the quaternion yourself where necessary. - * - * @param {quat} out the receiving quaternion - * @param {mat3} m rotation matrix - * @returns {quat} out - * @function - */ -quat.fromMat3 = function (out, m) { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - - var m00 = m.m00, m01 = m.m03, m02 = m.m06, - m10 = m.m01, m11 = m.m04, m12 = m.m07, - m20 = m.m02, m21 = m.m05, m22 = m.m08; - - var trace = m00 + m11 + m22; - - if (trace > 0) { - var s = 0.5 / Math.sqrt(trace + 1.0); - - out.w = 0.25 / s; - out.x = (m21 - m12) * s; - out.y = (m02 - m20) * s; - out.z = (m10 - m01) * s; - - } else if ((m00 > m11) && (m00 > m22)) { - var s$1 = 2.0 * Math.sqrt(1.0 + m00 - m11 - m22); - - out.w = (m21 - m12) / s$1; - out.x = 0.25 * s$1; - out.y = (m01 + m10) / s$1; - out.z = (m02 + m20) / s$1; - - } else if (m11 > m22) { - var s$2 = 2.0 * Math.sqrt(1.0 + m11 - m00 - m22); - - out.w = (m02 - m20) / s$2; - out.x = (m01 + m10) / s$2; - out.y = 0.25 * s$2; - out.z = (m12 + m21) / s$2; - - } else { - var s$3 = 2.0 * Math.sqrt(1.0 + m22 - m00 - m11); - - out.w = (m10 - m01) / s$3; - out.x = (m02 + m20) / s$3; - out.y = (m12 + m21) / s$3; - out.z = 0.25 * s$3; - } - - return out; -}; - -/** - * Creates a quaternion from the given euler angle x, y, z. - * - * @param {quat} out the receiving quaternion - * @param {x} Angle to rotate around X axis in degrees. - * @param {y} Angle to rotate around Y axis in degrees. - * @param {z} Angle to rotate around Z axis in degrees. - * @returns {quat} out - * @function - */ -quat.fromEuler = function (out, x, y, z) { - var halfToRad = 0.5 * Math.PI / 180.0; - x *= halfToRad; - y *= halfToRad; - z *= halfToRad; - - var sx = Math.sin(x); - var cx = Math.cos(x); - var sy = Math.sin(y); - var cy = Math.cos(y); - var sz = Math.sin(z); - var cz = Math.cos(z); - - out.x = sx * cy * cz + cx * sy * sz; - out.y = cx * sy * cz + sx * cy * sz; - out.z = cx * cy * sz - sx * sy * cz; - out.w = cx * cy * cz - sx * sy * sz; - - return out; -}; - -/** - * Convert a quaternion back to euler angle (in degrees). - * - * @param {vec3} out - Euler angle stored as a vec3 - * @param {number} q - the quaternion to be converted - * @returns {vec3} out. - */ -quat.toEuler = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var heading, attitude, bank; - var test = x * y + z * w; - if (test > 0.499) { // singularity at north pole - heading = 2 * Math.atan2(x,w); - attitude = Math.PI/2; - bank = 0; - } - if (test < -0.499) { // singularity at south pole - heading = -2 * Math.atan2(x,w); - attitude = - Math.PI/2; - bank = 0; - } - if(isNaN(heading)){ - var sqx = x*x; - var sqy = y*y; - var sqz = z*z; - heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // heading - attitude = Math.asin(2*test); // attitude - bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank - } - - out.y = toDegree(heading); - out.z = toDegree(attitude); - out.x = toDegree(bank); - - return out; -} - - -/** - * Returns a string representation of a quatenion - * - * @param {quat} a vector to represent as a string - * @returns {String} string representation of the vector - */ -quat.str = function (a) { - return ("quat(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ", " + (a.w) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {quat} q - * @returns {array} - */ -quat.array = function (out, q) { - out[0] = q.x; - out[1] = q.y; - out[2] = q.z; - out[3] = q.w; - - return out; -}; - -/** - * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===) - * - * @param {quat} a The first quaternion. - * @param {quat} b The second quaternion. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -quat.exactEquals = vec4.exactEquals; - -/** - * Returns whether or not the quaternions have approximately the same elements in the same position. - * - * @param {quat} a The first vector. - * @param {quat} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -quat.equals = vec4.equals; - -var _tmp$5 = new Array(4); - -var _mat2 = function _mat2(m00, m01, m02, m03) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; -}; - -_mat2.prototype.toJSON = function toJSON () { - _tmp$5[0] = this.m00; - _tmp$5[1] = this.m01; - _tmp$5[2] = this.m02; - _tmp$5[3] = this.m03; - - return _tmp$5; -}; - -/** - * @class 2x2 Matrix - * @name mat2 - */ -var mat2 = {}; - -/** - * Creates a new identity mat2 - * - * @returns {mat2} a new 2x2 matrix - */ -mat2.create = function() { - return new _mat2(1, 0, 0, 1); -}; - -/** - * Create a new mat2 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m10 Component in column 1, row 0 position (index 2) - * @param {Number} m11 Component in column 1, row 1 position (index 3) - * @returns {mat2} out A new 2x2 matrix - */ -mat2.new = function (m00, m01, m10, m11) { - return new _mat2(m00, m01, m10, m11); -}; - -/** - * Creates a new mat2 initialized with values from an existing matrix - * - * @param {mat2} a matrix to clone - * @returns {mat2} a new 2x2 matrix - */ -mat2.clone = function (a) { - return new _mat2(a.m00, a.m01, a.m02, a.m03); -}; - -/** - * Copy the values from one mat2 to another - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - return out; -}; - -/** - * Set a mat2 to the identity matrix - * - * @param {mat2} out the receiving matrix - * @returns {mat2} out - */ -mat2.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - return out; -}; - -/** - * Set the components of a mat2 to the given values - * - * @param {mat2} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m10 Component in column 1, row 0 position (index 2) - * @param {Number} m11 Component in column 1, row 1 position (index 3) - * @returns {mat2} out - */ -mat2.set = function (out, m00, m01, m10, m11) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m10; - out.m03 = m11; - return out; -}; - - -/** - * Transpose the values of a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a1 = a.m01; - out.m01 = a.m02; - out.m02 = a1; - } else { - out.m00 = a.m00; - out.m01 = a.m02; - out.m02 = a.m01; - out.m03 = a.m03; - } - - return out; -}; - -/** - * Inverts a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.invert = function (out, a) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - - // Calculate the determinant - var det = a0 * a3 - a2 * a1; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = a3 * det; - out.m01 = -a1 * det; - out.m02 = -a2 * det; - out.m03 = a0 * det; - - return out; -}; - -/** - * Calculates the adjugate of a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.adjoint = function (out, a) { - // Caching this value is nessecary if out == a - var a0 = a.m00; - out.m00 = a.m03; - out.m01 = -a.m01; - out.m02 = -a.m02; - out.m03 = a0; - - return out; -}; - -/** - * Calculates the determinant of a mat2 - * - * @param {mat2} a the source matrix - * @returns {Number} determinant of a - */ -mat2.determinant = function (a) { - return a.m00 * a.m03 - a.m02 * a.m01; -}; - -/** - * Multiplies two mat2's - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.multiply = function (out, a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - out.m00 = a0 * b0 + a2 * b1; - out.m01 = a1 * b0 + a3 * b1; - out.m02 = a0 * b2 + a2 * b3; - out.m03 = a1 * b2 + a3 * b3; - return out; -}; - -/** - * Alias for {@link mat2.multiply} - * @function - */ -mat2.mul = mat2.multiply; - -/** - * Rotates a mat2 by the given angle - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat2} out - */ -mat2.rotate = function (out, a, rad) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = a0 * c + a2 * s; - out.m01 = a1 * c + a3 * s; - out.m02 = a0 * -s + a2 * c; - out.m03 = a1 * -s + a3 * c; - return out; -}; - -/** - * Scales the mat2 by the dimensions in the given vec2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to rotate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat2} out - **/ -mat2.scale = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - v0 = v.x, v1 = v.y; - out.m00 = a0 * v0; - out.m01 = a1 * v0; - out.m02 = a2 * v1; - out.m03 = a3 * v1; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat2.identity(dest); - * mat2.rotate(dest, dest, rad); - * - * @param {mat2} out mat2 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat2} out - */ -mat2.fromRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = c; - out.m01 = s; - out.m02 = -s; - out.m03 = c; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat2.identity(dest); - * mat2.scale(dest, dest, vec); - * - * @param {mat2} out mat2 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat2} out - */ -mat2.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - out.m03 = v.y; - return out; -}; - -/** - * Returns a string representation of a mat2 - * - * @param {mat2} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat2.str = function (a) { - return ("mat2(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat2} m - * @returns {array} - */ -mat2.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - - return out; -}; - -/** - * Returns Frobenius norm of a mat2 - * - * @param {mat2} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat2.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2))); -}; - -/** - * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix - * @param {mat2} L the lower triangular matrix - * @param {mat2} D the diagonal matrix - * @param {mat2} U the upper triangular matrix - * @param {mat2} a the input matrix to factorize - */ - -mat2.LDU = function (L, D, U, a) { - L.m02 = a.m02 / a.m00; - U.m00 = a.m00; - U.m01 = a.m01; - U.m03 = a.m03 - L.m02 * U.m01; -}; - -/** - * Adds two mat2's - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - return out; -}; - -/** - * Alias for {@link mat2.subtract} - * @function - */ -mat2.sub = mat2.subtract; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat2} a The first matrix. - * @param {mat2} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat2.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat2} a The first matrix. - * @param {mat2} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat2.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) - ); -}; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat2} out - */ -mat2.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - return out; -}; - -/** - * Adds two mat2's after multiplying each element of the second operand by a scalar value. - * - * @param {mat2} out the receiving vector - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat2} out - */ -mat2.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - return out; -}; - -var _tmp$6 = new Array(6); - -var _mat23 = function _mat23(m00, m01, m02, m03, m04, m05) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; -}; - -_mat23.prototype.toJSON = function toJSON () { - _tmp$6[0] = this.m00; - _tmp$6[1] = this.m01; - _tmp$6[2] = this.m02; - _tmp$6[3] = this.m03; - _tmp$6[4] = this.m04; - _tmp$6[5] = this.m05; - - return _tmp$6; -}; - -/** - * @class 2x3 Matrix - * @name mat23 - * - * @description - * A mat23 contains six elements defined as: - *
- * [a, c, tx,
- *  b, d, ty]
- * 
- * This is a short form for the 3x3 matrix: - *
- * [a, c, tx,
- *  b, d, ty,
- *  0, 0, 1]
- * 
- * The last row is ignored so the array is shorter and operations are faster. - */ -var mat23 = {}; - -/** - * Creates a new identity mat23 - * - * @returns {mat23} a new 2x3 matrix - */ -mat23.create = function () { - return new _mat23( - 1, 0, - 0, 1, - 0, 0 - ); -}; - -/** - * Create a new mat23 with the given values - * - * @param {Number} a Component A (index 0) - * @param {Number} b Component B (index 1) - * @param {Number} c Component C (index 2) - * @param {Number} d Component D (index 3) - * @param {Number} tx Component TX (index 4) - * @param {Number} ty Component TY (index 5) - * @returns {mat23} A new mat23 - */ -mat23.new = function (a, b, c, d, tx, ty) { - return new _mat23( - a, b, - c, d, - tx, ty - ); -}; - -/** - * Creates a new mat23 initialized with values from an existing matrix - * - * @param {mat23} a matrix to clone - * @returns {mat23} a new 2x3 matrix - */ -mat23.clone = function (a) { - return new _mat23( - a.m00, a.m01, - a.m02, a.m03, - a.m04, a.m05 - ); -}; - -/** - * Copy the values from one mat23 to another - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the source matrix - * @returns {mat23} out - */ -mat23.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - return out; -}; - -/** - * Set a mat23 to the identity matrix - * - * @param {mat23} out the receiving matrix - * @returns {mat23} out - */ -mat23.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Set the components of a mat23 to the given values - * - * @param {mat23} out the receiving matrix - * @param {Number} a Component A (index 0) - * @param {Number} b Component B (index 1) - * @param {Number} c Component C (index 2) - * @param {Number} d Component D (index 3) - * @param {Number} tx Component TX (index 4) - * @param {Number} ty Component TY (index 5) - * @returns {mat23} out - */ -mat23.set = function (out, a, b, c, d, tx, ty) { - out.m00 = a; - out.m01 = b; - out.m02 = c; - out.m03 = d; - out.m04 = tx; - out.m05 = ty; - return out; -}; - -/** - * Inverts a mat23 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the source matrix - * @returns {mat23} out - */ -mat23.invert = function (out, a) { - var aa = a.m00, ab = a.m01, ac = a.m02, ad = a.m03, - atx = a.m04, aty = a.m05; - - var det = aa * ad - ab * ac; - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = ad * det; - out.m01 = -ab * det; - out.m02 = -ac * det; - out.m03 = aa * det; - out.m04 = (ac * aty - ad * atx) * det; - out.m05 = (ab * atx - aa * aty) * det; - return out; -}; - -/** - * Calculates the determinant of a mat23 - * - * @param {mat23} a the source matrix - * @returns {Number} determinant of a - */ -mat23.determinant = function (a) { - return a.m00 * a.m03 - a.m01 * a.m02; -}; - -/** - * Multiplies two mat23's - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.multiply = function (out, a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; - out.m00 = a0 * b0 + a2 * b1; - out.m01 = a1 * b0 + a3 * b1; - out.m02 = a0 * b2 + a2 * b3; - out.m03 = a1 * b2 + a3 * b3; - out.m04 = a0 * b4 + a2 * b5 + a4; - out.m05 = a1 * b4 + a3 * b5 + a5; - return out; -}; - -/** - * Alias for {@link mat23.multiply} - * @function - */ -mat23.mul = mat23.multiply; - -/** - * Rotates a mat23 by the given angle - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat23} out - */ -mat23.rotate = function (out, a, rad) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = a0 * c + a2 * s; - out.m01 = a1 * c + a3 * s; - out.m02 = a0 * -s + a2 * c; - out.m03 = a1 * -s + a3 * c; - out.m04 = a4; - out.m05 = a5; - return out; -}; - -/** - * Scales the mat23 by the dimensions in the given vec2 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to translate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat23} out - **/ -mat23.scale = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - v0 = v.x, v1 = v.y; - out.m00 = a0 * v0; - out.m01 = a1 * v0; - out.m02 = a2 * v1; - out.m03 = a3 * v1; - out.m04 = a4; - out.m05 = a5; - return out; -}; - -/** - * Translates the mat23 by the dimensions in the given vec2 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to translate - * @param {vec2} v the vec2 to translate the matrix by - * @returns {mat23} out - **/ -mat23.translate = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - v0 = v.x, v1 = v.y; - out.m00 = a0; - out.m01 = a1; - out.m02 = a2; - out.m03 = a3; - out.m04 = a0 * v0 + a2 * v1 + a4; - out.m05 = a1 * v0 + a3 * v1 + a5; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.rotate(dest, dest, rad); - * - * @param {mat23} out mat23 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat23} out - */ -mat23.fromRotation = function (out, rad) { - var s = Math.sin(rad), c = Math.cos(rad); - out.m00 = c; - out.m01 = s; - out.m02 = -s; - out.m03 = c; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.scale(dest, dest, vec); - * - * @param {mat23} out mat23 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat23} out - */ -mat23.fromScaling = function (out, v) { - out.m00 = v.m00; - out.m01 = 0; - out.m02 = 0; - out.m03 = v.m01; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.translate(dest, dest, vec); - * - * @param {mat23} out mat23 receiving operation result - * @param {vec2} v Translation vector - * @returns {mat23} out - */ -mat23.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - out.m04 = v.x; - out.m05 = v.y; - return out; -}; - -/** - * Returns a string representation of a mat23 - * - * @param {mat23} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat23.str = function (a) { - return ("mat23(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat23} m - * @returns {array} - */ -mat23.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - - return out; -}; - -/** - * Returns typed array to 16 float array - * - * @param {array} out - * @param {mat23} m - * @returns {array} - */ -mat23.array4x4 = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = 0; - out[3] = 0; - out[4] = m.m02; - out[5] = m.m03; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 1; - out[11] = 0; - out[12] = m.m04; - out[13] = m.m05; - out[14] = 0; - out[15] = 1; - - return out; -}; - -/** - * Returns Frobenius norm of a mat23 - * - * @param {mat23} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat23.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + 1)); -}; - -/** - * Adds two mat23's - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - return out; -}; - -/** - * Alias for {@link mat23.subtract} - * @function - */ -mat23.sub = mat23.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat23} out - */ -mat23.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - return out; -}; - -/** - * Adds two mat23's after multiplying each element of the second operand by a scalar value. - * - * @param {mat23} out the receiving vector - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat23} out - */ -mat23.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat23} a The first matrix. - * @param {mat23} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat23.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat23} a The first matrix. - * @param {mat23} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat23.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) - ); -}; - -var _tmp$7 = new Array(16); - -var _mat4 = function _mat4( - m00, m01, m02, m03, - m04, m05, m06, m07, - m08, m09, m10, m11, - m12, m13, m14, m15 -) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; - this.m06 = m06; - this.m07 = m07; - this.m08 = m08; - this.m09 = m09; - this.m10 = m10; - this.m11 = m11; - this.m12 = m12; - this.m13 = m13; - this.m14 = m14; - this.m15 = m15; -}; - -_mat4.prototype.toJSON = function toJSON () { - _tmp$7[0] = this.m00; - _tmp$7[1] = this.m01; - _tmp$7[2] = this.m02; - _tmp$7[3] = this.m03; - _tmp$7[4] = this.m04; - _tmp$7[5] = this.m05; - _tmp$7[6] = this.m06; - _tmp$7[7] = this.m07; - _tmp$7[8] = this.m08; - _tmp$7[9] = this.m09; - _tmp$7[10] = this.m10; - _tmp$7[11] = this.m11; - _tmp$7[12] = this.m12; - _tmp$7[13] = this.m13; - _tmp$7[14] = this.m14; - _tmp$7[15] = this.m15; - - return _tmp$7; -}; - -/** - * @class 4x4 Matrix - * @name mat4 - * - * NOTE: we use column-major matrix for all matrix calculation. - * - * This may lead to some confusion when referencing OpenGL documentation, - * however, which represents out all matricies in column-major format. - * This means that while in code a matrix may be typed out as: - * - * [1, 0, 0, 0, - * 0, 1, 0, 0, - * 0, 0, 1, 0, - * x, y, z, 0] - * - * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) - * is written as: - * - * 1 0 0 x - * 0 1 0 y - * 0 0 1 z - * 0 0 0 0 - * - * Please rest assured, however, that they are the same thing! - * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the - * apparent lack of consistency between the memory layout and the documentation. - */ -var mat4 = {}; - -/** - * Creates a new identity mat4 - * - * @returns {mat4} a new 4x4 matrix - */ -mat4.create = function () { - return new _mat4( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ); -}; - -/** - * Create a new mat4 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m03 Component in column 0, row 3 position (index 3) - * @param {Number} m10 Component in column 1, row 0 position (index 4) - * @param {Number} m11 Component in column 1, row 1 position (index 5) - * @param {Number} m12 Component in column 1, row 2 position (index 6) - * @param {Number} m13 Component in column 1, row 3 position (index 7) - * @param {Number} m20 Component in column 2, row 0 position (index 8) - * @param {Number} m21 Component in column 2, row 1 position (index 9) - * @param {Number} m22 Component in column 2, row 2 position (index 10) - * @param {Number} m23 Component in column 2, row 3 position (index 11) - * @param {Number} m30 Component in column 3, row 0 position (index 12) - * @param {Number} m31 Component in column 3, row 1 position (index 13) - * @param {Number} m32 Component in column 3, row 2 position (index 14) - * @param {Number} m33 Component in column 3, row 3 position (index 15) - * @returns {mat4} A new mat4 - */ -mat4.new = function (m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { - return new _mat4( - m00, m01, m02, m03, - m10, m11, m12, m13, - m20, m21, m22, m23, - m30, m31, m32, m33 - ); -}; - -/** - * Creates a new mat4 initialized with values from an existing matrix - * - * @param {mat4} a matrix to clone - * @returns {mat4} a new 4x4 matrix - */ -mat4.clone = function (a) { - return new _mat4( - a.m00, a.m01, a.m02, a.m03, - a.m04, a.m05, a.m06, a.m07, - a.m08, a.m09, a.m10, a.m11, - a.m12, a.m13, a.m14, a.m15 - ); -}; - -/** - * Copy the values from one mat4 to another - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - out.m09 = a.m09; - out.m10 = a.m10; - out.m11 = a.m11; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - return out; -}; - -/** - * Set the components of a mat4 to the given values - * - * @param {mat4} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m03 Component in column 0, row 3 position (index 3) - * @param {Number} m10 Component in column 1, row 0 position (index 4) - * @param {Number} m11 Component in column 1, row 1 position (index 5) - * @param {Number} m12 Component in column 1, row 2 position (index 6) - * @param {Number} m13 Component in column 1, row 3 position (index 7) - * @param {Number} m20 Component in column 2, row 0 position (index 8) - * @param {Number} m21 Component in column 2, row 1 position (index 9) - * @param {Number} m22 Component in column 2, row 2 position (index 10) - * @param {Number} m23 Component in column 2, row 3 position (index 11) - * @param {Number} m30 Component in column 3, row 0 position (index 12) - * @param {Number} m31 Component in column 3, row 1 position (index 13) - * @param {Number} m32 Component in column 3, row 2 position (index 14) - * @param {Number} m33 Component in column 3, row 3 position (index 15) - * @returns {mat4} out - */ -mat4.set = function (out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m02; - out.m03 = m03; - out.m04 = m10; - out.m05 = m11; - out.m06 = m12; - out.m07 = m13; - out.m08 = m20; - out.m09 = m21; - out.m10 = m22; - out.m11 = m23; - out.m12 = m30; - out.m13 = m31; - out.m14 = m32; - out.m15 = m33; - return out; -}; - - -/** - * Set a mat4 to the identity matrix - * - * @param {mat4} out the receiving matrix - * @returns {mat4} out - */ -mat4.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Transpose the values of a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a01 = a.m01, a02 = a.m02, a03 = a.m03, - a12 = a.m06, a13 = a.m07, - a23 = a.m11; - - out.m01 = a.m04; - out.m02 = a.m08; - out.m03 = a.m12; - out.m04 = a01; - out.m06 = a.m09; - out.m07 = a.m13; - out.m08 = a02; - out.m09 = a12; - out.m11 = a.m14; - out.m12 = a03; - out.m13 = a13; - out.m14 = a23; - } else { - out.m00 = a.m00; - out.m01 = a.m04; - out.m02 = a.m08; - out.m03 = a.m12; - out.m04 = a.m01; - out.m05 = a.m05; - out.m06 = a.m09; - out.m07 = a.m13; - out.m08 = a.m02; - out.m09 = a.m06; - out.m10 = a.m10; - out.m11 = a.m14; - out.m12 = a.m03; - out.m13 = a.m07; - out.m14 = a.m11; - out.m15 = a.m15; - } - - return out; -}; - -/** - * Inverts a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.invert = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out.m01 = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out.m02 = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out.m03 = (a22 * b04 - a21 * b05 - a23 * b03) * det; - out.m04 = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out.m05 = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out.m06 = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out.m07 = (a20 * b05 - a22 * b02 + a23 * b01) * det; - out.m08 = (a10 * b10 - a11 * b08 + a13 * b06) * det; - out.m09 = (a01 * b08 - a00 * b10 - a03 * b06) * det; - out.m10 = (a30 * b04 - a31 * b02 + a33 * b00) * det; - out.m11 = (a21 * b02 - a20 * b04 - a23 * b00) * det; - out.m12 = (a11 * b07 - a10 * b09 - a12 * b06) * det; - out.m13 = (a00 * b09 - a01 * b07 + a02 * b06) * det; - out.m14 = (a31 * b01 - a30 * b03 - a32 * b00) * det; - out.m15 = (a20 * b03 - a21 * b01 + a22 * b00) * det; - - return out; -}; - -/** - * Calculates the adjugate of a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.adjoint = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - out.m00 = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); - out.m01 = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); - out.m02 = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); - out.m03 = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); - out.m04 = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); - out.m05 = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); - out.m06 = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); - out.m07 = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); - out.m08 = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); - out.m09 = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); - out.m10 = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); - out.m11 = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); - out.m12 = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); - out.m13 = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); - out.m14 = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); - out.m15 = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); - return out; -}; - -/** - * Calculates the determinant of a mat4 - * - * @param {mat4} a the source matrix - * @returns {Number} determinant of a - */ -mat4.determinant = function (a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; -}; - -/** - * Multiplies two mat4's explicitly - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.multiply = function (out, a, b) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - // Cache only the current line of the second matrix - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - out.m00 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m01 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m02 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m03 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m04; b1 = b.m05; b2 = b.m06; b3 = b.m07; - out.m04 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m05 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m06 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m07 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m08; b1 = b.m09; b2 = b.m10; b3 = b.m11; - out.m08 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m09 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m10 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m11 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m12; b1 = b.m13; b2 = b.m14; b3 = b.m15; - out.m12 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m13 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m14 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m15 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - return out; -}; - -/** - * Alias for {@link mat4.multiply} - * @function - */ -mat4.mul = mat4.multiply; - -/** - * Translate a mat4 by the given vector - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to translate - * @param {vec3} v vector to translate by - * @returns {mat4} out - */ -mat4.translate = function (out, a, v) { - var x = v.x, y = v.y, z = v.z, - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23; - - if (a === out) { - out.m12 = a.m00 * x + a.m04 * y + a.m08 * z + a.m12; - out.m13 = a.m01 * x + a.m05 * y + a.m09 * z + a.m13; - out.m14 = a.m02 * x + a.m06 * y + a.m10 * z + a.m14; - out.m15 = a.m03 * x + a.m07 * y + a.m11 * z + a.m15; - } else { - a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; - a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; - a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; - - out.m00 = a00; out.m01 = a01; out.m02 = a02; out.m03 = a03; - out.m04 = a10; out.m05 = a11; out.m06 = a12; out.m07 = a13; - out.m08 = a20; out.m09 = a21; out.m10 = a22; out.m11 = a23; - - out.m12 = a00 * x + a10 * y + a20 * z + a.m12; - out.m13 = a01 * x + a11 * y + a21 * z + a.m13; - out.m14 = a02 * x + a12 * y + a22 * z + a.m14; - out.m15 = a03 * x + a13 * y + a23 * z + a.m15; - } - - return out; -}; - -/** - * Scales the mat4 by the dimensions in the given vec3 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to scale - * @param {vec3} v the vec3 to scale the matrix by - * @returns {mat4} out - **/ -mat4.scale = function (out, a, v) { - var x = v.x, y = v.y, z = v.z; - - out.m00 = a.m00 * x; - out.m01 = a.m01 * x; - out.m02 = a.m02 * x; - out.m03 = a.m03 * x; - out.m04 = a.m04 * y; - out.m05 = a.m05 * y; - out.m06 = a.m06 * y; - out.m07 = a.m07 * y; - out.m08 = a.m08 * z; - out.m09 = a.m09 * z; - out.m10 = a.m10 * z; - out.m11 = a.m11 * z; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - return out; -}; - -/** - * Rotates a mat4 by the given angle around the given axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @param {vec3} axis the axis to rotate around - * @returns {mat4} out - */ -mat4.rotate = function (out, a, rad, axis) { - var x = axis.x, y = axis.y, z = axis.z; - var s, c, t, - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23, - b00, b01, b02, - b10, b11, b12, - b20, b21, b22; - - var len = Math.sqrt(x * x + y * y + z * z); - - if (Math.abs(len) < EPSILON) { - return null; - } - - len = 1 / len; - x *= len; - y *= len; - z *= len; - - s = Math.sin(rad); - c = Math.cos(rad); - t = 1 - c; - - a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; - a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; - a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; - - // Construct the elements of the rotation matrix - b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; - b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; - b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; - - // Perform rotation-specific matrix multiplication - out.m00 = a00 * b00 + a10 * b01 + a20 * b02; - out.m01 = a01 * b00 + a11 * b01 + a21 * b02; - out.m02 = a02 * b00 + a12 * b01 + a22 * b02; - out.m03 = a03 * b00 + a13 * b01 + a23 * b02; - out.m04 = a00 * b10 + a10 * b11 + a20 * b12; - out.m05 = a01 * b10 + a11 * b11 + a21 * b12; - out.m06 = a02 * b10 + a12 * b11 + a22 * b12; - out.m07 = a03 * b10 + a13 * b11 + a23 * b12; - out.m08 = a00 * b20 + a10 * b21 + a20 * b22; - out.m09 = a01 * b20 + a11 * b21 + a21 * b22; - out.m10 = a02 * b20 + a12 * b21 + a22 * b22; - out.m11 = a03 * b20 + a13 * b21 + a23 * b22; - - // If the source and destination differ, copy the unchanged last row - if (a !== out) { - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - return out; -}; - -/** - * Rotates a matrix by the given angle around the X axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateX = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a10 = a.m04, - a11 = a.m05, - a12 = a.m06, - a13 = a.m07, - a20 = a.m08, - a21 = a.m09, - a22 = a.m10, - a23 = a.m11; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m04 = a10 * c + a20 * s; - out.m05 = a11 * c + a21 * s; - out.m06 = a12 * c + a22 * s; - out.m07 = a13 * c + a23 * s; - out.m08 = a20 * c - a10 * s; - out.m09 = a21 * c - a11 * s; - out.m10 = a22 * c - a12 * s; - out.m11 = a23 * c - a13 * s; - - return out; -}; - -/** - * Rotates a matrix by the given angle around the Y axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateY = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a.m00, - a01 = a.m01, - a02 = a.m02, - a03 = a.m03, - a20 = a.m08, - a21 = a.m09, - a22 = a.m10, - a23 = a.m11; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m00 = a00 * c - a20 * s; - out.m01 = a01 * c - a21 * s; - out.m02 = a02 * c - a22 * s; - out.m03 = a03 * c - a23 * s; - out.m08 = a00 * s + a20 * c; - out.m09 = a01 * s + a21 * c; - out.m10 = a02 * s + a22 * c; - out.m11 = a03 * s + a23 * c; - - return out; -}; - -/** - * Rotates a matrix by the given angle around the Z axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateZ = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a.m00, - a01 = a.m01, - a02 = a.m02, - a03 = a.m03, - a10 = a.m04, - a11 = a.m05, - a12 = a.m06, - a13 = a.m07; - - // If the source and destination differ, copy the unchanged last row - if (a !== out) { - out.m08 = a.m08; - out.m09 = a.m09; - out.m10 = a.m10; - out.m11 = a.m11; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m00 = a00 * c + a10 * s; - out.m01 = a01 * c + a11 * s; - out.m02 = a02 * c + a12 * s; - out.m03 = a03 * c + a13 * s; - out.m04 = a10 * c - a00 * s; - out.m05 = a11 * c - a01 * s; - out.m06 = a12 * c - a02 * s; - out.m07 = a13 * c - a03 * s; - - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, dest, vec); - * - * @param {mat4} out mat4 receiving operation result - * @param {vec3} v Translation vector - * @returns {mat4} out - */ -mat4.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.scale(dest, dest, vec); - * - * @param {mat4} out mat4 receiving operation result - * @param {vec3} v Scaling vector - * @returns {mat4} out - */ -mat4.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = v.y; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = v.z; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a given angle around a given axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotate(dest, dest, rad, axis); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @param {vec3} axis the axis to rotate around - * @returns {mat4} out - */ -mat4.fromRotation = function (out, rad, axis) { - var x = axis.x, y = axis.y, z = axis.z; - var len = Math.sqrt(x * x + y * y + z * z); - var s, c, t; - - if (Math.abs(len) < EPSILON) { - return null; - } - - len = 1 / len; - x *= len; - y *= len; - z *= len; - - s = Math.sin(rad); - c = Math.cos(rad); - t = 1 - c; - - // Perform rotation-specific matrix multiplication - out.m00 = x * x * t + c; - out.m01 = y * x * t + z * s; - out.m02 = z * x * t - y * s; - out.m03 = 0; - out.m04 = x * y * t - z * s; - out.m05 = y * y * t + c; - out.m06 = z * y * t + x * s; - out.m07 = 0; - out.m08 = x * z * t + y * s; - out.m09 = y * z * t - x * s; - out.m10 = z * z * t + c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the X axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateX(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromXRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = c; - out.m06 = s; - out.m07 = 0; - out.m08 = 0; - out.m09 = -s; - out.m10 = c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the Y axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateY(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromYRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = c; - out.m01 = 0; - out.m02 = -s; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = s; - out.m09 = 0; - out.m10 = c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the Z axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateZ(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromZRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = c; - out.m01 = s; - out.m02 = 0; - out.m03 = 0; - out.m04 = -s; - out.m05 = c; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a quaternion rotation and vector translation - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @returns {mat4} out - */ -mat4.fromRT = function (out, q, v) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - (yy + zz); - out.m01 = xy + wz; - out.m02 = xz - wy; - out.m03 = 0; - out.m04 = xy - wz; - out.m05 = 1 - (xx + zz); - out.m06 = yz + wx; - out.m07 = 0; - out.m08 = xz + wy; - out.m09 = yz - wx; - out.m10 = 1 - (xx + yy); - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - - return out; -}; - -/** - * Returns the translation vector component of a transformation - * matrix. If a matrix is built with fromRT, - * the returned vector will be the same as the translation vector - * originally supplied. - * @param {vec3} out Vector to receive translation component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {vec3} out - */ -mat4.getTranslation = function (out, mat) { - out.x = mat.m12; - out.y = mat.m13; - out.z = mat.m14; - - return out; -}; - -/** - * Returns the scaling factor component of a transformation - * matrix. If a matrix is built with fromRTS - * with a normalized Quaternion paramter, the returned vector will be - * the same as the scaling vector - * originally supplied. - * @param {vec3} out Vector to receive scaling factor component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {vec3} out - */ -mat4.getScaling = function (out, mat) { - var m11 = mat.m00, - m12 = mat.m01, - m13 = mat.m02, - m21 = mat.m04, - m22 = mat.m05, - m23 = mat.m06, - m31 = mat.m08, - m32 = mat.m09, - m33 = mat.m10; - - out.x = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13); - out.y = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23); - out.z = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33); - - return out; -}; - -/** - * Returns a quaternion representing the rotational component - * of a transformation matrix. If a matrix is built with - * fromRT, the returned quaternion will be the - * same as the quaternion originally supplied. - * @param {quat} out Quaternion to receive the rotation component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {quat} out - */ -mat4.getRotation = function (out, mat) { - // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - var trace = mat.m00 + mat.m05 + mat.m10; - var S = 0; - - if (trace > 0) { - S = Math.sqrt(trace + 1.0) * 2; - out.w = 0.25 * S; - out.x = (mat.m06 - mat.m09) / S; - out.y = (mat.m08 - mat.m02) / S; - out.z = (mat.m01 - mat.m04) / S; - } else if ((mat.m00 > mat.m05) & (mat.m00 > mat.m10)) { - S = Math.sqrt(1.0 + mat.m00 - mat.m05 - mat.m10) * 2; - out.w = (mat.m06 - mat.m09) / S; - out.x = 0.25 * S; - out.y = (mat.m01 + mat.m04) / S; - out.z = (mat.m08 + mat.m02) / S; - } else if (mat.m05 > mat.m10) { - S = Math.sqrt(1.0 + mat.m05 - mat.m00 - mat.m10) * 2; - out.w = (mat.m08 - mat.m02) / S; - out.x = (mat.m01 + mat.m04) / S; - out.y = 0.25 * S; - out.z = (mat.m06 + mat.m09) / S; - } else { - S = Math.sqrt(1.0 + mat.m10 - mat.m00 - mat.m05) * 2; - out.w = (mat.m01 - mat.m04) / S; - out.x = (mat.m08 + mat.m02) / S; - out.y = (mat.m06 + mat.m09) / S; - out.z = 0.25 * S; - } - - return out; -}; - -/** - * Creates a matrix from a quaternion rotation, vector translation and vector scale - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * mat4.scale(dest, scale) - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @param {vec3} s Scaling vector - * @returns {mat4} out - */ -mat4.fromRTS = function (out, q, v, s) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - var sx = s.x; - var sy = s.y; - var sz = s.z; - - out.m00 = (1 - (yy + zz)) * sx; - out.m01 = (xy + wz) * sx; - out.m02 = (xz - wy) * sx; - out.m03 = 0; - out.m04 = (xy - wz) * sy; - out.m05 = (1 - (xx + zz)) * sy; - out.m06 = (yz + wx) * sy; - out.m07 = 0; - out.m08 = (xz + wy) * sz; - out.m09 = (yz - wx) * sz; - out.m10 = (1 - (xx + yy)) * sz; - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - - return out; -}; - -/** - * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * mat4.translate(dest, origin); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * mat4.scale(dest, scale) - * mat4.translate(dest, negativeOrigin); - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @param {vec3} s Scaling vector - * @param {vec3} o The origin vector around which to scale and rotate - * @returns {mat4} out - */ -mat4.fromRTSOrigin = function (out, q, v, s, o) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - var sx = s.x; - var sy = s.y; - var sz = s.z; - - var ox = o.x; - var oy = o.y; - var oz = o.z; - - out.m00 = (1 - (yy + zz)) * sx; - out.m01 = (xy + wz) * sx; - out.m02 = (xz - wy) * sx; - out.m03 = 0; - out.m04 = (xy - wz) * sy; - out.m05 = (1 - (xx + zz)) * sy; - out.m06 = (yz + wx) * sy; - out.m07 = 0; - out.m08 = (xz + wy) * sz; - out.m09 = (yz - wx) * sz; - out.m10 = (1 - (xx + yy)) * sz; - out.m11 = 0; - out.m12 = v.x + ox - (out.m00 * ox + out.m04 * oy + out.m08 * oz); - out.m13 = v.y + oy - (out.m01 * ox + out.m05 * oy + out.m09 * oz); - out.m14 = v.z + oz - (out.m02 * ox + out.m06 * oy + out.m10 * oz); - out.m15 = 1; - - return out; -}; - -/** - * Calculates a 4x4 matrix from the given quaternion - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Quaternion to create matrix from - * - * @returns {mat4} out - */ -mat4.fromQuat = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var yx = y * x2; - var yy = y * y2; - var zx = z * x2; - var zy = z * y2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - yy - zz; - out.m01 = yx + wz; - out.m02 = zx - wy; - out.m03 = 0; - - out.m04 = yx - wz; - out.m05 = 1 - xx - zz; - out.m06 = zy + wx; - out.m07 = 0; - - out.m08 = zx + wy; - out.m09 = zy - wx; - out.m10 = 1 - xx - yy; - out.m11 = 0; - - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - - return out; -}; - -/** - * Generates a frustum matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {Number} left Left bound of the frustum - * @param {Number} right Right bound of the frustum - * @param {Number} bottom Bottom bound of the frustum - * @param {Number} top Top bound of the frustum - * @param {Number} near Near bound of the frustum - * @param {Number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.frustum = function (out, left, right, bottom, top, near, far) { - var rl = 1 / (right - left); - var tb = 1 / (top - bottom); - var nf = 1 / (near - far); - - out.m00 = (near * 2) * rl; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = (near * 2) * tb; - out.m06 = 0; - out.m07 = 0; - out.m08 = (right + left) * rl; - out.m09 = (top + bottom) * tb; - out.m10 = (far + near) * nf; - out.m11 = -1; - out.m12 = 0; - out.m13 = 0; - out.m14 = (far * near * 2) * nf; - out.m15 = 0; - return out; -}; - -/** - * Generates a perspective projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} fovy Vertical field of view in radians - * @param {number} aspect Aspect ratio. typically viewport width/height - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.perspective = function (out, fovy, aspect, near, far) { - var f = 1.0 / Math.tan(fovy / 2); - var nf = 1 / (near - far); - - out.m00 = f / aspect; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = f; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = (far + near) * nf; - out.m11 = -1; - out.m12 = 0; - out.m13 = 0; - out.m14 = (2 * far * near) * nf; - out.m15 = 0; - return out; -}; - -/** - * Generates a perspective projection matrix with the given field of view. - * This is primarily useful for generating projection matrices to be used - * with the still experiemental WebVR API. - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.perspectiveFromFieldOfView = function (out, fov, near, far) { - var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0); - var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0); - var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0); - var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0); - var xScale = 2.0 / (leftTan + rightTan); - var yScale = 2.0 / (upTan + downTan); - - out.m00 = xScale; - out.m01 = 0.0; - out.m02 = 0.0; - out.m03 = 0.0; - out.m04 = 0.0; - out.m05 = yScale; - out.m06 = 0.0; - out.m07 = 0.0; - out.m08 = -((leftTan - rightTan) * xScale * 0.5); - out.m09 = ((upTan - downTan) * yScale * 0.5); - out.m10 = far / (near - far); - out.m11 = -1.0; - out.m12 = 0.0; - out.m13 = 0.0; - out.m14 = (far * near) / (near - far); - out.m15 = 0.0; - return out; -}; - -/** - * Generates a orthogonal projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} left Left bound of the frustum - * @param {number} right Right bound of the frustum - * @param {number} bottom Bottom bound of the frustum - * @param {number} top Top bound of the frustum - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.ortho = function (out, left, right, bottom, top, near, far) { - var lr = 1 / (left - right); - var bt = 1 / (bottom - top); - var nf = 1 / (near - far); - out.m00 = -2 * lr; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = -2 * bt; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 2 * nf; - out.m11 = 0; - out.m12 = (left + right) * lr; - out.m13 = (top + bottom) * bt; - out.m14 = (far + near) * nf; - out.m15 = 1; - return out; -}; - -/** - * Generates a look-at matrix with the given eye position, focal point, and up axis - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {vec3} eye Position of the viewer - * @param {vec3} center Point the viewer is looking at - * @param {vec3} up vec3 pointing up - * @returns {mat4} out - */ -mat4.lookAt = function (out, eye, center, up) { - var x0, x1, x2, y0, y1, y2, z0, z1, z2, len; - var eyex = eye.x; - var eyey = eye.y; - var eyez = eye.z; - var upx = up.x; - var upy = up.y; - var upz = up.z; - var centerx = center.x; - var centery = center.y; - var centerz = center.z; - - if ( - Math.abs(eyex - centerx) < EPSILON && - Math.abs(eyey - centery) < EPSILON && - Math.abs(eyez - centerz) < EPSILON - ) { - return mat4.identity(out); - } - - z0 = eyex - centerx; - z1 = eyey - centery; - z2 = eyez - centerz; - - len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); - z0 *= len; - z1 *= len; - z2 *= len; - - x0 = upy * z2 - upz * z1; - x1 = upz * z0 - upx * z2; - x2 = upx * z1 - upy * z0; - len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); - if (!len) { - x0 = 0; - x1 = 0; - x2 = 0; - } else { - len = 1 / len; - x0 *= len; - x1 *= len; - x2 *= len; - } - - y0 = z1 * x2 - z2 * x1; - y1 = z2 * x0 - z0 * x2; - y2 = z0 * x1 - z1 * x0; - - len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); - if (!len) { - y0 = 0; - y1 = 0; - y2 = 0; - } else { - len = 1 / len; - y0 *= len; - y1 *= len; - y2 *= len; - } - - out.m00 = x0; - out.m01 = y0; - out.m02 = z0; - out.m03 = 0; - out.m04 = x1; - out.m05 = y1; - out.m06 = z1; - out.m07 = 0; - out.m08 = x2; - out.m09 = y2; - out.m10 = z2; - out.m11 = 0; - out.m12 = -(x0 * eyex + x1 * eyey + x2 * eyez); - out.m13 = -(y0 * eyex + y1 * eyey + y2 * eyez); - out.m14 = -(z0 * eyex + z1 * eyey + z2 * eyez); - out.m15 = 1; - - return out; -}; - -/** - * Returns a string representation of a mat4 - * - * @param {mat4} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat4.str = function (a) { - return ("mat4(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ", " + (a.m06) + ", " + (a.m07) + ", " + (a.m08) + ", " + (a.m09) + ", " + (a.m10) + ", " + (a.m11) + ", " + (a.m12) + ", " + (a.m13) + ", " + (a.m14) + ", " + (a.m15) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat4} m - * @returns {array} - */ -mat4.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - out[6] = m.m06; - out[7] = m.m07; - out[8] = m.m08; - out[9] = m.m09; - out[10] = m.m10; - out[11] = m.m11; - out[12] = m.m12; - out[13] = m.m13; - out[14] = m.m14; - out[15] = m.m15; - - return out; -}; - -/** - * Returns Frobenius norm of a mat4 - * - * @param {mat4} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat4.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2) + Math.pow(a.m09, 2) + Math.pow(a.m10, 2) + Math.pow(a.m11, 2) + Math.pow(a.m12, 2) + Math.pow(a.m13, 2) + Math.pow(a.m14, 2) + Math.pow(a.m15, 2))) -}; - -/** - * Adds two mat4's - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - out.m06 = a.m06 + b.m06; - out.m07 = a.m07 + b.m07; - out.m08 = a.m08 + b.m08; - out.m09 = a.m09 + b.m09; - out.m10 = a.m10 + b.m10; - out.m11 = a.m11 + b.m11; - out.m12 = a.m12 + b.m12; - out.m13 = a.m13 + b.m13; - out.m14 = a.m14 + b.m14; - out.m15 = a.m15 + b.m15; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - out.m06 = a.m06 - b.m06; - out.m07 = a.m07 - b.m07; - out.m08 = a.m08 - b.m08; - out.m09 = a.m09 - b.m09; - out.m10 = a.m10 - b.m10; - out.m11 = a.m11 - b.m11; - out.m12 = a.m12 - b.m12; - out.m13 = a.m13 - b.m13; - out.m14 = a.m14 - b.m14; - out.m15 = a.m15 - b.m15; - return out; -}; - -/** - * Alias for {@link mat4.subtract} - * @function - */ -mat4.sub = mat4.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat4} out - */ -mat4.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - out.m06 = a.m06 * b; - out.m07 = a.m07 * b; - out.m08 = a.m08 * b; - out.m09 = a.m09 * b; - out.m10 = a.m10 * b; - out.m11 = a.m11 * b; - out.m12 = a.m12 * b; - out.m13 = a.m13 * b; - out.m14 = a.m14 * b; - out.m15 = a.m15 * b; - return out; -}; - -/** - * Adds two mat4's after multiplying each element of the second operand by a scalar value. - * - * @param {mat4} out the receiving vector - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat4} out - */ -mat4.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - out.m06 = a.m06 + (b.m06 * scale); - out.m07 = a.m07 + (b.m07 * scale); - out.m08 = a.m08 + (b.m08 * scale); - out.m09 = a.m09 + (b.m09 * scale); - out.m10 = a.m10 + (b.m10 * scale); - out.m11 = a.m11 + (b.m11 * scale); - out.m12 = a.m12 + (b.m12 * scale); - out.m13 = a.m13 + (b.m13 * scale); - out.m14 = a.m14 + (b.m14 * scale); - out.m15 = a.m15 + (b.m15 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat4} a The first matrix. - * @param {mat4} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat4.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && - a.m04 === b.m04 && a.m05 === b.m05 && a.m06 === b.m06 && a.m07 === b.m07 && - a.m08 === b.m08 && a.m09 === b.m09 && a.m10 === b.m10 && a.m11 === b.m11 && - a.m12 === b.m12 && a.m13 === b.m13 && a.m14 === b.m14 && a.m15 === b.m15; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat4} a The first matrix. - * @param {mat4} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat4.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, - a8 = a.m08, a9 = a.m09, a10 = a.m10, a11 = a.m11, - a12 = a.m12, a13 = a.m13, a14 = a.m14, a15 = a.m15; - - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, - b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, - b8 = b.m08, b9 = b.m09, b10 = b.m10, b11 = b.m11, - b12 = b.m12, b13 = b.m13, b14 = b.m14, b15 = b.m15; - - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && - Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && - Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && - Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && - Math.abs(a9 - b9) <= EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && - Math.abs(a10 - b10) <= EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && - Math.abs(a11 - b11) <= EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && - Math.abs(a12 - b12) <= EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && - Math.abs(a13 - b13) <= EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && - Math.abs(a14 - b14) <= EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && - Math.abs(a15 - b15) <= EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15)) - ); -}; - -var _tmp$8 = new Array(3); - -var _color3 = function _color3(r, g, b) { - this.r = r; - this.g = g; - this.b = b; -}; - -_color3.prototype.toJSON = function toJSON () { - _tmp$8[0] = this.r; - _tmp$8[1] = this.g; - _tmp$8[2] = this.b; - - return _tmp$8; -}; - -/** - * @class Color - * @name color3 - */ -var color3 = {}; - -/** - * Creates a new color - * - * @returns {color3} a new color - */ -color3.create = function () { - return new _color3(1, 1, 1); -}; - -/** - * Creates a new color initialized with the given values - * - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @returns {color3} a new color - * @function - */ -color3.new = function (r, g, b) { - return new _color3(r, g, b); -}; - -/** - * Creates a new color initialized with values from an existing quaternion - * - * @param {color3} a color to clone - * @returns {color3} a new color - * @function - */ -color3.clone = function (a) { - return new _color3(a.r, a.g, a.b, a.a); -}; - -/** - * Copy the values from one color to another - * - * @param {color3} out the receiving color - * @param {color3} a the source color - * @returns {color3} out - * @function - */ -color3.copy = function (out, a) { - out.r = a.r; - out.g = a.g; - out.b = a.b; - return out; -}; - -/** - * Set the components of a color to the given values - * - * @param {color3} out the receiving color - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @returns {color3} out - * @function - */ -color3.set = function (out, r, g, b) { - out.r = r; - out.g = g; - out.b = b; - return out; -}; - -/** - * Set from hex - * - * @param {color3} out the receiving color - * @param {Number} hex - * @returns {color3} out - * @function - */ -color3.fromHex = function (out, hex) { - var r = ((hex >> 16)) / 255.0; - var g = ((hex >> 8) & 0xff) / 255.0; - var b = ((hex) & 0xff) / 255.0; - - out.r = r; - out.g = g; - out.b = b; - return out; -}; - -/** - * Adds two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - * @function - */ -color3.add = function (out, a, b) { - out.r = a.r + b.r; - out.g = a.g + b.g; - out.b = a.b + b.b; - return out; -}; - -/** - * Subtracts color b from color a - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - */ -color3.subtract = function (out, a, b) { - out.r = a.r - b.r; - out.g = a.g - b.g; - out.b = a.b - b.b; - return out; -}; - -/** - * Alias for {@link color3.subtract} - * @function - */ -color3.sub = color3.subtract; - -/** - * Multiplies two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - * @function - */ -color3.multiply = function (out, a, b) { - out.r = a.r * b.r; - out.g = a.g * b.g; - out.b = a.b * b.b; - return out; -}; - -/** - * Alias for {@link color3.multiply} - * @function - */ -color3.mul = color3.multiply; - -/** - * Divides two color's - * - * @param {color3} out the receiving vector - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - */ -color3.divide = function (out, a, b) { - out.r = a.r / b.r; - out.g = a.g / b.g; - out.b = a.b / b.b; - return out; -}; - -/** - * Alias for {@link color3.divide} - * @function - */ -color3.div = color3.divide; - - -/** - * Scales a color by a scalar number - * - * @param {color3} out the receiving vector - * @param {color3} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {color3} out - * @function - */ -color3.scale = function (out, a, b) { - out.r = a.r * b; - out.g = a.g * b; - out.b = a.b * b; - return out; -}; - -/** - * Performs a linear interpolation between two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {color3} out - * @function - */ -color3.lerp = function (out, a, b, t) { - var ar = a.r, - ag = a.g, - ab = a.b; - out.r = ar + t * (b.r - ar); - out.g = ag + t * (b.g - ag); - out.b = ab + t * (b.b - ab); - return out; -}; - -/** - * Returns a string representation of a color - * - * @param {color3} a vector to represent as a string - * @returns {String} string representation of the vector - */ -color3.str = function (a) { - return ("color3(" + (a.r) + ", " + (a.g) + ", " + (a.b) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {color3} a - * @returns {array} - */ -color3.array = function (out, a) { - out[0] = a.r; - out[1] = a.g; - out[2] = a.b; - - return out; -}; - -/** - * Returns whether or not the color have exactly the same elements in the same position (when compared with ===) - * - * @param {color3} a The first color3. - * @param {color3} b The second color3. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color3.exactEquals = function (a, b) { - return a.r === b.r && a.g === b.g && a.b === b.b; -}; - -/** - * Returns whether or not the colors have approximately the same elements in the same position. - * - * @param {color3} a The first color3. - * @param {color3} b The second color3. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color3.equals = function (a, b) { - var a0 = a.r, a1 = a.g, a2 = a.b; - var b0 = b.r, b1 = b.g, b2 = b.b; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); -}; - -/** - * Returns the hex value - * - * @param {color3} a The color - * @returns {Number} - */ -color3.hex = function (a) { - return (a.r * 255) << 16 | (a.g * 255) << 8 | (a.b * 255); -}; - -var _tmp$9 = new Array(4); - -var _color4 = function _color4(r, g, b, a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; -}; - -_color4.prototype.toJSON = function toJSON () { - _tmp$9[0] = this.r; - _tmp$9[1] = this.g; - _tmp$9[2] = this.b; - _tmp$9[3] = this.a; - - return _tmp$9; -}; - -/** - * @class Color - * @name color4 - */ -var color4 = {}; - -/** - * Creates a new color - * - * @returns {color4} a new color - */ -color4.create = function () { - return new _color4(1, 1, 1, 1); -}; - -/** - * Creates a new color initialized with the given values - * - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @param {Number} a alpha component - * @returns {color4} a new color - * @function - */ -color4.new = function (r, g, b, a) { - return new _color4(r, g, b, a); -}; - -/** - * Creates a new color initialized with values from an existing quaternion - * - * @param {color4} a color to clone - * @returns {color4} a new color - * @function - */ -color4.clone = function (a) { - return new _color4(a.r, a.g, a.b, a.a); -}; - -/** - * Copy the values from one color to another - * - * @param {color4} out the receiving color - * @param {color4} a the source color - * @returns {color4} out - * @function - */ -color4.copy = function (out, a) { - out.r = a.r; - out.g = a.g; - out.b = a.b; - out.a = a.a; - return out; -}; - -/** - * Set the components of a color to the given values - * - * @param {color4} out the receiving color - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @param {Number} a alpha component - * @returns {color4} out - * @function - */ -color4.set = function (out, r, g, b, a) { - out.r = r; - out.g = g; - out.b = b; - out.a = a; - return out; -}; - -/** - * Set from hex - * - * @param {color4} out the receiving color - * @param {Number} hex - * @returns {color4} out - * @function - */ -color4.fromHex = function (out, hex) { - var r = ((hex >> 24)) / 255.0; - var g = ((hex >> 16) & 0xff) / 255.0; - var b = ((hex >> 8) & 0xff) / 255.0; - var a = ((hex) & 0xff) / 255.0; - - out.r = r; - out.g = g; - out.b = b; - out.a = a; - return out; -}; - -/** - * Adds two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - * @function - */ -color4.add = function (out, a, b) { - out.r = a.r + b.r; - out.g = a.g + b.g; - out.b = a.b + b.b; - out.a = a.a + b.a; - return out; -}; - -/** - * Subtracts color b from color a - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - */ -color4.subtract = function (out, a, b) { - out.r = a.r - b.r; - out.g = a.g - b.g; - out.b = a.b - b.b; - out.a = a.a - b.a; - return out; -}; - -/** - * Alias for {@link color4.subtract} - * @function - */ -color4.sub = color4.subtract; - -/** - * Multiplies two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - * @function - */ -color4.multiply = function (out, a, b) { - out.r = a.r * b.r; - out.g = a.g * b.g; - out.b = a.b * b.b; - out.a = a.a * b.a; - return out; -}; - -/** - * Alias for {@link color4.multiply} - * @function - */ -color4.mul = color4.multiply; - -/** - * Divides two color's - * - * @param {color4} out the receiving vector - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - */ -color4.divide = function (out, a, b) { - out.r = a.r / b.r; - out.g = a.g / b.g; - out.b = a.b / b.b; - out.a = a.a / b.a; - return out; -}; - -/** - * Alias for {@link color4.divide} - * @function - */ -color4.div = color4.divide; - - -/** - * Scales a color by a scalar number - * - * @param {color4} out the receiving vector - * @param {color4} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {color4} out - * @function - */ -color4.scale = function (out, a, b) { - out.r = a.r * b; - out.g = a.g * b; - out.b = a.b * b; - out.a = a.a * b; - return out; -}; - -/** - * Performs a linear interpolation between two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {color4} out - * @function - */ -color4.lerp = function (out, a, b, t) { - var ar = a.r, - ag = a.g, - ab = a.b, - aa = a.a; - out.r = ar + t * (b.r - ar); - out.g = ag + t * (b.g - ag); - out.b = ab + t * (b.b - ab); - out.a = aa + t * (b.a - aa); - return out; -}; - -/** - * Returns a string representation of a color - * - * @param {color4} a vector to represent as a string - * @returns {String} string representation of the vector - */ -color4.str = function (a) { - return ("color4(" + (a.r) + ", " + (a.g) + ", " + (a.b) + ", " + (a.a) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {color4} a - * @returns {array} - */ -color4.array = function (out, a) { - out[0] = a.r; - out[1] = a.g; - out[2] = a.b; - out[3] = a.a; - - return out; -}; - -/** - * Returns whether or not the color have exactly the same elements in the same position (when compared with ===) - * - * @param {color4} a The first color4. - * @param {color4} b The second color4. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color4.exactEquals = function (a, b) { - return a.r === b.r && a.g === b.g && a.b === b.b && a.a === b.a; -}; - -/** - * Returns whether or not the colors have approximately the same elements in the same position. - * - * @param {color4} a The first color4. - * @param {color4} b The second color4. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color4.equals = function (a, b) { - var a0 = a.r, a1 = a.g, a2 = a.b, a3 = a.a; - var b0 = b.r, b1 = b.g, b2 = b.b, b3 = b.a; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); -}; - -/** - * Returns the hex value - * - * @param {color4} a The color - * @returns {Number} - */ -color4.hex = function (a) { - return ((a.r * 255) << 24 | (a.g * 255) << 16 | (a.b * 255) << 8 | a.a * 255) >>> 0; -}; - -// NOTE: there is no syntax for: export {* as bits} from './lib/bits'; -var bits = bits_; - - - -var math = Object.freeze({ - bits: bits, - vec2: vec2, - vec3: vec3, - vec4: vec4, - quat: quat, - mat2: mat2, - mat23: mat23, - mat3: mat3, - mat4: mat4, - color3: color3, - color4: color4, - EPSILON: EPSILON, - equals: equals, - approx: approx, - clamp: clamp, - clamp01: clamp01, - lerp: lerp, - toRadian: toRadian, - toDegree: toDegree, - random: random, - randomRange: randomRange, - randomRangeInt: randomRangeInt, - nextPow2: nextPow2 -}); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Device = function Device(canvasEL) { - var ctx; - - try { - ctx = canvasEL.getContext('2d'); - } catch (err) { - console.error(err); - return; - } - - // statics - this._canvas = canvasEL; - this._ctx = ctx; - this._caps = {}; // capability - this._stats = { - drawcalls: 0, - }; - - // runtime - this._vx = this._vy = this._vw = this._vh = 0; - this._sx = this._sy = this._sw = this._sh = 0; -}; - -Device.prototype._restoreTexture = function _restoreTexture (unit) { -}; - -// =============================== -// Immediate Settings -// =============================== - -/** - * @method setViewport - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device.prototype.setViewport = function setViewport (x, y, w, h) { - if ( - this._vx !== x || - this._vy !== y || - this._vw !== w || - this._vh !== h - ) { - this._vx = x; - this._vy = y; - this._vw = w; - this._vh = h; - } -}; - -/** - * @method setScissor - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device.prototype.setScissor = function setScissor (x, y, w, h) { - if ( - this._sx !== x || - this._sy !== y || - this._sw !== w || - this._sh !== h - ) { - this._sx = x; - this._sy = y; - this._sw = w; - this._sh = h; - } -}; - -Device.prototype.clear = function clear (color) { - var ctx = this._ctx; - ctx.clearRect(this._vx, this._vy, this._vw, this._vh); - if (color && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { - ctx.fillStyle = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] +')'; - ctx.globalAlpha = color[3]; - ctx.fillRect(this._vx, this._vy, this._vw, this._vh); - } -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Texture2D = function Texture2D(device, options) { - this._device = device; - - this._width = 4; - this._height = 4; - - this._image = null; - - if (options) { - if (options.width !== undefined) { - this._width = options.width; - } - if (options.height !== undefined) { - this._height = options.height; - } - - this.updateImage(options); - } -}; - -Texture2D.prototype.update = function update (options) { - this.updateImage(options); -}; - -Texture2D.prototype.updateImage = function updateImage (options) { - if (options.images && options.images[0]) { - var image = options.images[0]; - if (image && image !== this._image) { - this._image = image; - } - } -}; - -Texture2D.prototype.destroy = function destroy () { - this._image = null; -}; - -var canvas = { - Device: Device, - Texture2D: Texture2D -}; - -// intenral -// deps -var Texture2D$2 = canvas.Texture2D; -var Device$2 = canvas.Device; -var gfx = {}; - -var renderEngine = { - // core classes - Device: Device$2, - Texture2D: Texture2D$2, - - // Canvas render support - canvas: canvas, - - // render scene - RenderData: RenderData, - - // memop - RecyclePool: RecyclePool, - Pool: Pool, - - // modules - math: math, - gfx: gfx -}; - -module.exports = renderEngine; diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js deleted file mode 100644 index 29d9926c6a5..00000000000 --- a/cocos2d/core/renderer/render-engine.js +++ /dev/null @@ -1,14878 +0,0 @@ - -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - render-engine v1.2.0 - 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. - ****************************************************************************/ - - -'use strict'; - -var _d2r = Math.PI / 180.0; -var _r2d = 180.0 / Math.PI; - -/** - * @property {number} EPSILON - */ -var EPSILON = 0.000001; - -/** - * Tests whether or not the arguments have approximately the same value, within an absolute - * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less - * than or equal to 1.0, and a relative tolerance is used for larger values) - * - * @param {Number} a The first number to test. - * @param {Number} b The second number to test. - * @returns {Boolean} True if the numbers are approximately equal, false otherwise. - */ -function equals(a, b) { - return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b)); -} - -/** - * Tests whether or not the arguments have approximately the same value by given maxDiff - * - * @param {Number} a The first number to test. - * @param {Number} b The second number to test. - * @param {Number} maxDiff Maximum difference. - * @returns {Boolean} True if the numbers are approximately equal, false otherwise. - */ -function approx(a, b, maxDiff) { - maxDiff = maxDiff || EPSILON; - return Math.abs(a - b) <= maxDiff; -} - -/** - * Clamps a value between a minimum float and maximum float value. - * - * @method clamp - * @param {number} val - * @param {number} min - * @param {number} max - * @return {number} - */ -function clamp(val, min, max) { - return val < min ? min : val > max ? max : val; -} - -/** - * Clamps a value between 0 and 1. - * - * @method clamp01 - * @param {number} val - * @return {number} - */ -function clamp01(val) { - return val < 0 ? 0 : val > 1 ? 1 : val; -} - -/** - * @method lerp - * @param {number} from - * @param {number} to - * @param {number} ratio - the interpolation coefficient - * @return {number} - */ -function lerp(from, to, ratio) { - return from + (to - from) * ratio; -} - -/** -* Convert Degree To Radian -* -* @param {Number} a Angle in Degrees -*/ -function toRadian(a) { - return a * _d2r; -} - -/** -* Convert Radian To Degree -* -* @param {Number} a Angle in Radian -*/ -function toDegree(a) { - return a * _r2d; -} - -/** -* @method random -*/ -var random = Math.random; - -/** - * Returns a floating-point random number between min (inclusive) and max (exclusive). - * - * @method randomRange - * @param {number} min - * @param {number} max - * @return {number} the random number - */ -function randomRange(min, max) { - return Math.random() * (max - min) + min; -} - -/** - * Returns a random integer between min (inclusive) and max (exclusive). - * - * @method randomRangeInt - * @param {number} min - * @param {number} max - * @return {number} the random integer - */ -function randomRangeInt(min, max) { - return Math.floor(randomRange(min, max)); -} - -/** - * Returns the next power of two for the value - * - * @method nextPow2 - * @param {number} val - * @return {number} the the next power of two - */ -function nextPow2(val) { - --val; - val = (val >> 1) | val; - val = (val >> 2) | val; - val = (val >> 4) | val; - val = (val >> 8) | val; - val = (val >> 16) | val; - ++val; - - return val; -} - -/** - * Bit twiddling hacks for JavaScript. - * - * Author: Mikola Lysenko - * - * Ported from Stanford bit twiddling hack library: - * http://graphics.stanford.edu/~seander/bithacks.html - */ - -// Number of bits in an integer -var INT_BITS = 32; -var INT_MAX = 0x7fffffff; -var INT_MIN = -1<<(INT_BITS-1); - -/** - * Returns -1, 0, +1 depending on sign of x - * - * @param {number} v - * @returns {number} - */ -function sign(v) { - return (v > 0) - (v < 0); -} - -/** - * Computes absolute value of integer - * - * @param {number} v - * @returns {number} - */ -function abs(v) { - var mask = v >> (INT_BITS-1); - return (v ^ mask) - mask; -} - -/** - * Computes minimum of integers x and y - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function min(x, y) { - return y ^ ((x ^ y) & -(x < y)); -} - -/** - * Computes maximum of integers x and y - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function max(x, y) { - return x ^ ((x ^ y) & -(x < y)); -} - -/** - * Checks if a number is a power of two - * - * @param {number} v - * @returns {boolean} - */ -function isPow2(v) { - return !(v & (v-1)) && (!!v); -} - -/** - * Computes log base 2 of v - * - * @param {number} v - * @returns {number} - */ -function log2(v) { - var r, shift; - r = (v > 0xFFFF) << 4; v >>>= r; - shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; - return r | (v >> 1); -} - -/** - * Computes log base 10 of v - * - * @param {number} v - * @returns {number} - */ -function log10(v) { - return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : - (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : - (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; -} - -/** - * Counts number of bits - * - * @param {number} v - * @returns {number} - */ -function popCount(v) { - v = v - ((v >>> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); - return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; -} - -/** - * Counts number of trailing zeros - * - * @param {number} v - * @returns {number} - */ -function countTrailingZeros(v) { - var c = 32; - v &= -v; - if (v) { c--; } - if (v & 0x0000FFFF) { c -= 16; } - if (v & 0x00FF00FF) { c -= 8; } - if (v & 0x0F0F0F0F) { c -= 4; } - if (v & 0x33333333) { c -= 2; } - if (v & 0x55555555) { c -= 1; } - return c; -} - -/** - * Rounds to next power of 2 - * - * @param {number} v - * @returns {number} - */ -function nextPow2$1(v) { - v += v === 0; - --v; - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v + 1; -} - -/** - * Rounds down to previous power of 2 - * - * @param {number} v - * @returns {number} - */ -function prevPow2(v) { - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v - (v>>>1); -} - -/** - * Computes parity of word - * - * @param {number} v - * @returns {number} - */ -function parity(v) { - v ^= v >>> 16; - v ^= v >>> 8; - v ^= v >>> 4; - v &= 0xf; - return (0x6996 >>> v) & 1; -} - -var REVERSE_TABLE = new Array(256); - -(function(tab) { - for(var i=0; i<256; ++i) { - var v = i, r = i, s = 7; - for (v >>>= 1; v; v >>>= 1) { - r <<= 1; - r |= v & 1; - --s; - } - tab[i] = (r << s) & 0xff; - } -})(REVERSE_TABLE); - -/** - * Reverse bits in a 32 bit word - * - * @param {number} v - * @returns {number} - */ -function reverse(v) { - return (REVERSE_TABLE[v & 0xff] << 24) | - (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | - (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | - REVERSE_TABLE[(v >>> 24) & 0xff]; -} - -/** - * Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function interleave2(x, y) { - x &= 0xFFFF; - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y &= 0xFFFF; - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -/** - * Extracts the nth interleaved component - * - * @param {number} v - * @param {number} n - * @returns {number} - */ -function deinterleave2(v, n) { - v = (v >>> n) & 0x55555555; - v = (v | (v >>> 1)) & 0x33333333; - v = (v | (v >>> 2)) & 0x0F0F0F0F; - v = (v | (v >>> 4)) & 0x00FF00FF; - v = (v | (v >>> 16)) & 0x000FFFF; - return (v << 16) >> 16; -} - -/** - * Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes - * - * @param {number} x - * @param {number} y - * @param {number} z - * @returns {number} - */ -function interleave3(x, y, z) { - x &= 0x3FF; - x = (x | (x<<16)) & 4278190335; - x = (x | (x<<8)) & 251719695; - x = (x | (x<<4)) & 3272356035; - x = (x | (x<<2)) & 1227133513; - - y &= 0x3FF; - y = (y | (y<<16)) & 4278190335; - y = (y | (y<<8)) & 251719695; - y = (y | (y<<4)) & 3272356035; - y = (y | (y<<2)) & 1227133513; - x |= (y << 1); - - z &= 0x3FF; - z = (z | (z<<16)) & 4278190335; - z = (z | (z<<8)) & 251719695; - z = (z | (z<<4)) & 3272356035; - z = (z | (z<<2)) & 1227133513; - - return x | (z << 2); -} - -/** - * Extracts nth interleaved component of a 3-tuple - * - * @param {number} v - * @param {number} n - * @returns {number} - */ -function deinterleave3(v, n) { - v = (v >>> n) & 1227133513; - v = (v | (v>>>2)) & 3272356035; - v = (v | (v>>>4)) & 251719695; - v = (v | (v>>>8)) & 4278190335; - v = (v | (v>>>16)) & 0x3FF; - return (v<<22)>>22; -} - -/** - * Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) - * - * @param {number} v - * @returns {number} - */ -function nextCombination(v) { - var t = v | (v - 1); - return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); -} - -var bits_ = Object.freeze({ - INT_BITS: INT_BITS, - INT_MAX: INT_MAX, - INT_MIN: INT_MIN, - sign: sign, - abs: abs, - min: min, - max: max, - isPow2: isPow2, - log2: log2, - log10: log10, - popCount: popCount, - countTrailingZeros: countTrailingZeros, - nextPow2: nextPow2$1, - prevPow2: prevPow2, - parity: parity, - reverse: reverse, - interleave2: interleave2, - deinterleave2: deinterleave2, - interleave3: interleave3, - deinterleave3: deinterleave3, - nextCombination: nextCombination -}); - -var _tmp = new Array(2); - -var _vec2 = function _vec2(x, y) { - this.x = x; - this.y = y; -}; - -_vec2.prototype.toJSON = function toJSON () { - _tmp[0] = this.x; - _tmp[1] = this.y; - - return _tmp; -}; - -/** - * @class 2 Dimensional Vector - * @name vec2 - */ -var vec2 = {}; - -/** - * Creates a new, empty vec2 - * - * @returns {vec2} a new 2D vector - */ -vec2.create = function () { - return new _vec2(0, 0); -}; - -/** - * Creates a new vec2 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @returns {vec2} a new 2D vector - */ -vec2.new = function (x, y) { - return new _vec2(x, y); -}; - -/** - * Creates a new vec2 initialized with values from an existing vector - * - * @param {vec2} a vector to clone - * @returns {vec2} a new 2D vector - */ -vec2.clone = function (a) { - return new _vec2(a.x, a.y); -}; - -/** - * Copy the values from one vec2 to another - * - * @param {vec2} out the receiving vector - * @param {vec2} a the source vector - * @returns {vec2} out - */ -vec2.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - return out; -}; - -/** - * Set the components of a vec2 to the given values - * - * @param {vec2} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @returns {vec2} out - */ -vec2.set = function (out, x, y) { - out.x = x; - out.y = y; - return out; -}; - -/** - * Adds two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - return out; -}; - -/** - * Alias for {@link vec2.subtract} - * @function - */ -vec2.sub = vec2.subtract; - -/** - * Multiplies two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - return out; -}; - -/** - * Alias for {@link vec2.multiply} - * @function - */ -vec2.mul = vec2.multiply; - -/** - * Divides two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - return out; -}; - -/** - * Alias for {@link vec2.divide} - * @function - */ -vec2.div = vec2.divide; - -/** - * Math.ceil the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to ceil - * @returns {vec2} out - */ -vec2.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - return out; -}; - -/** - * Math.floor the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to floor - * @returns {vec2} out - */ -vec2.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - return out; -}; - -/** - * Returns the minimum of two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - return out; -}; - -/** - * Returns the maximum of two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - return out; -}; - -/** - * Math.round the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to round - * @returns {vec2} out - */ -vec2.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - return out; -}; - -/** - * Scales a vec2 by a scalar number - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec2} out - */ -vec2.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - return out; -}; - -/** - * Adds two vec2's after scaling the second operand by a scalar value - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec2} out - */ -vec2.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} distance between a and b - */ -vec2.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y; - return Math.sqrt(x * x + y * y); -}; - -/** - * Alias for {@link vec2.distance} - * @function - */ -vec2.dist = vec2.distance; - -/** - * Calculates the squared euclidian distance between two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} squared distance between a and b - */ -vec2.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y; - return x * x + y * y; -}; - -/** - * Alias for {@link vec2.squaredDistance} - * @function - */ -vec2.sqrDist = vec2.squaredDistance; - -/** - * Calculates the length of a vec2 - * - * @param {vec2} a vector to calculate length of - * @returns {Number} length of a - */ -vec2.length = function (a) { - var x = a.x, - y = a.y; - return Math.sqrt(x * x + y * y); -}; - -/** - * Alias for {@link vec2.length} - * @function - */ -vec2.len = vec2.length; - -/** - * Calculates the squared length of a vec2 - * - * @param {vec2} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec2.squaredLength = function (a) { - var x = a.x, - y = a.y; - return x * x + y * y; -}; - -/** - * Alias for {@link vec2.squaredLength} - * @function - */ -vec2.sqrLen = vec2.squaredLength; - -/** - * Negates the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to negate - * @returns {vec2} out - */ -vec2.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - return out; -}; - -/** - * Returns the inverse of the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to invert - * @returns {vec2} out - */ -vec2.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - return out; -}; - -/** - * Returns the inverse of the components of a vec2 safely - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to invert - * @returns {vec2} out - */ -vec2.inverseSafe = function (out, a) { - var x = a.x, - y = a.y; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / a.y; - } - - return out; -}; - -/** - * Normalize a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to normalize - * @returns {vec2} out - */ -vec2.normalize = function (out, a) { - var x = a.x, - y = a.y; - var len = x * x + y * y; - if (len > 0) { - //TODO: evaluate use of glm_invsqrt here? - len = 1 / Math.sqrt(len); - out.x = a.x * len; - out.y = a.y * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} dot product of a and b - */ -vec2.dot = function (a, b) { - return a.x * b.x + a.y * b.y; -}; - -/** - * Computes the cross product of two vec2's - * Note that the cross product must by definition produce a 3D vector - * - * @param {vec3} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec3} out - */ -vec2.cross = function (out, a, b) { - var z = a.x * b.y - a.y * b.x; - out.x = out.y = 0; - out.z = z; - return out; -}; - -/** - * Performs a linear interpolation between two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec2} out - */ -vec2.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec2} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec2} out - */ -vec2.random = function (out, scale) { - scale = scale || 1.0; - var r = random() * 2.0 * Math.PI; - out.x = Math.cos(r) * scale; - out.y = Math.sin(r) * scale; - return out; -}; - -/** - * Transforms the vec2 with a mat2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat2} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat2 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m02 * y; - out.y = m.m01 * x + m.m03 * y; - return out; -}; - -/** - * Transforms the vec2 with a mat23 - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat23} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat23 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m02 * y + m.m04; - out.y = m.m01 * x + m.m03 * y + m.m05; - return out; -}; - -/** - * Transforms the vec2 with a mat3 - * 3rd vector component is implicitly '1' - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat3} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat3 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m03 * y + m.m06; - out.y = m.m01 * x + m.m04 * y + m.m07; - return out; -}; - -/** - * Transforms the vec2 with a mat4 - * 3rd vector component is implicitly '0' - * 4th vector component is implicitly '1' - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat4 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m04 * y + m.m12; - out.y = m.m01 * x + m.m05 * y + m.m13; - return out; -}; - -/** - * Perform some operation over an array of vec2s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec2.forEach = (function () { - var vec = vec2.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 2; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; - } - - return a; - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec2} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec2.str = function (a) { - return ("vec2(" + (a.x) + ", " + (a.y) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec2} v - * @returns {array} - */ -vec2.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - - return out; -}; - -/** - * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===) - * - * @param {vec2} a The first vector. - * @param {vec2} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec2.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec2} a The first vector. - * @param {vec2} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec2.equals = function (a, b) { - var a0 = a.x, a1 = a.y; - var b0 = b.x, b1 = b.y; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1))); -}; - -var _tmp$1 = new Array(3); - -var _vec3 = function _vec3(x, y, z) { - this.x = x; - this.y = y; - this.z = z; -}; - -_vec3.prototype.toJSON = function toJSON () { - _tmp$1[0] = this.x; - _tmp$1[1] = this.y; - _tmp$1[2] = this.z; - - return _tmp$1; -}; - -/** - * @class 3 Dimensional Vector - * @name vec3 - */ -var vec3 = {}; - -/** - * Creates a new, empty vec3 - * - * @returns {vec3} a new 3D vector - */ -vec3.create = function () { - return new _vec3(0, 0, 0); -}; - -/** - * Creates a new vec3 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} a new 3D vector - */ -vec3.new = function (x, y, z) { - return new _vec3(x, y, z); -}; - -/** - * Creates a new vec3 initialized with values from an existing vector - * - * @param {vec3} a vector to clone - * @returns {vec3} a new 3D vector - */ -vec3.clone = function (a) { - return new _vec3(a.x, a.y, a.z); -}; - -/** - * Copy the values from one vec3 to another - * - * @param {vec3} out the receiving vector - * @param {vec3} a the source vector - * @returns {vec3} out - */ -vec3.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - out.z = a.z; - return out; -}; - -/** - * Set the components of a vec3 to the given values - * - * @param {vec3} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} out - */ -vec3.set = function (out, x, y, z) { - out.x = x; - out.y = y; - out.z = z; - return out; -}; - -/** - * Adds two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - out.z = a.z + b.z; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; - return out; -}; - -/** - * Alias for {@link vec3.subtract} - * @function - */ -vec3.sub = vec3.subtract; - -/** - * Multiplies two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - out.z = a.z * b.z; - return out; -}; - -/** - * Alias for {@link vec3.multiply} - * @function - */ -vec3.mul = vec3.multiply; - -/** - * Divides two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - out.z = a.z / b.z; - return out; -}; - -/** - * Alias for {@link vec3.divide} - * @function - */ -vec3.div = vec3.divide; - -/** - * Math.ceil the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to ceil - * @returns {vec3} out - */ -vec3.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - out.z = Math.ceil(a.z); - return out; -}; - -/** - * Math.floor the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to floor - * @returns {vec3} out - */ -vec3.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - out.z = Math.floor(a.z); - return out; -}; - -/** - * Returns the minimum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - out.z = Math.min(a.z, b.z); - return out; -}; - -/** - * Returns the maximum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - out.z = Math.max(a.z, b.z); - return out; -}; - -/** - * Math.round the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to round - * @returns {vec3} out - */ -vec3.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - out.z = Math.round(a.z); - return out; -}; - -/** - * Scales a vec3 by a scalar number - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec3} out - */ -vec3.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - out.z = a.z * b; - return out; -}; - -/** - * Adds two vec3's after scaling the second operand by a scalar value - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec3} out - */ -vec3.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - out.z = a.z + (b.z * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} distance between a and b - */ -vec3.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z; - return Math.sqrt(x * x + y * y + z * z); -}; - -/** - * Alias for {@link vec3.distance} - * @function - */ -vec3.dist = vec3.distance; - -/** - * Calculates the squared euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} squared distance between a and b - */ -vec3.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z; - return x * x + y * y + z * z; -}; - -/** - * Alias for {@link vec3.squaredDistance} - * @function - */ -vec3.sqrDist = vec3.squaredDistance; - -/** - * Calculates the length of a vec3 - * - * @param {vec3} a vector to calculate length of - * @returns {Number} length of a - */ -vec3.length = function (a) { - var x = a.x, - y = a.y, - z = a.z; - return Math.sqrt(x * x + y * y + z * z); -}; - -/** - * Alias for {@link vec3.length} - * @function - */ -vec3.len = vec3.length; - -/** - * Calculates the squared length of a vec3 - * - * @param {vec3} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec3.squaredLength = function (a) { - var x = a.x, - y = a.y, - z = a.z; - return x * x + y * y + z * z; -}; - -/** - * Alias for {@link vec3.squaredLength} - * @function - */ -vec3.sqrLen = vec3.squaredLength; - -/** - * Negates the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to negate - * @returns {vec3} out - */ -vec3.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - return out; -}; - -/** - * Returns the inverse of the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to invert - * @returns {vec3} out - */ -vec3.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - out.z = 1.0 / a.z; - return out; -}; - -/** - * Returns the inverse of the components of a vec3 safely - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to invert - * @returns {vec3} out - */ -vec3.inverseSafe = function (out, a) { - var x = a.x, - y = a.y, - z = a.z; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / y; - } - - if (Math.abs(z) < EPSILON) { - out.z = 0; - } else { - out.z = 1.0 / z; - } - - return out; -}; - -/** - * Normalize a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to normalize - * @returns {vec3} out - */ -vec3.normalize = function (out, a) { - var x = a.x, - y = a.y, - z = a.z; - - var len = x * x + y * y + z * z; - if (len > 0) { - //TODO: evaluate use of glm_invsqrt here? - len = 1 / Math.sqrt(len); - out.x = x * len; - out.y = y * len; - out.z = z * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} dot product of a and b - */ -vec3.dot = function (a, b) { - return a.x * b.x + a.y * b.y + a.z * b.z; -}; - -/** - * Computes the cross product of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.cross = function (out, a, b) { - var ax = a.x, ay = a.y, az = a.z, - bx = b.x, by = b.y, bz = b.z; - - out.x = ay * bz - az * by; - out.y = az * bx - ax * bz; - out.z = ax * by - ay * bx; - return out; -}; - -/** - * Performs a linear interpolation between two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y, - az = a.z; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - out.z = az + t * (b.z - az); - return out; -}; - -/** - * Performs a hermite interpolation with two control points - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {vec3} c the third operand - * @param {vec3} d the fourth operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.hermite = function (out, a, b, c, d, t) { - var factorTimes2 = t * t, - factor1 = factorTimes2 * (2 * t - 3) + 1, - factor2 = factorTimes2 * (t - 2) + t, - factor3 = factorTimes2 * (t - 1), - factor4 = factorTimes2 * (3 - 2 * t); - - out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; - out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; - out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; - - return out; -}; - -/** - * Performs a bezier interpolation with two control points - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {vec3} c the third operand - * @param {vec3} d the fourth operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.bezier = function (out, a, b, c, d, t) { - var inverseFactor = 1 - t, - inverseFactorTimesTwo = inverseFactor * inverseFactor, - factorTimes2 = t * t, - factor1 = inverseFactorTimesTwo * inverseFactor, - factor2 = 3 * t * inverseFactorTimesTwo, - factor3 = 3 * factorTimes2 * inverseFactor, - factor4 = factorTimes2 * t; - - out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; - out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; - out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; - - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec3} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec3} out - */ -vec3.random = function (out, scale) { - scale = scale || 1.0; - - var r = random() * 2.0 * Math.PI; - var z = (random() * 2.0) - 1.0; - var zScale = Math.sqrt(1.0 - z * z) * scale; - - out.x = Math.cos(r) * zScale; - out.y = Math.sin(r) * zScale; - out.z = z * scale; - return out; -}; - -/** - * Transforms the vec3 with a mat4. - * 4th vector component is implicitly '1' - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec3} out - */ -vec3.transformMat4 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z, - w = m.m03 * x + m.m07 * y + m.m11 * z + m.m15; - w = w || 1.0; - out.x = (m.m00 * x + m.m04 * y + m.m08 * z + m.m12) / w; - out.y = (m.m01 * x + m.m05 * y + m.m09 * z + m.m13) / w; - out.z = (m.m02 * x + m.m06 * y + m.m10 * z + m.m14) / w; - return out; -}; - -/** - * Transforms the vec3 with a mat3. - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m the 3x3 matrix to transform with - * @returns {vec3} out - */ -vec3.transformMat3 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z; - out.x = x * m.m00 + y * m.m03 + z * m.m06; - out.y = x * m.m01 + y * m.m04 + z * m.m07; - out.z = x * m.m02 + y * m.m05 + z * m.m08; - return out; -}; - -/** - * Transforms the vec3 with a quat - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec3} out - */ -vec3.transformQuat = function (out, a, q) { - // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations - - var x = a.x, y = a.y, z = a.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vec - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - - // calculate result * inverse quat - out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - return out; -}; - -/** - * Rotate a 3D vector around the x-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateX = function (out, a, b, c) { - var p = [], r = []; - // Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.x; - r.y = p.y * Math.cos(c) - p.z * Math.sin(c); - r.z = p.y * Math.sin(c) + p.z * Math.cos(c); - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Rotate a 3D vector around the y-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateY = function (out, a, b, c) { - var p = [], r = []; - //Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.z * Math.sin(c) + p.x * Math.cos(c); - r.y = p.y; - r.z = p.z * Math.cos(c) - p.x * Math.sin(c); - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Rotate a 3D vector around the z-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateZ = function (out, a, b, c) { - var p = [], r = []; - //Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.x * Math.cos(c) - p.y * Math.sin(c); - r.y = p.x * Math.sin(c) + p.y * Math.cos(c); - r.z = p.z; - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Perform some operation over an array of vec3s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec3.forEach = (function () { - var vec = vec3.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 3; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; vec.z = a[i + 2]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; a[i + 2] = vec.z; - } - - return a; - }; -})(); - -/** - * Get the angle between two 3D vectors - * @param {vec3} a The first operand - * @param {vec3} b The second operand - * @returns {Number} The angle in radians - */ -vec3.angle = (function () { - var tempA = vec3.create(); - var tempB = vec3.create(); - - return function (a, b) { - vec3.copy(tempA, a); - vec3.copy(tempB, b); - - vec3.normalize(tempA, tempA); - vec3.normalize(tempB, tempB); - - var cosine = vec3.dot(tempA, tempB); - - if (cosine > 1.0) { - return 0; - } - - if (cosine < -1.0) { - return Math.PI; - } - - return Math.acos(cosine); - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec3} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec3.str = function (a) { - return ("vec3(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec3} v - * @returns {array} - */ -vec3.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - out[2] = v.z; - - return out; -}; - -/** - * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec3.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y && a.z === b.z; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec3.equals = function (a, b) { - var a0 = a.x, a1 = a.y, a2 = a.z; - var b0 = b.x, b1 = b.y, b2 = b.z; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); -}; - -var _tmp$2 = new Array(4); - -var _vec4 = function _vec4(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; -}; - -_vec4.prototype.toJSON = function toJSON () { - _tmp$2[0] = this.x; - _tmp$2[1] = this.y; - _tmp$2[2] = this.z; - _tmp$2[3] = this.w; - - return _tmp$2; -}; - -/** - * @class 4 Dimensional Vector - * @name vec4 - */ -var vec4 = {}; - -/** - * Creates a new, empty vec4 - * - * @returns {vec4} a new 4D vector - */ -vec4.create = function () { - return new _vec4(0, 0, 0, 0); -}; - -/** - * Creates a new vec4 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} a new 4D vector - */ -vec4.new = function (x, y, z, w) { - return new _vec4(x, y, z, w); -}; - -/** - * Creates a new vec4 initialized with values from an existing vector - * - * @param {vec4} a vector to clone - * @returns {vec4} a new 4D vector - */ -vec4.clone = function (a) { - return new _vec4(a.x, a.y, a.z, a.w); -}; - -/** - * Copy the values from one vec4 to another - * - * @param {vec4} out the receiving vector - * @param {vec4} a the source vector - * @returns {vec4} out - */ -vec4.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - out.z = a.z; - out.w = a.w; - return out; -}; - -/** - * Set the components of a vec4 to the given values - * - * @param {vec4} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} out - */ -vec4.set = function (out, x, y, z, w) { - out.x = x; - out.y = y; - out.z = z; - out.w = w; - return out; -}; - -/** - * Adds two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - out.z = a.z + b.z; - out.w = a.w + b.w; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; - out.w = a.w - b.w; - return out; -}; - -/** - * Alias for {@link vec4.subtract} - * @function - */ -vec4.sub = vec4.subtract; - -/** - * Multiplies two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - out.z = a.z * b.z; - out.w = a.w * b.w; - return out; -}; - -/** - * Alias for {@link vec4.multiply} - * @function - */ -vec4.mul = vec4.multiply; - -/** - * Divides two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - out.z = a.z / b.z; - out.w = a.w / b.w; - return out; -}; - -/** - * Alias for {@link vec4.divide} - * @function - */ -vec4.div = vec4.divide; - -/** - * Math.ceil the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to ceil - * @returns {vec4} out - */ -vec4.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - out.z = Math.ceil(a.z); - out.w = Math.ceil(a.w); - return out; -}; - -/** - * Math.floor the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to floor - * @returns {vec4} out - */ -vec4.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - out.z = Math.floor(a.z); - out.w = Math.floor(a.w); - return out; -}; - -/** - * Returns the minimum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - out.z = Math.min(a.z, b.z); - out.w = Math.min(a.w, b.w); - return out; -}; - -/** - * Returns the maximum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - out.z = Math.max(a.z, b.z); - out.w = Math.max(a.w, b.w); - return out; -}; - -/** - * Math.round the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to round - * @returns {vec4} out - */ -vec4.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - out.z = Math.round(a.z); - out.w = Math.round(a.w); - return out; -}; - -/** - * Scales a vec4 by a scalar number - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec4} out - */ -vec4.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - out.z = a.z * b; - out.w = a.w * b; - return out; -}; - -/** - * Adds two vec4's after scaling the second operand by a scalar value - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec4} out - */ -vec4.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - out.z = a.z + (b.z * scale); - out.w = a.w + (b.w * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} distance between a and b - */ -vec4.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z, - w = b.w - a.w; - return Math.sqrt(x * x + y * y + z * z + w * w); -}; - -/** - * Alias for {@link vec4.distance} - * @function - */ -vec4.dist = vec4.distance; - -/** - * Calculates the squared euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} squared distance between a and b - */ -vec4.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z, - w = b.w - a.w; - return x * x + y * y + z * z + w * w; -}; - -/** - * Alias for {@link vec4.squaredDistance} - * @function - */ -vec4.sqrDist = vec4.squaredDistance; - -/** - * Calculates the length of a vec4 - * - * @param {vec4} a vector to calculate length of - * @returns {Number} length of a - */ -vec4.length = function (a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - return Math.sqrt(x * x + y * y + z * z + w * w); -}; - -/** - * Alias for {@link vec4.length} - * @function - */ -vec4.len = vec4.length; - -/** - * Calculates the squared length of a vec4 - * - * @param {vec4} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec4.squaredLength = function (a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - return x * x + y * y + z * z + w * w; -}; - -/** - * Alias for {@link vec4.squaredLength} - * @function - */ -vec4.sqrLen = vec4.squaredLength; - -/** - * Negates the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to negate - * @returns {vec4} out - */ -vec4.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - out.w = -a.w; - return out; -}; - -/** - * Returns the inverse of the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to invert - * @returns {vec4} out - */ -vec4.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - out.z = 1.0 / a.z; - out.w = 1.0 / a.w; - return out; -}; - -/** - * Returns the inverse of the components of a vec4 safely - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to invert - * @returns {vec4} out - */ -vec4.inverseSafe = function (out, a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / y; - } - - if (Math.abs(z) < EPSILON) { - out.z = 0; - } else { - out.z = 1.0 / z; - } - - if (Math.abs(w) < EPSILON) { - out.w = 0; - } else { - out.w = 1.0 / w; - } - - return out; -}; - -/** - * Normalize a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to normalize - * @returns {vec4} out - */ -vec4.normalize = function (out, a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - var len = x * x + y * y + z * z + w * w; - if (len > 0) { - len = 1 / Math.sqrt(len); - out.x = x * len; - out.y = y * len; - out.z = z * len; - out.w = w * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} dot product of a and b - */ -vec4.dot = function (a, b) { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -}; - -/** - * Performs a linear interpolation between two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec4} out - */ -vec4.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y, - az = a.z, - aw = a.w; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - out.z = az + t * (b.z - az); - out.w = aw + t * (b.w - aw); - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec4} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec4} out - */ -vec4.random = function (out, scale) { - scale = scale || 1.0; - - //TODO: This is a pretty awful way of doing this. Find something better. - out.x = random(); - out.y = random(); - out.z = random(); - out.w = random(); - vec4.normalize(out, out); - vec4.scale(out, out, scale); - return out; -}; - -/** - * Transforms the vec4 with a mat4. - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec4} out - */ -vec4.transformMat4 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z, w = a.w; - out.x = m.m00 * x + m.m04 * y + m.m08 * z + m.m12 * w; - out.y = m.m01 * x + m.m05 * y + m.m09 * z + m.m13 * w; - out.z = m.m02 * x + m.m06 * y + m.m10 * z + m.m14 * w; - out.w = m.m03 * x + m.m07 * y + m.m11 * z + m.m15 * w; - return out; -}; - -/** - * Transforms the vec4 with a quat - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec4} out - */ -vec4.transformQuat = function (out, a, q) { - var x = a.x, y = a.y, z = a.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vec - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - - // calculate result * inverse quat - out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - out.w = a.w; - return out; -}; - -/** - * Perform some operation over an array of vec4s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec4.forEach = (function () { - var vec = vec4.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 4; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; vec.z = a[i + 2]; vec.w = a[i + 3]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; a[i + 2] = vec.z; a[i + 3] = vec.w; - } - - return a; - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec4} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec4.str = function (a) { - return ("vec4(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ", " + (a.w) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec4} v - * @returns {array} - */ -vec4.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - out[2] = v.z; - out[3] = v.w; - - return out; -}; - -/** - * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) - * - * @param {vec4} a The first vector. - * @param {vec4} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec4.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y && a.z === b.z && a.w === b.w; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec4} a The first vector. - * @param {vec4} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec4.equals = function (a, b) { - var a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; - var b0 = b.x, b1 = b.y, b2 = b.z, b3 = b.w; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); -}; - -var _tmp$3 = new Array(9); - -var _mat3 = function _mat3(m00, m01, m02, m03, m04, m05, m06, m07, m08) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; - this.m06 = m06; - this.m07 = m07; - this.m08 = m08; -}; - -_mat3.prototype.toJSON = function toJSON () { - _tmp$3[0] = this.m00; - _tmp$3[1] = this.m01; - _tmp$3[2] = this.m02; - _tmp$3[3] = this.m03; - _tmp$3[4] = this.m04; - _tmp$3[5] = this.m05; - _tmp$3[6] = this.m06; - _tmp$3[7] = this.m07; - _tmp$3[8] = this.m08; - - return _tmp$3; -}; - -/** - * @class 3x3 Matrix - * @name mat3 - * - * NOTE: we use column-major matrix for all matrix calculation. - * - * This may lead to some confusion when referencing OpenGL documentation, - * however, which represents out all matricies in column-major format. - * This means that while in code a matrix may be typed out as: - * - * [1, 0, 0, 0, - * 0, 1, 0, 0, - * 0, 0, 1, 0, - * x, y, z, 0] - * - * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) - * is written as: - * - * 1 0 0 x - * 0 1 0 y - * 0 0 1 z - * 0 0 0 0 - * - * Please rest assured, however, that they are the same thing! - * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the - * apparent lack of consistency between the memory layout and the documentation. - */ -var mat3 = {}; - -/** - * Creates a new identity mat3 - * - * @returns {mat3} a new 3x3 matrix - */ -mat3.create = function () { - return new _mat3( - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - ); -}; - -/** - * Create a new mat3 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m10 Component in column 1, row 0 position (index 3) - * @param {Number} m11 Component in column 1, row 1 position (index 4) - * @param {Number} m12 Component in column 1, row 2 position (index 5) - * @param {Number} m20 Component in column 2, row 0 position (index 6) - * @param {Number} m21 Component in column 2, row 1 position (index 7) - * @param {Number} m22 Component in column 2, row 2 position (index 8) - * @returns {mat3} A new mat3 - */ -mat3.new = function (m00, m01, m02, m10, m11, m12, m20, m21, m22) { - return new _mat3( - m00, m01, m02, - m10, m11, m12, - m20, m21, m22 - ); -}; - -/** - * Creates a new mat3 initialized with values from an existing matrix - * - * @param {mat3} a matrix to clone - * @returns {mat3} a new 3x3 matrix - */ -mat3.clone = function (a) { - return new _mat3( - a.m00, a.m01, a.m02, - a.m03, a.m04, a.m05, - a.m06, a.m07, a.m08 - ); -}; - -/** - * Copy the values from one mat3 to another - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - return out; -}; - -/** - * Set the components of a mat3 to the given values - * - * @param {mat3} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m10 Component in column 1, row 0 position (index 3) - * @param {Number} m11 Component in column 1, row 1 position (index 4) - * @param {Number} m12 Component in column 1, row 2 position (index 5) - * @param {Number} m20 Component in column 2, row 0 position (index 6) - * @param {Number} m21 Component in column 2, row 1 position (index 7) - * @param {Number} m22 Component in column 2, row 2 position (index 8) - * @returns {mat3} out - */ -mat3.set = function (out, m00, m01, m02, m10, m11, m12, m20, m21, m22) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m02; - out.m03 = m10; - out.m04 = m11; - out.m05 = m12; - out.m06 = m20; - out.m07 = m21; - out.m08 = m22; - return out; -}; - -/** - * Set a mat3 to the identity matrix - * - * @param {mat3} out the receiving matrix - * @returns {mat3} out - */ -mat3.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 1; - out.m05 = 0; - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Transpose the values of a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a01 = a.m01, a02 = a.m02, a12 = a.m05; - out.m01 = a.m03; - out.m02 = a.m06; - out.m03 = a01; - out.m05 = a.m07; - out.m06 = a02; - out.m07 = a12; - } else { - out.m00 = a.m00; - out.m01 = a.m03; - out.m02 = a.m06; - out.m03 = a.m01; - out.m04 = a.m04; - out.m05 = a.m07; - out.m06 = a.m02; - out.m07 = a.m05; - out.m08 = a.m08; - } - - return out; -}; - -/** - * Inverts a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.invert = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var b01 = a22 * a11 - a12 * a21; - var b11 = -a22 * a10 + a12 * a20; - var b21 = a21 * a10 - a11 * a20; - - // Calculate the determinant - var det = a00 * b01 + a01 * b11 + a02 * b21; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = b01 * det; - out.m01 = (-a22 * a01 + a02 * a21) * det; - out.m02 = (a12 * a01 - a02 * a11) * det; - out.m03 = b11 * det; - out.m04 = (a22 * a00 - a02 * a20) * det; - out.m05 = (-a12 * a00 + a02 * a10) * det; - out.m06 = b21 * det; - out.m07 = (-a21 * a00 + a01 * a20) * det; - out.m08 = (a11 * a00 - a01 * a10) * det; - return out; -}; - -/** - * Calculates the adjugate of a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.adjoint = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - out.m00 = (a11 * a22 - a12 * a21); - out.m01 = (a02 * a21 - a01 * a22); - out.m02 = (a01 * a12 - a02 * a11); - out.m03 = (a12 * a20 - a10 * a22); - out.m04 = (a00 * a22 - a02 * a20); - out.m05 = (a02 * a10 - a00 * a12); - out.m06 = (a10 * a21 - a11 * a20); - out.m07 = (a01 * a20 - a00 * a21); - out.m08 = (a00 * a11 - a01 * a10); - return out; -}; - -/** - * Calculates the determinant of a mat3 - * - * @param {mat3} a the source matrix - * @returns {Number} determinant of a - */ -mat3.determinant = function (a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); -}; - -/** - * Multiplies two mat3's - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.multiply = function (out, a, b) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var b00 = b.m00, b01 = b.m01, b02 = b.m02; - var b10 = b.m03, b11 = b.m04, b12 = b.m05; - var b20 = b.m06, b21 = b.m07, b22 = b.m08; - - out.m00 = b00 * a00 + b01 * a10 + b02 * a20; - out.m01 = b00 * a01 + b01 * a11 + b02 * a21; - out.m02 = b00 * a02 + b01 * a12 + b02 * a22; - - out.m03 = b10 * a00 + b11 * a10 + b12 * a20; - out.m04 = b10 * a01 + b11 * a11 + b12 * a21; - out.m05 = b10 * a02 + b11 * a12 + b12 * a22; - - out.m06 = b20 * a00 + b21 * a10 + b22 * a20; - out.m07 = b20 * a01 + b21 * a11 + b22 * a21; - out.m08 = b20 * a02 + b21 * a12 + b22 * a22; - return out; -}; - -/** - * Alias for {@link mat3.multiply} - * @function - */ -mat3.mul = mat3.multiply; - -/** - * Translate a mat3 by the given vector - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to translate - * @param {vec2} v vector to translate by - * @returns {mat3} out - */ -mat3.translate = function (out, a, v) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - var x = v.x, y = v.y; - - out.m00 = a00; - out.m01 = a01; - out.m02 = a02; - - out.m03 = a10; - out.m04 = a11; - out.m05 = a12; - - out.m06 = x * a00 + y * a10 + a20; - out.m07 = x * a01 + y * a11 + a21; - out.m08 = x * a02 + y * a12 + a22; - return out; -}; - -/** - * Rotates a mat3 by the given angle - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat3} out - */ -mat3.rotate = function (out, a, rad) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var s = Math.sin(rad); - var c = Math.cos(rad); - - out.m00 = c * a00 + s * a10; - out.m01 = c * a01 + s * a11; - out.m02 = c * a02 + s * a12; - - out.m03 = c * a10 - s * a00; - out.m04 = c * a11 - s * a01; - out.m05 = c * a12 - s * a02; - - out.m06 = a20; - out.m07 = a21; - out.m08 = a22; - return out; -}; - -/** - * Scales the mat3 by the dimensions in the given vec2 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to rotate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat3} out - **/ -mat3.scale = function (out, a, v) { - var x = v.x, y = v.y; - - out.m00 = x * a.m00; - out.m01 = x * a.m01; - out.m02 = x * a.m02; - - out.m03 = y * a.m03; - out.m04 = y * a.m04; - out.m05 = y * a.m05; - - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - return out; -}; - -/** - * Copies the upper-left 3x3 values into the given mat3. - * - * @param {mat3} out the receiving 3x3 matrix - * @param {mat4} a the source 4x4 matrix - * @returns {mat3} out - */ -mat3.fromMat4 = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m04; - out.m04 = a.m05; - out.m05 = a.m06; - out.m06 = a.m08; - out.m07 = a.m09; - out.m08 = a.m10; - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.translate(dest, dest, vec); - * - * @param {mat3} out mat3 receiving operation result - * @param {vec2} v Translation vector - * @returns {mat3} out - */ -mat3.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 1; - out.m05 = 0; - out.m06 = v.x; - out.m07 = v.y; - out.m08 = 1; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.rotate(dest, dest, rad); - * - * @param {mat3} out mat3 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat3} out - */ -mat3.fromRotation = function (out, rad) { - var s = Math.sin(rad), c = Math.cos(rad); - - out.m00 = c; - out.m01 = s; - out.m02 = 0; - - out.m03 = -s; - out.m04 = c; - out.m05 = 0; - - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.scale(dest, dest, vec); - * - * @param {mat3} out mat3 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat3} out - */ -mat3.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - - out.m03 = 0; - out.m04 = v.y; - out.m05 = 0; - - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Copies the values from a mat2d into a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat2d} a the matrix to copy - * @returns {mat3} out - **/ -mat3.fromMat2d = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = 0; - - out.m03 = a.m02; - out.m04 = a.m03; - out.m05 = 0; - - out.m06 = a.m04; - out.m07 = a.m05; - out.m08 = 1; - return out; -}; - -/** -* Calculates a 3x3 matrix from the given quaternion -* -* @param {mat3} out mat3 receiving operation result -* @param {quat} q Quaternion to create matrix from -* -* @returns {mat3} out -*/ -mat3.fromQuat = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var yx = y * x2; - var yy = y * y2; - var zx = z * x2; - var zy = z * y2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - yy - zz; - out.m03 = yx - wz; - out.m06 = zx + wy; - - out.m01 = yx + wz; - out.m04 = 1 - xx - zz; - out.m07 = zy - wx; - - out.m02 = zx - wy; - out.m05 = zy + wx; - out.m08 = 1 - xx - yy; - - return out; -}; - -/** -* Calculates a 3x3 matrix from view direction and up direction -* -* @param {mat3} out mat3 receiving operation result -* @param {vec3} view view direction (must be normalized) -* @param {vec3} [up] up direction, default is (0,1,0) (must be normalized) -* -* @returns {mat3} out -*/ -mat3.fromViewUp = (function () { - var default_up = vec3.new(0, 1, 0); - var x = vec3.create(); - var y = vec3.create(); - - return function (out, view, up) { - if (vec3.sqrLen(view) < EPSILON * EPSILON) { - mat3.identity(out); - return out; - } - - up = up || default_up; - vec3.cross(x, up, view); - - if (vec3.sqrLen(x) < EPSILON * EPSILON) { - mat3.identity(out); - return out; - } - - vec3.cross(y, view, x); - mat3.set(out, - x.x, x.y, x.z, - y.x, y.y, y.z, - view.x, view.y, view.z - ); - - return out; - }; -})(); - -/** -* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix -* -* @param {mat3} out mat3 receiving operation result -* @param {mat4} a Mat4 to derive the normal matrix from -* -* @returns {mat3} out -*/ -mat3.normalFromMat4 = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out.m01 = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out.m02 = (a10 * b10 - a11 * b08 + a13 * b06) * det; - - out.m03 = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out.m04 = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out.m05 = (a01 * b08 - a00 * b10 - a03 * b06) * det; - - out.m06 = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out.m07 = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out.m08 = (a30 * b04 - a31 * b02 + a33 * b00) * det; - - return out; -}; - -/** - * Returns a string representation of a mat3 - * - * @param {mat3} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat3.str = function (a) { - return ("mat3(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ", " + (a.m06) + ", " + (a.m07) + ", " + (a.m08) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat3} m - * @returns {array} - */ -mat3.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - out[6] = m.m06; - out[7] = m.m07; - out[8] = m.m08; - - return out; -}; - -/** - * Returns Frobenius norm of a mat3 - * - * @param {mat3} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat3.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2))); -}; - -/** - * Adds two mat3's - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - out.m06 = a.m06 + b.m06; - out.m07 = a.m07 + b.m07; - out.m08 = a.m08 + b.m08; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - out.m06 = a.m06 - b.m06; - out.m07 = a.m07 - b.m07; - out.m08 = a.m08 - b.m08; - return out; -}; - -/** - * Alias for {@link mat3.subtract} - * @function - */ -mat3.sub = mat3.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat3} out - */ -mat3.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - out.m06 = a.m06 * b; - out.m07 = a.m07 * b; - out.m08 = a.m08 * b; - return out; -}; - -/** - * Adds two mat3's after multiplying each element of the second operand by a scalar value. - * - * @param {mat3} out the receiving vector - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat3} out - */ -mat3.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - out.m06 = a.m06 + (b.m06 * scale); - out.m07 = a.m07 + (b.m07 * scale); - out.m08 = a.m08 + (b.m08 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat3} a The first matrix. - * @param {mat3} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat3.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && - a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05 && - a.m06 === b.m06 && a.m07 === b.m07 && a.m08 === b.m08; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat3} a The first matrix. - * @param {mat3} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat3.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, a8 = a.m08; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, b8 = b.m08; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && - Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && - Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && - Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) - ); -}; - -var _tmp$4 = new Array(4); - -var _quat = function _quat(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; -}; - -_quat.prototype.toJSON = function toJSON () { - _tmp$4[0] = this.x; - _tmp$4[1] = this.y; - _tmp$4[2] = this.z; - _tmp$4[3] = this.w; - - return _tmp$4; -}; - -/** - * @class Quaternion - * @name quat - */ -var quat = {}; - -/** - * Creates a new identity quat - * - * @returns {quat} a new quaternion - */ -quat.create = function () { - return new _quat(0, 0, 0, 1); -}; - -/** - * Creates a new quat initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {quat} a new quaternion - * @function - */ -quat.new = function (x, y, z, w) { - return new _quat(x, y, z, w); -}; - -/** - * Creates a new quat initialized with values from an existing quaternion - * - * @param {quat} a quaternion to clone - * @returns {quat} a new quaternion - * @function - */ -quat.clone = function (a) { - return new _quat(a.x, a.y, a.z, a.w); -}; - -/** - * Copy the values from one quat to another - * - * @param {quat} out the receiving quaternion - * @param {quat} a the source quaternion - * @returns {quat} out - * @function - */ -quat.copy = vec4.copy; - -/** - * Set the components of a quat to the given values - * - * @param {quat} out the receiving quaternion - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {quat} out - * @function - */ -quat.set = vec4.set; - -/** - * Set a quat to the identity quaternion - * - * @param {quat} out the receiving quaternion - * @returns {quat} out - */ -quat.identity = function (out) { - out.x = 0; - out.y = 0; - out.z = 0; - out.w = 1; - return out; -}; - -/** - * Sets a quaternion to represent the shortest rotation from one - * vector to another. - * - * Both vectors are assumed to be unit length. - * - * @param {quat} out the receiving quaternion. - * @param {vec3} a the initial vector - * @param {vec3} b the destination vector - * @returns {quat} out - */ -quat.rotationTo = (function () { - var tmpvec3 = vec3.create(); - var xUnitVec3 = vec3.new(1, 0, 0); - var yUnitVec3 = vec3.new(0, 1, 0); - - return function (out, a, b) { - var dot = vec3.dot(a, b); - if (dot < -0.999999) { - vec3.cross(tmpvec3, xUnitVec3, a); - if (vec3.length(tmpvec3) < 0.000001) { - vec3.cross(tmpvec3, yUnitVec3, a); - } - vec3.normalize(tmpvec3, tmpvec3); - quat.fromAxisAngle(out, tmpvec3, Math.PI); - return out; - } else if (dot > 0.999999) { - out.x = 0; - out.y = 0; - out.z = 0; - out.w = 1; - return out; - } else { - vec3.cross(tmpvec3, a, b); - out.x = tmpvec3.x; - out.y = tmpvec3.y; - out.z = tmpvec3.z; - out.w = 1 + dot; - return quat.normalize(out, out); - } - }; -})(); - -/** - * Gets the rotation axis and angle for a given - * quaternion. If a quaternion is created with - * fromAxisAngle, this method will return the same - * values as providied in the original parameter list - * OR functionally equivalent values. - * Example: The quaternion formed by axis [0, 0, 1] and - * angle -90 is the same as the quaternion formed by - * [0, 0, 1] and 270. This method favors the latter. - * @param {vec3} out_axis Vector receiving the axis of rotation - * @param {quat} q Quaternion to be decomposed - * @return {Number} Angle, in radians, of the rotation - */ -quat.getAxisAngle = function (out_axis, q) { - var rad = Math.acos(q.w) * 2.0; - var s = Math.sin(rad / 2.0); - if (s != 0.0) { - out_axis.x = q.x / s; - out_axis.y = q.y / s; - out_axis.z = q.z / s; - } else { - // If s is zero, return any axis (no rotation - axis does not matter) - out_axis.x = 1; - out_axis.y = 0; - out_axis.z = 0; - } - return rad; -}; - -/** - * Multiplies two quat's - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @returns {quat} out - */ -quat.multiply = function (out, a, b) { - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = b.x, by = b.y, bz = b.z, bw = b.w; - - out.x = ax * bw + aw * bx + ay * bz - az * by; - out.y = ay * bw + aw * by + az * bx - ax * bz; - out.z = az * bw + aw * bz + ax * by - ay * bx; - out.w = aw * bw - ax * bx - ay * by - az * bz; - return out; -}; - -/** - * Alias for {@link quat.multiply} - * @function - */ -quat.mul = quat.multiply; - -/** - * Scales a quat by a scalar number - * - * @param {quat} out the receiving vector - * @param {quat} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {quat} out - * @function - */ -quat.scale = vec4.scale; - -/** - * Rotates a quaternion by the given angle about the X axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateX = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw + aw * bx; - out.y = ay * bw + az * bx; - out.z = az * bw - ay * bx; - out.w = aw * bw - ax * bx; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the Y axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateY = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - by = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw - az * by; - out.y = ay * bw + aw * by; - out.z = az * bw + ax * by; - out.w = aw * bw - ay * by; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the Z axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateZ = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bz = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw + ay * bz; - out.y = ay * bw - ax * bz; - out.z = az * bw + aw * bz; - out.w = aw * bw - az * bz; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the axis in world space - * - * @param {quat} out quat receiving operation result - * @param {quat} rot quat to rotate - * @param {vec3} axis the axis around which to rotate in world space - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateAround = (function () { - var v3_tmp = vec3.create(); - var q_tmp = quat.create(); - - return function (out, rot, axis, rad) { - // get inv-axis (local to rot) - quat.invert(q_tmp, rot); - vec3.transformQuat(v3_tmp, axis, q_tmp); - // rotate by inv-axis - quat.fromAxisAngle(q_tmp, v3_tmp, rad); - quat.mul(out, rot, q_tmp); - - return out; - }; -})(); - -/** - * Rotates a quaternion by the given angle about the axis in local space - * - * @param {quat} out quat receiving operation result - * @param {quat} rot quat to rotate - * @param {vec3} axis the axis around which to rotate in local space - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateAroundLocal = (function () { - var q_tmp = quat.create(); - - return function (out, rot, axis, rad) { - quat.fromAxisAngle(q_tmp, axis, rad); - quat.mul(out, rot, q_tmp); - - return out; - }; -})(); - -/** - * Calculates the W component of a quat from the X, Y, and Z components. - * Assumes that quaternion is 1 unit in length. - * Any existing W component will be ignored. - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate W component of - * @returns {quat} out - */ -quat.calculateW = function (out, a) { - var x = a.x, y = a.y, z = a.z; - - out.x = x; - out.y = y; - out.z = z; - out.w = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); - return out; -}; - -/** - * Calculates the dot product of two quat's - * - * @param {quat} a the first operand - * @param {quat} b the second operand - * @returns {Number} dot product of a and b - * @function - */ -quat.dot = vec4.dot; - -/** - * Performs a linear interpolation between two quat's - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {quat} out - * @function - */ -quat.lerp = vec4.lerp; - -/** - * Performs a spherical linear interpolation between two quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {quat} out - */ -quat.slerp = function (out, a, b, t) { - // benchmarks: - // http://jsperf.com/quaternion-slerp-implementations - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = b.x, by = b.y, bz = b.z, bw = b.w; - - var omega, cosom, sinom, scale0, scale1; - - // calc cosine - cosom = ax * bx + ay * by + az * bz + aw * bw; - // adjust signs (if necessary) - if (cosom < 0.0) { - cosom = -cosom; - bx = - bx; - by = - by; - bz = - bz; - bw = - bw; - } - // calculate coefficients - if ((1.0 - cosom) > 0.000001) { - // standard case (slerp) - omega = Math.acos(cosom); - sinom = Math.sin(omega); - scale0 = Math.sin((1.0 - t) * omega) / sinom; - scale1 = Math.sin(t * omega) / sinom; - } else { - // "from" and "to" quaternions are very close - // ... so we can do a linear interpolation - scale0 = 1.0 - t; - scale1 = t; - } - // calculate final values - out.x = scale0 * ax + scale1 * bx; - out.y = scale0 * ay + scale1 * by; - out.z = scale0 * az + scale1 * bz; - out.w = scale0 * aw + scale1 * bw; - - return out; -}; - -/** - * Performs a spherical linear interpolation with two control points - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {quat} c the third operand - * @param {quat} d the fourth operand - * @param {Number} t interpolation amount - * @returns {quat} out - */ -quat.sqlerp = (function () { - var temp1 = quat.create(); - var temp2 = quat.create(); - - return function (out, a, b, c, d, t) { - quat.slerp(temp1, a, d, t); - quat.slerp(temp2, b, c, t); - quat.slerp(out, temp1, temp2, 2 * t * (1 - t)); - - return out; - }; -}()); - -/** - * Calculates the inverse of a quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate inverse of - * @returns {quat} out - */ -quat.invert = function (out, a) { - var a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; - var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3; - var invDot = dot ? 1.0 / dot : 0; - - // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 - - out.x = -a0 * invDot; - out.y = -a1 * invDot; - out.z = -a2 * invDot; - out.w = a3 * invDot; - return out; -}; - -/** - * Calculates the conjugate of a quat - * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate conjugate of - * @returns {quat} out - */ -quat.conjugate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - out.w = a.w; - return out; -}; - -/** - * Calculates the length of a quat - * - * @param {quat} a vector to calculate length of - * @returns {Number} length of a - * @function - */ -quat.length = vec4.length; - -/** - * Alias for {@link quat.length} - * @function - */ -quat.len = quat.length; - -/** - * Calculates the squared length of a quat - * - * @param {quat} a vector to calculate squared length of - * @returns {Number} squared length of a - * @function - */ -quat.squaredLength = vec4.squaredLength; - -/** - * Alias for {@link quat.squaredLength} - * @function - */ -quat.sqrLen = quat.squaredLength; - -/** - * Normalize a quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a quaternion to normalize - * @returns {quat} out - * @function - */ -quat.normalize = vec4.normalize; - -/** - * Sets the specified quaternion with values corresponding to the given - * axes. Each axis is a vec3 and is expected to be unit length and - * perpendicular to all other specified axes. - * - * @param {vec3} xAxis the vector representing the local "right" direction - * @param {vec3} yAxis the vector representing the local "up" direction - * @param {vec3} zAxis the vector representing the viewing direction - * @returns {quat} out - */ -quat.fromAxes = (function () { - var matr = mat3.create(); - - return function (out, xAxis, yAxis, zAxis) { - mat3.set( - matr, - xAxis.x, xAxis.y, xAxis.z, - yAxis.x, yAxis.y, yAxis.z, - zAxis.x, zAxis.y, zAxis.z - ); - return quat.normalize(out, quat.fromMat3(out, matr)); - }; -})(); - -/** -* Calculates a quaternion from view direction and up direction -* -* @param {quat} out mat3 receiving operation result -* @param {vec3} view view direction (must be normalized) -* @param {vec3} [up] up direction, default is (0,1,0) (must be normalized) -* -* @returns {quat} out -*/ -quat.fromViewUp = (function () { - var matr = mat3.create(); - - return function (out, view, up) { - mat3.fromViewUp(matr, view, up); - if (!matr) { - return null; - } - - return quat.normalize(out, quat.fromMat3(out, matr)); - }; -})(); - -/** - * Sets a quat from the given angle and rotation axis, - * then returns it. - * - * @param {quat} out the receiving quaternion - * @param {vec3} axis the axis around which to rotate - * @param {Number} rad the angle in radians - * @returns {quat} out - **/ -quat.fromAxisAngle = function (out, axis, rad) { - rad = rad * 0.5; - var s = Math.sin(rad); - out.x = s * axis.x; - out.y = s * axis.y; - out.z = s * axis.z; - out.w = Math.cos(rad); - return out; -}; - -/** - * Creates a quaternion from the given 3x3 rotation matrix. - * - * NOTE: The resultant quaternion is not normalized, so you should be sure - * to renormalize the quaternion yourself where necessary. - * - * @param {quat} out the receiving quaternion - * @param {mat3} m rotation matrix - * @returns {quat} out - * @function - */ -quat.fromMat3 = function (out, m) { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - - var m00 = m.m00, m01 = m.m03, m02 = m.m06, - m10 = m.m01, m11 = m.m04, m12 = m.m07, - m20 = m.m02, m21 = m.m05, m22 = m.m08; - - var trace = m00 + m11 + m22; - - if (trace > 0) { - var s = 0.5 / Math.sqrt(trace + 1.0); - - out.w = 0.25 / s; - out.x = (m21 - m12) * s; - out.y = (m02 - m20) * s; - out.z = (m10 - m01) * s; - - } else if ((m00 > m11) && (m00 > m22)) { - var s$1 = 2.0 * Math.sqrt(1.0 + m00 - m11 - m22); - - out.w = (m21 - m12) / s$1; - out.x = 0.25 * s$1; - out.y = (m01 + m10) / s$1; - out.z = (m02 + m20) / s$1; - - } else if (m11 > m22) { - var s$2 = 2.0 * Math.sqrt(1.0 + m11 - m00 - m22); - - out.w = (m02 - m20) / s$2; - out.x = (m01 + m10) / s$2; - out.y = 0.25 * s$2; - out.z = (m12 + m21) / s$2; - - } else { - var s$3 = 2.0 * Math.sqrt(1.0 + m22 - m00 - m11); - - out.w = (m10 - m01) / s$3; - out.x = (m02 + m20) / s$3; - out.y = (m12 + m21) / s$3; - out.z = 0.25 * s$3; - } - - return out; -}; - -/** - * Creates a quaternion from the given euler angle x, y, z. - * - * @param {quat} out the receiving quaternion - * @param {x} Angle to rotate around X axis in degrees. - * @param {y} Angle to rotate around Y axis in degrees. - * @param {z} Angle to rotate around Z axis in degrees. - * @returns {quat} out - * @function - */ -quat.fromEuler = function (out, x, y, z) { - var halfToRad = 0.5 * Math.PI / 180.0; - x *= halfToRad; - y *= halfToRad; - z *= halfToRad; - - var sx = Math.sin(x); - var cx = Math.cos(x); - var sy = Math.sin(y); - var cy = Math.cos(y); - var sz = Math.sin(z); - var cz = Math.cos(z); - - out.x = sx * cy * cz + cx * sy * sz; - out.y = cx * sy * cz + sx * cy * sz; - out.z = cx * cy * sz - sx * sy * cz; - out.w = cx * cy * cz - sx * sy * sz; - - return out; -}; - -/** - * Convert a quaternion back to euler angle (in degrees). - * - * @param {vec3} out - Euler angle stored as a vec3 - * @param {number} q - the quaternion to be converted - * @returns {vec3} out. - */ -quat.toEuler = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var heading, attitude, bank; - var test = x * y + z * w; - if (test > 0.499) { // singularity at north pole - heading = 2 * Math.atan2(x,w); - attitude = Math.PI/2; - bank = 0; - } - if (test < -0.499) { // singularity at south pole - heading = -2 * Math.atan2(x,w); - attitude = - Math.PI/2; - bank = 0; - } - if(isNaN(heading)){ - var sqx = x*x; - var sqy = y*y; - var sqz = z*z; - heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // heading - attitude = Math.asin(2*test); // attitude - bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank - } - - out.y = toDegree(heading); - out.z = toDegree(attitude); - out.x = toDegree(bank); - - return out; -} - - -/** - * Returns a string representation of a quatenion - * - * @param {quat} a vector to represent as a string - * @returns {String} string representation of the vector - */ -quat.str = function (a) { - return ("quat(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ", " + (a.w) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {quat} q - * @returns {array} - */ -quat.array = function (out, q) { - out[0] = q.x; - out[1] = q.y; - out[2] = q.z; - out[3] = q.w; - - return out; -}; - -/** - * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===) - * - * @param {quat} a The first quaternion. - * @param {quat} b The second quaternion. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -quat.exactEquals = vec4.exactEquals; - -/** - * Returns whether or not the quaternions have approximately the same elements in the same position. - * - * @param {quat} a The first vector. - * @param {quat} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -quat.equals = vec4.equals; - -var _tmp$5 = new Array(4); - -var _mat2 = function _mat2(m00, m01, m02, m03) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; -}; - -_mat2.prototype.toJSON = function toJSON () { - _tmp$5[0] = this.m00; - _tmp$5[1] = this.m01; - _tmp$5[2] = this.m02; - _tmp$5[3] = this.m03; - - return _tmp$5; -}; - -/** - * @class 2x2 Matrix - * @name mat2 - */ -var mat2 = {}; - -/** - * Creates a new identity mat2 - * - * @returns {mat2} a new 2x2 matrix - */ -mat2.create = function() { - return new _mat2(1, 0, 0, 1); -}; - -/** - * Create a new mat2 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m10 Component in column 1, row 0 position (index 2) - * @param {Number} m11 Component in column 1, row 1 position (index 3) - * @returns {mat2} out A new 2x2 matrix - */ -mat2.new = function (m00, m01, m10, m11) { - return new _mat2(m00, m01, m10, m11); -}; - -/** - * Creates a new mat2 initialized with values from an existing matrix - * - * @param {mat2} a matrix to clone - * @returns {mat2} a new 2x2 matrix - */ -mat2.clone = function (a) { - return new _mat2(a.m00, a.m01, a.m02, a.m03); -}; - -/** - * Copy the values from one mat2 to another - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - return out; -}; - -/** - * Set a mat2 to the identity matrix - * - * @param {mat2} out the receiving matrix - * @returns {mat2} out - */ -mat2.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - return out; -}; - -/** - * Set the components of a mat2 to the given values - * - * @param {mat2} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m10 Component in column 1, row 0 position (index 2) - * @param {Number} m11 Component in column 1, row 1 position (index 3) - * @returns {mat2} out - */ -mat2.set = function (out, m00, m01, m10, m11) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m10; - out.m03 = m11; - return out; -}; - - -/** - * Transpose the values of a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a1 = a.m01; - out.m01 = a.m02; - out.m02 = a1; - } else { - out.m00 = a.m00; - out.m01 = a.m02; - out.m02 = a.m01; - out.m03 = a.m03; - } - - return out; -}; - -/** - * Inverts a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.invert = function (out, a) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - - // Calculate the determinant - var det = a0 * a3 - a2 * a1; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = a3 * det; - out.m01 = -a1 * det; - out.m02 = -a2 * det; - out.m03 = a0 * det; - - return out; -}; - -/** - * Calculates the adjugate of a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.adjoint = function (out, a) { - // Caching this value is nessecary if out == a - var a0 = a.m00; - out.m00 = a.m03; - out.m01 = -a.m01; - out.m02 = -a.m02; - out.m03 = a0; - - return out; -}; - -/** - * Calculates the determinant of a mat2 - * - * @param {mat2} a the source matrix - * @returns {Number} determinant of a - */ -mat2.determinant = function (a) { - return a.m00 * a.m03 - a.m02 * a.m01; -}; - -/** - * Multiplies two mat2's - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.multiply = function (out, a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - out.m00 = a0 * b0 + a2 * b1; - out.m01 = a1 * b0 + a3 * b1; - out.m02 = a0 * b2 + a2 * b3; - out.m03 = a1 * b2 + a3 * b3; - return out; -}; - -/** - * Alias for {@link mat2.multiply} - * @function - */ -mat2.mul = mat2.multiply; - -/** - * Rotates a mat2 by the given angle - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat2} out - */ -mat2.rotate = function (out, a, rad) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = a0 * c + a2 * s; - out.m01 = a1 * c + a3 * s; - out.m02 = a0 * -s + a2 * c; - out.m03 = a1 * -s + a3 * c; - return out; -}; - -/** - * Scales the mat2 by the dimensions in the given vec2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to rotate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat2} out - **/ -mat2.scale = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - v0 = v.x, v1 = v.y; - out.m00 = a0 * v0; - out.m01 = a1 * v0; - out.m02 = a2 * v1; - out.m03 = a3 * v1; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat2.identity(dest); - * mat2.rotate(dest, dest, rad); - * - * @param {mat2} out mat2 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat2} out - */ -mat2.fromRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = c; - out.m01 = s; - out.m02 = -s; - out.m03 = c; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat2.identity(dest); - * mat2.scale(dest, dest, vec); - * - * @param {mat2} out mat2 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat2} out - */ -mat2.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - out.m03 = v.y; - return out; -}; - -/** - * Returns a string representation of a mat2 - * - * @param {mat2} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat2.str = function (a) { - return ("mat2(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat2} m - * @returns {array} - */ -mat2.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - - return out; -}; - -/** - * Returns Frobenius norm of a mat2 - * - * @param {mat2} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat2.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2))); -}; - -/** - * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix - * @param {mat2} L the lower triangular matrix - * @param {mat2} D the diagonal matrix - * @param {mat2} U the upper triangular matrix - * @param {mat2} a the input matrix to factorize - */ - -mat2.LDU = function (L, D, U, a) { - L.m02 = a.m02 / a.m00; - U.m00 = a.m00; - U.m01 = a.m01; - U.m03 = a.m03 - L.m02 * U.m01; -}; - -/** - * Adds two mat2's - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - return out; -}; - -/** - * Alias for {@link mat2.subtract} - * @function - */ -mat2.sub = mat2.subtract; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat2} a The first matrix. - * @param {mat2} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat2.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat2} a The first matrix. - * @param {mat2} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat2.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) - ); -}; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat2} out - */ -mat2.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - return out; -}; - -/** - * Adds two mat2's after multiplying each element of the second operand by a scalar value. - * - * @param {mat2} out the receiving vector - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat2} out - */ -mat2.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - return out; -}; - -var _tmp$6 = new Array(6); - -var _mat23 = function _mat23(m00, m01, m02, m03, m04, m05) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; -}; - -_mat23.prototype.toJSON = function toJSON () { - _tmp$6[0] = this.m00; - _tmp$6[1] = this.m01; - _tmp$6[2] = this.m02; - _tmp$6[3] = this.m03; - _tmp$6[4] = this.m04; - _tmp$6[5] = this.m05; - - return _tmp$6; -}; - -/** - * @class 2x3 Matrix - * @name mat23 - * - * @description - * A mat23 contains six elements defined as: - *
- * [a, c, tx,
- *  b, d, ty]
- * 
- * This is a short form for the 3x3 matrix: - *
- * [a, c, tx,
- *  b, d, ty,
- *  0, 0, 1]
- * 
- * The last row is ignored so the array is shorter and operations are faster. - */ -var mat23 = {}; - -/** - * Creates a new identity mat23 - * - * @returns {mat23} a new 2x3 matrix - */ -mat23.create = function () { - return new _mat23( - 1, 0, - 0, 1, - 0, 0 - ); -}; - -/** - * Create a new mat23 with the given values - * - * @param {Number} a Component A (index 0) - * @param {Number} b Component B (index 1) - * @param {Number} c Component C (index 2) - * @param {Number} d Component D (index 3) - * @param {Number} tx Component TX (index 4) - * @param {Number} ty Component TY (index 5) - * @returns {mat23} A new mat23 - */ -mat23.new = function (a, b, c, d, tx, ty) { - return new _mat23( - a, b, - c, d, - tx, ty - ); -}; - -/** - * Creates a new mat23 initialized with values from an existing matrix - * - * @param {mat23} a matrix to clone - * @returns {mat23} a new 2x3 matrix - */ -mat23.clone = function (a) { - return new _mat23( - a.m00, a.m01, - a.m02, a.m03, - a.m04, a.m05 - ); -}; - -/** - * Copy the values from one mat23 to another - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the source matrix - * @returns {mat23} out - */ -mat23.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - return out; -}; - -/** - * Set a mat23 to the identity matrix - * - * @param {mat23} out the receiving matrix - * @returns {mat23} out - */ -mat23.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Set the components of a mat23 to the given values - * - * @param {mat23} out the receiving matrix - * @param {Number} a Component A (index 0) - * @param {Number} b Component B (index 1) - * @param {Number} c Component C (index 2) - * @param {Number} d Component D (index 3) - * @param {Number} tx Component TX (index 4) - * @param {Number} ty Component TY (index 5) - * @returns {mat23} out - */ -mat23.set = function (out, a, b, c, d, tx, ty) { - out.m00 = a; - out.m01 = b; - out.m02 = c; - out.m03 = d; - out.m04 = tx; - out.m05 = ty; - return out; -}; - -/** - * Inverts a mat23 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the source matrix - * @returns {mat23} out - */ -mat23.invert = function (out, a) { - var aa = a.m00, ab = a.m01, ac = a.m02, ad = a.m03, - atx = a.m04, aty = a.m05; - - var det = aa * ad - ab * ac; - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = ad * det; - out.m01 = -ab * det; - out.m02 = -ac * det; - out.m03 = aa * det; - out.m04 = (ac * aty - ad * atx) * det; - out.m05 = (ab * atx - aa * aty) * det; - return out; -}; - -/** - * Calculates the determinant of a mat23 - * - * @param {mat23} a the source matrix - * @returns {Number} determinant of a - */ -mat23.determinant = function (a) { - return a.m00 * a.m03 - a.m01 * a.m02; -}; - -/** - * Multiplies two mat23's - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.multiply = function (out, a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; - out.m00 = a0 * b0 + a2 * b1; - out.m01 = a1 * b0 + a3 * b1; - out.m02 = a0 * b2 + a2 * b3; - out.m03 = a1 * b2 + a3 * b3; - out.m04 = a0 * b4 + a2 * b5 + a4; - out.m05 = a1 * b4 + a3 * b5 + a5; - return out; -}; - -/** - * Alias for {@link mat23.multiply} - * @function - */ -mat23.mul = mat23.multiply; - -/** - * Rotates a mat23 by the given angle - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat23} out - */ -mat23.rotate = function (out, a, rad) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = a0 * c + a2 * s; - out.m01 = a1 * c + a3 * s; - out.m02 = a0 * -s + a2 * c; - out.m03 = a1 * -s + a3 * c; - out.m04 = a4; - out.m05 = a5; - return out; -}; - -/** - * Scales the mat23 by the dimensions in the given vec2 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to translate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat23} out - **/ -mat23.scale = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - v0 = v.x, v1 = v.y; - out.m00 = a0 * v0; - out.m01 = a1 * v0; - out.m02 = a2 * v1; - out.m03 = a3 * v1; - out.m04 = a4; - out.m05 = a5; - return out; -}; - -/** - * Translates the mat23 by the dimensions in the given vec2 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to translate - * @param {vec2} v the vec2 to translate the matrix by - * @returns {mat23} out - **/ -mat23.translate = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - v0 = v.x, v1 = v.y; - out.m00 = a0; - out.m01 = a1; - out.m02 = a2; - out.m03 = a3; - out.m04 = a0 * v0 + a2 * v1 + a4; - out.m05 = a1 * v0 + a3 * v1 + a5; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.rotate(dest, dest, rad); - * - * @param {mat23} out mat23 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat23} out - */ -mat23.fromRotation = function (out, rad) { - var s = Math.sin(rad), c = Math.cos(rad); - out.m00 = c; - out.m01 = s; - out.m02 = -s; - out.m03 = c; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.scale(dest, dest, vec); - * - * @param {mat23} out mat23 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat23} out - */ -mat23.fromScaling = function (out, v) { - out.m00 = v.m00; - out.m01 = 0; - out.m02 = 0; - out.m03 = v.m01; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.translate(dest, dest, vec); - * - * @param {mat23} out mat23 receiving operation result - * @param {vec2} v Translation vector - * @returns {mat23} out - */ -mat23.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - out.m04 = v.x; - out.m05 = v.y; - return out; -}; - -/** - * Returns a string representation of a mat23 - * - * @param {mat23} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat23.str = function (a) { - return ("mat23(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat23} m - * @returns {array} - */ -mat23.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - - return out; -}; - -/** - * Returns typed array to 16 float array - * - * @param {array} out - * @param {mat23} m - * @returns {array} - */ -mat23.array4x4 = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = 0; - out[3] = 0; - out[4] = m.m02; - out[5] = m.m03; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 1; - out[11] = 0; - out[12] = m.m04; - out[13] = m.m05; - out[14] = 0; - out[15] = 1; - - return out; -}; - -/** - * Returns Frobenius norm of a mat23 - * - * @param {mat23} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat23.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + 1)); -}; - -/** - * Adds two mat23's - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - return out; -}; - -/** - * Alias for {@link mat23.subtract} - * @function - */ -mat23.sub = mat23.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat23} out - */ -mat23.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - return out; -}; - -/** - * Adds two mat23's after multiplying each element of the second operand by a scalar value. - * - * @param {mat23} out the receiving vector - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat23} out - */ -mat23.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat23} a The first matrix. - * @param {mat23} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat23.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat23} a The first matrix. - * @param {mat23} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat23.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) - ); -}; - -var _tmp$7 = new Array(16); - -var _mat4 = function _mat4( - m00, m01, m02, m03, - m04, m05, m06, m07, - m08, m09, m10, m11, - m12, m13, m14, m15 -) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; - this.m06 = m06; - this.m07 = m07; - this.m08 = m08; - this.m09 = m09; - this.m10 = m10; - this.m11 = m11; - this.m12 = m12; - this.m13 = m13; - this.m14 = m14; - this.m15 = m15; -}; - -_mat4.prototype.toJSON = function toJSON () { - _tmp$7[0] = this.m00; - _tmp$7[1] = this.m01; - _tmp$7[2] = this.m02; - _tmp$7[3] = this.m03; - _tmp$7[4] = this.m04; - _tmp$7[5] = this.m05; - _tmp$7[6] = this.m06; - _tmp$7[7] = this.m07; - _tmp$7[8] = this.m08; - _tmp$7[9] = this.m09; - _tmp$7[10] = this.m10; - _tmp$7[11] = this.m11; - _tmp$7[12] = this.m12; - _tmp$7[13] = this.m13; - _tmp$7[14] = this.m14; - _tmp$7[15] = this.m15; - - return _tmp$7; -}; - -/** - * @class 4x4 Matrix - * @name mat4 - * - * NOTE: we use column-major matrix for all matrix calculation. - * - * This may lead to some confusion when referencing OpenGL documentation, - * however, which represents out all matricies in column-major format. - * This means that while in code a matrix may be typed out as: - * - * [1, 0, 0, 0, - * 0, 1, 0, 0, - * 0, 0, 1, 0, - * x, y, z, 0] - * - * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) - * is written as: - * - * 1 0 0 x - * 0 1 0 y - * 0 0 1 z - * 0 0 0 0 - * - * Please rest assured, however, that they are the same thing! - * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the - * apparent lack of consistency between the memory layout and the documentation. - */ -var mat4 = {}; - -/** - * Creates a new identity mat4 - * - * @returns {mat4} a new 4x4 matrix - */ -mat4.create = function () { - return new _mat4( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ); -}; - -/** - * Create a new mat4 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m03 Component in column 0, row 3 position (index 3) - * @param {Number} m10 Component in column 1, row 0 position (index 4) - * @param {Number} m11 Component in column 1, row 1 position (index 5) - * @param {Number} m12 Component in column 1, row 2 position (index 6) - * @param {Number} m13 Component in column 1, row 3 position (index 7) - * @param {Number} m20 Component in column 2, row 0 position (index 8) - * @param {Number} m21 Component in column 2, row 1 position (index 9) - * @param {Number} m22 Component in column 2, row 2 position (index 10) - * @param {Number} m23 Component in column 2, row 3 position (index 11) - * @param {Number} m30 Component in column 3, row 0 position (index 12) - * @param {Number} m31 Component in column 3, row 1 position (index 13) - * @param {Number} m32 Component in column 3, row 2 position (index 14) - * @param {Number} m33 Component in column 3, row 3 position (index 15) - * @returns {mat4} A new mat4 - */ -mat4.new = function (m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { - return new _mat4( - m00, m01, m02, m03, - m10, m11, m12, m13, - m20, m21, m22, m23, - m30, m31, m32, m33 - ); -}; - -/** - * Creates a new mat4 initialized with values from an existing matrix - * - * @param {mat4} a matrix to clone - * @returns {mat4} a new 4x4 matrix - */ -mat4.clone = function (a) { - return new _mat4( - a.m00, a.m01, a.m02, a.m03, - a.m04, a.m05, a.m06, a.m07, - a.m08, a.m09, a.m10, a.m11, - a.m12, a.m13, a.m14, a.m15 - ); -}; - -/** - * Copy the values from one mat4 to another - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - out.m09 = a.m09; - out.m10 = a.m10; - out.m11 = a.m11; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - return out; -}; - -/** - * Set the components of a mat4 to the given values - * - * @param {mat4} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m03 Component in column 0, row 3 position (index 3) - * @param {Number} m10 Component in column 1, row 0 position (index 4) - * @param {Number} m11 Component in column 1, row 1 position (index 5) - * @param {Number} m12 Component in column 1, row 2 position (index 6) - * @param {Number} m13 Component in column 1, row 3 position (index 7) - * @param {Number} m20 Component in column 2, row 0 position (index 8) - * @param {Number} m21 Component in column 2, row 1 position (index 9) - * @param {Number} m22 Component in column 2, row 2 position (index 10) - * @param {Number} m23 Component in column 2, row 3 position (index 11) - * @param {Number} m30 Component in column 3, row 0 position (index 12) - * @param {Number} m31 Component in column 3, row 1 position (index 13) - * @param {Number} m32 Component in column 3, row 2 position (index 14) - * @param {Number} m33 Component in column 3, row 3 position (index 15) - * @returns {mat4} out - */ -mat4.set = function (out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m02; - out.m03 = m03; - out.m04 = m10; - out.m05 = m11; - out.m06 = m12; - out.m07 = m13; - out.m08 = m20; - out.m09 = m21; - out.m10 = m22; - out.m11 = m23; - out.m12 = m30; - out.m13 = m31; - out.m14 = m32; - out.m15 = m33; - return out; -}; - - -/** - * Set a mat4 to the identity matrix - * - * @param {mat4} out the receiving matrix - * @returns {mat4} out - */ -mat4.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Transpose the values of a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a01 = a.m01, a02 = a.m02, a03 = a.m03, - a12 = a.m06, a13 = a.m07, - a23 = a.m11; - - out.m01 = a.m04; - out.m02 = a.m08; - out.m03 = a.m12; - out.m04 = a01; - out.m06 = a.m09; - out.m07 = a.m13; - out.m08 = a02; - out.m09 = a12; - out.m11 = a.m14; - out.m12 = a03; - out.m13 = a13; - out.m14 = a23; - } else { - out.m00 = a.m00; - out.m01 = a.m04; - out.m02 = a.m08; - out.m03 = a.m12; - out.m04 = a.m01; - out.m05 = a.m05; - out.m06 = a.m09; - out.m07 = a.m13; - out.m08 = a.m02; - out.m09 = a.m06; - out.m10 = a.m10; - out.m11 = a.m14; - out.m12 = a.m03; - out.m13 = a.m07; - out.m14 = a.m11; - out.m15 = a.m15; - } - - return out; -}; - -/** - * Inverts a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.invert = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out.m01 = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out.m02 = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out.m03 = (a22 * b04 - a21 * b05 - a23 * b03) * det; - out.m04 = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out.m05 = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out.m06 = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out.m07 = (a20 * b05 - a22 * b02 + a23 * b01) * det; - out.m08 = (a10 * b10 - a11 * b08 + a13 * b06) * det; - out.m09 = (a01 * b08 - a00 * b10 - a03 * b06) * det; - out.m10 = (a30 * b04 - a31 * b02 + a33 * b00) * det; - out.m11 = (a21 * b02 - a20 * b04 - a23 * b00) * det; - out.m12 = (a11 * b07 - a10 * b09 - a12 * b06) * det; - out.m13 = (a00 * b09 - a01 * b07 + a02 * b06) * det; - out.m14 = (a31 * b01 - a30 * b03 - a32 * b00) * det; - out.m15 = (a20 * b03 - a21 * b01 + a22 * b00) * det; - - return out; -}; - -/** - * Calculates the adjugate of a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.adjoint = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - out.m00 = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); - out.m01 = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); - out.m02 = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); - out.m03 = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); - out.m04 = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); - out.m05 = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); - out.m06 = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); - out.m07 = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); - out.m08 = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); - out.m09 = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); - out.m10 = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); - out.m11 = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); - out.m12 = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); - out.m13 = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); - out.m14 = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); - out.m15 = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); - return out; -}; - -/** - * Calculates the determinant of a mat4 - * - * @param {mat4} a the source matrix - * @returns {Number} determinant of a - */ -mat4.determinant = function (a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; -}; - -/** - * Multiplies two mat4's explicitly - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.multiply = function (out, a, b) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - // Cache only the current line of the second matrix - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - out.m00 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m01 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m02 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m03 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m04; b1 = b.m05; b2 = b.m06; b3 = b.m07; - out.m04 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m05 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m06 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m07 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m08; b1 = b.m09; b2 = b.m10; b3 = b.m11; - out.m08 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m09 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m10 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m11 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m12; b1 = b.m13; b2 = b.m14; b3 = b.m15; - out.m12 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m13 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m14 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m15 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - return out; -}; - -/** - * Alias for {@link mat4.multiply} - * @function - */ -mat4.mul = mat4.multiply; - -/** - * Translate a mat4 by the given vector - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to translate - * @param {vec3} v vector to translate by - * @returns {mat4} out - */ -mat4.translate = function (out, a, v) { - var x = v.x, y = v.y, z = v.z, - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23; - - if (a === out) { - out.m12 = a.m00 * x + a.m04 * y + a.m08 * z + a.m12; - out.m13 = a.m01 * x + a.m05 * y + a.m09 * z + a.m13; - out.m14 = a.m02 * x + a.m06 * y + a.m10 * z + a.m14; - out.m15 = a.m03 * x + a.m07 * y + a.m11 * z + a.m15; - } else { - a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; - a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; - a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; - - out.m00 = a00; out.m01 = a01; out.m02 = a02; out.m03 = a03; - out.m04 = a10; out.m05 = a11; out.m06 = a12; out.m07 = a13; - out.m08 = a20; out.m09 = a21; out.m10 = a22; out.m11 = a23; - - out.m12 = a00 * x + a10 * y + a20 * z + a.m12; - out.m13 = a01 * x + a11 * y + a21 * z + a.m13; - out.m14 = a02 * x + a12 * y + a22 * z + a.m14; - out.m15 = a03 * x + a13 * y + a23 * z + a.m15; - } - - return out; -}; - -/** - * Scales the mat4 by the dimensions in the given vec3 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to scale - * @param {vec3} v the vec3 to scale the matrix by - * @returns {mat4} out - **/ -mat4.scale = function (out, a, v) { - var x = v.x, y = v.y, z = v.z; - - out.m00 = a.m00 * x; - out.m01 = a.m01 * x; - out.m02 = a.m02 * x; - out.m03 = a.m03 * x; - out.m04 = a.m04 * y; - out.m05 = a.m05 * y; - out.m06 = a.m06 * y; - out.m07 = a.m07 * y; - out.m08 = a.m08 * z; - out.m09 = a.m09 * z; - out.m10 = a.m10 * z; - out.m11 = a.m11 * z; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - return out; -}; - -/** - * Rotates a mat4 by the given angle around the given axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @param {vec3} axis the axis to rotate around - * @returns {mat4} out - */ -mat4.rotate = function (out, a, rad, axis) { - var x = axis.x, y = axis.y, z = axis.z; - var s, c, t, - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23, - b00, b01, b02, - b10, b11, b12, - b20, b21, b22; - - var len = Math.sqrt(x * x + y * y + z * z); - - if (Math.abs(len) < EPSILON) { - return null; - } - - len = 1 / len; - x *= len; - y *= len; - z *= len; - - s = Math.sin(rad); - c = Math.cos(rad); - t = 1 - c; - - a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; - a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; - a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; - - // Construct the elements of the rotation matrix - b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; - b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; - b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; - - // Perform rotation-specific matrix multiplication - out.m00 = a00 * b00 + a10 * b01 + a20 * b02; - out.m01 = a01 * b00 + a11 * b01 + a21 * b02; - out.m02 = a02 * b00 + a12 * b01 + a22 * b02; - out.m03 = a03 * b00 + a13 * b01 + a23 * b02; - out.m04 = a00 * b10 + a10 * b11 + a20 * b12; - out.m05 = a01 * b10 + a11 * b11 + a21 * b12; - out.m06 = a02 * b10 + a12 * b11 + a22 * b12; - out.m07 = a03 * b10 + a13 * b11 + a23 * b12; - out.m08 = a00 * b20 + a10 * b21 + a20 * b22; - out.m09 = a01 * b20 + a11 * b21 + a21 * b22; - out.m10 = a02 * b20 + a12 * b21 + a22 * b22; - out.m11 = a03 * b20 + a13 * b21 + a23 * b22; - - // If the source and destination differ, copy the unchanged last row - if (a !== out) { - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - return out; -}; - -/** - * Rotates a matrix by the given angle around the X axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateX = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a10 = a.m04, - a11 = a.m05, - a12 = a.m06, - a13 = a.m07, - a20 = a.m08, - a21 = a.m09, - a22 = a.m10, - a23 = a.m11; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m04 = a10 * c + a20 * s; - out.m05 = a11 * c + a21 * s; - out.m06 = a12 * c + a22 * s; - out.m07 = a13 * c + a23 * s; - out.m08 = a20 * c - a10 * s; - out.m09 = a21 * c - a11 * s; - out.m10 = a22 * c - a12 * s; - out.m11 = a23 * c - a13 * s; - - return out; -}; - -/** - * Rotates a matrix by the given angle around the Y axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateY = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a.m00, - a01 = a.m01, - a02 = a.m02, - a03 = a.m03, - a20 = a.m08, - a21 = a.m09, - a22 = a.m10, - a23 = a.m11; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m00 = a00 * c - a20 * s; - out.m01 = a01 * c - a21 * s; - out.m02 = a02 * c - a22 * s; - out.m03 = a03 * c - a23 * s; - out.m08 = a00 * s + a20 * c; - out.m09 = a01 * s + a21 * c; - out.m10 = a02 * s + a22 * c; - out.m11 = a03 * s + a23 * c; - - return out; -}; - -/** - * Rotates a matrix by the given angle around the Z axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateZ = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a.m00, - a01 = a.m01, - a02 = a.m02, - a03 = a.m03, - a10 = a.m04, - a11 = a.m05, - a12 = a.m06, - a13 = a.m07; - - // If the source and destination differ, copy the unchanged last row - if (a !== out) { - out.m08 = a.m08; - out.m09 = a.m09; - out.m10 = a.m10; - out.m11 = a.m11; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m00 = a00 * c + a10 * s; - out.m01 = a01 * c + a11 * s; - out.m02 = a02 * c + a12 * s; - out.m03 = a03 * c + a13 * s; - out.m04 = a10 * c - a00 * s; - out.m05 = a11 * c - a01 * s; - out.m06 = a12 * c - a02 * s; - out.m07 = a13 * c - a03 * s; - - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, dest, vec); - * - * @param {mat4} out mat4 receiving operation result - * @param {vec3} v Translation vector - * @returns {mat4} out - */ -mat4.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.scale(dest, dest, vec); - * - * @param {mat4} out mat4 receiving operation result - * @param {vec3} v Scaling vector - * @returns {mat4} out - */ -mat4.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = v.y; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = v.z; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a given angle around a given axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotate(dest, dest, rad, axis); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @param {vec3} axis the axis to rotate around - * @returns {mat4} out - */ -mat4.fromRotation = function (out, rad, axis) { - var x = axis.x, y = axis.y, z = axis.z; - var len = Math.sqrt(x * x + y * y + z * z); - var s, c, t; - - if (Math.abs(len) < EPSILON) { - return null; - } - - len = 1 / len; - x *= len; - y *= len; - z *= len; - - s = Math.sin(rad); - c = Math.cos(rad); - t = 1 - c; - - // Perform rotation-specific matrix multiplication - out.m00 = x * x * t + c; - out.m01 = y * x * t + z * s; - out.m02 = z * x * t - y * s; - out.m03 = 0; - out.m04 = x * y * t - z * s; - out.m05 = y * y * t + c; - out.m06 = z * y * t + x * s; - out.m07 = 0; - out.m08 = x * z * t + y * s; - out.m09 = y * z * t - x * s; - out.m10 = z * z * t + c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the X axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateX(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromXRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = c; - out.m06 = s; - out.m07 = 0; - out.m08 = 0; - out.m09 = -s; - out.m10 = c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the Y axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateY(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromYRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = c; - out.m01 = 0; - out.m02 = -s; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = s; - out.m09 = 0; - out.m10 = c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the Z axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateZ(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromZRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = c; - out.m01 = s; - out.m02 = 0; - out.m03 = 0; - out.m04 = -s; - out.m05 = c; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a quaternion rotation and vector translation - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @returns {mat4} out - */ -mat4.fromRT = function (out, q, v) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - (yy + zz); - out.m01 = xy + wz; - out.m02 = xz - wy; - out.m03 = 0; - out.m04 = xy - wz; - out.m05 = 1 - (xx + zz); - out.m06 = yz + wx; - out.m07 = 0; - out.m08 = xz + wy; - out.m09 = yz - wx; - out.m10 = 1 - (xx + yy); - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - - return out; -}; - -/** - * Returns the translation vector component of a transformation - * matrix. If a matrix is built with fromRT, - * the returned vector will be the same as the translation vector - * originally supplied. - * @param {vec3} out Vector to receive translation component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {vec3} out - */ -mat4.getTranslation = function (out, mat) { - out.x = mat.m12; - out.y = mat.m13; - out.z = mat.m14; - - return out; -}; - -/** - * Returns the scaling factor component of a transformation - * matrix. If a matrix is built with fromRTS - * with a normalized Quaternion paramter, the returned vector will be - * the same as the scaling vector - * originally supplied. - * @param {vec3} out Vector to receive scaling factor component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {vec3} out - */ -mat4.getScaling = function (out, mat) { - var m11 = mat.m00, - m12 = mat.m01, - m13 = mat.m02, - m21 = mat.m04, - m22 = mat.m05, - m23 = mat.m06, - m31 = mat.m08, - m32 = mat.m09, - m33 = mat.m10; - - out.x = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13); - out.y = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23); - out.z = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33); - - return out; -}; - -/** - * Returns a quaternion representing the rotational component - * of a transformation matrix. If a matrix is built with - * fromRT, the returned quaternion will be the - * same as the quaternion originally supplied. - * @param {quat} out Quaternion to receive the rotation component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {quat} out - */ -mat4.getRotation = function (out, mat) { - // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - var trace = mat.m00 + mat.m05 + mat.m10; - var S = 0; - - if (trace > 0) { - S = Math.sqrt(trace + 1.0) * 2; - out.w = 0.25 * S; - out.x = (mat.m06 - mat.m09) / S; - out.y = (mat.m08 - mat.m02) / S; - out.z = (mat.m01 - mat.m04) / S; - } else if ((mat.m00 > mat.m05) & (mat.m00 > mat.m10)) { - S = Math.sqrt(1.0 + mat.m00 - mat.m05 - mat.m10) * 2; - out.w = (mat.m06 - mat.m09) / S; - out.x = 0.25 * S; - out.y = (mat.m01 + mat.m04) / S; - out.z = (mat.m08 + mat.m02) / S; - } else if (mat.m05 > mat.m10) { - S = Math.sqrt(1.0 + mat.m05 - mat.m00 - mat.m10) * 2; - out.w = (mat.m08 - mat.m02) / S; - out.x = (mat.m01 + mat.m04) / S; - out.y = 0.25 * S; - out.z = (mat.m06 + mat.m09) / S; - } else { - S = Math.sqrt(1.0 + mat.m10 - mat.m00 - mat.m05) * 2; - out.w = (mat.m01 - mat.m04) / S; - out.x = (mat.m08 + mat.m02) / S; - out.y = (mat.m06 + mat.m09) / S; - out.z = 0.25 * S; - } - - return out; -}; - -/** - * Creates a matrix from a quaternion rotation, vector translation and vector scale - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * mat4.scale(dest, scale) - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @param {vec3} s Scaling vector - * @returns {mat4} out - */ -mat4.fromRTS = function (out, q, v, s) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - var sx = s.x; - var sy = s.y; - var sz = s.z; - - out.m00 = (1 - (yy + zz)) * sx; - out.m01 = (xy + wz) * sx; - out.m02 = (xz - wy) * sx; - out.m03 = 0; - out.m04 = (xy - wz) * sy; - out.m05 = (1 - (xx + zz)) * sy; - out.m06 = (yz + wx) * sy; - out.m07 = 0; - out.m08 = (xz + wy) * sz; - out.m09 = (yz - wx) * sz; - out.m10 = (1 - (xx + yy)) * sz; - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - - return out; -}; - -/** - * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * mat4.translate(dest, origin); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * mat4.scale(dest, scale) - * mat4.translate(dest, negativeOrigin); - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @param {vec3} s Scaling vector - * @param {vec3} o The origin vector around which to scale and rotate - * @returns {mat4} out - */ -mat4.fromRTSOrigin = function (out, q, v, s, o) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - var sx = s.x; - var sy = s.y; - var sz = s.z; - - var ox = o.x; - var oy = o.y; - var oz = o.z; - - out.m00 = (1 - (yy + zz)) * sx; - out.m01 = (xy + wz) * sx; - out.m02 = (xz - wy) * sx; - out.m03 = 0; - out.m04 = (xy - wz) * sy; - out.m05 = (1 - (xx + zz)) * sy; - out.m06 = (yz + wx) * sy; - out.m07 = 0; - out.m08 = (xz + wy) * sz; - out.m09 = (yz - wx) * sz; - out.m10 = (1 - (xx + yy)) * sz; - out.m11 = 0; - out.m12 = v.x + ox - (out.m00 * ox + out.m04 * oy + out.m08 * oz); - out.m13 = v.y + oy - (out.m01 * ox + out.m05 * oy + out.m09 * oz); - out.m14 = v.z + oz - (out.m02 * ox + out.m06 * oy + out.m10 * oz); - out.m15 = 1; - - return out; -}; - -/** - * Calculates a 4x4 matrix from the given quaternion - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Quaternion to create matrix from - * - * @returns {mat4} out - */ -mat4.fromQuat = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var yx = y * x2; - var yy = y * y2; - var zx = z * x2; - var zy = z * y2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - yy - zz; - out.m01 = yx + wz; - out.m02 = zx - wy; - out.m03 = 0; - - out.m04 = yx - wz; - out.m05 = 1 - xx - zz; - out.m06 = zy + wx; - out.m07 = 0; - - out.m08 = zx + wy; - out.m09 = zy - wx; - out.m10 = 1 - xx - yy; - out.m11 = 0; - - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - - return out; -}; - -/** - * Generates a frustum matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {Number} left Left bound of the frustum - * @param {Number} right Right bound of the frustum - * @param {Number} bottom Bottom bound of the frustum - * @param {Number} top Top bound of the frustum - * @param {Number} near Near bound of the frustum - * @param {Number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.frustum = function (out, left, right, bottom, top, near, far) { - var rl = 1 / (right - left); - var tb = 1 / (top - bottom); - var nf = 1 / (near - far); - - out.m00 = (near * 2) * rl; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = (near * 2) * tb; - out.m06 = 0; - out.m07 = 0; - out.m08 = (right + left) * rl; - out.m09 = (top + bottom) * tb; - out.m10 = (far + near) * nf; - out.m11 = -1; - out.m12 = 0; - out.m13 = 0; - out.m14 = (far * near * 2) * nf; - out.m15 = 0; - return out; -}; - -/** - * Generates a perspective projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} fovy Vertical field of view in radians - * @param {number} aspect Aspect ratio. typically viewport width/height - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.perspective = function (out, fovy, aspect, near, far) { - var f = 1.0 / Math.tan(fovy / 2); - var nf = 1 / (near - far); - - out.m00 = f / aspect; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = f; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = (far + near) * nf; - out.m11 = -1; - out.m12 = 0; - out.m13 = 0; - out.m14 = (2 * far * near) * nf; - out.m15 = 0; - return out; -}; - -/** - * Generates a perspective projection matrix with the given field of view. - * This is primarily useful for generating projection matrices to be used - * with the still experiemental WebVR API. - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.perspectiveFromFieldOfView = function (out, fov, near, far) { - var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0); - var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0); - var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0); - var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0); - var xScale = 2.0 / (leftTan + rightTan); - var yScale = 2.0 / (upTan + downTan); - - out.m00 = xScale; - out.m01 = 0.0; - out.m02 = 0.0; - out.m03 = 0.0; - out.m04 = 0.0; - out.m05 = yScale; - out.m06 = 0.0; - out.m07 = 0.0; - out.m08 = -((leftTan - rightTan) * xScale * 0.5); - out.m09 = ((upTan - downTan) * yScale * 0.5); - out.m10 = far / (near - far); - out.m11 = -1.0; - out.m12 = 0.0; - out.m13 = 0.0; - out.m14 = (far * near) / (near - far); - out.m15 = 0.0; - return out; -}; - -/** - * Generates a orthogonal projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} left Left bound of the frustum - * @param {number} right Right bound of the frustum - * @param {number} bottom Bottom bound of the frustum - * @param {number} top Top bound of the frustum - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.ortho = function (out, left, right, bottom, top, near, far) { - var lr = 1 / (left - right); - var bt = 1 / (bottom - top); - var nf = 1 / (near - far); - out.m00 = -2 * lr; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = -2 * bt; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 2 * nf; - out.m11 = 0; - out.m12 = (left + right) * lr; - out.m13 = (top + bottom) * bt; - out.m14 = (far + near) * nf; - out.m15 = 1; - return out; -}; - -/** - * Generates a look-at matrix with the given eye position, focal point, and up axis - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {vec3} eye Position of the viewer - * @param {vec3} center Point the viewer is looking at - * @param {vec3} up vec3 pointing up - * @returns {mat4} out - */ -mat4.lookAt = function (out, eye, center, up) { - var x0, x1, x2, y0, y1, y2, z0, z1, z2, len; - var eyex = eye.x; - var eyey = eye.y; - var eyez = eye.z; - var upx = up.x; - var upy = up.y; - var upz = up.z; - var centerx = center.x; - var centery = center.y; - var centerz = center.z; - - if ( - Math.abs(eyex - centerx) < EPSILON && - Math.abs(eyey - centery) < EPSILON && - Math.abs(eyez - centerz) < EPSILON - ) { - return mat4.identity(out); - } - - z0 = eyex - centerx; - z1 = eyey - centery; - z2 = eyez - centerz; - - len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); - z0 *= len; - z1 *= len; - z2 *= len; - - x0 = upy * z2 - upz * z1; - x1 = upz * z0 - upx * z2; - x2 = upx * z1 - upy * z0; - len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); - if (!len) { - x0 = 0; - x1 = 0; - x2 = 0; - } else { - len = 1 / len; - x0 *= len; - x1 *= len; - x2 *= len; - } - - y0 = z1 * x2 - z2 * x1; - y1 = z2 * x0 - z0 * x2; - y2 = z0 * x1 - z1 * x0; - - len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); - if (!len) { - y0 = 0; - y1 = 0; - y2 = 0; - } else { - len = 1 / len; - y0 *= len; - y1 *= len; - y2 *= len; - } - - out.m00 = x0; - out.m01 = y0; - out.m02 = z0; - out.m03 = 0; - out.m04 = x1; - out.m05 = y1; - out.m06 = z1; - out.m07 = 0; - out.m08 = x2; - out.m09 = y2; - out.m10 = z2; - out.m11 = 0; - out.m12 = -(x0 * eyex + x1 * eyey + x2 * eyez); - out.m13 = -(y0 * eyex + y1 * eyey + y2 * eyez); - out.m14 = -(z0 * eyex + z1 * eyey + z2 * eyez); - out.m15 = 1; - - return out; -}; - -/** - * Returns a string representation of a mat4 - * - * @param {mat4} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat4.str = function (a) { - return ("mat4(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ", " + (a.m06) + ", " + (a.m07) + ", " + (a.m08) + ", " + (a.m09) + ", " + (a.m10) + ", " + (a.m11) + ", " + (a.m12) + ", " + (a.m13) + ", " + (a.m14) + ", " + (a.m15) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat4} m - * @returns {array} - */ -mat4.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - out[6] = m.m06; - out[7] = m.m07; - out[8] = m.m08; - out[9] = m.m09; - out[10] = m.m10; - out[11] = m.m11; - out[12] = m.m12; - out[13] = m.m13; - out[14] = m.m14; - out[15] = m.m15; - - return out; -}; - -/** - * Returns Frobenius norm of a mat4 - * - * @param {mat4} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat4.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2) + Math.pow(a.m09, 2) + Math.pow(a.m10, 2) + Math.pow(a.m11, 2) + Math.pow(a.m12, 2) + Math.pow(a.m13, 2) + Math.pow(a.m14, 2) + Math.pow(a.m15, 2))) -}; - -/** - * Adds two mat4's - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - out.m06 = a.m06 + b.m06; - out.m07 = a.m07 + b.m07; - out.m08 = a.m08 + b.m08; - out.m09 = a.m09 + b.m09; - out.m10 = a.m10 + b.m10; - out.m11 = a.m11 + b.m11; - out.m12 = a.m12 + b.m12; - out.m13 = a.m13 + b.m13; - out.m14 = a.m14 + b.m14; - out.m15 = a.m15 + b.m15; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - out.m06 = a.m06 - b.m06; - out.m07 = a.m07 - b.m07; - out.m08 = a.m08 - b.m08; - out.m09 = a.m09 - b.m09; - out.m10 = a.m10 - b.m10; - out.m11 = a.m11 - b.m11; - out.m12 = a.m12 - b.m12; - out.m13 = a.m13 - b.m13; - out.m14 = a.m14 - b.m14; - out.m15 = a.m15 - b.m15; - return out; -}; - -/** - * Alias for {@link mat4.subtract} - * @function - */ -mat4.sub = mat4.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat4} out - */ -mat4.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - out.m06 = a.m06 * b; - out.m07 = a.m07 * b; - out.m08 = a.m08 * b; - out.m09 = a.m09 * b; - out.m10 = a.m10 * b; - out.m11 = a.m11 * b; - out.m12 = a.m12 * b; - out.m13 = a.m13 * b; - out.m14 = a.m14 * b; - out.m15 = a.m15 * b; - return out; -}; - -/** - * Adds two mat4's after multiplying each element of the second operand by a scalar value. - * - * @param {mat4} out the receiving vector - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat4} out - */ -mat4.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - out.m06 = a.m06 + (b.m06 * scale); - out.m07 = a.m07 + (b.m07 * scale); - out.m08 = a.m08 + (b.m08 * scale); - out.m09 = a.m09 + (b.m09 * scale); - out.m10 = a.m10 + (b.m10 * scale); - out.m11 = a.m11 + (b.m11 * scale); - out.m12 = a.m12 + (b.m12 * scale); - out.m13 = a.m13 + (b.m13 * scale); - out.m14 = a.m14 + (b.m14 * scale); - out.m15 = a.m15 + (b.m15 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat4} a The first matrix. - * @param {mat4} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat4.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && - a.m04 === b.m04 && a.m05 === b.m05 && a.m06 === b.m06 && a.m07 === b.m07 && - a.m08 === b.m08 && a.m09 === b.m09 && a.m10 === b.m10 && a.m11 === b.m11 && - a.m12 === b.m12 && a.m13 === b.m13 && a.m14 === b.m14 && a.m15 === b.m15; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat4} a The first matrix. - * @param {mat4} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat4.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, - a8 = a.m08, a9 = a.m09, a10 = a.m10, a11 = a.m11, - a12 = a.m12, a13 = a.m13, a14 = a.m14, a15 = a.m15; - - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, - b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, - b8 = b.m08, b9 = b.m09, b10 = b.m10, b11 = b.m11, - b12 = b.m12, b13 = b.m13, b14 = b.m14, b15 = b.m15; - - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && - Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && - Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && - Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && - Math.abs(a9 - b9) <= EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && - Math.abs(a10 - b10) <= EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && - Math.abs(a11 - b11) <= EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && - Math.abs(a12 - b12) <= EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && - Math.abs(a13 - b13) <= EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && - Math.abs(a14 - b14) <= EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && - Math.abs(a15 - b15) <= EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15)) - ); -}; - -var _tmp$8 = new Array(3); - -var _color3 = function _color3(r, g, b) { - this.r = r; - this.g = g; - this.b = b; -}; - -_color3.prototype.toJSON = function toJSON () { - _tmp$8[0] = this.r; - _tmp$8[1] = this.g; - _tmp$8[2] = this.b; - - return _tmp$8; -}; - -/** - * @class Color - * @name color3 - */ -var color3 = {}; - -/** - * Creates a new color - * - * @returns {color3} a new color - */ -color3.create = function () { - return new _color3(1, 1, 1); -}; - -/** - * Creates a new color initialized with the given values - * - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @returns {color3} a new color - * @function - */ -color3.new = function (r, g, b) { - return new _color3(r, g, b); -}; - -/** - * Creates a new color initialized with values from an existing quaternion - * - * @param {color3} a color to clone - * @returns {color3} a new color - * @function - */ -color3.clone = function (a) { - return new _color3(a.r, a.g, a.b, a.a); -}; - -/** - * Copy the values from one color to another - * - * @param {color3} out the receiving color - * @param {color3} a the source color - * @returns {color3} out - * @function - */ -color3.copy = function (out, a) { - out.r = a.r; - out.g = a.g; - out.b = a.b; - return out; -}; - -/** - * Set the components of a color to the given values - * - * @param {color3} out the receiving color - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @returns {color3} out - * @function - */ -color3.set = function (out, r, g, b) { - out.r = r; - out.g = g; - out.b = b; - return out; -}; - -/** - * Set from hex - * - * @param {color3} out the receiving color - * @param {Number} hex - * @returns {color3} out - * @function - */ -color3.fromHex = function (out, hex) { - var r = ((hex >> 16)) / 255.0; - var g = ((hex >> 8) & 0xff) / 255.0; - var b = ((hex) & 0xff) / 255.0; - - out.r = r; - out.g = g; - out.b = b; - return out; -}; - -/** - * Adds two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - * @function - */ -color3.add = function (out, a, b) { - out.r = a.r + b.r; - out.g = a.g + b.g; - out.b = a.b + b.b; - return out; -}; - -/** - * Subtracts color b from color a - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - */ -color3.subtract = function (out, a, b) { - out.r = a.r - b.r; - out.g = a.g - b.g; - out.b = a.b - b.b; - return out; -}; - -/** - * Alias for {@link color3.subtract} - * @function - */ -color3.sub = color3.subtract; - -/** - * Multiplies two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - * @function - */ -color3.multiply = function (out, a, b) { - out.r = a.r * b.r; - out.g = a.g * b.g; - out.b = a.b * b.b; - return out; -}; - -/** - * Alias for {@link color3.multiply} - * @function - */ -color3.mul = color3.multiply; - -/** - * Divides two color's - * - * @param {color3} out the receiving vector - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - */ -color3.divide = function (out, a, b) { - out.r = a.r / b.r; - out.g = a.g / b.g; - out.b = a.b / b.b; - return out; -}; - -/** - * Alias for {@link color3.divide} - * @function - */ -color3.div = color3.divide; - - -/** - * Scales a color by a scalar number - * - * @param {color3} out the receiving vector - * @param {color3} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {color3} out - * @function - */ -color3.scale = function (out, a, b) { - out.r = a.r * b; - out.g = a.g * b; - out.b = a.b * b; - return out; -}; - -/** - * Performs a linear interpolation between two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {color3} out - * @function - */ -color3.lerp = function (out, a, b, t) { - var ar = a.r, - ag = a.g, - ab = a.b; - out.r = ar + t * (b.r - ar); - out.g = ag + t * (b.g - ag); - out.b = ab + t * (b.b - ab); - return out; -}; - -/** - * Returns a string representation of a color - * - * @param {color3} a vector to represent as a string - * @returns {String} string representation of the vector - */ -color3.str = function (a) { - return ("color3(" + (a.r) + ", " + (a.g) + ", " + (a.b) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {color3} a - * @returns {array} - */ -color3.array = function (out, a) { - out[0] = a.r; - out[1] = a.g; - out[2] = a.b; - - return out; -}; - -/** - * Returns whether or not the color have exactly the same elements in the same position (when compared with ===) - * - * @param {color3} a The first color3. - * @param {color3} b The second color3. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color3.exactEquals = function (a, b) { - return a.r === b.r && a.g === b.g && a.b === b.b; -}; - -/** - * Returns whether or not the colors have approximately the same elements in the same position. - * - * @param {color3} a The first color3. - * @param {color3} b The second color3. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color3.equals = function (a, b) { - var a0 = a.r, a1 = a.g, a2 = a.b; - var b0 = b.r, b1 = b.g, b2 = b.b; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); -}; - -/** - * Returns the hex value - * - * @param {color3} a The color - * @returns {Number} - */ -color3.hex = function (a) { - return (a.r * 255) << 16 | (a.g * 255) << 8 | (a.b * 255); -}; - -var _tmp$9 = new Array(4); - -var _color4 = function _color4(r, g, b, a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; -}; - -_color4.prototype.toJSON = function toJSON () { - _tmp$9[0] = this.r; - _tmp$9[1] = this.g; - _tmp$9[2] = this.b; - _tmp$9[3] = this.a; - - return _tmp$9; -}; - -/** - * @class Color - * @name color4 - */ -var color4 = {}; - -/** - * Creates a new color - * - * @returns {color4} a new color - */ -color4.create = function () { - return new _color4(1, 1, 1, 1); -}; - -/** - * Creates a new color initialized with the given values - * - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @param {Number} a alpha component - * @returns {color4} a new color - * @function - */ -color4.new = function (r, g, b, a) { - return new _color4(r, g, b, a); -}; - -/** - * Creates a new color initialized with values from an existing quaternion - * - * @param {color4} a color to clone - * @returns {color4} a new color - * @function - */ -color4.clone = function (a) { - return new _color4(a.r, a.g, a.b, a.a); -}; - -/** - * Copy the values from one color to another - * - * @param {color4} out the receiving color - * @param {color4} a the source color - * @returns {color4} out - * @function - */ -color4.copy = function (out, a) { - out.r = a.r; - out.g = a.g; - out.b = a.b; - out.a = a.a; - return out; -}; - -/** - * Set the components of a color to the given values - * - * @param {color4} out the receiving color - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @param {Number} a alpha component - * @returns {color4} out - * @function - */ -color4.set = function (out, r, g, b, a) { - out.r = r; - out.g = g; - out.b = b; - out.a = a; - return out; -}; - -/** - * Set from hex - * - * @param {color4} out the receiving color - * @param {Number} hex - * @returns {color4} out - * @function - */ -color4.fromHex = function (out, hex) { - var r = ((hex >> 24)) / 255.0; - var g = ((hex >> 16) & 0xff) / 255.0; - var b = ((hex >> 8) & 0xff) / 255.0; - var a = ((hex) & 0xff) / 255.0; - - out.r = r; - out.g = g; - out.b = b; - out.a = a; - return out; -}; - -/** - * Adds two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - * @function - */ -color4.add = function (out, a, b) { - out.r = a.r + b.r; - out.g = a.g + b.g; - out.b = a.b + b.b; - out.a = a.a + b.a; - return out; -}; - -/** - * Subtracts color b from color a - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - */ -color4.subtract = function (out, a, b) { - out.r = a.r - b.r; - out.g = a.g - b.g; - out.b = a.b - b.b; - out.a = a.a - b.a; - return out; -}; - -/** - * Alias for {@link color4.subtract} - * @function - */ -color4.sub = color4.subtract; - -/** - * Multiplies two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - * @function - */ -color4.multiply = function (out, a, b) { - out.r = a.r * b.r; - out.g = a.g * b.g; - out.b = a.b * b.b; - out.a = a.a * b.a; - return out; -}; - -/** - * Alias for {@link color4.multiply} - * @function - */ -color4.mul = color4.multiply; - -/** - * Divides two color's - * - * @param {color4} out the receiving vector - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - */ -color4.divide = function (out, a, b) { - out.r = a.r / b.r; - out.g = a.g / b.g; - out.b = a.b / b.b; - out.a = a.a / b.a; - return out; -}; - -/** - * Alias for {@link color4.divide} - * @function - */ -color4.div = color4.divide; - - -/** - * Scales a color by a scalar number - * - * @param {color4} out the receiving vector - * @param {color4} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {color4} out - * @function - */ -color4.scale = function (out, a, b) { - out.r = a.r * b; - out.g = a.g * b; - out.b = a.b * b; - out.a = a.a * b; - return out; -}; - -/** - * Performs a linear interpolation between two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {color4} out - * @function - */ -color4.lerp = function (out, a, b, t) { - var ar = a.r, - ag = a.g, - ab = a.b, - aa = a.a; - out.r = ar + t * (b.r - ar); - out.g = ag + t * (b.g - ag); - out.b = ab + t * (b.b - ab); - out.a = aa + t * (b.a - aa); - return out; -}; - -/** - * Returns a string representation of a color - * - * @param {color4} a vector to represent as a string - * @returns {String} string representation of the vector - */ -color4.str = function (a) { - return ("color4(" + (a.r) + ", " + (a.g) + ", " + (a.b) + ", " + (a.a) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {color4} a - * @returns {array} - */ -color4.array = function (out, a) { - let scale = a instanceof cc.Color ? 1 / 255 : 1; - out[0] = a.r * scale; - out[1] = a.g * scale; - out[2] = a.b * scale; - out[3] = a.a * scale; - - return out; -}; - -/** - * Returns whether or not the color have exactly the same elements in the same position (when compared with ===) - * - * @param {color4} a The first color4. - * @param {color4} b The second color4. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color4.exactEquals = function (a, b) { - return a.r === b.r && a.g === b.g && a.b === b.b && a.a === b.a; -}; - -/** - * Returns whether or not the colors have approximately the same elements in the same position. - * - * @param {color4} a The first color4. - * @param {color4} b The second color4. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color4.equals = function (a, b) { - var a0 = a.r, a1 = a.g, a2 = a.b, a3 = a.a; - var b0 = b.r, b1 = b.g, b2 = b.b, b3 = b.a; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); -}; - -/** - * Returns the hex value - * - * @param {color4} a The color - * @returns {Number} - */ -color4.hex = function (a) { - return ((a.r * 255) << 24 | (a.g * 255) << 16 | (a.b * 255) << 8 | a.a * 255) >>> 0; -}; - -// NOTE: there is no syntax for: export {* as bits} from './lib/bits'; -var bits = bits_; - - - -var math = Object.freeze({ - bits: bits, - vec2: vec2, - vec3: vec3, - vec4: vec4, - quat: quat, - mat2: mat2, - mat23: mat23, - mat3: mat3, - mat4: mat4, - color3: color3, - color4: color4, - EPSILON: EPSILON, - equals: equals, - approx: approx, - clamp: clamp, - clamp01: clamp01, - lerp: lerp, - toRadian: toRadian, - toDegree: toDegree, - random: random, - randomRange: randomRange, - randomRangeInt: randomRangeInt, - nextPow2: nextPow2 -}); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var enums = { - // projection - PROJ_PERSPECTIVE: 0, - PROJ_ORTHO: 1, - - // lights - LIGHT_DIRECTIONAL: 0, - LIGHT_POINT: 1, - LIGHT_SPOT: 2, - - // shadows - SHADOW_NONE: 0, - SHADOW_HARD: 1, - SHADOW_SOFT: 2, - - // parameter type - PARAM_INT: 0, - PARAM_INT2: 1, - PARAM_INT3: 2, - PARAM_INT4: 3, - PARAM_FLOAT: 4, - PARAM_FLOAT2: 5, - PARAM_FLOAT3: 6, - PARAM_FLOAT4: 7, - PARAM_COLOR3: 8, - PARAM_COLOR4: 9, - PARAM_MAT2: 10, - PARAM_MAT3: 11, - PARAM_MAT4: 12, - PARAM_TEXTURE_2D: 13, - PARAM_TEXTURE_CUBE: 14, - - // clear flags - CLEAR_COLOR: 1, - CLEAR_DEPTH: 2, - CLEAR_STENCIL: 4, -}; - -var GL_NEAREST = 9728; // gl.NEAREST -var GL_LINEAR = 9729; // gl.LINEAR -var GL_NEAREST_MIPMAP_NEAREST = 9984; // gl.NEAREST_MIPMAP_NEAREST -var GL_LINEAR_MIPMAP_NEAREST = 9985; // gl.LINEAR_MIPMAP_NEAREST -var GL_NEAREST_MIPMAP_LINEAR = 9986; // gl.NEAREST_MIPMAP_LINEAR -var GL_LINEAR_MIPMAP_LINEAR = 9987; // gl.LINEAR_MIPMAP_LINEAR - -// const GL_BYTE = 5120; // gl.BYTE -var GL_UNSIGNED_BYTE = 5121; // gl.UNSIGNED_BYTE -// const GL_SHORT = 5122; // gl.SHORT -var GL_UNSIGNED_SHORT = 5123; // gl.UNSIGNED_SHORT -var GL_UNSIGNED_INT = 5125; // gl.UNSIGNED_INT -var GL_FLOAT = 5126; // gl.FLOAT -var GL_UNSIGNED_SHORT_5_6_5 = 33635; // gl.UNSIGNED_SHORT_5_6_5 -var GL_UNSIGNED_SHORT_4_4_4_4 = 32819; // gl.UNSIGNED_SHORT_4_4_4_4 -var GL_UNSIGNED_SHORT_5_5_5_1 = 32820; // gl.UNSIGNED_SHORT_5_5_5_1 -var GL_HALF_FLOAT_OES = 36193; // gl.HALF_FLOAT_OES - -var GL_DEPTH_COMPONENT = 6402; // gl.DEPTH_COMPONENT - -var GL_ALPHA = 6406; // gl.ALPHA -var GL_RGB = 6407; // gl.RGB -var GL_RGBA = 6408; // gl.RGBA -var GL_LUMINANCE = 6409; // gl.LUMINANCE -var GL_LUMINANCE_ALPHA = 6410; // gl.LUMINANCE_ALPHA - -var GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; // ext.COMPRESSED_RGB_S3TC_DXT1_EXT -var GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; // ext.COMPRESSED_RGBA_S3TC_DXT1_EXT -var GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; // ext.COMPRESSED_RGBA_S3TC_DXT3_EXT -var GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; // ext.COMPRESSED_RGBA_S3TC_DXT5_EXT - -var GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; // ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG -var GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; // ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG -var GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; // ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG -var GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; // ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG - -var GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; // ext.COMPRESSED_RGB_ETC1_WEBGL - -var _filterGL = [ - [ GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR ], - [ GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR ] ]; - -var _textureFmtGL = [ - // TEXTURE_FMT_RGB_DXT1: 0 - { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixelType: null }, - - // TEXTURE_FMT_RGBA_DXT1: 1 - { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixelType: null }, - - // TEXTURE_FMT_RGBA_DXT3: 2 - { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, pixelType: null }, - - // TEXTURE_FMT_RGBA_DXT5: 3 - { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, pixelType: null }, - - // TEXTURE_FMT_RGB_ETC1: 4 - { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_ETC1_WEBGL, pixelType: null }, - - // TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5 - { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, pixelType: null }, - - // TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6 - { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, pixelType: null }, - - // TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7 - { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, pixelType: null }, - - // TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8 - { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, pixelType: null }, - - // TEXTURE_FMT_A8: 9 - { format: GL_ALPHA, internalFormat: GL_ALPHA, pixelType: GL_UNSIGNED_BYTE }, - - // TEXTURE_FMT_L8: 10 - { format: GL_LUMINANCE, internalFormat: GL_LUMINANCE, pixelType: GL_UNSIGNED_BYTE }, - - // TEXTURE_FMT_L8_A8: 11 - { format: GL_LUMINANCE_ALPHA, internalFormat: GL_LUMINANCE_ALPHA, pixelType: GL_UNSIGNED_BYTE }, - - // TEXTURE_FMT_R5_G6_B5: 12 - { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_SHORT_5_6_5 }, - - // TEXTURE_FMT_R5_G5_B5_A1: 13 - { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_5_5_5_1 }, - - // TEXTURE_FMT_R4_G4_B4_A4: 14 - { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_4_4_4_4 }, - - // TEXTURE_FMT_RGB8: 15 - { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_BYTE }, - - // TEXTURE_FMT_RGBA8: 16 - { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_BYTE }, - - // TEXTURE_FMT_RGB16F: 17 - { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_HALF_FLOAT_OES }, - - // TEXTURE_FMT_RGBA16F: 18 - { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_HALF_FLOAT_OES }, - - // TEXTURE_FMT_RGB32F: 19 - { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_FLOAT }, - - // TEXTURE_FMT_RGBA32F: 20 - { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_FLOAT }, - - // TEXTURE_FMT_R32F: 21 - { format: null, internalFormat: null, pixelType: null }, - - // TEXTURE_FMT_111110F: 22 - { format: null, internalFormat: null, pixelType: null }, - - // TEXTURE_FMT_SRGB: 23 - { format: null, internalFormat: null, pixelType: null }, - - // TEXTURE_FMT_SRGBA: 24 - { format: null, internalFormat: null, pixelType: null }, - - // TEXTURE_FMT_D16: 25 - { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_SHORT }, - - // TEXTURE_FMT_D32: 26 - { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_INT }, - - // TEXTURE_FMT_D24S8: 27 - { format: null, internalFormat: null, pixelType: null } ]; - -/** - * enums - */ -var enums$1 = { - // buffer usage - USAGE_STATIC: 35044, // gl.STATIC_DRAW - USAGE_DYNAMIC: 35048, // gl.DYNAMIC_DRAW - USAGE_STREAM: 35040, // gl.STREAM_DRAW - - // index buffer format - INDEX_FMT_UINT8: 5121, // gl.UNSIGNED_BYTE - INDEX_FMT_UINT16: 5123, // gl.UNSIGNED_SHORT - INDEX_FMT_UINT32: 5125, // gl.UNSIGNED_INT (OES_element_index_uint) - - // vertex attribute semantic - ATTR_POSITION: 'a_position', - ATTR_NORMAL: 'a_normal', - ATTR_TANGENT: 'a_tangent', - ATTR_BITANGENT: 'a_bitangent', - ATTR_WEIGHTS: 'a_weights', - ATTR_JOINTS: 'a_joints', - ATTR_COLOR: 'a_color', - ATTR_COLOR0: 'a_color0', - ATTR_COLOR1: 'a_color1', - ATTR_UV: 'a_uv', - ATTR_UV0: 'a_uv0', - ATTR_UV1: 'a_uv1', - ATTR_UV2: 'a_uv2', - ATTR_UV3: 'a_uv3', - ATTR_UV4: 'a_uv4', - ATTR_UV5: 'a_uv5', - ATTR_UV6: 'a_uv6', - ATTR_UV7: 'a_uv7', - - // vertex attribute type - ATTR_TYPE_INT8: 5120, // gl.BYTE - ATTR_TYPE_UINT8: 5121, // gl.UNSIGNED_BYTE - ATTR_TYPE_INT16: 5122, // gl.SHORT - ATTR_TYPE_UINT16: 5123, // gl.UNSIGNED_SHORT - ATTR_TYPE_INT32: 5124, // gl.INT - ATTR_TYPE_UINT32: 5125, // gl.UNSIGNED_INT - ATTR_TYPE_FLOAT32: 5126, // gl.FLOAT - - // texture filter - FILTER_NEAREST: 0, - FILTER_LINEAR: 1, - - // texture wrap mode - WRAP_REPEAT: 10497, // gl.REPEAT - WRAP_CLAMP: 33071, // gl.CLAMP_TO_EDGE - WRAP_MIRROR: 33648, // gl.MIRRORED_REPEAT - - // texture format - // compress formats - TEXTURE_FMT_RGB_DXT1: 0, - TEXTURE_FMT_RGBA_DXT1: 1, - TEXTURE_FMT_RGBA_DXT3: 2, - TEXTURE_FMT_RGBA_DXT5: 3, - TEXTURE_FMT_RGB_ETC1: 4, - TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5, - TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6, - TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7, - TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8, - - // normal formats - TEXTURE_FMT_A8: 9, - TEXTURE_FMT_L8: 10, - TEXTURE_FMT_L8_A8: 11, - TEXTURE_FMT_R5_G6_B5: 12, - TEXTURE_FMT_R5_G5_B5_A1: 13, - TEXTURE_FMT_R4_G4_B4_A4: 14, - TEXTURE_FMT_RGB8: 15, - TEXTURE_FMT_RGBA8: 16, - TEXTURE_FMT_RGB16F: 17, - TEXTURE_FMT_RGBA16F: 18, - TEXTURE_FMT_RGB32F: 19, - TEXTURE_FMT_RGBA32F: 20, - TEXTURE_FMT_R32F: 21, - TEXTURE_FMT_111110F: 22, - TEXTURE_FMT_SRGB: 23, - TEXTURE_FMT_SRGBA: 24, - - // depth formats - TEXTURE_FMT_D16: 25, - TEXTURE_FMT_D32: 26, - TEXTURE_FMT_D24S8: 27, - - // depth and stencil function - DS_FUNC_NEVER: 512, // gl.NEVER - DS_FUNC_LESS: 513, // gl.LESS - DS_FUNC_EQUAL: 514, // gl.EQUAL - DS_FUNC_LEQUAL: 515, // gl.LEQUAL - DS_FUNC_GREATER: 516, // gl.GREATER - DS_FUNC_NOTEQUAL: 517, // gl.NOTEQUAL - DS_FUNC_GEQUAL: 518, // gl.GEQUAL - DS_FUNC_ALWAYS: 519, // gl.ALWAYS - - // render-buffer format - RB_FMT_RGBA4: 32854, // gl.RGBA4 - RB_FMT_RGB5_A1: 32855, // gl.RGB5_A1 - RB_FMT_RGB565: 36194, // gl.RGB565 - RB_FMT_D16: 33189, // gl.DEPTH_COMPONENT16 - RB_FMT_S8: 36168, // gl.STENCIL_INDEX8 - RB_FMT_D24S8: 34041, // gl.DEPTH_STENCIL - - // blend-equation - BLEND_FUNC_ADD: 32774, // gl.FUNC_ADD - BLEND_FUNC_SUBTRACT: 32778, // gl.FUNC_SUBTRACT - BLEND_FUNC_REVERSE_SUBTRACT: 32779, // gl.FUNC_REVERSE_SUBTRACT - - // blend - BLEND_ZERO: 0, // gl.ZERO - BLEND_ONE: 1, // gl.ONE - BLEND_SRC_COLOR: 768, // gl.SRC_COLOR - BLEND_ONE_MINUS_SRC_COLOR: 769, // gl.ONE_MINUS_SRC_COLOR - BLEND_DST_COLOR: 774, // gl.DST_COLOR - BLEND_ONE_MINUS_DST_COLOR: 775, // gl.ONE_MINUS_DST_COLOR - BLEND_SRC_ALPHA: 770, // gl.SRC_ALPHA - BLEND_ONE_MINUS_SRC_ALPHA: 771, // gl.ONE_MINUS_SRC_ALPHA - BLEND_DST_ALPHA: 772, // gl.DST_ALPHA - BLEND_ONE_MINUS_DST_ALPHA: 773, // gl.ONE_MINUS_DST_ALPHA - BLEND_CONSTANT_COLOR: 32769, // gl.CONSTANT_COLOR - BLEND_ONE_MINUS_CONSTANT_COLOR: 32770, // gl.ONE_MINUS_CONSTANT_COLOR - BLEND_CONSTANT_ALPHA: 32771, // gl.CONSTANT_ALPHA - BLEND_ONE_MINUS_CONSTANT_ALPHA: 32772, // gl.ONE_MINUS_CONSTANT_ALPHA - BLEND_SRC_ALPHA_SATURATE: 776, // gl.SRC_ALPHA_SATURATE - - // stencil operation - STENCIL_OP_KEEP: 7680, // gl.KEEP - STENCIL_OP_ZERO: 0, // gl.ZERO - STENCIL_OP_REPLACE: 7681, // gl.REPLACE - STENCIL_OP_INCR: 7682, // gl.INCR - STENCIL_OP_INCR_WRAP: 34055, // gl.INCR_WRAP - STENCIL_OP_DECR: 7683, // gl.DECR - STENCIL_OP_DECR_WRAP: 34056, // gl.DECR_WRAP - STENCIL_OP_INVERT: 5386, // gl.INVERT - - // cull - CULL_NONE: 0, - CULL_FRONT: 1028, - CULL_BACK: 1029, - CULL_FRONT_AND_BACK: 1032, - - // primitive type - PT_POINTS: 0, // gl.POINTS - PT_LINES: 1, // gl.LINES - PT_LINE_LOOP: 2, // gl.LINE_LOOP - PT_LINE_STRIP: 3, // gl.LINE_STRIP - PT_TRIANGLES: 4, // gl.TRIANGLES - PT_TRIANGLE_STRIP: 5, // gl.TRIANGLE_STRIP - PT_TRIANGLE_FAN: 6, // gl.TRIANGLE_FAN -}; - -/** - * @method attrTypeBytes - * @param {ATTR_TYPE_*} attrType - */ -function attrTypeBytes(attrType) { - if (attrType === enums$1.ATTR_TYPE_INT8) { - return 1; - } else if (attrType === enums$1.ATTR_TYPE_UINT8) { - return 1; - } else if (attrType === enums$1.ATTR_TYPE_INT16) { - return 2; - } else if (attrType === enums$1.ATTR_TYPE_UINT16) { - return 2; - } else if (attrType === enums$1.ATTR_TYPE_INT32) { - return 4; - } else if (attrType === enums$1.ATTR_TYPE_UINT32) { - return 4; - } else if (attrType === enums$1.ATTR_TYPE_FLOAT32) { - return 4; - } - - console.warn(("Unknown ATTR_TYPE: " + attrType)); - return 0; -} - -/** - * @method glFilter - * @param {WebGLContext} gl - * @param {FILTER_*} filter - * @param {FILTER_*} mipFilter - */ -function glFilter(gl, filter, mipFilter) { - if ( mipFilter === void 0 ) mipFilter = -1; - - var result = _filterGL[filter][mipFilter+1]; - if (result === undefined) { - console.warn(("Unknown FILTER: " + filter)); - return mipFilter === -1 ? gl.LINEAR : gl.LINEAR_MIPMAP_LINEAR; - } - - return result; -} - -/** - * @method glTextureFmt - * @param {TEXTURE_FMT_*} fmt - */ -function glTextureFmt(fmt) { - var result = _textureFmtGL[fmt]; - if (result === undefined) { - console.warn(("Unknown TEXTURE_FMT: " + fmt)); - return _textureFmtGL[enums$1.TEXTURE_FMT_RGBA8]; - } - - return result; -} - -// ==================== -// exports -// ==================== - -var VertexFormat = function VertexFormat(infos) { - var this$1 = this; - - this._attr2el = {}; - this._elements = []; - this._bytes = 0; - - var offset = 0; - for (var i = 0, len = infos.length; i < len; ++i) { - var info = infos[i]; - var el = { - name: info.name, - offset: offset, - stride: 0, - stream: -1, - type: info.type, - num: info.num, - normalize: (info.normalize === undefined) ? false : info.normalize, - bytes: info.num * attrTypeBytes(info.type), - }; - - this$1._attr2el[el.name] = el; - this$1._elements.push(el); - - this$1._bytes += el.bytes; - offset += el.bytes; - } - - for (var i$1 = 0, len$1 = this._elements.length; i$1 < len$1; ++i$1) { - var el$1 = this$1._elements[i$1]; - el$1.stride = this$1._bytes; - } -}; - -/** - * @method element - * @param {string} attrName - */ -VertexFormat.prototype.element = function element (attrName) { - return this._attr2el[attrName]; -}; - -var IndexBuffer = function IndexBuffer(device, format, usage, data, numIndices) { - this._device = device; - this._format = format; - this._usage = usage; - this._numIndices = numIndices; - this._bytesPerIndex = 0; - - // calculate bytes - if (format === enums$1.INDEX_FMT_UINT8) { - this._bytesPerIndex = 1; - } else if (format === enums$1.INDEX_FMT_UINT16) { - this._bytesPerIndex = 2; - } else if (format === enums$1.INDEX_FMT_UINT32) { - this._bytesPerIndex = 4; - } - this._bytes = this._bytesPerIndex * numIndices; - - // update - this._glID = device._gl.createBuffer(); - this.update(0, data); - - // stats - device._stats.ib += this._bytes; -}; - -var prototypeAccessors = { count: { configurable: true } }; - -/** - * @method destroy - */ -IndexBuffer.prototype.destroy = function destroy () { - if (this._glID === -1) { - console.error('The buffer already destroyed'); - return; - } - - var gl = this._device._gl; - gl.deleteBuffer(this._glID); - this._device._stats.ib -= this.bytes; - - this._glID = -1; -}; - -/** - * @method update - * @param {Number} offset - * @param {ArrayBuffer} data - */ -IndexBuffer.prototype.update = function update (offset, data) { - if (this._glID === -1) { - console.error('The buffer is destroyed'); - return; - } - - if (data && data.byteLength + offset > this._bytes) { - console.error('Failed to update data, bytes exceed.'); - return; - } - - var gl = this._device._gl; - var glUsage = this._usage; - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._glID); - if (!data) { - if (this._bytes) { - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._bytes, glUsage); - } else { - console.warn('bufferData should not submit 0 bytes data'); - } - } else { - if (offset) { - gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, offset, data); - } else { - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, glUsage); - } - } - this._device._restoreIndexBuffer(); -}; - -prototypeAccessors.count.get = function () { - return this._numIndices; -}; - -Object.defineProperties( IndexBuffer.prototype, prototypeAccessors ); - -var VertexBuffer = function VertexBuffer(device, format, usage, data, numVertices) { - this._device = device; - this._format = format; - this._usage = usage; - this._numVertices = numVertices; - - // calculate bytes - this._bytes = this._format._bytes * numVertices; - - // update - this._glID = device._gl.createBuffer(); - this.update(0, data); - - // stats - device._stats.vb += this._bytes; -}; - -var prototypeAccessors$1 = { count: { configurable: true } }; - -/** - * @method destroy - */ -VertexBuffer.prototype.destroy = function destroy () { - if (this._glID === -1) { - console.error('The buffer already destroyed'); - return; - } - - var gl = this._device._gl; - gl.deleteBuffer(this._glID); - this._device._stats.vb -= this.bytes; - - this._glID = -1; -}; - -/** - * @method update - * @param {Number} offset - * @param {ArrayBuffer} data - */ -VertexBuffer.prototype.update = function update (offset, data) { - if (this._glID === -1) { - console.error('The buffer is destroyed'); - return; - } - - if (data && data.byteLength + offset > this._bytes) { - console.error('Failed to update data, bytes exceed.'); - return; - } - - var gl = this._device._gl; - var glUsage = this._usage; - - gl.bindBuffer(gl.ARRAY_BUFFER, this._glID); - if (!data) { - if (this._bytes) { - gl.bufferData(gl.ARRAY_BUFFER, this._bytes, glUsage); - } else { - console.warn('bufferData should not submit 0 bytes data'); - } - } else { - if (offset) { - gl.bufferSubData(gl.ARRAY_BUFFER, offset, data); - } else { - gl.bufferData(gl.ARRAY_BUFFER, data, glUsage); - } - } - gl.bindBuffer(gl.ARRAY_BUFFER, null); -}; - -prototypeAccessors$1.count.get = function () { - return this._numVertices; -}; - -Object.defineProperties( VertexBuffer.prototype, prototypeAccessors$1 ); - -var _genID = 0; - -function _parseError(out, type, errorLog) { - errorLog.split('\n').forEach(function (msg) { - if (msg.length < 5) { - return; - } - - var parts = /^ERROR\:\s+(\d+)\:(\d+)\:\s*(.*)$/.exec(msg); - if (parts) { - out.push({ - type: type, - fileID: parts[1] | 0, - line: parts[2] | 0, - message: parts[3].trim() - }); - } else if (msg.length > 0) { - out.push({ - type: type, - fileID: -1, - line: 0, - message: msg - }); - } - }); -} - -var Program = function Program(device, options) { - this._device = device; - - // stores gl information: { location, type } - this._attributes = []; - this._uniforms = []; - this._samplers = []; - this._errors = []; - this._linked = false; - this._vertSource = options.vert; - this._fragSource = options.frag; - this._glID = null; - this._id = _genID++; -}; - -var prototypeAccessors$2 = { id: { configurable: true } }; - -prototypeAccessors$2.id.get = function () { - return this._id; -}; - -Program.prototype.link = function link () { - var this$1 = this; - - if (this._linked) { - return; - } - - var gl = this._device._gl; - - var vertShader = _createShader(gl, gl.VERTEX_SHADER, this._vertSource); - var fragShader = _createShader(gl, gl.FRAGMENT_SHADER, this._fragSource); - - var program = gl.createProgram(); - gl.attachShader(program, vertShader); - gl.attachShader(program, fragShader); - gl.linkProgram(program); - - var failed = false; - var errors = this._errors; - - if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) { - _parseError(errors, 'vs', gl.getShaderInfoLog(vertShader)); - failed = true; - } - - if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)) { - _parseError(errors, 'fs', gl.getShaderInfoLog(fragShader)); - failed = true; - } - - gl.deleteShader(vertShader); - gl.deleteShader(fragShader); - - if (failed) { - errors.forEach(function (err) { - console.error(("Failed to compile " + (err.type) + " " + (err.fileID) + " (ln " + (err.line) + "): " + (err.message))); - }); - return; - } - - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - console.error(("Failed to link shader program: " + (gl.getProgramInfoLog(program)))); - failed = true; - } - - if (failed) { - return; - } - - this._glID = program; - - // parse attribute - var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); - for (var i = 0; i < numAttributes; ++i) { - var info = gl.getActiveAttrib(program, i); - var location = gl.getAttribLocation(program, info.name); - - this$1._attributes.push({ - name: info.name, - location: location, - type: info.type, - }); - } - - // parse uniform - var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - for (var i$1 = 0; i$1 < numUniforms; ++i$1) { - var info$1 = gl.getActiveUniform(program, i$1); - var name = info$1.name; - var location$1 = gl.getUniformLocation(program, name); - var isArray = name.substr(name.length - 3) === '[0]'; - if (isArray) { - name = name.substr(0, name.length - 3); - } - - this$1._uniforms.push({ - name: name, - location: location$1, - type: info$1.type, - size: isArray ? info$1.size : undefined, // used when uniform is an array - }); - } - - this._linked = true; -}; - -Program.prototype.destroy = function destroy () { - var gl = this._device._gl; - gl.deleteProgram(this._glID); - - this._linked = false; - this._glID = null; - this._attributes = []; - this._uniforms = []; - this._samplers = []; -}; - -Object.defineProperties( Program.prototype, prototypeAccessors$2 ); - -// ==================== -// internal -// ==================== - -function _createShader(gl, type, src) { - var shader = gl.createShader(type); - gl.shaderSource(shader, src); - gl.compileShader(shader); - - return shader; -} - -var _textureInstanceId = 0; -var Texture = function Texture(device) { - this._device = device; - - this._width = 4; - this._height = 4; - this._hasMipmap = false; - this._compressed = false; - - this._anisotropy = 1; - this._minFilter = enums$1.FILTER_LINEAR; - this._magFilter = enums$1.FILTER_LINEAR; - this._mipFilter = enums$1.FILTER_LINEAR; - this._wrapS = enums$1.WRAP_REPEAT; - this._wrapT = enums$1.WRAP_REPEAT; - // wrapR available in webgl2 - // this._wrapR = enums.WRAP_REPEAT; - this._format = enums$1.TEXTURE_FMT_RGBA8; - - this._target = -1; - - this._id = _textureInstanceId++; -}; - -/** - * @method destroy - */ -Texture.prototype.destroy = function destroy () { - if (this._glID === -1) { - console.error('The texture already destroyed'); - return; - } - - var gl = this._device._gl; - gl.deleteTexture(this._glID); - - this._device._stats.tex -= this.bytes; - this._glID = -1; -}; - -function isPow2$1(v) { - return !(v & (v - 1)) && (!!v); -} - -var Texture2D = (function (Texture$$1) { - function Texture2D(device, options) { - Texture$$1.call(this, device); - - var gl = this._device._gl; - this._target = gl.TEXTURE_2D; - this._glID = gl.createTexture(); - - // always alloc texture in GPU when we create it. - options.images = options.images || [null]; - this.update(options); - } - - if ( Texture$$1 ) Texture2D.__proto__ = Texture$$1; - Texture2D.prototype = Object.create( Texture$$1 && Texture$$1.prototype ); - Texture2D.prototype.constructor = Texture2D; - - /** - * @method update - * @param {Object} options - * @param {Array} options.images - * @param {Boolean} options.mipmap - * @param {Number} options.width - * @param {Number} options.height - * @param {TEXTURE_FMT_*} options.format - * @param {Number} options.anisotropy - * @param {FILTER_*} options.minFilter - * @param {FILTER_*} options.magFilter - * @param {FILTER_*} options.mipFilter - * @param {WRAP_*} options.wrapS - * @param {WRAP_*} options.wrapT - * @param {Boolean} options.flipY - * @param {Boolean} options.premultiplyAlpha - */ - Texture2D.prototype.update = function update (options) { - var gl = this._device._gl; - var genMipmap = this._hasMipmap; - - if (options) { - if (options.width !== undefined) { - this._width = options.width; - } - if (options.height !== undefined) { - this._height = options.height; - } - if (options.anisotropy !== undefined) { - this._anisotropy = options.anisotropy; - } - if (options.minFilter !== undefined) { - this._minFilter = options.minFilter; - } - if (options.magFilter !== undefined) { - this._magFilter = options.magFilter; - } - if (options.mipFilter !== undefined) { - this._mipFilter = options.mipFilter; - } - if (options.wrapS !== undefined) { - this._wrapS = options.wrapS; - } - if (options.wrapT !== undefined) { - this._wrapT = options.wrapT; - } - if (options.format !== undefined) { - this._format = options.format; - this._compressed = ( - this._format >= enums$1.TEXTURE_FMT_RGB_DXT1 && - this._format <= enums$1.TEXTURE_FMT_RGBA_PVRTC_4BPPV1 - ); - } - - // check if generate mipmap - if (options.mipmap !== undefined) { - this._hasMipmap = options.mipmap; - genMipmap = options.mipmap; - } - - if (options.images !== undefined) { - if (options.images.length > 1) { - genMipmap = false; - var maxLength = options.width > options.height ? options.width : options.height; - if (maxLength >> (options.images.length - 1) !== 1) { - console.error('texture-2d mipmap is invalid, should have a 1x1 mipmap.'); - } - } - } - } - - // NOTE: get pot after this._width, this._height has been assigned. - var pot = isPow2$1(this._width) && isPow2$1(this._height); - if (!pot) { - genMipmap = false; - } - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this._glID); - if (options.images !== undefined && options.images.length > 0) { - this._setMipmap(options.images, options.flipY, options.premultiplyAlpha); - } - - this._setTexInfo(); - - if (genMipmap) { - gl.hint(gl.GENERATE_MIPMAP_HINT, gl.NICEST); - gl.generateMipmap(gl.TEXTURE_2D); - } - this._device._restoreTexture(0); - }; - - /** - * @method updateSubImage - * @param {Object} options - * @param {Number} options.x - * @param {Number} options.y - * @param {Number} options.width - * @param {Number} options.height - * @param {Number} options.level - * @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image - * @param {Boolean} options.flipY - * @param {Boolean} options.premultiplyAlpha - */ - Texture2D.prototype.updateSubImage = function updateSubImage (options) { - var gl = this._device._gl; - var glFmt = glTextureFmt(this._format); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this._glID); - this._setSubImage(glFmt, options); - this._device._restoreTexture(0); - }; - - /** - * @method updateImage - * @param {Object} options - * @param {Number} options.width - * @param {Number} options.height - * @param {Number} options.level - * @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image - * @param {Boolean} options.flipY - * @param {Boolean} options.premultiplyAlpha - */ - Texture2D.prototype.updateImage = function updateImage (options) { - var gl = this._device._gl; - var glFmt = glTextureFmt(this._format); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this._glID); - this._setImage(glFmt, options); - this._device._restoreTexture(0); - }; - - Texture2D.prototype._setSubImage = function _setSubImage (glFmt, options) { - var gl = this._device._gl; - var flipY = options.flipY; - var premultiplyAlpha = options.premultiplyAlpha; - var img = options.image; - - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { - if (flipY === undefined) { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - } else { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - } - - if (premultiplyAlpha === undefined) { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); - } - - gl.texSubImage2D(gl.TEXTURE_2D, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); - } else { - if (flipY === undefined) { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - } - - if (premultiplyAlpha === undefined) { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); - } - - if (this._compressed) { - gl.compressedTexSubImage2D(gl.TEXTURE_2D, - options.level, - options.x, - options.y, - options.width, - options.height, - glFmt.format, - img - ); - } else { - gl.texSubImage2D( - gl.TEXTURE_2D, - options.level, - options.x, - options.y, - options.width, - options.height, - glFmt.format, - glFmt.pixelType, - img - ); - } - } - }; - - Texture2D.prototype._setImage = function _setImage (glFmt, options) { - var gl = this._device._gl; - var flipY = options.flipY; - var premultiplyAlpha = options.premultiplyAlpha; - var img = options.image; - - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { - if (flipY === undefined) { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - } else { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - } - - if (premultiplyAlpha === undefined) { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); - } - - gl.texImage2D( - gl.TEXTURE_2D, - options.level, - glFmt.internalFormat, - glFmt.format, - glFmt.pixelType, - img - ); - } else { - if (flipY === undefined) { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - } - - if (premultiplyAlpha === undefined) { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); - } - - if (this._compressed) { - gl.compressedTexImage2D( - gl.TEXTURE_2D, - options.level, - glFmt.internalFormat, - options.width, - options.height, - 0, - img - ); - } else { - gl.texImage2D( - gl.TEXTURE_2D, - options.level, - glFmt.internalFormat, - options.width, - options.height, - 0, - glFmt.format, - glFmt.pixelType, - img - ); - } - } - }; - - Texture2D.prototype._setMipmap = function _setMipmap (images, flipY, premultiplyAlpha) { - var this$1 = this; - - var glFmt = glTextureFmt(this._format); - var options = { - width: this._width, - height: this._height, - flipY: flipY, - premultiplyAlpha: premultiplyAlpha, - level: 0, - image: null - }; - - for (var i = 0; i < images.length; ++i) { - options.level = i; - options.width = this$1._width >> i; - options.height = this$1._height >> i; - options.image = images[i]; - this$1._setImage(glFmt, options); - } - }; - - Texture2D.prototype._setTexInfo = function _setTexInfo () { - var gl = this._device._gl; - var pot = isPow2$1(this._width) && isPow2$1(this._height); - - // WebGL1 doesn't support all wrap modes with NPOT textures - if (!pot && (this._wrapS !== enums$1.WRAP_CLAMP || this._wrapT !== enums$1.WRAP_CLAMP)) { - console.warn('WebGL1 doesn\'t support all wrap modes with NPOT textures'); - this._wrapS = enums$1.WRAP_CLAMP; - this._wrapT = enums$1.WRAP_CLAMP; - } - - var mipFilter = this._hasMipmap ? this._mipFilter : -1; - if (!pot && mipFilter !== -1) { - console.warn('NPOT textures do not support mipmap filter'); - mipFilter = -1; - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, glFilter(gl, this._minFilter, mipFilter)); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, glFilter(gl, this._magFilter, -1)); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._wrapT); - - var ext = this._device.ext('EXT_texture_filter_anisotropic'); - if (ext && ext.TEXTURE_MAX_ANISOTROPY_EXT) { - gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy); - } - }; - - return Texture2D; -}(Texture)); - -var TextureCube = (function (Texture$$1) { - function TextureCube(device, options) { - Texture$$1.call(this, device); - var gl = this._device._gl; - this._target = gl.TEXTURE_CUBE_MAP; - this._glID = gl.createTexture(); - this.update(options); - } - - if ( Texture$$1 ) TextureCube.__proto__ = Texture$$1; - TextureCube.prototype = Object.create( Texture$$1 && Texture$$1.prototype ); - TextureCube.prototype.constructor = TextureCube; - - /** - * @method update - * @param {Object} options - * @param {Array} options.images - * @param {Boolean} options.mipmap - * @param {Number} options.width - * @param {Number} options.height - * @param {TEXTURE_FMT_*} options.format - * @param {Number} options.anisotropy - * @param {FILTER_*} options.minFilter - * @param {FILTER_*} options.magFilter - * @param {FILTER_*} options.mipFilter - * @param {WRAP_*} options.wrapS - * @param {WRAP_*} options.wrapT - * @param {WRAP_*} options.wrapR - * @param {Boolean} options.flipY - * @param {Boolean} options.premultiplyAlpha - */ - TextureCube.prototype.update = function update (options) { - var gl = this._device._gl; - var genMipmap = this._hasMipmap; - - if (options) { - if (options.width !== undefined) { - this._width = options.width; - } - if (options.height !== undefined) { - this._height = options.height; - } - if (options.anisotropy !== undefined) { - this._anisotropy = options.anisotropy; - } - if (options.minFilter !== undefined) { - this._minFilter = options.minFilter; - } - if (options.magFilter !== undefined) { - this._magFilter = options.magFilter; - } - if (options.mipFilter !== undefined) { - this._mipFilter = options.mipFilter; - } - if (options.wrapS !== undefined) { - this._wrapS = options.wrapS; - } - if (options.wrapT !== undefined) { - this._wrapT = options.wrapT; - } - // wrapR available in webgl2 - // if (options.wrapR !== undefined) { - // this._wrapR = options.wrapR; - // } - if (options.format !== undefined) { - this._format = options.format; - this._compressed = ( - this._format >= enums$1.TEXTURE_FMT_RGB_DXT1 && - this._format <= enums$1.TEXTURE_FMT_RGBA_PVRTC_4BPPV1 - ); - } - - // check if generate mipmap - if (options.mipmap !== undefined) { - this._hasMipmap = options.mipmap; - genMipmap = options.mipmap; - } - - if (options.images !== undefined) { - if (options.images.length > 1) { - genMipmap = false; - if (options.width !== options.height) { - console.warn('texture-cube width and height should be identical.'); - } - if (options.width >> (options.images.length - 1) !== 1) { - console.error('texture-cube mipmap is invalid. please set mipmap as 1x1, 2x2, 4x4 ... nxn'); - } - } - } - } - - // NOTE: get pot after this._width, this._height has been assigned. - var pot = isPow2$1(this._width) && isPow2$1(this._height); - if (!pot) { - genMipmap = false; - } - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID); - if (options.images !== undefined && options.images.length > 0) { - this._setMipmap(options.images, options.flipY, options.premultiplyAlpha); - } - - this._setTexInfo(); - - if (genMipmap) { - gl.hint(gl.GENERATE_MIPMAP_HINT, gl.NICEST); - gl.generateMipmap(gl.TEXTURE_CUBE_MAP); - } - this._device._restoreTexture(0); - }; - - /** - * @method updateSubImage - * @param {Object} options - * @param {Number} options.x - * @param {Number} options.y - * @param {Number} options.width - * @param {Number} options.height - * @param {Number} options.level - * @param {Number} options.faceIndex - * @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image - * @param {Boolean} options.flipY - * @param {Boolean} options.premultiplyAlpha - */ - TextureCube.prototype.updateSubImage = function updateSubImage (options) { - var gl = this._device._gl; - var glFmt = glTextureFmt(this._format); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID); - this._setSubImage(glFmt, options); - - this._device._restoreTexture(0); - }; - - /** - * @method updateImage - * @param {Object} options - * @param {Number} options.width - * @param {Number} options.height - * @param {Number} options.level - * @param {Number} options.faceIndex - * @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image - * @param {Boolean} options.flipY - * @param {Boolean} options.premultiplyAlpha - */ - TextureCube.prototype.updateImage = function updateImage (options) { - var gl = this._device._gl; - var glFmt = glTextureFmt(this._format); - - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID); - this._setImage(glFmt, options); - this._device._restoreTexture(0); - }; - - TextureCube.prototype._setSubImage = function _setSubImage (glFmt, options) { - var gl = this._device._gl; - var flipY = options.flipY; - var premultiplyAlpha = options.premultiplyAlpha; - var faceIndex = options.faceIndex; - var img = options.image; - - if (flipY === undefined) { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - } - - if (premultiplyAlpha === undefined) { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); - } - - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { - gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); - } else { - if (this._compressed) { - gl.compressedTexSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, - options.level, - options.x, - options.y, - options.width, - options.height, - glFmt.format, - img - ); - } else { - gl.texSubImage2D( - gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, - options.level, - options.x, - options.y, - options.width, - options.height, - glFmt.format, - glFmt.pixelType, - img - ); - } - } - }; - - TextureCube.prototype._setImage = function _setImage (glFmt, options) { - var gl = this._device._gl; - var flipY = options.flipY; - var premultiplyAlpha = options.premultiplyAlpha; - var faceIndex = options.faceIndex; - var img = options.image; - - if (flipY === undefined) { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); - } - - if (premultiplyAlpha === undefined) { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); - } else { - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); - } - if ( - img instanceof HTMLCanvasElement || - img instanceof HTMLImageElement || - img instanceof HTMLVideoElement - ) { - gl.texImage2D( - gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, - options.level, - glFmt.internalFormat, - glFmt.format, - glFmt.pixelType, - img - ); - } else { - if (this._compressed) { - gl.compressedTexImage2D( - gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, - options.level, - glFmt.internalFormat, - options.width, - options.height, - 0, - img - ); - } else { - gl.texImage2D( - gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, - options.level, - glFmt.internalFormat, - options.width, - options.height, - 0, - glFmt.format, - glFmt.pixelType, - img - ); - } - } - }; - - // levelImages = [imagePosX, imageNegX, imagePosY, imageNegY, imagePosZ, imageNegz] - // images = [levelImages0, levelImages1, ...] - TextureCube.prototype._setMipmap = function _setMipmap (images, flipY, premultiplyAlpha) { - var this$1 = this; - - var glFmt = glTextureFmt(this._format); - var options = { - width: this._width, - height: this._height, - faceIndex: 0, - flipY: flipY, - premultiplyAlpha: premultiplyAlpha, - level: 0, - image: null - }; - - for (var i = 0; i < images.length; ++i) { - var levelImages = images[i]; - options.level = i; - options.width = this$1._width >> i; - options.height = this$1._height >> i; - - for (var face = 0; face < 6; ++face) { - options.faceIndex = face; - options.image = levelImages[face]; - this$1._setImage(glFmt, options); - } - } - }; - - TextureCube.prototype._setTexInfo = function _setTexInfo () { - var gl = this._device._gl; - var pot = isPow2$1(this._width) && isPow2$1(this._height); - - // WebGL1 doesn't support all wrap modes with NPOT textures - if (!pot && (this._wrapS !== enums$1.WRAP_CLAMP || this._wrapT !== enums$1.WRAP_CLAMP)) { - console.warn('WebGL1 doesn\'t support all wrap modes with NPOT textures'); - this._wrapS = enums$1.WRAP_CLAMP; - this._wrapT = enums$1.WRAP_CLAMP; - } - - var mipFilter = this._hasMipmap ? this._mipFilter : -1; - if (!pot && mipFilter !== -1) { - console.warn('NPOT textures do not support mipmap filter'); - mipFilter = -1; - } - - gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, glFilter(gl, this._minFilter, mipFilter)); - gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, glFilter(gl, this._magFilter, -1)); - gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, this._wrapS); - gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, this._wrapT); - // wrapR available in webgl2 - // gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, this._wrapR); - - var ext = this._device.ext('EXT_texture_filter_anisotropic'); - if (ext && ext.TEXTURE_MAX_ANISOTROPY_EXT) { - gl.texParameteri(gl.TEXTURE_CUBE_MAP, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy); - } - }; - - return TextureCube; -}(Texture)); - -var RenderBuffer = function RenderBuffer(device, format, width, height) { - this._device = device; - this._format = format; - this._width = width; - this._height = height; - - var gl = device._gl; - this._glID = gl.createRenderbuffer(); - - gl.bindRenderbuffer(gl.RENDERBUFFER, this._glID); - gl.renderbufferStorage(gl.RENDERBUFFER, format, width, height); - gl.bindRenderbuffer(gl.RENDERBUFFER, null); -}; - -/** - * @method destroy - */ -RenderBuffer.prototype.destroy = function destroy () { - if (this._glID === null) { - console.error('The render-buffer already destroyed'); - return; - } - - var gl = this._device._gl; - - gl.bindRenderbuffer(gl.RENDERBUFFER, null); - gl.deleteRenderbuffer(this._glID); - - this._glID = null; -}; - -var FrameBuffer = function FrameBuffer(device, width, height, options) { - this._device = device; - this._width = width; - this._height = height; - - this._colors = options.colors || []; - this._depth = options.depth || null; - this._stencil = options.stencil || null; - this._depthStencil = options.depthStencil || null; - - this._glID = device._gl.createFramebuffer(); -}; - -/** - * @method destroy - */ -FrameBuffer.prototype.destroy = function destroy () { - if (this._glID === null) { - console.error('The frame-buffer already destroyed'); - return; - } - - var gl = this._device._gl; - - gl.deleteFramebuffer(this._glID); - - this._glID = null; -}; - -var _default = { - // blend - blend: false, - blendSep: false, - blendColor: 0xffffffff, - blendEq: enums$1.BLEND_FUNC_ADD, - blendAlphaEq: enums$1.BLEND_FUNC_ADD, - blendSrc: enums$1.BLEND_ONE, - blendDst: enums$1.BLEND_ZERO, - blendSrcAlpha: enums$1.BLEND_ONE, - blendDstAlpha: enums$1.BLEND_ZERO, - - // depth - depthTest: false, - depthWrite: false, - depthFunc: enums$1.DS_FUNC_LESS, - - // stencil - stencilTest: false, - stencilSep: false, - stencilFuncFront: enums$1.DS_FUNC_ALWAYS, - stencilRefFront: 0, - stencilMaskFront: 0xff, - stencilFailOpFront: enums$1.STENCIL_OP_KEEP, - stencilZFailOpFront: enums$1.STENCIL_OP_KEEP, - stencilZPassOpFront: enums$1.STENCIL_OP_KEEP, - stencilWriteMaskFront: 0xff, - stencilFuncBack: enums$1.DS_FUNC_ALWAYS, - stencilRefBack: 0, - stencilMaskBack: 0xff, - stencilFailOpBack: enums$1.STENCIL_OP_KEEP, - stencilZFailOpBack: enums$1.STENCIL_OP_KEEP, - stencilZPassOpBack: enums$1.STENCIL_OP_KEEP, - stencilWriteMaskBack: 0xff, - - // cull-mode - cullMode: enums$1.CULL_BACK, - - // primitive-type - primitiveType: enums$1.PT_TRIANGLES, - - // bindings - maxStream: -1, - vertexBuffers: [], - vertexBufferOffsets: [], - indexBuffer: null, - maxTextureSlot: -1, - textureUnits: [], - program: null, -}; - -var State = function State(device) { - // bindings - this.vertexBuffers = new Array(device._caps.maxVertexStreams); - this.vertexBufferOffsets = new Array(device._caps.maxVertexStreams); - this.textureUnits = new Array(device._caps.maxTextureUnits); - - this.set(_default); -}; - -State.initDefault = function initDefault (device) { - _default.vertexBuffers = new Array(device._caps.maxVertexStreams); - _default.vertexBufferOffsets = new Array(device._caps.maxVertexStreams); - _default.textureUnits = new Array(device._caps.maxTextureUnits); -}; - -State.prototype.reset = function reset () { - this.set(_default); -}; - -State.prototype.set = function set (cpy) { - var this$1 = this; - - // blending - this.blend = cpy.blend; - this.blendSep = cpy.blendSep; - this.blendColor = cpy.blendColor; - this.blendEq = cpy.blendEq; - this.blendAlphaEq = cpy.blendAlphaEq; - this.blendSrc = cpy.blendSrc; - this.blendDst = cpy.blendDst; - this.blendSrcAlpha = cpy.blendSrcAlpha; - this.blendDstAlpha = cpy.blendDstAlpha; - - // depth - this.depthTest = cpy.depthTest; - this.depthWrite = cpy.depthWrite; - this.depthFunc = cpy.depthFunc; - - // stencil - this.stencilTest = cpy.stencilTest; - this.stencilSep = cpy.stencilSep; - this.stencilFuncFront = cpy.stencilFuncFront; - this.stencilRefFront = cpy.stencilRefFront; - this.stencilMaskFront = cpy.stencilMaskFront; - this.stencilFailOpFront = cpy.stencilFailOpFront; - this.stencilZFailOpFront = cpy.stencilZFailOpFront; - this.stencilZPassOpFront = cpy.stencilZPassOpFront; - this.stencilWriteMaskFront = cpy.stencilWriteMaskFront; - this.stencilFuncBack = cpy.stencilFuncBack; - this.stencilRefBack = cpy.stencilRefBack; - this.stencilMaskBack = cpy.stencilMaskBack; - this.stencilFailOpBack = cpy.stencilFailOpBack; - this.stencilZFailOpBack = cpy.stencilZFailOpBack; - this.stencilZPassOpBack = cpy.stencilZPassOpBack; - this.stencilWriteMaskBack = cpy.stencilWriteMaskBack; - - // cull-mode - this.cullMode = cpy.cullMode; - - // primitive-type - this.primitiveType = cpy.primitiveType; - - // buffer bindings - this.maxStream = cpy.maxStream; - for (var i = 0; i < cpy.vertexBuffers.length; ++i) { - this$1.vertexBuffers[i] = cpy.vertexBuffers[i]; - } - for (var i$1 = 0; i$1 < cpy.vertexBufferOffsets.length; ++i$1) { - this$1.vertexBufferOffsets[i$1] = cpy.vertexBufferOffsets[i$1]; - } - this.indexBuffer = cpy.indexBuffer; - - // texture bindings - this.maxTextureSlot = cpy.maxTextureSlot; - for (var i$2 = 0; i$2 < cpy.textureUnits.length; ++i$2) { - this$1.textureUnits[i$2] = cpy.textureUnits[i$2]; - } - - this.program = cpy.program; -}; - -var GL_INT = 5124; -var GL_FLOAT$1 = 5126; -var GL_FLOAT_VEC2 = 35664; -var GL_FLOAT_VEC3 = 35665; -var GL_FLOAT_VEC4 = 35666; -var GL_INT_VEC2 = 35667; -var GL_INT_VEC3 = 35668; -var GL_INT_VEC4 = 35669; -var GL_BOOL = 35670; -var GL_BOOL_VEC2 = 35671; -var GL_BOOL_VEC3 = 35672; -var GL_BOOL_VEC4 = 35673; -var GL_FLOAT_MAT2 = 35674; -var GL_FLOAT_MAT3 = 35675; -var GL_FLOAT_MAT4 = 35676; -var GL_SAMPLER_2D = 35678; -var GL_SAMPLER_CUBE = 35680; - -/** - * _type2uniformCommit - */ -var _type2uniformCommit = {}; -_type2uniformCommit[GL_INT] = function (gl, id, value) { - gl.uniform1i(id, value); - }; -_type2uniformCommit[GL_FLOAT$1] = function (gl, id, value) { - gl.uniform1f(id, value); - }; -_type2uniformCommit[GL_FLOAT_VEC2] = function (gl, id, value) { - gl.uniform2fv(id, value); - }; -_type2uniformCommit[GL_FLOAT_VEC3] = function (gl, id, value) { - gl.uniform3fv(id, value); - }; -_type2uniformCommit[GL_FLOAT_VEC4] = function (gl, id, value) { - gl.uniform4fv(id, value); - }; -_type2uniformCommit[GL_INT_VEC2] = function (gl, id, value) { - gl.uniform2iv(id, value); - }; -_type2uniformCommit[GL_INT_VEC3] = function (gl, id, value) { - gl.uniform3iv(id, value); - }; -_type2uniformCommit[GL_INT_VEC4] = function (gl, id, value) { - gl.uniform4iv(id, value); - }; -_type2uniformCommit[GL_BOOL] = function (gl, id, value) { - gl.uniform1i(id, value); - }; -_type2uniformCommit[GL_BOOL_VEC2] = function (gl, id, value) { - gl.uniform2iv(id, value); - }; -_type2uniformCommit[GL_BOOL_VEC3] = function (gl, id, value) { - gl.uniform3iv(id, value); - }; -_type2uniformCommit[GL_BOOL_VEC4] = function (gl, id, value) { - gl.uniform4iv(id, value); - }; -_type2uniformCommit[GL_FLOAT_MAT2] = function (gl, id, value) { - gl.uniformMatrix2fv(id, false, value); - }; -_type2uniformCommit[GL_FLOAT_MAT3] = function (gl, id, value) { - gl.uniformMatrix3fv(id, false, value); - }; -_type2uniformCommit[GL_FLOAT_MAT4] = function (gl, id, value) { - gl.uniformMatrix4fv(id, false, value); - }; -_type2uniformCommit[GL_SAMPLER_2D] = function (gl, id, value) { - gl.uniform1i(id, value); - }; -_type2uniformCommit[GL_SAMPLER_CUBE] = function (gl, id, value) { - gl.uniform1i(id, value); - }; - -/** - * _type2uniformArrayCommit - */ -var _type2uniformArrayCommit = {}; -_type2uniformArrayCommit[GL_INT] = function (gl, id, value) { - gl.uniform1iv(id, value); - }; -_type2uniformArrayCommit[GL_FLOAT$1] = function (gl, id, value) { - gl.uniform1fv(id, value); - }; -_type2uniformArrayCommit[GL_FLOAT_VEC2] = function (gl, id, value) { - gl.uniform2fv(id, value); - }; -_type2uniformArrayCommit[GL_FLOAT_VEC3] = function (gl, id, value) { - gl.uniform3fv(id, value); - }; -_type2uniformArrayCommit[GL_FLOAT_VEC4] = function (gl, id, value) { - gl.uniform4fv(id, value); - }; -_type2uniformArrayCommit[GL_INT_VEC2] = function (gl, id, value) { - gl.uniform2iv(id, value); - }; -_type2uniformArrayCommit[GL_INT_VEC3] = function (gl, id, value) { - gl.uniform3iv(id, value); - }; -_type2uniformArrayCommit[GL_INT_VEC4] = function (gl, id, value) { - gl.uniform4iv(id, value); - }; -_type2uniformArrayCommit[GL_BOOL] = function (gl, id, value) { - gl.uniform1iv(id, value); - }; -_type2uniformArrayCommit[GL_BOOL_VEC2] = function (gl, id, value) { - gl.uniform2iv(id, value); - }; -_type2uniformArrayCommit[GL_BOOL_VEC3] = function (gl, id, value) { - gl.uniform3iv(id, value); - }; -_type2uniformArrayCommit[GL_BOOL_VEC4] = function (gl, id, value) { - gl.uniform4iv(id, value); - }; -_type2uniformArrayCommit[GL_FLOAT_MAT2] = function (gl, id, value) { - gl.uniformMatrix2fv(id, false, value); - }; -_type2uniformArrayCommit[GL_FLOAT_MAT3] = function (gl, id, value) { - gl.uniformMatrix3fv(id, false, value); - }; -_type2uniformArrayCommit[GL_FLOAT_MAT4] = function (gl, id, value) { - gl.uniformMatrix4fv(id, false, value); - }; -_type2uniformArrayCommit[GL_SAMPLER_2D] = function (gl, id, value) { - gl.uniform1iv(id, value); - }; -_type2uniformArrayCommit[GL_SAMPLER_CUBE] = function (gl, id, value) { - gl.uniform1iv(id, value); - }; - -/** - * _commitBlendStates - */ -function _commitBlendStates(gl, cur, next) { - // enable/disable blend - if (cur.blend !== next.blend) { - if (!next.blend) { - gl.disable(gl.BLEND); - return; - } - - gl.enable(gl.BLEND); - - if ( - next.blendSrc === enums$1.BLEND_CONSTANT_COLOR || - next.blendSrc === enums$1.BLEND_ONE_MINUS_CONSTANT_COLOR || - next.blendDst === enums$1.BLEND_CONSTANT_COLOR || - next.blendDst === enums$1.BLEND_ONE_MINUS_CONSTANT_COLOR - ) { - gl.blendColor( - (next.blendColor >> 24) / 255, - (next.blendColor >> 16 & 0xff) / 255, - (next.blendColor >> 8 & 0xff) / 255, - (next.blendColor & 0xff) / 255 - ); - } - - if (next.blendSep) { - gl.blendFuncSeparate(next.blendSrc, next.blendDst, next.blendSrcAlpha, next.blendDstAlpha); - gl.blendEquationSeparate(next.blendEq, next.blendAlphaEq); - } else { - gl.blendFunc(next.blendSrc, next.blendDst); - gl.blendEquation(next.blendEq); - } - - return; - } - - // nothing to update - if (next.blend === false) { - return; - } - - // blend-color - if (cur.blendColor !== next.blendColor) { - gl.blendColor( - (next.blendColor >> 24) / 255, - (next.blendColor >> 16 & 0xff) / 255, - (next.blendColor >> 8 & 0xff) / 255, - (next.blendColor & 0xff) / 255 - ); - } - - // separate diff, reset all - if (cur.blendSep !== next.blendSep) { - if (next.blendSep) { - gl.blendFuncSeparate(next.blendSrc, next.blendDst, next.blendSrcAlpha, next.blendDstAlpha); - gl.blendEquationSeparate(next.blendEq, next.blendAlphaEq); - } else { - gl.blendFunc(next.blendSrc, next.blendDst); - gl.blendEquation(next.blendEq); - } - - return; - } - - if (next.blendSep) { - // blend-func-separate - if ( - cur.blendSrc !== next.blendSrc || - cur.blendDst !== next.blendDst || - cur.blendSrcAlpha !== next.blendSrcAlpha || - cur.blendDstAlpha !== next.blendDstAlpha - ) { - gl.blendFuncSeparate(next.blendSrc, next.blendDst, next.blendSrcAlpha, next.blendDstAlpha); - } - - // blend-equation-separate - if ( - cur.blendEq !== next.blendEq || - cur.blendAlphaEq !== next.blendAlphaEq - ) { - gl.blendEquationSeparate(next.blendEq, next.blendAlphaEq); - } - } else { - // blend-func - if ( - cur.blendSrc !== next.blendSrc || - cur.blendDst !== next.blendDst - ) { - gl.blendFunc(next.blendSrc, next.blendDst); - } - - // blend-equation - if (cur.blendEq !== next.blendEq) { - gl.blendEquation(next.blendEq); - } - } -} - -/** - * _commitDepthStates - */ -function _commitDepthStates(gl, cur, next) { - // enable/disable depth-test - if (cur.depthTest !== next.depthTest) { - if (!next.depthTest) { - gl.disable(gl.DEPTH_TEST); - return; - } - - gl.enable(gl.DEPTH_TEST); - gl.depthFunc(next.depthFunc); - gl.depthMask(next.depthWrite); - - return; - } - - // commit depth-write - if (cur.depthWrite !== next.depthWrite) { - gl.depthMask(next.depthWrite); - } - - // check if depth-write enabled - if (next.depthTest === false) { - if (next.depthWrite) { - next.depthTest = true; - next.depthFunc = enums$1.DS_FUNC_ALWAYS; - - gl.enable(gl.DEPTH_TEST); - gl.depthFunc(next.depthFunc); - } - - return; - } - - // depth-func - if (cur.depthFunc !== next.depthFunc) { - gl.depthFunc(next.depthFunc); - } -} - -/** - * _commitStencilStates - */ -function _commitStencilStates(gl, cur, next) { - if (next.stencilTest !== cur.stencilTest) { - if (!next.stencilTest) { - gl.disable(gl.STENCIL_TEST); - return; - } - - gl.enable(gl.STENCIL_TEST); - - if (next.stencilSep) { - gl.stencilFuncSeparate(gl.FRONT, next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); - gl.stencilMaskSeparate(gl.FRONT, next.stencilWriteMaskFront); - gl.stencilOpSeparate(gl.FRONT, next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); - gl.stencilFuncSeparate(gl.BACK, next.stencilFuncBack, next.stencilRefBack, next.stencilMaskBack); - gl.stencilMaskSeparate(gl.BACK, next.stencilWriteMaskBack); - gl.stencilOpSeparate(gl.BACK, next.stencilFailOpBack, next.stencilZFailOpBack, next.stencilZPassOpBack); - } else { - gl.stencilFunc(next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); - gl.stencilMask(next.stencilWriteMaskFront); - gl.stencilOp(next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); - } - - return; - } - - // fast return - if (!next.stencilTest) { - return; - } - - if (cur.stencilSep !== next.stencilSep) { - if (next.stencilSep) { - gl.stencilFuncSeparate(gl.FRONT, next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); - gl.stencilMaskSeparate(gl.FRONT, next.stencilWriteMaskFront); - gl.stencilOpSeparate(gl.FRONT, next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); - gl.stencilFuncSeparate(gl.BACK, next.stencilFuncBack, next.stencilRefBack, next.stencilMaskBack); - gl.stencilMaskSeparate(gl.BACK, next.stencilWriteMaskBack); - gl.stencilOpSeparate(gl.BACK, next.stencilFailOpBack, next.stencilZFailOpBack, next.stencilZPassOpBack); - } else { - gl.stencilFunc(next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); - gl.stencilMask(next.stencilWriteMaskFront); - gl.stencilOp(next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); - } - return; - } - - if (next.stencilSep) { - // front - if ( - cur.stencilFuncFront !== next.stencilFuncFront || - cur.stencilRefFront !== next.stencilRefFront || - cur.stencilMaskFront !== next.stencilMaskFront - ) { - gl.stencilFuncSeparate(gl.FRONT, next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); - } - if (cur.stencilWriteMaskFront !== next.stencilWriteMaskFront) { - gl.stencilMaskSeparate(gl.FRONT, next.stencilWriteMaskFront); - } - if ( - cur.stencilFailOpFront !== next.stencilFailOpFront || - cur.stencilZFailOpFront !== next.stencilZFailOpFront || - cur.stencilZPassOpFront !== next.stencilZPassOpFront - ) { - gl.stencilOpSeparate(gl.FRONT, next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); - } - - // back - if ( - cur.stencilFuncBack !== next.stencilFuncBack || - cur.stencilRefBack !== next.stencilRefBack || - cur.stencilMaskBack !== next.stencilMaskBack - ) { - gl.stencilFuncSeparate(gl.BACK, next.stencilFuncBack, next.stencilRefBack, next.stencilMaskBack); - } - if (cur.stencilWriteMaskBack !== next.stencilWriteMaskBack) { - gl.stencilMaskSeparate(gl.BACK, next.stencilWriteMaskBack); - } - if ( - cur.stencilFailOpBack !== next.stencilFailOpBack || - cur.stencilZFailOpBack !== next.stencilZFailOpBack || - cur.stencilZPassOpBack !== next.stencilZPassOpBack - ) { - gl.stencilOpSeparate(gl.BACK, next.stencilFailOpBack, next.stencilZFailOpBack, next.stencilZPassOpBack); - } - } else { - if ( - cur.stencilFuncFront !== next.stencilFuncFront || - cur.stencilRefFront !== next.stencilRefFront || - cur.stencilMaskFront !== next.stencilMaskFront - ) { - gl.stencilFunc(next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); - } - if (cur.stencilWriteMaskFront !== next.stencilWriteMaskFront) { - gl.stencilMask(next.stencilWriteMaskFront); - } - if ( - cur.stencilFailOpFront !== next.stencilFailOpFront || - cur.stencilZFailOpFront !== next.stencilZFailOpFront || - cur.stencilZPassOpFront !== next.stencilZPassOpFront - ) { - gl.stencilOp(next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); - } - } - -} - -/** - * _commitCullMode - */ -function _commitCullMode(gl, cur, next) { - if (cur.cullMode === next.cullMode) { - return; - } - - if (next.cullMode === enums$1.CULL_NONE) { - gl.disable(gl.CULL_FACE); - return; - } - - gl.enable(gl.CULL_FACE); - gl.cullFace(next.cullMode); -} - -/** - * _commitVertexBuffers - */ -function _commitVertexBuffers(device, gl, cur, next) { - var attrsDirty = false; - - // nothing changed for vertex buffer - if (next.maxStream === -1) { - console.warn('VertexBuffer not assigned, please call setVertexBuffer before every draw.'); - return; - } - - if (cur.maxStream !== next.maxStream) { - attrsDirty = true; - } else if (cur.program !== next.program) { - attrsDirty = true; - } else { - for (var i = 0; i < next.maxStream + 1; ++i) { - if ( - cur.vertexBuffers[i] !== next.vertexBuffers[i] || - cur.vertexBufferOffsets[i] !== next.vertexBufferOffsets[i] - ) { - attrsDirty = true; - break; - } - } - } - - if (attrsDirty) { - for (var i$1 = 0; i$1 < device._caps.maxVertexAttribs; ++i$1) { - device._newAttributes[i$1] = 0; - } - - for (var i$2 = 0; i$2 < next.maxStream + 1; ++i$2) { - var vb = next.vertexBuffers[i$2]; - var vbOffset = next.vertexBufferOffsets[i$2]; - if (!vb) { - continue; - } - - gl.bindBuffer(gl.ARRAY_BUFFER, vb._glID); - - for (var j = 0; j < next.program._attributes.length; ++j) { - var attr = next.program._attributes[j]; - - var el = vb._format.element(attr.name); - if (!el) { - console.warn(("Can not find vertex attribute: " + (attr.name))); - continue; - } - - if (device._enabledAttributes[attr.location] === 0) { - gl.enableVertexAttribArray(attr.location); - device._enabledAttributes[attr.location] = 1; - } - device._newAttributes[attr.location] = 1; - - gl.vertexAttribPointer( - attr.location, - el.num, - el.type, - el.normalize, - el.stride, - el.offset + vbOffset * el.stride - ); - } - } - - // disable unused attributes - for (var i$3 = 0; i$3 < device._caps.maxVertexAttribs; ++i$3) { - if (device._enabledAttributes[i$3] !== device._newAttributes[i$3]) { - gl.disableVertexAttribArray(i$3); - device._enabledAttributes[i$3] = 0; - } - } - } -} - -/** - * _commitTextures - */ -function _commitTextures(gl, cur, next) { - for (var i = 0; i < next.maxTextureSlot + 1; ++i) { - if (cur.textureUnits[i] !== next.textureUnits[i]) { - var texture = next.textureUnits[i]; - if (texture && texture._glID !== -1) { - gl.activeTexture(gl.TEXTURE0 + i); - gl.bindTexture(texture._target, texture._glID); - } - } - } -} - -/** - * _attach - */ -function _attach(gl, location, attachment, face) { - if ( face === void 0 ) face = 0; - - if (attachment instanceof Texture2D) { - gl.framebufferTexture2D( - gl.FRAMEBUFFER, - location, - gl.TEXTURE_2D, - attachment._glID, - 0 - ); - } else if (attachment instanceof TextureCube) { - gl.framebufferTexture2D( - gl.FRAMEBUFFER, - location, - gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, - attachment._glID, - 0 - ); - } else { - gl.framebufferRenderbuffer( - gl.FRAMEBUFFER, - location, - gl.RENDERBUFFER, - attachment._glID - ); - } -} - -var Device = function Device(canvasEL, opts) { - var this$1 = this; - - var gl; - - // default options - opts = opts || {}; - if (opts.alpha === undefined) { - opts.alpha = false; - } - if (opts.stencil === undefined) { - opts.stencil = true; - } - if (opts.depth === undefined) { - opts.depth = true; - } - if (opts.antialias === undefined) { - opts.antialias = false; - } - // NOTE: it is said the performance improved in mobile device with this flag off. - if (opts.preserveDrawingBuffer === undefined) { - opts.preserveDrawingBuffer = false; - } - - try { - gl = canvasEL.getContext('webgl', opts) - || canvasEL.getContext('experimental-webgl', opts) - || canvasEL.getContext('webkit-3d', opts) - || canvasEL.getContext('moz-webgl', opts); - } catch (err) { - console.error(err); - return; - } - - // statics - this._gl = gl; - this._extensions = {}; - this._caps = {}; // capability - this._stats = { - texture: 0, - vb: 0, - ib: 0, - drawcalls: 0, - }; - - this._initExtensions([ - 'EXT_texture_filter_anisotropic', - 'EXT_shader_texture_lod', - 'OES_standard_derivatives', - 'OES_texture_float', - 'OES_texture_float_linear', - 'OES_texture_half_float', - 'OES_texture_half_float_linear', - 'OES_vertex_array_object', - 'WEBGL_compressed_texture_atc', - 'WEBGL_compressed_texture_etc1', - 'WEBGL_compressed_texture_pvrtc', - 'WEBGL_compressed_texture_s3tc', - 'WEBGL_depth_texture', - 'WEBGL_draw_buffers' ]); - this._initCaps(); - this._initStates(); - - // runtime - State.initDefault(this); - this._current = new State(this); - this._next = new State(this); - this._uniforms = {}; // name: { value, num, dirty } - this._vx = this._vy = this._vw = this._vh = 0; - this._sx = this._sy = this._sw = this._sh = 0; - this._framebuffer = null; - - // - this._enabledAttributes = new Array(this._caps.maxVertexAttribs); - this._newAttributes = new Array(this._caps.maxVertexAttribs); - - for (var i = 0; i < this._caps.maxVertexAttribs; ++i) { - this$1._enabledAttributes[i] = 0; - this$1._newAttributes[i] = 0; - } -}; - -Device.prototype._initExtensions = function _initExtensions (extensions) { - var this$1 = this; - - var gl = this._gl; - - for (var i = 0; i < extensions.length; ++i) { - var name = extensions[i]; - - var vendorPrefixes = ["", "WEBKIT_", "MOZ_"]; - for (var j = 0; j < vendorPrefixes.length; j++) { - try { - var ext = gl.getExtension(vendorPrefixes[j] + name); - if (ext) { - this$1._extensions[name] = ext; - } - } catch (e) { - console.error(e); - } - } - } -}; - -Device.prototype._initCaps = function _initCaps () { - var gl = this._gl; - var extDrawBuffers = this.ext('WEBGL_draw_buffers'); - - this._caps.maxVertexStreams = 4; - this._caps.maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS); - this._caps.maxFragUniforms = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS); - this._caps.maxTextureUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); - this._caps.maxVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); - - this._caps.maxDrawBuffers = extDrawBuffers ? gl.getParameter(extDrawBuffers.MAX_DRAW_BUFFERS_WEBGL) : 1; - this._caps.maxColorAttachments = extDrawBuffers ? gl.getParameter(extDrawBuffers.MAX_COLOR_ATTACHMENTS_WEBGL) : 1; -}; - -Device.prototype._initStates = function _initStates () { - var gl = this._gl; - - // gl.frontFace(gl.CCW); - gl.disable(gl.BLEND); - gl.blendFunc(gl.ONE, gl.ZERO); - gl.blendEquation(gl.FUNC_ADD); - gl.blendColor(1,1,1,1); - - gl.colorMask(true, true, true, true); - - gl.enable(gl.CULL_FACE); - gl.cullFace(gl.BACK); - - gl.disable(gl.DEPTH_TEST); - gl.depthFunc(gl.LESS); - gl.depthMask(false); - gl.disable(gl.POLYGON_OFFSET_FILL); - gl.depthRange(0,1); - - gl.disable(gl.STENCIL_TEST); - gl.stencilFunc(gl.ALWAYS, 0, 0xFF); - gl.stencilMask(0xFF); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); - - // TODO: - // this.setAlphaToCoverage(false); - // this.setTransformFeedbackBuffer(null); - // this.setRaster(true); - // this.setDepthBias(false); - - gl.clearDepth(1); - gl.clearColor(0, 0, 0, 0); - gl.clearStencil(0); - - gl.disable(gl.SCISSOR_TEST); -}; - -Device.prototype._restoreTexture = function _restoreTexture (unit) { - var gl = this._gl; - - var texture = this._current.textureUnits[unit]; - if (texture && texture._glID !== -1) { - gl.bindTexture(texture._target, texture._glID); - } else { - gl.bindTexture(gl.TEXTURE_2D, null); - } -}; - -Device.prototype._restoreIndexBuffer = function _restoreIndexBuffer () { - var gl = this._gl; - - var ib = this._current.indexBuffer; - if (ib && ib._glID !== -1) { - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ib._glID); - } - else { - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - } -}; - -/** - * @method ext - * @param {string} name - */ -Device.prototype.ext = function ext (name) { - return this._extensions[name]; -}; - -// =============================== -// Immediate Settings -// =============================== - -/** - * @method setFrameBuffer - * @param {FrameBuffer} fb - null means use the backbuffer - */ -Device.prototype.setFrameBuffer = function setFrameBuffer (fb) { - var this$1 = this; - - if (this._framebuffer === fb) { - return; - } - - this._framebuffer = fb; - var gl = this._gl; - - if (fb === null) { - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - return; - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, fb._glID); - - var numColors = this._framebuffer._colors.length; - for (var i = 0; i < numColors; ++i) { - var colorBuffer = this$1._framebuffer._colors[i]; - _attach(gl, gl.COLOR_ATTACHMENT0 + i, colorBuffer); - - // TODO: what about cubemap face??? should be the target parameter for colorBuffer - } - for (var i$1 = numColors; i$1 < this._caps.maxColorAttachments; ++i$1) { - gl.framebufferTexture2D( - gl.FRAMEBUFFER, - gl.COLOR_ATTACHMENT0 + i$1, - gl.TEXTURE_2D, - null, - 0 - ); - } - - if (this._framebuffer._depth) { - _attach(gl, gl.DEPTH_ATTACHMENT, this._framebuffer._depth); - } - - if (this._framebuffer._stencil) { - _attach(gl, gl.STENCIL_ATTACHMENT, fb._stencil); - } - - if (this._framebuffer._depthStencil) { - _attach(gl, gl.DEPTH_STENCIL_ATTACHMENT, fb._depthStencil); - } -}; - -/** - * @method setViewport - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device.prototype.setViewport = function setViewport (x, y, w, h) { - if ( - this._vx !== x || - this._vy !== y || - this._vw !== w || - this._vh !== h - ) { - this._gl.viewport(x, y, w, h); - this._vx = x; - this._vy = y; - this._vw = w; - this._vh = h; - } -}; - -/** - * @method setScissor - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device.prototype.setScissor = function setScissor (x, y, w, h) { - if ( - this._sx !== x || - this._sy !== y || - this._sw !== w || - this._sh !== h - ) { - this._gl.scissor(x, y, w, h); - this._sx = x; - this._sy = y; - this._sw = w; - this._sh = h; - } -}; - -/** - * @method clear - * @param {Object} opts - * @param {Array} opts.color - * @param {Number} opts.depth - * @param {Number} opts.stencil - */ -Device.prototype.clear = function clear (opts) { - var gl = this._gl; - var flags = 0; - - if (opts.color !== undefined) { - flags |= gl.COLOR_BUFFER_BIT; - gl.clearColor(opts.color[0], opts.color[1], opts.color[2], opts.color[3]); - } - - if (opts.depth !== undefined) { - flags |= gl.DEPTH_BUFFER_BIT; - gl.clearDepth(opts.depth); - - gl.enable(gl.DEPTH_TEST); - gl.depthMask(true); - gl.depthFunc(gl.ALWAYS); - } - - if (opts.stencil !== undefined) { - flags |= gl.STENCIL_BUFFER_BIT; - gl.clearStencil(opts.stencil); - } - - gl.clear(flags); - - // restore depth-write - if (opts.depth !== undefined) { - if (this._current.depthTest === false) { - gl.disable(gl.DEPTH_TEST); - } else { - if (this._current.depthWrite === false) { - gl.depthMask(false); - } - if (this._current.depthFunc !== enums$1.DS_FUNC_ALWAYS) { - gl.depthFunc(this._current.depthFunc); - } - } - } -}; - -// =============================== -// Deferred States -// =============================== - -/** - * @method enableBlend - */ -Device.prototype.enableBlend = function enableBlend () { - this._next.blend = true; -}; - -/** - * @method enableDepthTest - */ -Device.prototype.enableDepthTest = function enableDepthTest () { - this._next.depthTest = true; -}; - -/** - * @method enableDepthWrite - */ -Device.prototype.enableDepthWrite = function enableDepthWrite () { - this._next.depthWrite = true; -}; - -/** - * @method enableStencilTest - */ -Device.prototype.enableStencilTest = function enableStencilTest () { - this._next.stencilTest = true; -}; - -/** - * @method setStencilFunc - * @param {DS_FUNC_*} func - * @param {Number} ref - * @param {Number} mask - */ -Device.prototype.setStencilFunc = function setStencilFunc (func, ref, mask) { - this._next.stencilSep = false; - this._next.stencilFuncFront = this._next.stencilFuncBack = func; - this._next.stencilRefFront = this._next.stencilRefBack = ref; - this._next.stencilMaskFront = this._next.stencilMaskBack = mask; -}; - -/** - * @method setStencilFuncFront - * @param {DS_FUNC_*} func - * @param {Number} ref - * @param {Number} mask - */ -Device.prototype.setStencilFuncFront = function setStencilFuncFront (func, ref, mask) { - this._next.stencilSep = true; - this._next.stencilFuncFront = func; - this._next.stencilRefFront = ref; - this._next.stencilMaskFront = mask; -}; - -/** - * @method setStencilFuncBack - * @param {DS_FUNC_*} func - * @param {Number} ref - * @param {Number} mask - */ -Device.prototype.setStencilFuncBack = function setStencilFuncBack (func, ref, mask) { - this._next.stencilSep = true; - this._next.stencilFuncBack = func; - this._next.stencilRefBack = ref; - this._next.stencilMaskBack = mask; -}; - -/** - * @method setStencilOp - * @param {STENCIL_OP_*} failOp - * @param {STENCIL_OP_*} zFailOp - * @param {STENCIL_OP_*} zPassOp - * @param {Number} writeMask - */ -Device.prototype.setStencilOp = function setStencilOp (failOp, zFailOp, zPassOp, writeMask) { - this._next.stencilFailOpFront = this._next.stencilFailOpBack = failOp; - this._next.stencilZFailOpFront = this._next.stencilZFailOpBack = zFailOp; - this._next.stencilZPassOpFront = this._next.stencilZPassOpBack = zPassOp; - this._next.stencilWriteMaskFront = this._next.stencilWriteMaskBack = writeMask; -}; - -/** - * @method setStencilOpFront - * @param {STENCIL_OP_*} failOp - * @param {STENCIL_OP_*} zFailOp - * @param {STENCIL_OP_*} zPassOp - * @param {Number} writeMask - */ -Device.prototype.setStencilOpFront = function setStencilOpFront (failOp, zFailOp, zPassOp, writeMask) { - this._next.stencilSep = true; - this._next.stencilFailOpFront = failOp; - this._next.stencilZFailOpFront = zFailOp; - this._next.stencilZPassOpFront = zPassOp; - this._next.stencilWriteMaskFront = writeMask; -}; - -/** - * @method setStencilOpBack - * @param {STENCIL_OP_*} failOp - * @param {STENCIL_OP_*} zFailOp - * @param {STENCIL_OP_*} zPassOp - * @param {Number} writeMask - */ -Device.prototype.setStencilOpBack = function setStencilOpBack (failOp, zFailOp, zPassOp, writeMask) { - this._next.stencilSep = true; - this._next.stencilFailOpBack = failOp; - this._next.stencilZFailOpBack = zFailOp; - this._next.stencilZPassOpBack = zPassOp; - this._next.stencilWriteMaskBack = writeMask; -}; - -/** - * @method setDepthFunc - * @param {DS_FUNC_*} depthFunc - */ -Device.prototype.setDepthFunc = function setDepthFunc (depthFunc) { - this._next.depthFunc = depthFunc; -}; - -/** - * @method setBlendColor32 - * @param {Number} rgba - */ -Device.prototype.setBlendColor32 = function setBlendColor32 (rgba) { - this._next.blendColor = rgba; -}; - -/** - * @method setBlendColor - * @param {Number} r - * @param {Number} g - * @param {Number} b - * @param {Number} a - */ -Device.prototype.setBlendColor = function setBlendColor (r, g, b, a) { - this._next.blendColor = ((r * 255) << 24 | (g * 255) << 16 | (b * 255) << 8 | a * 255) >>> 0; -}; - -/** - * @method setBlendFunc - * @param {BELND_*} src - * @param {BELND_*} dst - */ -Device.prototype.setBlendFunc = function setBlendFunc (src, dst) { - this._next.blendSep = false; - this._next.blendSrc = src; - this._next.blendDst = dst; -}; - -/** - * @method setBlendFuncSep - * @param {BELND_*} src - * @param {BELND_*} dst - * @param {BELND_*} srcAlpha - * @param {BELND_*} dstAlpha - */ -Device.prototype.setBlendFuncSep = function setBlendFuncSep (src, dst, srcAlpha, dstAlpha) { - this._next.blendSep = true; - this._next.blendSrc = src; - this._next.blendDst = dst; - this._next.blendSrcAlpha = srcAlpha; - this._next.blendDstAlpha = dstAlpha; -}; - -/** - * @method setBlendEq - * @param {BELND_FUNC_*} eq - */ -Device.prototype.setBlendEq = function setBlendEq (eq) { - this._next.blendSep = false; - this._next.blendEq = eq; -}; - -/** - * @method setBlendEqSep - * @param {BELND_FUNC_*} eq - * @param {BELND_FUNC_*} alphaEq - */ -Device.prototype.setBlendEqSep = function setBlendEqSep (eq, alphaEq) { - this._next.blendSep = true; - this._next.blendEq = eq; - this._next.blendAlphaEq = alphaEq; -}; - -/** - * @method setCullMode - * @param {CULL_*} mode - */ -Device.prototype.setCullMode = function setCullMode (mode) { - this._next.cullMode = mode; -}; - -/** - * @method setVertexBuffer - * @param {Number} stream - * @param {VertexBuffer} buffer - * @param {Number} start - start vertex - */ -Device.prototype.setVertexBuffer = function setVertexBuffer (stream, buffer, start) { - if ( start === void 0 ) start = 0; - - this._next.vertexBuffers[stream] = buffer; - this._next.vertexBufferOffsets[stream] = start; - if (this._next.maxStream < stream) { - this._next.maxStream = stream; - } -}; - -/** - * @method setIndexBuffer - * @param {IndexBuffer} buffer - */ -Device.prototype.setIndexBuffer = function setIndexBuffer (buffer) { - this._next.indexBuffer = buffer; -}; - -/** - * @method setProgram - * @param {Program} program - */ -Device.prototype.setProgram = function setProgram (program) { - this._next.program = program; -}; - -/** - * @method setTexture - * @param {String} name - * @param {Texture} texture - * @param {Number} slot - */ -Device.prototype.setTexture = function setTexture (name, texture, slot) { - if (slot >= this._caps.maxTextureUnits) { - console.warn(("Can not set texture " + name + " at stage " + slot + ", max texture exceed: " + (this._caps.maxTextureUnits))); - return; - } - - this._next.textureUnits[slot] = texture; - this.setUniform(name, slot); - - if (this._next.maxTextureSlot < slot) { - this._next.maxTextureSlot = slot; - } -}; - -/** - * @method setTextureArray - * @param {String} name - * @param {Array} textures - * @param {Int32Array} slots - */ -Device.prototype.setTextureArray = function setTextureArray (name, textures, slots) { - var this$1 = this; - - var len = textures.length; - if (len >= this._caps.maxTextureUnits) { - console.warn(("Can not set " + len + " textures for " + name + ", max texture exceed: " + (this._caps.maxTextureUnits))); - return; - } - for (var i = 0; i < len; ++i) { - var slot = slots[i]; - this$1._next.textureUnits[slot] = textures[i]; - } - this.setUniform(name, slots); -}; - -/** - * @method setUniform - * @param {String} name - * @param {*} value - */ -Device.prototype.setUniform = function setUniform (name, value) { - var uniform = this._uniforms[name]; - if (!uniform || (uniform.isArray && uniform.value.length < value.length)) { - var newValue = value; - var isArray = false; - if (value instanceof Float32Array || Array.isArray(value)) { - newValue = new Float32Array(value); - isArray = true; - } - else if (value instanceof Int32Array) { - newValue = new Int32Array(value); - isArray = true; - } - - uniform = { - dirty: true, - value: newValue, - isArray: isArray - }; - } else { - var oldValue = uniform.value; - var dirty = false; - if (uniform.isArray) { - for (var i = 0, l = oldValue.length; i < l; i++) { - if (oldValue[i] !== value[i]) { - dirty = true; - oldValue[i] = value[i]; - } - } - } - else { - if (oldValue !== value) { - dirty = true; - uniform.value = value; - } - } - - if (dirty) { - uniform.dirty = true; - } - } - this._uniforms[name] = uniform; -}; - -/** - * @method setPrimitiveType - * @param {PT_*} type - */ -Device.prototype.setPrimitiveType = function setPrimitiveType (type) { - this._next.primitiveType = type; -}; - -/** - * @method draw - * @param {Number} base - * @param {Number} count - */ -Device.prototype.draw = function draw (base, count) { - var this$1 = this; - - var gl = this._gl; - var cur = this._current; - var next = this._next; - - // commit blend - _commitBlendStates(gl, cur, next); - - // commit depth - _commitDepthStates(gl, cur, next); - - // commit stencil - _commitStencilStates(gl, cur, next); - - // commit cull - _commitCullMode(gl, cur, next); - - // commit vertex-buffer - _commitVertexBuffers(this, gl, cur, next); - - // commit index-buffer - if (cur.indexBuffer !== next.indexBuffer) { - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, next.indexBuffer ? next.indexBuffer._glID : null); - } - - // commit program - var programDirty = false; - if (cur.program !== next.program) { - if (next.program._linked) { - gl.useProgram(next.program._glID); - } else { - console.warn('Failed to use program: has not linked yet.'); - } - programDirty = true; - } - - // commit texture/sampler - _commitTextures(gl, cur, next); - - // commit uniforms - for (var i = 0; i < next.program._uniforms.length; ++i) { - var uniformInfo = next.program._uniforms[i]; - var uniform = this$1._uniforms[uniformInfo.name]; - if (!uniform) { - // console.warn(`Can not find uniform ${uniformInfo.name}`); - continue; - } - - if (!programDirty && !uniform.dirty) { - continue; - } - - uniform.dirty = false; - - // TODO: please consider array uniform: uniformInfo.size > 0 - - var commitFunc = (uniformInfo.size === undefined) ? _type2uniformCommit[uniformInfo.type] : _type2uniformArrayCommit[uniformInfo.type]; - if (!commitFunc) { - console.warn(("Can not find commit function for uniform " + (uniformInfo.name))); - continue; - } - - commitFunc(gl, uniformInfo.location, uniform.value); - } - - // drawPrimitives - if (next.indexBuffer) { - gl.drawElements( - this._next.primitiveType, - count, - next.indexBuffer._format, - base * next.indexBuffer._bytesPerIndex - ); - } else { - gl.drawArrays( - this._next.primitiveType, - base, - count - ); - } - - // TODO: autogen mipmap for color buffer - // if (this._framebuffer && this._framebuffer.colors[0].mipmap) { - // gl.bindTexture(this._framebuffer.colors[i]._target, colors[i]._glID); - // gl.generateMipmap(this._framebuffer.colors[i]._target); - // } - - // update stats - this._stats.drawcalls += 1; - - // reset states - cur.set(next); - next.reset(); -}; - -var gfx = { - // classes - VertexFormat: VertexFormat, - IndexBuffer: IndexBuffer, - VertexBuffer: VertexBuffer, - Program: Program, - Texture: Texture, - Texture2D: Texture2D, - TextureCube: TextureCube, - RenderBuffer: RenderBuffer, - FrameBuffer: FrameBuffer, - Device: Device, - - // functions - attrTypeBytes: attrTypeBytes, - glFilter: glFilter, - glTextureFmt: glTextureFmt, -}; -Object.assign(gfx, enums$1); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var InputAssembler = function InputAssembler(vb, ib, pt) { - if ( pt === void 0 ) pt = gfx.PT_TRIANGLES; - - this._vertexBuffer = vb; - this._indexBuffer = ib; - this._primitiveType = pt; - this._start = 0; - this._count = -1; - - // TODO: instancing data - // this._stream = 0; -}; - -InputAssembler.prototype.getPrimitiveCount = function getPrimitiveCount () { - if (this._count !== -1) { - return this._count; - } - - if (this._indexBuffer) { - return this._indexBuffer.count; - } - - return this._vertexBuffer.count; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Pass = function Pass(name) { - this._programName = name; - - // cullmode - this._cullMode = gfx.CULL_BACK; - - // blending - this._blend = false; - this._blendEq = gfx.BLEND_FUNC_ADD; - this._blendAlphaEq = gfx.BLEND_FUNC_ADD; - this._blendSrc = gfx.BLEND_ONE; - this._blendDst = gfx.BLEND_ZERO; - this._blendSrcAlpha = gfx.BLEND_ONE; - this._blendDstAlpha = gfx.BLEND_ZERO; - this._blendColor = 0xffffffff; - - // depth - this._depthTest = false; - this._depthWrite = false; - this._depthFunc = gfx.DS_FUNC_LESS; - this._stencilTest = false; - // front - this._stencilFuncFront = gfx.DS_FUNC_ALWAYS; - this._stencilRefFront = 0; - this._stencilMaskFront = 0xff; - this._stencilFailOpFront = gfx.STENCIL_OP_KEEP; - this._stencilZFailOpFront = gfx.STENCIL_OP_KEEP; - this._stencilZPassOpFront = gfx.STENCIL_OP_KEEP; - this._stencilWriteMaskFront = 0xff; - // back - this._stencilFuncBack = gfx.DS_FUNC_ALWAYS; - this._stencilRefBack = 0; - this._stencilMaskBack = 0xff; - this._stencilFailOpBack = gfx.STENCIL_OP_KEEP; - this._stencilZFailOpBack = gfx.STENCIL_OP_KEEP; - this._stencilZPassOpBack = gfx.STENCIL_OP_KEEP; - this._stencilWriteMaskBack = 0xff; -}; - -Pass.prototype.copy = function (pass) { - this._programName = pass._programName; - // cullmode - this._cullMode = pass._cullMode; - // blending - this._blend = pass._blend; - this._blendEq = pass._blendEq; - this._blendAlphaEq = pass._blendAlphaEq; - this._blendSrc = pass._blendSrc; - this._blendDst = pass._blendDst; - this._blendSrcAlpha = pass._blendSrcAlpha; - this._blendDstAlpha = pass._blendDstAlpha; - this._blendColor = pass._blendColor; - // depth - this._depthTest = pass._depthTest; - this._depthWrite = pass._depthWrite; - this._depthFunc = pass._depthFunc; - this._stencilTest = pass._stencilTest; - // front - this._stencilFuncFront = pass._stencilFuncFront; - this._stencilRefFront = pass._stencilRefFront; - this._stencilMaskFront = pass._stencilMaskFront; - this._stencilFailOpFront = pass._stencilFailOpFront; - this._stencilZFailOpFront = pass._stencilZFailOpFront; - this._stencilZPassOpFront = pass._stencilZPassOpFront; - this._stencilWriteMaskFront = pass._stencilWriteMaskFront; - // back - this._stencilFuncBack = pass._stencilFuncBack; - this._stencilRefBack = pass._stencilRefBack; - this._stencilMaskBack = pass._stencilMaskBack; - this._stencilFailOpBack = pass._stencilFailOpBack; - this._stencilZFailOpBack = pass._stencilZFailOpBack; - this._stencilZPassOpBack = pass._stencilZPassOpBack; - this._stencilWriteMaskBack = pass._stencilWriteMaskBack; -}; - -Pass.prototype.setCullMode = function setCullMode (cullMode) { - this._cullMode = cullMode; -}; - -Pass.prototype.setBlend = function setBlend ( - enabled, - blendEq, - blendSrc, - blendDst, - blendAlphaEq, - blendSrcAlpha, - blendDstAlpha, - blendColor -) { - if ( enabled === void 0 ) enabled = false; - if ( blendEq === void 0 ) blendEq = gfx.BLEND_FUNC_ADD; - if ( blendSrc === void 0 ) blendSrc = gfx.BLEND_ONE; - if ( blendDst === void 0 ) blendDst = gfx.BLEND_ZERO; - if ( blendAlphaEq === void 0 ) blendAlphaEq = gfx.BLEND_FUNC_ADD; - if ( blendSrcAlpha === void 0 ) blendSrcAlpha = gfx.BLEND_ONE; - if ( blendDstAlpha === void 0 ) blendDstAlpha = gfx.BLEND_ZERO; - if ( blendColor === void 0 ) blendColor = 0xffffffff; - - this._blend = enabled; - this._blendEq = blendEq; - this._blendSrc = blendSrc; - this._blendDst = blendDst; - this._blendAlphaEq = blendAlphaEq; - this._blendSrcAlpha = blendSrcAlpha; - this._blendDstAlpha = blendDstAlpha; - this._blendColor = blendColor; -}; - -Pass.prototype.setDepth = function setDepth ( - depthTest, - depthWrite, - depthFunc -) { - if ( depthTest === void 0 ) depthTest = false; - if ( depthWrite === void 0 ) depthWrite = false; - if ( depthFunc === void 0 ) depthFunc = gfx.DS_FUNC_LESS; - - this._depthTest = depthTest; - this._depthWrite = depthWrite; - this._depthFunc = depthFunc; -}; - -Pass.prototype.setStencilFront = function setStencilFront ( - stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask -) { - if ( stencilFunc === void 0 ) stencilFunc = gfx.DS_FUNC_ALWAYS; - if ( stencilRef === void 0 ) stencilRef = 0; - if ( stencilMask === void 0 ) stencilMask = 0xff; - if ( stencilFailOp === void 0 ) stencilFailOp = gfx.STENCIL_OP_KEEP; - if ( stencilZFailOp === void 0 ) stencilZFailOp = gfx.STENCIL_OP_KEEP; - if ( stencilZPassOp === void 0 ) stencilZPassOp = gfx.STENCIL_OP_KEEP; - if ( stencilWriteMask === void 0 ) stencilWriteMask = 0xff; - - this._stencilTest = true; - this._stencilFuncFront = stencilFunc; - this._stencilRefFront = stencilRef; - this._stencilMaskFront = stencilMask; - this._stencilFailOpFront = stencilFailOp; - this._stencilZFailOpFront = stencilZFailOp; - this._stencilZPassOpFront = stencilZPassOp; - this._stencilWriteMaskFront = stencilWriteMask; -}; - -Pass.prototype.setStencilBack = function setStencilBack ( - stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask -) { - if ( stencilFunc === void 0 ) stencilFunc = gfx.DS_FUNC_ALWAYS; - if ( stencilRef === void 0 ) stencilRef = 0; - if ( stencilMask === void 0 ) stencilMask = 0xff; - if ( stencilFailOp === void 0 ) stencilFailOp = gfx.STENCIL_OP_KEEP; - if ( stencilZFailOp === void 0 ) stencilZFailOp = gfx.STENCIL_OP_KEEP; - if ( stencilZPassOp === void 0 ) stencilZPassOp = gfx.STENCIL_OP_KEEP; - if ( stencilWriteMask === void 0 ) stencilWriteMask = 0xff; - - this._stencilTest = true; - this._stencilFuncBack = stencilFunc; - this._stencilRefBack = stencilRef; - this._stencilMaskBack = stencilMask; - this._stencilFailOpBack = stencilFailOp; - this._stencilZFailOpBack = stencilZFailOp; - this._stencilZPassOpBack = stencilZPassOp; - this._stencilWriteMaskBack = stencilWriteMask; -}; - -Pass.prototype.disableStencilTest = function disableStencilTest () { - this._stencilTest = false; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _stageOffset = 0; -var _name2stageID = {}; - -var config = { - addStage: function (name) { - // already added - if (_name2stageID[name] !== undefined) { - return; - } - - var stageID = 1 << _stageOffset; - _name2stageID[name] = stageID; - - _stageOffset += 1; - }, - - stageID: function (name) { - var id = _name2stageID[name]; - if (id === undefined) { - return -1; - } - return id; - }, - - stageIDs: function (nameList) { - var key = 0; - for (var i = 0; i < nameList.length; ++i) { - var id = _name2stageID[nameList[i]]; - if (id !== undefined) { - key |= id; - } - } - return key; - } -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _genID$1 = 0; - -var Technique = function Technique(stages, passes, layer) { - if ( layer === void 0 ) layer = 0; - - this._id = _genID$1++; - this._stageIDs = config.stageIDs(stages); - // this._parameters = parameters; // {name, type, size, val} - this._passes = passes; - this._layer = layer; - // TODO: this._version = 'webgl' or 'webgl2' // ???? -}; - -var prototypeAccessors$3 = { passes: { configurable: true },stageIDs: { configurable: true } }; - -Technique.prototype.copy = function (technique) { - this._id = technique._id; - this._stageIDs = technique._stageIDs; - - // this._parameters = []; - // for (let i = 0; i < technique._parameters.length; ++i) { - // let parameter = technique._parameters[i]; - // this._parameters.push({name: parameter.name, type: parameter.type}); - // } - - for (let i = 0; i < technique._passes.length; ++i) { - let pass = this._passes[i]; - if (!pass) { - pass = new renderer.Pass(); - this._passes.push(pass); - } - pass.copy(technique._passes[i]); - } - this._passes.length = technique._passes.length; - - this._layer = technique._layer; -}; - -Technique.prototype.setStages = function setStages (stages) { - this._stageIDs = config.stageIDs(stages); -}; - -prototypeAccessors$3.passes.get = function () { - return this._passes; -}; - -prototypeAccessors$3.stageIDs.get = function () { - return this._stageIDs; -}; - -Object.defineProperties( Technique.prototype, prototypeAccessors$3 ); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Effect = function Effect(techniques, properties, defines) { - if ( properties === void 0 ) properties = {}; - if ( defines === void 0 ) defines = []; - - this._techniques = techniques; - this._properties = properties; - this._defines = defines; - - // TODO: check if params is valid for current technique??? -}; - -Effect.prototype.clear = function clear () { - this._techniques.length = 0; - this._properties = null; - this._defines.length = 0; -}; - -Effect.prototype.getTechnique = function getTechnique (stage) { - var this$1 = this; - - var stageID = config.stageID(stage); - for (var i = 0; i < this._techniques.length; ++i) { - var tech = this$1._techniques[i]; - if (tech.stageIDs & stageID) { - return tech; - } - } - - return null; -}; - -Effect.prototype.getProperty = function getProperty (name) { - return this._properties[name]; -}; - -Effect.prototype.setProperty = function setProperty (name, value) { - // TODO: check if params is valid for current technique??? - this._properties[name] = value; -}; - -Effect.prototype.getDefine = function getDefine (name) { - var this$1 = this; - - for (var i = 0; i < this._defines.length; ++i) { - var def = this$1._defines[i]; - if ( def.name === name ) { - return def.value; - } - } - - console.warn(("Failed to get define " + name + ", define not found.")); - return null; -}; - -Effect.prototype.define = function define (name, value) { - var this$1 = this; - - for (var i = 0; i < this._defines.length; ++i) { - var def = this$1._defines[i]; - if ( def.name === name ) { - def.value = value; - return; - } - } - - console.warn(("Failed to set define " + name + ", define not found.")); -}; - -Effect.prototype.extractDefines = function extractDefines (out) { - var this$1 = this; - if ( out === void 0 ) out = {}; - - for (var i = 0; i < this._defines.length; ++i) { - var def = this$1._defines[i]; - out[def.name] = def.value; - } - - return out; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -/** - * @param {object} json - */ - - -/** - * @param {gfx.Device} device - * @param {Object} data - */ -function createIA(device, data) { - if (!data.positions) { - console.error('The data must have positions field'); - return null; - } - - var verts = []; - var vcount = data.positions.length / 3; - - for (var i = 0; i < vcount; ++i) { - verts.push(data.positions[3 * i], data.positions[3 * i + 1], data.positions[3 * i + 2]); - - if (data.normals) { - verts.push(data.normals[3 * i], data.normals[3 * i + 1], data.normals[3 * i + 2]); - } - - if (data.uvs) { - verts.push(data.uvs[2 * i], data.uvs[2 * i + 1]); - } - } - - var vfmt = []; - vfmt.push({ name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 3 }); - if (data.normals) { - vfmt.push({ name: gfx.ATTR_NORMAL, type: gfx.ATTR_TYPE_FLOAT32, num: 3 }); - } - if (data.uvs) { - vfmt.push({ name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }); - } - - var vb = new gfx.VertexBuffer( - device, - new gfx.VertexFormat(vfmt), - gfx.USAGE_STATIC, - new Float32Array(verts), - vcount - ); - - var ib = null; - if (data.indices) { - ib = new gfx.IndexBuffer( - device, - gfx.INDEX_FMT_UINT16, - gfx.USAGE_STATIC, - new Uint16Array(data.indices), - data.indices.length - ); - } - - return new InputAssembler(vb, ib); -} - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _m4_tmp = mat4.create(); -var _genID$2 = 0; - -var View = function View() { - this._id = _genID$2++; - - // viewport - this._rect = { - x: 0, y: 0, w: 1, h: 1 - }; - - // TODO: - // this._scissor = { - // x: 0, y: 0, w: 1, h: 1 - // }; - - // clear options - this._color = color4.new(0.3, 0.3, 0.3, 1); - this._depth = 1; - this._stencil = 0; - this._clearFlags = enums.CLEAR_COLOR | enums.CLEAR_DEPTH; - - // matrix - this._matView = mat4.create(); - this._matProj = mat4.create(); - this._matViewProj = mat4.create(); - this._matInvViewProj = mat4.create(); - - // stages & framebuffer - this._stages = []; - this._cullingMask = 1; - this._framebuffer = null; - - this._shadowLight = null; // TODO: should not refer light in view. -}; - -View.prototype.getForward = function getForward (out) { - return vec3.set( - out, - -this._matView.m02, - -this._matView.m06, - -this._matView.m10 - ); -}; - -View.prototype.getPosition = function getPosition (out) { - mat4.invert(_m4_tmp, this._matView); - return mat4.getTranslation(out, _m4_tmp); -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _forward = vec3.new(0, 0, -1); - -var _m4_tmp$1 = mat4.create(); -var _m3_tmp = mat3.create(); -var _transformedLightDirection = vec3.create(); - -// compute light viewProjMat for shadow. -function _computeSpotLightViewProjMatrix(light, outView, outProj) { - // view matrix - light._node.getWorldRT(outView); - mat4.invert(outView, outView); - - // proj matrix - mat4.perspective(outProj, light._spotAngle * light._spotAngleScale, 1, light._shadowMinDepth, light._shadowMaxDepth); -} - -function _computeDirectionalLightViewProjMatrix(light, outView, outProj) { - // view matrix - light._node.getWorldRT(outView); - mat4.invert(outView, outView); - - // TODO: should compute directional light frustum based on rendered meshes in scene. - // proj matrix - var halfSize = light._shadowFustumSize / 2; - mat4.ortho(outProj, -halfSize, halfSize, -halfSize, halfSize, light._shadowMinDepth, light._shadowMaxDepth); -} - -function _computePointLightViewProjMatrix(light, outView, outProj) { - // TODO: -} - -var Light = function Light() { - this._poolID = -1; - this._node = null; - - this._type = enums.LIGHT_DIRECTIONAL; - - this._color = color3.new(1, 1, 1); - this._intensity = 1; - - // used for spot and point light - this._range = 1; - // used for spot light, default to 60 degrees - this._spotAngle = toRadian(60); - this._spotExp = 1; - // cached for uniform - this._directionUniform = new Float32Array(3); - this._positionUniform = new Float32Array(3); - this._colorUniform = new Float32Array([this._color.r * this._intensity, this._color.g * this._intensity, this._color.b * this._intensity]); - this._spotUniform = new Float32Array([Math.cos(this._spotAngle * 0.5), this._spotExp]); - - // shadow params - this._shadowType = enums.SHADOW_NONE; - this._shadowFrameBuffer = null; - this._shadowMap = null; - this._shadowMapDirty = false; - this._shadowDepthBuffer = null; - this._shadowResolution = 1024; - this._shadowBias = 0.00005; - this._shadowDarkness = 1; - this._shadowMinDepth = 1; - this._shadowMaxDepth = 1000; - this._shadowDepthScale = 50; // maybe need to change it if the distance between shadowMaxDepth and shadowMinDepth is small. - this._frustumEdgeFalloff = 0; // used by directional and spot light. - this._viewProjMatrix = mat4.create(); - this._spotAngleScale = 1; // used for spot light. - this._shadowFustumSize = 80; // used for directional light. -}; - -var prototypeAccessors$4 = { color: { configurable: true },intensity: { configurable: true },type: { configurable: true },spotAngle: { configurable: true },spotExp: { configurable: true },range: { configurable: true },shadowType: { configurable: true },shadowMap: { configurable: true },viewProjMatrix: { configurable: true },shadowResolution: { configurable: true },shadowBias: { configurable: true },shadowDarkness: { configurable: true },shadowMinDepth: { configurable: true },shadowMaxDepth: { configurable: true },shadowDepthScale: { configurable: true },frustumEdgeFalloff: { configurable: true } }; - -Light.prototype.setNode = function setNode (node) { - this._node = node; -}; - -Light.prototype.setColor = function setColor (r, g, b) { - color3.set(this._color, r, g, b); - this._colorUniform[0] = r * this._intensity; - this._colorUniform[1] = g * this._intensity; - this._colorUniform[2] = b * this._intensity; -}; -prototypeAccessors$4.color.get = function () { - return this._color; -}; - -Light.prototype.setIntensity = function setIntensity (val) { - this._intensity = val; - this._colorUniform[0] = val * this._color.r; - this._colorUniform[1] = val * this._color.g; - this._colorUniform[2] = val * this._color.b; -}; -prototypeAccessors$4.intensity.get = function () { - return this._intensity; -}; - -Light.prototype.setType = function setType (tpe) { - this._type = tpe; -}; -prototypeAccessors$4.type.get = function () { - return this._type; -}; - -Light.prototype.setSpotAngle = function setSpotAngle (val) { - this._spotAngle = val; - this._spotUniform[0] = Math.cos(this._spotAngle * 0.5); -}; -prototypeAccessors$4.spotAngle.get = function () { - return this._spotAngle; -}; - -Light.prototype.setSpotExp = function setSpotExp (val) { - this._spotExp = val; - this._spotUniform[1] = val; -}; -prototypeAccessors$4.spotExp.get = function () { - return this._spotExp; -}; - -Light.prototype.setRange = function setRange (tpe) { - this._range = tpe; -}; -prototypeAccessors$4.range.get = function () { - return this._range; -}; - -Light.prototype.setShadowType = function setShadowType (type) { - if (this._shadowType === enums.SHADOW_NONE && type !== enums.SHADOW_NONE) { - this._shadowMapDirty = true; - } - this._shadowType = type; -}; -prototypeAccessors$4.shadowType.get = function () { - return this._shadowType; -}; - -prototypeAccessors$4.shadowMap.get = function () { - return this._shadowMap; -}; - -prototypeAccessors$4.viewProjMatrix.get = function () { - return this._viewProjMatrix; -}; - -Light.prototype.setShadowResolution = function setShadowResolution (val) { - if (this._shadowResolution !== val) { - this._shadowMapDirty = true; - } - this._shadowResolution = val; -}; -prototypeAccessors$4.shadowResolution.get = function () { - return this._shadowResolution; -}; - -Light.prototype.setShadowBias = function setShadowBias (val) { - this._shadowBias = val; -}; -prototypeAccessors$4.shadowBias.get = function () { - return this._shadowBias; -}; - -Light.prototype.setShadowDarkness = function setShadowDarkness (val) { - this._shadowDarkness = val; -}; -prototypeAccessors$4.shadowDarkness.get = function () { - return this._shadowDarkness; -}; - -Light.prototype.setShadowMinDepth = function setShadowMinDepth (val) { - this._shadowMinDepth = val; -}; -prototypeAccessors$4.shadowMinDepth.get = function () { - if (this._type === enums.LIGHT_DIRECTIONAL) { - return 1.0; - } - return this._shadowMinDepth; -}; - -Light.prototype.setShadowMaxDepth = function setShadowMaxDepth (val) { - this._shadowMaxDepth = val; -}; -prototypeAccessors$4.shadowMaxDepth.get = function () { - if (this._type === enums.LIGHT_DIRECTIONAL) { - return 1.0; - } - return this._shadowMaxDepth; -}; - -Light.prototype.setShadowDepthScale = function setShadowDepthScale (val) { - this._shadowDepthScale = val; -}; -prototypeAccessors$4.shadowDepthScale.get = function () { - return this._shadowDepthScale; -}; - -Light.prototype.setFrustumEdgeFalloff = function setFrustumEdgeFalloff (val) { - this._frustumEdgeFalloff = val; -}; -prototypeAccessors$4.frustumEdgeFalloff.get = function () { - return this._frustumEdgeFalloff; -}; - -Light.prototype.extractView = function extractView (out, stages) { - // TODO: view should not handle light. - out._shadowLight = this; - - // rect - out._rect.x = 0; - out._rect.y = 0; - out._rect.w = this._shadowResolution; - out._rect.h = this._shadowResolution; - - // clear opts - color4.set(out._color, 1, 1, 1, 1); - out._depth = 1; - out._stencil = 0; - out._clearFlags = enums.CLEAR_COLOR | enums.CLEAR_DEPTH; - - // stages & framebuffer - out._stages = stages; - out._framebuffer = this._shadowFrameBuffer; - - // view projection matrix - switch(this._type) { - case enums.LIGHT_SPOT: - _computeSpotLightViewProjMatrix(this, out._matView, out._matProj); - break; - - case enums.LIGHT_DIRECTIONAL: - _computeDirectionalLightViewProjMatrix(this, out._matView, out._matProj); - break; - - case enums.LIGHT_POINT: - _computePointLightViewProjMatrix(this, out._matView, out._matProj); - break; - - default: - console.warn('shadow of this light type is not supported'); - } - - // view-projection - mat4.mul(out._matViewProj, out._matProj, out._matView); - this._viewProjMatrix = out._matViewProj; - mat4.invert(out._matInvViewProj, out._matViewProj); -}; - -Light.prototype._updateLightPositionAndDirection = function _updateLightPositionAndDirection () { - this._node.getWorldMatrix(_m4_tmp$1); - mat3.fromMat4(_m3_tmp, _m4_tmp$1); - vec3.transformMat3(_transformedLightDirection, _forward, _m3_tmp); - vec3.array(this._directionUniform, _transformedLightDirection); - var pos = this._positionUniform; - pos[0] = _m4_tmp$1.m12; - pos[1] = _m4_tmp$1.m13; - pos[2] = _m4_tmp$1.m14; -}; - -Light.prototype._generateShadowMap = function _generateShadowMap (device) { - this._shadowMap = new gfx.Texture2D(device, { - width: this._shadowResolution, - height: this._shadowResolution, - format: gfx.TEXTURE_FMT_RGBA8, - wrapS: gfx.WRAP_CLAMP, - wrapT: gfx.WRAP_CLAMP, - }); - this._shadowDepthBuffer = new gfx.RenderBuffer(device, - gfx.RB_FMT_D16, - this._shadowResolution, - this._shadowResolution - ); - this._shadowFrameBuffer = new gfx.FrameBuffer(device, this._shadowResolution, this._shadowResolution, { - colors: [this._shadowMap], - depth: this._shadowDepthBuffer, - }); -}; - -Light.prototype._destroyShadowMap = function _destroyShadowMap () { - if (this._shadowMap) { - this._shadowMap.destroy(); - this._shadowDepthBuffer.destroy(); - this._shadowFrameBuffer.destroy(); - this._shadowMap = null; - this._shadowDepthBuffer = null; - this._shadowFrameBuffer = null; - } -}; - -Light.prototype.update = function update (device) { - this._updateLightPositionAndDirection(); - - if (this._shadowType === enums.SHADOW_NONE) { - this._destroyShadowMap(); - } else if (this._shadowMapDirty) { - this._destroyShadowMap(); - this._generateShadowMap(device); - this._shadowMapDirty = false; - } - -}; - -Object.defineProperties( Light.prototype, prototypeAccessors$4 ); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _matView = mat4.create(); -var _matProj = mat4.create(); -var _matViewProj = mat4.create(); -var _matInvViewProj = mat4.create(); -var _tmp_v3 = vec3.create(); - -var Camera = function Camera() { - this._poolID = -1; - this._node = null; - - // - this._projection = enums.PROJ_PERSPECTIVE; - - // clear options - this._color = color4.new(0.2, 0.3, 0.47, 1); - this._depth = 1; - this._stencil = 0; - this._sortDepth = 0; - this._clearFlags = enums.CLEAR_COLOR | enums.CLEAR_DEPTH; - - // culling mask - this._cullingMask = 1; - - // stages & framebuffer - this._stages = []; - this._framebuffer = null; - - // projection properties - this._near = 0.01; - this._far = 1000.0; - this._fov = Math.PI/4.0; // vertical fov - // this._aspect = 16.0/9.0; // DISABLE: use _rect.w/_rect.h - this._rect = { - x: 0, y: 0, w: 1, h: 1 - }; - - // ortho properties - this._orthoHeight = 10; -}; - -var prototypeAccessors$5 = { cullingMask: { configurable: true } }; - -// culling mask -prototypeAccessors$5.cullingMask.get = function () { - return this._cullingMask; -}; - -prototypeAccessors$5.cullingMask.set = function (mask) { - this._cullingMask = mask; -}; - -// node -Camera.prototype.getNode = function getNode () { - return this._node; -}; -Camera.prototype.setNode = function setNode (node) { - this._node = node; -}; - -// type -Camera.prototype.getType = function getType () { - return this._projection; -}; -Camera.prototype.setType = function setType (type) { - this._projection = type; -}; - -// orthoHeight -Camera.prototype.getOrthoHeight = function getOrthoHeight () { - return this._orthoHeight; -}; -Camera.prototype.setOrthoHeight = function setOrthoHeight (val) { - this._orthoHeight = val; -}; - -// fov -Camera.prototype.getFov = function getFov () { - return this._fov; -}; -Camera.prototype.setFov = function setFov (fov) { - this._fov = fov; -}; - -// near -Camera.prototype.getNear = function getNear () { - return this._near; -}; -Camera.prototype.setNear = function setNear (near) { - this._near = near; -}; - -// far -Camera.prototype.getFar = function getFar () { - return this._far; -}; -Camera.prototype.setFar = function setFar (far) { - this._far = far; -}; - -// color -Camera.prototype.getColor = function getColor (out) { - return color4.copy(out, this._color); -}; -Camera.prototype.setColor = function setColor (r, g, b, a) { - color4.set(this._color, r, g, b, a); -}; - -// depth -Camera.prototype.getDepth = function getDepth () { - return this._depth; -}; -Camera.prototype.setDepth = function setDepth (depth) { - this._depth = depth; -}; - -// stencil -Camera.prototype.getStencil = function getStencil () { - return this._stencil; -}; -Camera.prototype.setStencil = function setStencil (stencil) { - this._stencil = stencil; -}; - -// clearFlags -Camera.prototype.getClearFlags = function getClearFlags () { - return this._clearFlags; -}; -Camera.prototype.setClearFlags = function setClearFlags (flags) { - this._clearFlags = flags; -}; - -// rect -Camera.prototype.getRect = function getRect (out) { - out.x = this._rect.x; - out.y = this._rect.y; - out.w = this._rect.w; - out.h = this._rect.h; - - return out; -}; -/** - * @param {Number} x - [0,1] - * @param {Number} y - [0,1] - * @param {Number} w - [0,1] - * @param {Number} h - [0,1] - */ -Camera.prototype.setRect = function setRect (x, y, w, h) { - this._rect.x = x; - this._rect.y = y; - this._rect.w = w; - this._rect.h = h; -}; - -// stages -Camera.prototype.getStages = function getStages () { - return this._stages; -}; -Camera.prototype.setStages = function setStages (stages) { - this._stages = stages; -}; - -// framebuffer -Camera.prototype.getFramebuffer = function getFramebuffer () { - return this._framebuffer; -}; -Camera.prototype.setFramebuffer = function setFramebuffer (framebuffer) { - this._framebuffer = framebuffer; -}; - -Camera.prototype.extractView = function extractView (out, width, height) { - // rect - out._rect.x = this._rect.x * width; - out._rect.y = this._rect.y * height; - out._rect.w = this._rect.w * width; - out._rect.h = this._rect.h * height; - - // clear opts - out._color = this._color; - out._depth = this._depth; - out._stencil = this._stencil; - out._clearFlags = this._clearFlags; - - // culling mask - out._cullingMask = this._cullingMask; - - // stages & framebuffer - out._stages = this._stages; - out._framebuffer = this._framebuffer; - - // view matrix - this._node.getWorldRT(out._matView); - mat4.invert(out._matView, out._matView); - - // projection matrix - // TODO: if this._projDirty - var aspect = width / height; - if (this._projection === enums.PROJ_PERSPECTIVE) { - mat4.perspective(out._matProj, - this._fov, - aspect, - this._near, - this._far - ); - } else { - var x = this._orthoHeight * aspect; - var y = this._orthoHeight; - mat4.ortho(out._matProj, - -x, x, -y, y, this._near, this._far - ); - } - - // view-projection - mat4.mul(out._matViewProj, out._matProj, out._matView); - mat4.invert(out._matInvViewProj, out._matViewProj); -}; - -Camera.prototype.screenToWorld = function screenToWorld (out, screenPos, width, height) { - var aspect = width / height; - var cx = this._rect.x * width; - var cy = this._rect.y * height; - var cw = this._rect.w * width; - var ch = this._rect.h * height; - - // view matrix - this._node.getWorldRT(_matView); - mat4.invert(_matView, _matView); - - // projection matrix - if (this._projection === enums.PROJ_PERSPECTIVE) { - mat4.perspective(_matProj, - this._fov, - aspect, - this._near, - this._far - ); - } else { - var x = this._orthoHeight * aspect; - var y = this._orthoHeight; - mat4.ortho(_matProj, - -x, x, -y, y, this._near, this._far - ); - } - - // view-projection - mat4.mul(_matViewProj, _matProj, _matView); - - // inv view-projection - mat4.invert(_matInvViewProj, _matViewProj); - - // - if (this._projection === enums.PROJ_PERSPECTIVE) { - // calculate screen pos in far clip plane - vec3.set(out, - (screenPos.x - cx) * 2.0 / cw - 1.0, - (screenPos.y - cy) * 2.0 / ch - 1.0, // DISABLE: (ch - (screenPos.y - cy)) * 2.0 / ch - 1.0, - 1.0 - ); - - // transform to world - vec3.transformMat4(out, out, _matInvViewProj); - - // - this._node.getWorldPosition(_tmp_v3); - vec3.lerp(out, _tmp_v3, out, cc.vmath.lerp(this._near / this._far, 1, screenPos.z)); - } else { - vec3.set(out, - (screenPos.x - cx) * 2.0 / cw - 1.0, - (screenPos.y - cy) * 2.0 / ch - 1.0, - screenPos.z * 2 - 1 - ); - - // transform to world - vec3.transformMat4(out, out, _matInvViewProj); - } - - return out; -}; - -Camera.prototype.worldToScreen = function worldToScreen (out, worldPos, width, height) { - var aspect = width / height; - var cx = this._rect.x * width; - var cy = this._rect.y * height; - var cw = this._rect.w * width; - var ch = this._rect.h * height; - - // view matrix - this._node.getWorldRT(_matView); - mat4.invert(_matView, _matView); - - // projection matrix - if (this._projection === enums.PROJ_PERSPECTIVE) { - mat4.perspective(_matProj, - this._fov, - aspect, - this._near, - this._far - ); - } else { - var x = this._orthoHeight * aspect; - var y = this._orthoHeight; - mat4.ortho(_matProj, - -x, x, -y, y, this._near, this._far - ); - } - - // view-projection - mat4.mul(_matViewProj, _matProj, _matView); - - vec3.transformMat4(out, worldPos, _matViewProj); - out.x = cx + (out.x + 1) * 0.5 * cw; - out.y = cy + (out.y + 1) * 0.5 * ch; - out.z = out.z * 0.5 + 0.5; - - return out; -}; - -Object.defineProperties( Camera.prototype, prototypeAccessors$5 ); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Model = function Model() { - this._poolID = -1; - this._node = null; - this._inputAssemblers = []; - this._effects = []; - this._defines = []; - this._dynamicIA = false; - this._cullingMask = -1; - - // TODO: we calculate aabb based on vertices - // this._aabb -}; - -var prototypeAccessors$6 = { inputAssemblerCount: { configurable: true },dynamicIA: { configurable: true },drawItemCount: { configurable: true },cullingMask: { configurable: true } }; - -prototypeAccessors$6.inputAssemblerCount.get = function () { - return this._inputAssemblers.length; -}; - -prototypeAccessors$6.dynamicIA.get = function () { - return this._dynamicIA; -}; - -prototypeAccessors$6.drawItemCount.get = function () { - return this._dynamicIA ? 1 : this._inputAssemblers.length; -}; - -prototypeAccessors$6.cullingMask.get = function () { - return this._cullingMask; -}; - -prototypeAccessors$6.cullingMask.set = function (mask) { - this._cullingMask = mask; -}; - -Model.prototype.setNode = function setNode (node) { - this._node = node; -}; - -Model.prototype.setDynamicIA = function setDynamicIA (enabled) { - this._dynamicIA = enabled; -}; - -Model.prototype.addInputAssembler = function addInputAssembler (ia) { - if (this._inputAssemblers.indexOf(ia) !== -1) { - return; - } - this._inputAssemblers.push(ia); -}; - -Model.prototype.clearInputAssemblers = function clearInputAssemblers () { - this._inputAssemblers.length = 0; -}; - -Model.prototype.addEffect = function addEffect (effect) { - if (this._effects.indexOf(effect) !== -1) { - return; - } - this._effects.push(effect); - - // - var defs = Object.create(null); - effect.extractDefines(defs); - this._defines.push(defs); -}; - -Model.prototype.clearEffects = function clearEffects () { - this._effects.length = 0; - this._defines.length = 0; -}; - -Model.prototype.extractDrawItem = function extractDrawItem (out, index) { - if (this._dynamicIA) { - out.model = this; - out.node = this._node; - out.ia = null; - out.effect = this._effects[0]; - out.defines = out.effect.extractDefines(this._defines[0]); - - return; - } - - if (index >= this._inputAssemblers.length ) { - out.model = null; - out.node = null; - out.ia = null; - out.effect = null; - out.defines = null; - - return; - } - - out.model = this; - out.node = this._node; - out.ia = this._inputAssemblers[index]; - - var effect, defines; - if (index < this._effects.length) { - effect = this._effects[index]; - defines = this._defines[index]; - } else { - effect = this._effects[this._effects.length-1]; - defines = this._defines[this._effects.length-1]; - } - out.effect = effect; - out.defines = effect.extractDefines(defines); -}; - -Object.defineProperties( Model.prototype, prototypeAccessors$6 ); - -// reference: https://github.com/mziccard/node-timsort - -/** - * Default minimum size of a run. - */ -var DEFAULT_MIN_MERGE = 32; - -/** - * Minimum ordered subsequece required to do galloping. - */ -var DEFAULT_MIN_GALLOPING = 7; - -/** - * Default tmp storage length. Can increase depending on the size of the - * smallest run to merge. - */ -var DEFAULT_TMP_STORAGE_LENGTH = 256; - -/** - * Pre-computed powers of 10 for efficient lexicographic comparison of - * small integers. - */ -var POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9]; - -/** - * Estimate the logarithm base 10 of a small integer. - * - * @param {number} x - The integer to estimate the logarithm of. - * @return {number} - The estimated logarithm of the integer. - */ -function log10$1(x) { - if (x < 1e5) { - if (x < 1e2) { - return x < 1e1 ? 0 : 1; - } - - if (x < 1e4) { - return x < 1e3 ? 2 : 3; - } - - return 4; - } - - if (x < 1e7) { - return x < 1e6 ? 5 : 6; - } - - if (x < 1e9) { - return x < 1e8 ? 7 : 8; - } - - return 9; -} - -/** - * Default alphabetical comparison of items. - * - * @param {string|object|number} a - First element to compare. - * @param {string|object|number} b - Second element to compare. - * @return {number} - A positive number if a.toString() > b.toString(), a - * negative number if .toString() < b.toString(), 0 otherwise. - */ -function alphabeticalCompare(a, b) { - if (a === b) { - return 0; - } - - if (~~a === a && ~~b === b) { - if (a === 0 || b === 0) { - return a < b ? -1 : 1; - } - - if (a < 0 || b < 0) { - if (b >= 0) { - return -1; - } - - if (a >= 0) { - return 1; - } - - a = -a; - b = -b; - } - - var al = log10$1(a); - var bl = log10$1(b); - - var t = 0; - - if (al < bl) { - a *= POWERS_OF_TEN[bl - al - 1]; - b /= 10; - t = -1; - } else if (al > bl) { - b *= POWERS_OF_TEN[al - bl - 1]; - a /= 10; - t = 1; - } - - if (a === b) { - return t; - } - - return a < b ? -1 : 1; - } - - var aStr = String(a); - var bStr = String(b); - - if (aStr === bStr) { - return 0; - } - - return aStr < bStr ? -1 : 1; -} - -/** - * Compute minimum run length for TimSort - * - * @param {number} n - The size of the array to sort. - */ -function minRunLength(n) { - var r = 0; - - while (n >= DEFAULT_MIN_MERGE) { - r |= (n & 1); - n >>= 1; - } - - return n + r; -} - -/** - * Counts the length of a monotonically ascending or strictly monotonically - * descending sequence (run) starting at array[lo] in the range [lo, hi). If - * the run is descending it is made ascending. - * - * @param {array} array - The array to reverse. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {function} compare - Item comparison function. - * @return {number} - The length of the run. - */ -function makeAscendingRun(array, lo, hi, compare) { - var runHi = lo + 1; - - if (runHi === hi) { - return 1; - } - - // Descending - if (compare(array[runHi++], array[lo]) < 0) { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { - runHi++; - } - - reverseRun(array, lo, runHi); - // Ascending - } else { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { - runHi++; - } - } - - return runHi - lo; -} - -/** - * Reverse an array in the range [lo, hi). - * - * @param {array} array - The array to reverse. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - */ -function reverseRun(array, lo, hi) { - hi--; - - while (lo < hi) { - var t = array[lo]; - array[lo++] = array[hi]; - array[hi--] = t; - } -} - -/** - * Perform the binary sort of the array in the range [lo, hi) where start is - * the first element possibly out of order. - * - * @param {array} array - The array to sort. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {number} start - First element possibly out of order. - * @param {function} compare - Item comparison function. - */ -function binaryInsertionSort(array, lo, hi, start, compare) { - if (start === lo) { - start++; - } - - for (; start < hi; start++) { - var pivot = array[start]; - - // Ranges of the array where pivot belongs - var left = lo; - var right = start; - - /* - * pivot >= array[i] for i in [lo, left) - * pivot < array[i] for i in in [right, start) - */ - while (left < right) { - var mid = (left + right) >>> 1; - - if (compare(pivot, array[mid]) < 0) { - right = mid; - } else { - left = mid + 1; - } - } - - /* - * Move elements right to make room for the pivot. If there are elements - * equal to pivot, left points to the first slot after them: this is also - * a reason for which TimSort is stable - */ - var n = start - left; - // Switch is just an optimization for small arrays - switch (n) { - case 3: - array[left + 3] = array[left + 2]; - /* falls through */ - case 2: - array[left + 2] = array[left + 1]; - /* falls through */ - case 1: - array[left + 1] = array[left]; - break; - default: - while (n > 0) { - array[left + n] = array[left + n - 1]; - n--; - } - } - - array[left] = pivot; - } -} - -/** - * Find the position at which to insert a value in a sorted range. If the range - * contains elements equal to the value the leftmost element index is returned - * (for stability). - * - * @param {number} value - Value to insert. - * @param {array} array - The array in which to insert value. - * @param {number} start - First element in the range. - * @param {number} length - Length of the range. - * @param {number} hint - The index at which to begin the search. - * @param {function} compare - Item comparison function. - * @return {number} - The index where to insert value. - */ -function gallopLeft(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) > 0) { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - lastOffset += hint; - offset += hint; - - // value <= array[start + hint] - } else { - maxOffset = hint + 1; - while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - } - - /* - * Now array[start+lastOffset] < value <= array[start+offset], so value - * belongs somewhere in the range (start + lastOffset, start + offset]. Do a - * binary search, with invariant array[start + lastOffset - 1] < value <= - * array[start + offset]. - */ - lastOffset++; - while (lastOffset < offset) { - var m = lastOffset + ((offset - lastOffset) >>> 1); - - if (compare(value, array[start + m]) > 0) { - lastOffset = m + 1; - - } else { - offset = m; - } - } - return offset; -} - -/** - * Find the position at which to insert a value in a sorted range. If the range - * contains elements equal to the value the rightmost element index is returned - * (for stability). - * - * @param {number} value - Value to insert. - * @param {array} array - The array in which to insert value. - * @param {number} start - First element in the range. - * @param {number} length - Length of the range. - * @param {number} hint - The index at which to begin the search. - * @param {function} compare - Item comparison function. - * @return {number} - The index where to insert value. - */ -function gallopRight(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) < 0) { - maxOffset = hint + 1; - - while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - - // value >= array[start + hint] - } else { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - lastOffset += hint; - offset += hint; - } - - /* - * Now array[start+lastOffset] < value <= array[start+offset], so value - * belongs somewhere in the range (start + lastOffset, start + offset]. Do a - * binary search, with invariant array[start + lastOffset - 1] < value <= - * array[start + offset]. - */ - lastOffset++; - - while (lastOffset < offset) { - var m = lastOffset + ((offset - lastOffset) >>> 1); - - if (compare(value, array[start + m]) < 0) { - offset = m; - - } else { - lastOffset = m + 1; - } - } - - return offset; -} - -var TimSort = function TimSort(array, compare) { - this.array = array; - this.compare = compare; - this.minGallop = DEFAULT_MIN_GALLOPING; - this.length = array.length; - - this.tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH; - if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) { - this.tmpStorageLength = this.length >>> 1; - } - - this.tmp = new Array(this.tmpStorageLength); - - this.stackLength = - (this.length < 120 ? 5 : - this.length < 1542 ? 10 : - this.length < 119151 ? 19 : 40); - - this.runStart = new Array(this.stackLength); - this.runLength = new Array(this.stackLength); - this.stackSize = 0; -}; - -/** - * Push a new run on TimSort's stack. - * - * @param {number} runStart - Start index of the run in the original array. - * @param {number} runLength - Length of the run; - */ -TimSort.prototype.pushRun = function pushRun (runStart, runLength) { - this.runStart[this.stackSize] = runStart; - this.runLength[this.stackSize] = runLength; - this.stackSize += 1; -}; - -/** - * Merge runs on TimSort's stack so that the following holds for all i: - * 1) runLength[i - 3] > runLength[i - 2] + runLength[i - 1] - * 2) runLength[i - 2] > runLength[i - 1] - */ -TimSort.prototype.mergeRuns = function mergeRuns () { - var this$1 = this; - - while (this.stackSize > 1) { - var n = this$1.stackSize - 2; - - if ((n >= 1 && - this$1.runLength[n - 1] <= this$1.runLength[n] + this$1.runLength[n + 1]) || - (n >= 2 && - this$1.runLength[n - 2] <= this$1.runLength[n] + this$1.runLength[n - 1])) { - - if (this$1.runLength[n - 1] < this$1.runLength[n + 1]) { - n--; - } - - } else if (this$1.runLength[n] > this$1.runLength[n + 1]) { - break; - } - this$1.mergeAt(n); - } -}; - -/** - * Merge all runs on TimSort's stack until only one remains. - */ -TimSort.prototype.forceMergeRuns = function forceMergeRuns () { - var this$1 = this; - - while (this.stackSize > 1) { - var n = this$1.stackSize - 2; - - if (n > 0 && this$1.runLength[n - 1] < this$1.runLength[n + 1]) { - n--; - } - - this$1.mergeAt(n); - } -}; - -/** - * Merge the runs on the stack at positions i and i+1. Must be always be called - * with i=stackSize-2 or i=stackSize-3 (that is, we merge on top of the stack). - * - * @param {number} i - Index of the run to merge in TimSort's stack. - */ -TimSort.prototype.mergeAt = function mergeAt (i) { - var compare = this.compare; - var array = this.array; - - var start1 = this.runStart[i]; - var length1 = this.runLength[i]; - var start2 = this.runStart[i + 1]; - var length2 = this.runLength[i + 1]; - - this.runLength[i] = length1 + length2; - - if (i === this.stackSize - 3) { - this.runStart[i + 1] = this.runStart[i + 2]; - this.runLength[i + 1] = this.runLength[i + 2]; - } - - this.stackSize--; - - /* - * Find where the first element in the second run goes in run1. Previous - * elements in run1 are already in place - */ - var k = gallopRight(array[start2], array, start1, length1, 0, compare); - start1 += k; - length1 -= k; - - if (length1 === 0) { - return; - } - - /* - * Find where the last element in the first run goes in run2. Next elements - * in run2 are already in place - */ - length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); - - if (length2 === 0) { - return; - } - - /* - * Merge remaining runs. A tmp array with length = min(length1, length2) is - * used - */ - if (length1 <= length2) { - this.mergeLow(start1, length1, start2, length2); - - } else { - this.mergeHigh(start1, length1, start2, length2); - } -}; - -/** - * Merge two adjacent runs in a stable way. The runs must be such that the - * first element of run1 is bigger than the first element in run2 and the - * last element of run1 is greater than all the elements in run2. - * The method should be called when run1.length <= run2.length as it uses - * TimSort temporary array to store run1. Use mergeHigh if run1.length > - * run2.length. - * - * @param {number} start1 - First element in run1. - * @param {number} length1 - Length of run1. - * @param {number} start2 - First element in run2. - * @param {number} length2 - Length of run2. - */ -TimSort.prototype.mergeLow = function mergeLow (start1, length1, start2, length2) { - - var compare = this.compare; - var array = this.array; - var tmp = this.tmp; - var i = 0; - - for (i = 0; i < length1; i++) { - tmp[i] = array[start1 + i]; - } - - var cursor1 = 0; - var cursor2 = start2; - var dest = start1; - - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - return; - } - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - array[dest + length2] = tmp[cursor1]; - return; - } - - var minGallop = this.minGallop; - - while (true) { - var count1 = 0; - var count2 = 0; - var exit = false; - - do { - if (compare(array[cursor2], tmp[cursor1]) < 0) { - array[dest++] = array[cursor2++]; - count2++; - count1 = 0; - - if (--length2 === 0) { - exit = true; - break; - } - - } else { - array[dest++] = tmp[cursor1++]; - count1++; - count2 = 0; - if (--length1 === 1) { - exit = true; - break; - } - } - } while ((count1 | count2) < minGallop); - - if (exit) { - break; - } - - do { - count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); - - if (count1 !== 0) { - for (i = 0; i < count1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - - dest += count1; - cursor1 += count1; - length1 -= count1; - if (length1 <= 1) { - exit = true; - break; - } - } - - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - exit = true; - break; - } - - count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); - - if (count2 !== 0) { - for (i = 0; i < count2; i++) { - array[dest + i] = array[cursor2 + i]; - } - - dest += count2; - cursor2 += count2; - length2 -= count2; - - if (length2 === 0) { - exit = true; - break; - } - } - array[dest++] = tmp[cursor1++]; - - if (--length1 === 1) { - exit = true; - break; - } - - minGallop--; - - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (minGallop < 0) { - minGallop = 0; - } - - minGallop += 2; - } - - this.minGallop = minGallop; - - if (minGallop < 1) { - this.minGallop = 1; - } - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - array[dest + length2] = tmp[cursor1]; - - } else if (length1 === 0) { - throw new Error('mergeLow preconditions were not respected'); - - } else { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - } -}; - -/** - * Merge two adjacent runs in a stable way. The runs must be such that the - * first element of run1 is bigger than the first element in run2 and the - * last element of run1 is greater than all the elements in run2. - * The method should be called when run1.length > run2.length as it uses - * TimSort temporary array to store run2. Use mergeLow if run1.length <= - * run2.length. - * - * @param {number} start1 - First element in run1. - * @param {number} length1 - Length of run1. - * @param {number} start2 - First element in run2. - * @param {number} length2 - Length of run2. - */ -TimSort.prototype.mergeHigh = function mergeHigh (start1, length1, start2, length2) { - var compare = this.compare; - var array = this.array; - var tmp = this.tmp; - var i = 0; - - for (i = 0; i < length2; i++) { - tmp[i] = array[start2 + i]; - } - - var cursor1 = start1 + length1 - 1; - var cursor2 = length2 - 1; - var dest = start2 + length2 - 1; - var customCursor = 0; - var customDest = 0; - - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - customCursor = dest - (length2 - 1); - - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - - return; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - return; - } - - var minGallop = this.minGallop; - - while (true) { - var count1 = 0; - var count2 = 0; - var exit = false; - - do { - if (compare(tmp[cursor2], array[cursor1]) < 0) { - array[dest--] = array[cursor1--]; - count1++; - count2 = 0; - if (--length1 === 0) { - exit = true; - break; - } - - } else { - array[dest--] = tmp[cursor2--]; - count2++; - count1 = 0; - if (--length2 === 1) { - exit = true; - break; - } - } - - } while ((count1 | count2) < minGallop); - - if (exit) { - break; - } - - do { - count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); - - if (count1 !== 0) { - dest -= count1; - cursor1 -= count1; - length1 -= count1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = count1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - if (length1 === 0) { - exit = true; - break; - } - } - - array[dest--] = tmp[cursor2--]; - - if (--length2 === 1) { - exit = true; - break; - } - - count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); - - if (count2 !== 0) { - dest -= count2; - cursor2 -= count2; - length2 -= count2; - customDest = dest + 1; - customCursor = cursor2 + 1; - - for (i = 0; i < count2; i++) { - array[customDest + i] = tmp[customCursor + i]; - } - - if (length2 <= 1) { - exit = true; - break; - } - } - - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - exit = true; - break; - } - - minGallop--; - - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (minGallop < 0) { - minGallop = 0; - } - - minGallop += 2; - } - - this.minGallop = minGallop; - - if (minGallop < 1) { - this.minGallop = 1; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - - } else if (length2 === 0) { - throw new Error('mergeHigh preconditions were not respected'); - - } else { - customCursor = dest - (length2 - 1); - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - } -}; - -/** - * Sort an array in the range [lo, hi) using TimSort. - * - * @param {array} array - The array to sort. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {function=} compare - Item comparison function. Default is alphabetical. - */ -function sort (array, lo, hi, compare) { - if (!Array.isArray(array)) { - throw new TypeError('Can only sort arrays'); - } - - /* - * Handle the case where a comparison function is not provided. We do - * lexicographic sorting - */ - - if (lo === undefined) { - lo = 0; - } - - if (hi === undefined) { - hi = array.length; - } - - if (compare === undefined) { - compare = alphabeticalCompare; - } - - var remaining = hi - lo; - - // The array is already sorted - if (remaining < 2) { - return; - } - - var runLength = 0; - // On small arrays binary sort can be used directly - if (remaining < DEFAULT_MIN_MERGE) { - runLength = makeAscendingRun(array, lo, hi, compare); - binaryInsertionSort(array, lo, hi, lo + runLength, compare); - return; - } - - var ts = new TimSort(array, compare); - - var minRun = minRunLength(remaining); - - do { - runLength = makeAscendingRun(array, lo, hi, compare); - if (runLength < minRun) { - var force = remaining; - if (force > minRun) { - force = minRun; - } - - binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); - runLength = force; - } - // Push new run and merge if necessary - ts.pushRun(lo, runLength); - ts.mergeRuns(); - - // Go find next run - remaining -= runLength; - lo += runLength; - - } while (remaining !== 0); - - // Force merging of remaining runs - ts.forceMergeRuns(); -} - -var FixedArray = function FixedArray(size) { - this._count = 0; - this._data = new Array(size); -}; - -var prototypeAccessors$7 = { length: { configurable: true },data: { configurable: true } }; - -FixedArray.prototype._resize = function _resize (size) { - var this$1 = this; - - if (size > this._data.length) { - for (var i = this._data.length; i < size; ++i) { - this$1._data[i] = undefined; - } - } -}; - -prototypeAccessors$7.length.get = function () { - return this._count; -}; - -prototypeAccessors$7.data.get = function () { - return this._data; -}; - -FixedArray.prototype.reset = function reset () { - var this$1 = this; - - for (var i = 0; i < this._count; ++i) { - this$1._data[i] = undefined; - } - - this._count = 0; -}; - -FixedArray.prototype.push = function push (val) { - if (this._count >= this._data.length) { - this._resize(this._data.length * 2); - } - - this._data[this._count] = val; - ++this._count; -}; - -FixedArray.prototype.pop = function pop () { - --this._count; - - if (this._count < 0) { - this._count = 0; - } - - var ret = this._data[this._count]; - this._data[this._count] = undefined; - - return ret; -}; - -FixedArray.prototype.fastRemove = function fastRemove (idx) { - if (idx >= this._count) { - return; - } - - var last = this._count - 1; - this._data[idx] = this._data[last]; - this._data[last] = undefined; - this._count -= 1; -}; - -FixedArray.prototype.indexOf = function indexOf (val) { - var idx = this._data.indexOf(val); - if (idx >= this._count) { - return -1; - } - - return idx; -}; - -FixedArray.prototype.sort = function sort$1 (cmp) { - return sort(this._data, 0, this._count, cmp); -}; - -Object.defineProperties( FixedArray.prototype, prototypeAccessors$7 ); - -var Pool = function Pool(fn, size) { - var this$1 = this; - - this._fn = fn; - this._idx = size - 1; - this._frees = new Array(size); - - for (var i = 0; i < size; ++i) { - this$1._frees[i] = fn(); - } -}; - -Pool.prototype._expand = function _expand (size) { - var this$1 = this; - - var old = this._frees; - this._frees = new Array(size); - - var len = size - old.length; - for (var i = 0; i < len; ++i) { - this$1._frees[i] = this$1._fn(); - } - - for (var i$1 = len, j = 0; i$1 < size; ++i$1, ++j) { - this$1._frees[i$1] = old[j]; - } - - this._idx += len; -}; - -Pool.prototype.alloc = function alloc () { - // create some more space (expand by 20%, minimum 1) - if (this._idx < 0) { - this._expand(Math.round(this._frees.length * 1.2) + 1); - } - - var ret = this._frees[this._idx]; - this._frees[this._idx] = null; - --this._idx; - - return ret; -}; - -Pool.prototype.free = function free (obj) { - ++this._idx; - this._frees[this._idx] = obj; -}; - -// NOTE: you must have `_prev` and `_next` field in the object returns by `fn` - -var LinkedArray = function LinkedArray(fn, size) { - this._fn = fn; - this._count = 0; - this._head = null; - this._tail = null; - - this._pool = new Pool(fn, size); -}; - -var prototypeAccessors$8 = { head: { configurable: true },tail: { configurable: true },length: { configurable: true } }; - -prototypeAccessors$8.head.get = function () { - return this._head; -}; - -prototypeAccessors$8.tail.get = function () { - return this._tail; -}; - -prototypeAccessors$8.length.get = function () { - return this._count; -}; - -LinkedArray.prototype.add = function add () { - var node = this._pool.alloc(); - - if (!this._tail) { - this._head = node; - } else { - this._tail._next = node; - node._prev = this._tail; - } - this._tail = node; - this._count += 1; - - return node; -}; - -LinkedArray.prototype.remove = function remove (node) { - if (node._prev) { - node._prev._next = node._next; - } else { - this._head = node._next; - } - - if (node._next) { - node._next._prev = node._prev; - } else { - this._tail = node._prev; - } - - node._next = null; - node._prev = null; - this._pool.free(node); - this._count -= 1; -}; - -LinkedArray.prototype.forEach = function forEach (fn, binder) { - var this$1 = this; - - var cursor = this._head; - if (!cursor) { - return; - } - - if (binder) { - fn = fn.bind(binder); - } - - var idx = 0; - var next = cursor; - - while (cursor) { - next = cursor._next; - fn(cursor, idx, this$1); - - cursor = next; - ++idx; - } -}; - -Object.defineProperties( LinkedArray.prototype, prototypeAccessors$8 ); - -var RecyclePool = function RecyclePool(fn, size) { - var this$1 = this; - - this._fn = fn; - this._count = 0; - this._data = new Array(size); - - for (var i = 0; i < size; ++i) { - this$1._data[i] = fn(); - } -}; - -var prototypeAccessors$9 = { length: { configurable: true },data: { configurable: true } }; - -prototypeAccessors$9.length.get = function () { - return this._count; -}; - -prototypeAccessors$9.data.get = function () { - return this._data; -}; - -RecyclePool.prototype.reset = function reset () { - this._count = 0; -}; - -RecyclePool.prototype.resize = function resize (size) { - var this$1 = this; - - if (size > this._data.length) { - for (var i = this._data.length; i < size; ++i) { - this$1._data[i] = this$1._fn(); - } - } -}; - -RecyclePool.prototype.add = function add () { - if (this._count >= this._data.length) { - this.resize(this._data.length * 2); - } - - return this._data[this._count++]; -}; - -RecyclePool.prototype.remove = function remove (idx) { - if (idx >= this._count) { - return; - } - - var last = this._count - 1; - var tmp = this._data[idx]; - this._data[idx] = this._data[last]; - this._data[last] = tmp; - this._count -= 1; -}; - -RecyclePool.prototype.sort = function sort$1 (cmp) { - return sort(this._data, 0, this._count, cmp); -}; - -Object.defineProperties( RecyclePool.prototype, prototypeAccessors$9 ); - -var _bufferPools = Array(8); -for (var i = 0; i < 8; ++i) { - _bufferPools[i] = []; -} - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Scene = function Scene() { - this._lights = new FixedArray(16); - this._models = new FixedArray(16); - this._cameras = new FixedArray(16); - this._debugCamera = null; - - // NOTE: we don't use pool for views (because it's less changed and it doesn't have poolID) - this._views = []; -}; - -Scene.prototype._add = function _add (pool, item) { - if (item._poolID !== -1) { - return; - } - - pool.push(item); - item._poolID = pool.length - 1; -}; - -Scene.prototype._remove = function _remove (pool, item) { - if (item._poolID === -1) { - return; - } - - pool.data[pool.length-1]._poolID = item._poolID; - pool.fastRemove(item._poolID); - item._poolID = -1; -}; - -Scene.prototype.reset = function reset () { - var this$1 = this; - - for (var i = 0; i < this._models.length; ++i) { - var model = this$1._models.data[i]; - model._cullingMask = -1; - } -}; - -Scene.prototype.setDebugCamera = function setDebugCamera (cam) { - this._debugCamera = cam; -}; - -// camera - -Scene.prototype.getCameraCount = function getCameraCount () { - return this._cameras.length; -}; - -Scene.prototype.getCamera = function getCamera (idx) { - return this._cameras.data[idx]; -}; - -Scene.prototype.addCamera = function addCamera (camera) { - this._add(this._cameras, camera); -}; - -Scene.prototype.removeCamera = function removeCamera (camera) { - this._remove(this._cameras, camera); -}; - -// model - -Scene.prototype.getModelCount = function getModelCount () { - return this._models.length; -}; - -Scene.prototype.getModel = function getModel (idx) { - return this._models.data[idx]; -}; - -Scene.prototype.addModel = function addModel (model) { - this._add(this._models, model); -}; - -Scene.prototype.removeModel = function removeModel (model) { - this._remove(this._models, model); -}; - -// light - -Scene.prototype.getLightCount = function getLightCount () { - return this._lights.length; -}; - -Scene.prototype.getLight = function getLight (idx) { - return this._lights.data[idx]; -}; - -Scene.prototype.addLight = function addLight (light) { - this._add(this._lights, light); -}; - -Scene.prototype.removeLight = function removeLight (light) { - this._remove(this._lights, light); -}; - -// view - -Scene.prototype.addView = function addView (view) { - if (this._views.indexOf(view) === -1) { - this._views.push(view); - } -}; - -Scene.prototype.removeView = function removeView (view) { - var idx = this._views.indexOf(view); - if (idx !== -1) { - this._views.splice(idx, 1); - } -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _shdID = 0; - -function _generateDefines(defs) { - var defines = []; - for (var def in defs) { - if (defs[def] === true) { - defines.push(("#define " + def)); - } - } - return defines.join('\n'); -} - -function _replaceMacroNums(string, defs) { - var cache = {}; - var tmp = string; - for (var def in defs) { - if (Number.isInteger(defs[def])) { - cache[def] = defs[def]; - } - } - for (var def$1 in cache) { - var reg = new RegExp(def$1, 'g'); - tmp = tmp.replace(reg, cache[def$1]); - } - return tmp; -} - -function _unrollLoops(string) { - var pattern = /#pragma for (\w+) in range\(\s*(\d+)\s*,\s*(\d+)\s*\)([\s\S]+?)#pragma endFor/g; - function replace(match, index, begin, end, snippet) { - var unroll = ''; - var parsedBegin = parseInt(begin); - var parsedEnd = parseInt(end); - if (parsedBegin.isNaN || parsedEnd.isNaN) { - console.error('Unroll For Loops Error: begin and end of range must be an int num.'); - } - for (var i = parsedBegin; i < parsedEnd; ++i) { - unroll += snippet.replace(new RegExp(("{" + index + "}"), 'g'), i); - } - return unroll; - } - return string.replace(pattern, replace); -} - -var ProgramLib = function ProgramLib(device, templates, chunks) { - var this$1 = this; - if ( templates === void 0 ) templates = []; - if ( chunks === void 0 ) chunks = {}; - - this._device = device; - this._precision = "precision highp float;\n"; - - // register templates - this._templates = {}; - for (var i = 0; i < templates.length; ++i) { - var tmpl = templates[i]; - this$1.define(tmpl); - } - - // register chunks - this._chunks = {}; - Object.assign(this._chunks, chunks); - - this._cache = {}; -}; - -/** - * @param {string} name - * @param {string} template - * @param {Array} options - * - * @example: - * programLib.define('foobar', vertTmpl, fragTmpl, [ - * { name: 'shadow' }, - * { name: 'lightCount', min: 1, max: 4 } - * ]); - */ -ProgramLib.prototype.define = function define (prog) { - let name = prog.name, vert = prog.vert, frag = prog.frag, defines = prog.defines; - if (this._templates[name]) { - console.warn(`Failed to define shader ${name}: already exists.`); - return; - } - - let id = ++_shdID; - - // calculate option mask offset - let offset = 0; - for (let i = 0; i < defines.length; ++i) { - let def = defines[i]; - let cnt = 1; - - if (def.type === 'number') { - let range = def.range || []; - def.min = range[0] || 0; - def.max = range[1] || 4; - cnt = Math.ceil(Math.log2(def.max - def.min)); - - def._map = function (value) { - return (value - this.min) << this._offset; - }.bind(def); - } else { // boolean - def._map = function (value) { - if (value) { - return 1 << this._offset; - } - return 0; - }.bind(def); - } - - offset += cnt; - def._offset = offset; - } - - vert = this._precision + vert; - frag = this._precision + frag; - - // store it - this._templates[name] = { - id, - name, - vert, - frag, - defines, - attributes: prog.attributes, - uniforms: prog.uniforms, - extensions: prog.extensions - }; -}; - -/** - * @param {string} name - * @param {Object} options - */ -ProgramLib.prototype.getKey = function getKey (name, defines) { - var tmpl = this._templates[name]; - var key = 0; - for (var i = 0; i < tmpl.defines.length; ++i) { - var tmplDefs = tmpl.defines[i]; - var value = defines[tmplDefs.name]; - if (value === undefined) { - continue; - } - - key |= tmplDefs._map(value); - } - - return key << 8 | tmpl.id; -}; - -ProgramLib.prototype.getTemplate = function (name) { - return this._templates[name]; -} - -/** - * @param {string} name - * @param {Object} options - */ -ProgramLib.prototype.getProgram = function getProgram (name, defines) { - var key = this.getKey(name, defines); - var program = this._cache[key]; - if (program) { - return program; - } - - // get template - var tmpl = this._templates[name]; - var customDef = _generateDefines(defines) + '\n'; - var vert = _replaceMacroNums(tmpl.vert, defines); - vert = customDef + _unrollLoops(vert); - var frag = _replaceMacroNums(tmpl.frag, defines); - frag = customDef + _unrollLoops(frag); - - program = new gfx.Program(this._device, { - vert: vert, - frag: frag - }); - program.link(); - this._cache[key] = program; - - return program; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _m3_tmp$1 = mat3.create(); -var _m4_tmp$2 = mat4.create(); - -var _stageInfos = new RecyclePool(function () { - return { - stage: null, - items: null, - }; -}, 8); - -var _float2_pool = new RecyclePool(function () { - return new Float32Array(2); -}, 8); - -var _float3_pool = new RecyclePool(function () { - return new Float32Array(3); -}, 8); - -var _float4_pool = new RecyclePool(function () { - return new Float32Array(4); -}, 8); - -var _float9_pool = new RecyclePool(function () { - return new Float32Array(9); -}, 8); - -var _float16_pool = new RecyclePool(function () { - return new Float32Array(16); -}, 8); - -var _float64_pool = new RecyclePool(function () { - return new Float32Array(64); -}, 8); - -var _int2_pool = new RecyclePool(function () { - return new Int32Array(2); -}, 8); - -var _int3_pool = new RecyclePool(function () { - return new Int32Array(3); -}, 8); - -var _int4_pool = new RecyclePool(function () { - return new Int32Array(4); -}, 8); - -var _int64_pool = new RecyclePool(function () { - return new Int32Array(64); -}, 8); - -var _type2uniformValue = {}; -_type2uniformValue[enums.PARAM_INT] = function (value) { - return value; - }; -_type2uniformValue[enums.PARAM_INT2] = function (value) { - return vec2.array(_int2_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_INT3] = function (value) { - return vec3.array(_int3_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_INT4] = function (value) { - return vec4.array(_int4_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_FLOAT] = function (value) { - return value; - }; -_type2uniformValue[enums.PARAM_FLOAT2] = function (value) { - return vec2.array(_float2_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_FLOAT3] = function (value) { - return vec3.array(_float3_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_FLOAT4] = function (value) { - return vec4.array(_float4_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_COLOR3] = function (value) { - return color3.array(_float3_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_COLOR4] = function (value) { - return color4.array(_float4_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_MAT2] = function (value) { - return mat2.array(_float4_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_MAT3] = function (value) { - return mat3.array(_float9_pool.add(), value); - }; -_type2uniformValue[enums.PARAM_MAT4] = function (value) { - return mat4.array(_float16_pool.add(), value); - }; - -var _type2uniformArrayValue = {}; -_type2uniformArrayValue[enums.PARAM_INT] = { - func: function func (values) { - var result = _int64_pool.add(); - for (var i = 0; i < values.length; ++i) { - result[i] = values[i]; - } - return result; - }, - size: 1, - }; -_type2uniformArrayValue[enums.PARAM_INT2] = { - func: function func (values) { - var result = _int64_pool.add(); - for (var i = 0; i < values.length; ++i) { - result[2 * i] = values[i].x; - result[2 * i + 1] = values[i].y; - } - return result; - }, - size: 2, - }; -_type2uniformArrayValue[enums.PARAM_INT3] = { - func: undefined, - size: 3, - }; -_type2uniformArrayValue[enums.PARAM_INT4] = { - func: function func (values) { - var result = _int64_pool.add(); - for (var i = 0; i < values.length; ++i) { - var v = values[i]; - result[4 * i] = v.x; - result[4 * i + 1] = v.y; - result[4 * i + 2] = v.z; - result[4 * i + 3] = v.w; - } - return result; - }, - size: 4, - }; -_type2uniformArrayValue[enums.PARAM_FLOAT] = { - func: function func (values) { - var result = _float64_pool.add(); - for (var i = 0; i < values.length; ++i) { - result[i] = values[i]; - } - return result; - }, - size: 1 - }; -_type2uniformArrayValue[enums.PARAM_FLOAT2] = { - func: function func (values) { - var result = _float64_pool.add(); - for (var i = 0; i < values.length; ++i) { - result[2 * i] = values[i].x; - result[2 * i + 1] = values[i].y; - } - return result; - }, - size: 2, - }; -_type2uniformArrayValue[enums.PARAM_FLOAT3] = { - func: undefined, - size: 3, - }; -_type2uniformArrayValue[enums.PARAM_FLOAT4] = { - func: function func (values) { - var result = _float64_pool.add(); - for (var i = 0; i < values.length; ++i) { - var v = values[i]; - result[4 * i] = v.x; - result[4 * i + 1] = v.y; - result[4 * i + 2] = v.z; - result[4 * i + 3] = v.w; - } - return result; - }, - size: 4, - }; -_type2uniformArrayValue[enums.PARAM_COLOR3] = { - func: undefined, - size: 3, - }; -_type2uniformArrayValue[enums.PARAM_COLOR4] = { - func: function func (values) { - var result = _float64_pool.add(); - for (var i = 0; i < values.length; ++i) { - var v = values[i]; - result[4 * i] = v.r; - result[4 * i + 1] = v.g; - result[4 * i + 2] = v.b; - result[4 * i + 3] = v.a; - } - return result; - }, - size: 4, - }; -_type2uniformArrayValue[enums.PARAM_MAT2] = { - func: function func (values) { - var result = _float64_pool.add(); - for (var i = 0; i < values.length; ++i) { - var v = values[i]; - result[4 * i] = v.m00; - result[4 * i + 1] = v.m01; - result[4 * i + 2] = v.m02; - result[4 * i + 3] = v.m03; - } - return result; - }, - size: 4 - }; -_type2uniformArrayValue[enums.PARAM_MAT3] = { - func: undefined, - size: 9 - }; -_type2uniformArrayValue[enums.PARAM_MAT4] = { - func: function func (values) { - var result = _float64_pool.add(); - for (var i = 0; i < values.length; ++i) { - var v = values[i]; - result[16 * i] = v.m00; - result[16 * i + 1] = v.m01; - result[16 * i + 2] = v.m02; - result[16 * i + 3] = v.m03; - result[16 * i + 4] = v.m04; - result[16 * i + 5] = v.m05; - result[16 * i + 6] = v.m06; - result[16 * i + 7] = v.m07; - result[16 * i + 8] = v.m08; - result[16 * i + 9] = v.m09; - result[16 * i + 10] = v.m10; - result[16 * i + 11] = v.m11; - result[16 * i + 12] = v.m12; - result[16 * i + 13] = v.m13; - result[16 * i + 14] = v.m14; - result[16 * i + 15] = v.m15; - } - return result; - }, - size: 16 - }; - -var Base = function Base(device, opts) { - var obj; - - this._device = device; - this._programLib = new ProgramLib(device, opts.programTemplates, opts.programChunks); - this._opts = opts; - this._type2defaultValue = ( obj = {}, obj[enums.PARAM_INT] = 0, obj[enums.PARAM_INT2] = vec2.new(0, 0), obj[enums.PARAM_INT3] = vec3.new(0, 0, 0), obj[enums.PARAM_INT4] = vec4.new(0, 0, 0, 0), obj[enums.PARAM_FLOAT] = 0.0, obj[enums.PARAM_FLOAT2] = vec2.new(0, 0), obj[enums.PARAM_FLOAT3] = vec3.new(0, 0, 0), obj[enums.PARAM_FLOAT4] = vec4.new(0, 0, 0, 0), obj[enums.PARAM_COLOR3] = color3.new(0, 0, 0), obj[enums.PARAM_COLOR4] = color4.new(0, 0, 0, 1), obj[enums.PARAM_MAT2] = mat2.create(), obj[enums.PARAM_MAT3] = mat3.create(), obj[enums.PARAM_MAT4] = mat4.create(), obj[enums.PARAM_TEXTURE_2D] = opts.defaultTexture, obj[enums.PARAM_TEXTURE_CUBE] = opts.defaultTextureCube, obj); - this._stage2fn = {}; - this._usedTextureUnits = 0; - - this._viewPools = new RecyclePool(function () { - return new View(); - }, 8); - - this._drawItemsPools = new RecyclePool(function () { - return { - model: null, - node: null, - ia: null, - effect: null, - defines: null, - }; - }, 100); - - this._stageItemsPools = new RecyclePool(function () { - return new RecyclePool(function () { - return { - model: null, - node: null, - ia: null, - effect: null, - defines: null, - technique: null, - sortKey: -1, - }; - }, 100); - }, 16); -}; - -Base.prototype._resetTextuerUnit = function _resetTextuerUnit () { - this._usedTextureUnits = 0; -}; - -Base.prototype._allocTextuerUnit = function _allocTextuerUnit () { - var device = this._device; - - var unit = this._usedTextureUnits; - if (unit >= device._caps.maxTextureUnits) { - console.warn(("Trying to use " + unit + " texture units while this GPU supports only " + (device._caps.maxTextureUnits))); - } - - this._usedTextureUnits += 1; - return unit; -}; - -Base.prototype._registerStage = function _registerStage (name, fn) { - this._stage2fn[name] = fn; -}; - -Base.prototype._reset = function _reset () { - this._viewPools.reset(); - this._stageItemsPools.reset(); -}; - -Base.prototype._requestView = function _requestView () { - return this._viewPools.add(); -}; - -Base.prototype._render = function _render (view, scene) { - var this$1 = this; - - var device = this._device; - - // setup framebuffer - device.setFrameBuffer(view._framebuffer); - - // setup viewport - device.setViewport( - view._rect.x, - view._rect.y, - view._rect.w, - view._rect.h - ); - - // setup clear - var clearOpts = {}; - if (view._clearFlags & enums.CLEAR_COLOR) { - clearOpts.color = [ - view._color.r, - view._color.g, - view._color.b, - view._color.a - ]; - } - if (view._clearFlags & enums.CLEAR_DEPTH) { - clearOpts.depth = view._depth; - } - if (view._clearFlags & enums.CLEAR_STENCIL) { - clearOpts.stencil = view._stencil; - } - device.clear(clearOpts); - - // get all draw items - this._drawItemsPools.reset(); - - for (var i = 0; i < scene._models.length; ++i) { - var model = scene._models.data[i]; - - // filter model by view - if ((model._cullingMask & view._cullingMask) === 0) { - continue; - } - - for (var m = 0; m < model.drawItemCount; ++m) { - var drawItem = this$1._drawItemsPools.add(); - model.extractDrawItem(drawItem, m); - } - } - - // TODO: update frustum - // TODO: visbility test - // frustum.update(view._viewProj); - - // dispatch draw items to different stage - _stageInfos.reset(); - - for (var i$1 = 0; i$1 < view._stages.length; ++i$1) { - var stage = view._stages[i$1]; - var stageItems = this$1._stageItemsPools.add(); - stageItems.reset(); - - for (var j = 0; j < this._drawItemsPools.length; ++j) { - var drawItem$1 = this$1._drawItemsPools.data[j]; - var tech = drawItem$1.effect.getTechnique(stage); - - if (tech) { - var stageItem = stageItems.add(); - stageItem.model = drawItem$1.model; - stageItem.node = drawItem$1.node; - stageItem.ia = drawItem$1.ia; - stageItem.effect = drawItem$1.effect; - stageItem.defines = drawItem$1.defines; - stageItem.technique = tech; - stageItem.sortKey = -1; - } - } - - var stageInfo = _stageInfos.add(); - stageInfo.stage = stage; - stageInfo.items = stageItems; - } - - // render stages - for (var i$2 = 0; i$2 < _stageInfos.length; ++i$2) { - var info = _stageInfos.data[i$2]; - var fn = this$1._stage2fn[info.stage]; - - fn(view, info.items); - } -}; - -Base.prototype._draw = function _draw (item) { - var this$1 = this; - - var device = this._device; - var programLib = this._programLib; - var node = item.node; - var ia = item.ia; - var effect = item.effect; - var technique = item.technique; - var defines = item.defines; - - // reset the pool - // NOTE: we can use drawCounter optimize this - // TODO: should be configurable - _float2_pool.reset(); - _float3_pool.reset(); - _float4_pool.reset(); - _float9_pool.reset(); - _float16_pool.reset(); - _float64_pool.reset(); - _int2_pool.reset(); - _int3_pool.reset(); - _int4_pool.reset(); - _int64_pool.reset(); - - // set common uniforms - // TODO: try commit this depends on effect - // { - node.getWorldMatrix(_m4_tmp$2); - device.setUniform('model', mat4.array(_float16_pool.add(), _m4_tmp$2)); - - var inverse = mat3.invert(_m3_tmp$1, mat3.fromMat4(_m3_tmp$1, _m4_tmp$2)); - if (inverse) { - mat3.transpose(_m3_tmp$1, inverse); - device.setUniform('normalMatrix', mat3.array(_float9_pool.add(), _m3_tmp$1)); - } - // } - - // set technique uniforms - for (let name in effect._properties) { - let prop = effect._properties[name]; - let param = prop.value; - - if (param === undefined) { - param = prop.val; - } - - if (param === undefined) { - param = this$1._type2defaultValue[prop.type]; - } - - if (param === undefined) { - console.warn(("Failed to set technique property " + (prop.name) + ", value not found.")); - continue; - } - - if ( - prop.type === enums.PARAM_TEXTURE_2D || - prop.type === enums.PARAM_TEXTURE_CUBE - ) { - if (prop.size !== undefined) { - if (prop.size !== param.length) { - console.error(("The length of texture array (" + (param.length) + ") is not corrent(expect " + (prop.size) + ").")); - continue; - } - var slots = _int64_pool.add(); - for (var index = 0; index < param.length; ++index) { - slots[index] = this$1._allocTextuerUnit(); - } - device.setTextureArray(prop.name, param, slots); - } else { - device.setTexture(prop.name, param, this$1._allocTextuerUnit()); - } - } else { - var convertedValue = (void 0); - if (param instanceof Float32Array || param instanceof Int32Array) { - convertedValue = param; - } - else if (prop.size !== undefined) { - var convertArray = _type2uniformArrayValue[prop.type]; - if (convertArray.func === undefined) { - console.error('Uniform array of color3/int3/float3/mat3 can not be supportted!'); - continue; - } - if (prop.size * convertArray.size > 64) { - console.error('Uniform array is too long!'); - continue; - } - convertedValue = convertArray.func(param); - } else { - var convertFn = _type2uniformValue[prop.type]; - convertedValue = convertFn(param); - } - device.setUniform(prop.name, convertedValue); - } - } - - // for each pass - for (var i$1 = 0; i$1 < technique._passes.length; ++i$1) { - var pass = technique._passes[i$1]; - var count = ia.getPrimitiveCount(); - - // set vertex buffer - device.setVertexBuffer(0, ia._vertexBuffer); - - // set index buffer - if (ia._indexBuffer) { - device.setIndexBuffer(ia._indexBuffer); - } - - // set primitive type - device.setPrimitiveType(ia._primitiveType); - - // set program - var program = programLib.getProgram(pass._programName, defines); - device.setProgram(program); - - // cull mode - device.setCullMode(pass._cullMode); - - // blend - if (pass._blend) { - device.enableBlend(); - device.setBlendFuncSep( - pass._blendSrc, - pass._blendDst, - pass._blendSrcAlpha, - pass._blendDstAlpha - ); - device.setBlendEqSep( - pass._blendEq, - pass._blendAlphaEq - ); - device.setBlendColor32(pass._blendColor); - } - - // depth test & write - if (pass._depthTest) { - device.enableDepthTest(); - device.setDepthFunc(pass._depthFunc); - } - if (pass._depthWrite) { - device.enableDepthWrite(); - } - - // stencil - if (pass._stencilTest) { - device.enableStencilTest(); - - // front - device.setStencilFuncFront( - pass._stencilFuncFront, - pass._stencilRefFront, - pass._stencilMaskFront - ); - device.setStencilOpFront( - pass._stencilFailOpFront, - pass._stencilZFailOpFront, - pass._stencilZPassOpFront, - pass._stencilWriteMaskFront - ); - - // back - device.setStencilFuncBack( - pass._stencilFuncBack, - pass._stencilRefBack, - pass._stencilMaskBack - ); - device.setStencilOpBack( - pass._stencilFailOpBack, - pass._stencilZFailOpBack, - pass._stencilZPassOpBack, - pass._stencilWriteMaskBack - ); - } - - // draw pass - device.draw(ia._start, count); - - this$1._resetTextuerUnit(); - } -}; - -var renderer = { - // config - addStage: config.addStage, - - // utils - createIA: createIA, - - // classes - Pass: Pass, - Technique: Technique, - Effect: Effect, - InputAssembler: InputAssembler, - View: View, - - Light: Light, - Camera: Camera, - Model: Model, - Scene: Scene, - - Base: Base, - ProgramLib: ProgramLib, -}; -Object.assign(renderer, enums); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _a16_view = new Float32Array(16); -var _a16_proj = new Float32Array(16); -var _a16_viewProj = new Float32Array(16); - -var ForwardRenderer = (function (superclass) { - function ForwardRenderer (device, builtin) { - superclass.call(this, device, builtin); - this._registerStage('transparent', this._transparentStage.bind(this)); - } - - if ( superclass ) ForwardRenderer.__proto__ = superclass; - ForwardRenderer.prototype = Object.create( superclass && superclass.prototype ); - ForwardRenderer.prototype.constructor = ForwardRenderer; - - ForwardRenderer.prototype.reset = function reset () { - this._reset(); - }; - - ForwardRenderer.prototype.render = function render (scene) { - var this$1 = this; - - this._reset(); - - scene._cameras.sort(function (a, b) { - if (a._sortDepth > b._sortDepth) { return 1; } - else if (a._sortDepth < b._sortDepth) { return -1; } - else { return 0; } - }); - - for (var i = 0; i < scene._cameras.length; ++i) { - var camera = scene._cameras.data[i]; - - // reset camera pollID after sort cameras - camera._poolID = i; - - this$1.renderCamera(camera, scene); - } - }; - - ForwardRenderer.prototype.renderCamera = function renderCamera (camera, scene) { - var canvas = this._device._gl.canvas; - - var view = camera.view; - var dirty = camera.dirty; - if (!view) { - view = this._requestView(); - dirty = true; - } - if (dirty) { - var width = canvas.width; - var height = canvas.height; - if (camera._framebuffer) { - width = camera._framebuffer._width; - height = camera._framebuffer._height; - } - camera.extractView(view, width, height); - } - this._render(view, scene); - }; - - ForwardRenderer.prototype._transparentStage = function _transparentStage (view, items) { - var this$1 = this; - - // update uniforms - this._device.setUniform('view', mat4.array(_a16_view, view._matView)); - this._device.setUniform('proj', mat4.array(_a16_proj, view._matProj)); - this._device.setUniform('viewProj', mat4.array(_a16_viewProj, view._matViewProj)); - - // draw it - for (var i = 0; i < items.length; ++i) { - var item = items.data[i]; - this$1._draw(item); - } - }; - - return ForwardRenderer; -}(renderer.Base)); - -var chunks = { - 'skinning.vert': '\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}', -}; - -var templates = [ - { - name: 'gray_sprite', - vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute mediump vec2 a_uv0;\nvarying mediump vec2 uv0;\nvoid main () {\n vec4 pos = viewProj * vec4(a_position, 1);\n gl_Position = pos;\n uv0 = a_uv0;\n}', - frag: '\n \nuniform sampler2D texture;\nvarying mediump vec2 uv0;\nuniform lowp vec4 color;\nvoid main () {\n vec4 c = color * texture2D(texture, uv0);\n float gray = 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;\n gl_FragColor = vec4(gray, gray, gray, c.a);\n}', - defines: [ - ], - }, - { - name: 'mesh', - vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\n#ifdef useAttributeColor\n attribute vec4 a_color;\n varying vec4 v_color;\n#endif\n#ifdef useTexture\n attribute vec2 a_uv0;\n varying vec2 uv0;\n#endif\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useSkinning\n \nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef useSkinning\n mvp = mvp * skinMatrix();\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n #ifdef useAttributeColor\n v_color = a_color;\n #endif\n gl_Position = pos;\n}', - frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying vec2 uv0;\n#endif\n#ifdef useAttributeColor\n varying vec4 v_color;\n#endif\nuniform vec4 color;\nvoid main () {\n vec4 o = color;\n \n #ifdef useAttributeColor\n o *= v_color;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n gl_FragColor = o;\n}', - defines: [ - { name: 'useTexture', }, - { name: 'useModel', }, - { name: 'useSkinning', }, - { name: 'useJointsTexture', }, - { name: 'useAttributeColor', } ], - }, - { - name: 'sprite', - vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', - frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', - defines: [ - { name: 'useTexture', }, - { name: 'useModel', }, - { name: 'alphaTest', }, - { name: 'useColor', } ], - } ]; - -var shaders = { - chunks: chunks, - templates: templates -}; - -// Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - -/** - * BaseRenderData is a core data abstraction for renderer, this is a abstract class. - * An inherited render data type should define raw vertex datas. - * User should also define the effect, vertex count and index count. - */ -var BaseRenderData = function BaseRenderData () { - this.material = null; - this.vertexCount = 0; - this.indiceCount = 0; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _pool; -var _dataPool = new Pool(function () { - return { - x: 0.0, - y: 0.0, - z: 0.0, - u: 0.0, - v: 0.0, - color: 0 - }; -}, 128); - -/** - * RenderData is most widely used render data type. - * It describes raw vertex data with a fixed data layout. - * Each vertex is described by five property: x, y, u, v, color. The data layout might be extended in the future. - * Vertex data objects are managed automatically by RenderData, user only need to set the dataLength property. - * User can also define rendering index orders for the vertex list. - */ -var RenderData = (function (BaseRenderData$$1) { - function RenderData () { - BaseRenderData$$1.call(this); - this._data = []; - this._indices = []; - - this._pivotX = 0; - this._pivotY = 0; - this._width = 0; - this._height = 0; - - this.uvDirty = true; - this.vertDirty = true; - } - - if ( BaseRenderData$$1 ) RenderData.__proto__ = BaseRenderData$$1; - RenderData.prototype = Object.create( BaseRenderData$$1 && BaseRenderData$$1.prototype ); - RenderData.prototype.constructor = RenderData; - - var prototypeAccessors = { type: { configurable: true },dataLength: { configurable: true } }; - - prototypeAccessors.type.get = function () { - return RenderData.type; - }; - - prototypeAccessors.dataLength.get = function () { - return this._data.length; - }; - - prototypeAccessors.dataLength.set = function (length) { - var data = this._data; - if (data.length !== length) { - // Free extra data - for (var i = length; i < data.length; i++) { - _dataPool.free(data[i]); - } - // Alloc needed data - for (var i$1 = data.length; i$1 < length; i$1++) { - data[i$1] = _dataPool.alloc(); - } - data.length = length; - } - }; - - RenderData.prototype.updateSizeNPivot = function updateSizeNPivot (width, height, pivotX, pivotY) { - if (width !== this._width || - height !== this._height || - pivotX !== this._pivotX || - pivotY !== this._pivotY) - { - this._width = width; - this._height = height; - this._pivotX = pivotX; - this._pivotY = pivotY; - this.vertDirty = true; - } - }; - - RenderData.alloc = function alloc () { - return _pool.alloc(); - }; - - RenderData.free = function free (data) { - if (data instanceof RenderData) { - for (var i = data.length-1; i > 0; i--) { - _dataPool.free(data._data[i]); - } - data._data.length = 0; - data._indices.length = 0; - data.material = null; - data.uvDirty = true; - data.vertDirty = true; - data.vertexCount = 0; - data.indiceCount = 0; - _pool.free(data); - } - }; - - Object.defineProperties( RenderData.prototype, prototypeAccessors ); - - return RenderData; -}(BaseRenderData)); - -RenderData.type = 'RenderData'; - -_pool = new Pool(function () { - return new RenderData(); -}, 32); - -// Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - -/** - * IARenderData is user customized render data type, user should provide the entier input assembler. - * IARenderData just defines a property `ia` for accessing the input assembler. - * It doesn't manage memory so users should manage the memory of input assembler by themselves. - */ -var IARenderData = (function (BaseRenderData$$1) { - function IARenderData () { - BaseRenderData$$1.call(this); - this.ia = null; - } - - if ( BaseRenderData$$1 ) IARenderData.__proto__ = BaseRenderData$$1; - IARenderData.prototype = Object.create( BaseRenderData$$1 && BaseRenderData$$1.prototype ); - IARenderData.prototype.constructor = IARenderData; - - var prototypeAccessors = { type: { configurable: true } }; - - prototypeAccessors.type.get = function () { - return IARenderData.type; - }; - - Object.defineProperties( IARenderData.prototype, prototypeAccessors ); - - return IARenderData; -}(BaseRenderData)); - -IARenderData.type = 'IARenderData'; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Asset = function Asset(persist) { - if ( persist === void 0 ) persist = true; - - this._loaded = false; - this._persist = persist; -}; - -Asset.prototype.unload = function unload () { - this._loaded = false; -}; - -Asset.prototype.reload = function reload () { - // TODO -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Texture$2 = (function (Asset$$1) { - function Texture(persist) { - if ( persist === void 0 ) persist = true; - - Asset$$1.call(this, persist); - - this._texture = null; - } - - if ( Asset$$1 ) Texture.__proto__ = Asset$$1; - Texture.prototype = Object.create( Asset$$1 && Asset$$1.prototype ); - Texture.prototype.constructor = Texture; - - Texture.prototype.getImpl = function getImpl () { - return this._texture; - }; - - Texture.prototype.getId = function getId () {}; - - Texture.prototype.destroy = function destroy () { - this._texture && this._texture.destroy(); - }; - - return Texture; -}(Asset)); - -/** - * JS Implementation of MurmurHash2 - * - * @author Gary Court - * @see http://github.com/garycourt/murmurhash-js - * @author Austin Appleby - * @see http://sites.google.com/site/murmurhash/ - * - * @param {string} str ASCII only - * @param {number} seed Positive integer only - * @return {number} 32-bit positive integer hash - */ - -function murmurhash2_32_gc(str, seed) { - var - l = str.length, - h = seed ^ l, - i = 0, - k; - - while (l >= 4) { - k = - ((str.charCodeAt(i) & 0xff)) | - ((str.charCodeAt(++i) & 0xff) << 8) | - ((str.charCodeAt(++i) & 0xff) << 16) | - ((str.charCodeAt(++i) & 0xff) << 24); - - k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - k ^= k >>> 24; - k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - - h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k; - - l -= 4; - ++i; - } - - switch (l) { - case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16; - case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8; - case 1: h ^= (str.charCodeAt(i) & 0xff); - h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - } - - h ^= h >>> 13; - h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - h ^= h >>> 15; - - return h >>> 0; -} - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -// function genHashCode (str) { -// var hash = 0; -// if (str.length == 0) { -// return hash; -// } -// for (var i = 0; i < str.length; i++) { -// var char = str.charCodeAt(i); -// hash = ((hash<<5)-hash)+char; -// hash = hash & hash; // Convert to 32bit integer -// } -// return hash; -// } - -function serializeDefines (defines) { - var str = ''; - for (var i = 0; i < defines.length; i++) { - str += defines[i].name + defines[i].value; - } - return str; -} - -function serializePass (pass) { - var str = pass._programName + pass._cullMode; - if (pass._blend) { - str += pass._blendEq + pass._blendAlphaEq + pass._blendSrc + pass._blendDst - + pass._blendSrcAlpha + pass._blendDstAlpha + pass._blendColor; - } - if (pass._depthTest) { - str += pass._depthWrite + pass._depthFunc; - } - if (pass._stencilTest) { - str += pass._stencilFuncFront + pass._stencilRefFront + pass._stencilMaskFront - + pass._stencilFailOpFront + pass._stencilZFailOpFront + pass._stencilZPassOpFront - + pass._stencilWriteMaskFront - + pass._stencilFuncBack + pass._stencilRefBack + pass._stencilMaskBack - + pass._stencilFailOpBack + pass._stencilZFailOpBack + pass._stencilZPassOpBack - + pass._stencilWriteMaskBack; - } - return str; -} - -function computeHash(material) { - var effect = material._effect; - var hashData = ''; - if (effect) { - var i, j, techData, param, prop, propKey; - - // effect._defines - hashData += serializeDefines(effect._defines); - // effect._techniques - for (i = 0; i < effect._techniques.length; i++) { - techData = effect._techniques[i]; - // technique.stageIDs - hashData += techData.stageIDs; - // technique._layer - // hashData += + techData._layer + "_"; - // technique.passes - for (j = 0; j < techData.passes.length; j++) { - hashData += serializePass(techData.passes[j]); - } - //technique._parameters - for (j = 0; j < techData._parameters.length; j++) { - param = techData._parameters[j]; - propKey = param.name; - prop = effect._properties[propKey]; - if (!prop) { - continue; - } - switch(param.type) { - case renderer.PARAM_INT: - case renderer.PARAM_FLOAT: - hashData += prop + ';'; - break; - case renderer.PARAM_INT2: - case renderer.PARAM_FLOAT2: - hashData += prop.x + ',' + prop.y + ';'; - break; - case renderer.PARAM_INT4: - case renderer.PARAM_FLOAT4: - hashData += prop.x + ',' + prop.y + ',' + prop.z + ',' + prop.w + ';'; - break; - case renderer.PARAM_COLOR4: - hashData += prop.r + ',' + prop.g + ',' + prop.b + ',' + prop.a + ';'; - break; - case renderer.PARAM_MAT2: - hashData += prop.m00 + ',' + prop.m01 + ',' + prop.m02 + ',' + prop.m03 + ';'; - break; - case renderer.PARAM_TEXTURE_2D: - case renderer.PARAM_TEXTURE_CUBE: - hashData += material._texIds[propKey] + ';'; - break; - case renderer.PARAM_INT3: - case renderer.PARAM_FLOAT3: - case renderer.PARAM_COLOR3: - case renderer.PARAM_MAT3: - case renderer.PARAM_MAT4: - hashData += JSON.stringify(prop) + ';'; - break; - default: - break; - } - } - } - } - return hashData ? murmurhash2_32_gc(hashData, 666) : hashData; -} - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Material = (function (Asset$$1) { - function Material(persist) { - if ( persist === void 0 ) persist = false; - - Asset$$1.call(this, persist); - - this._effect = null; // renderer.Effect - this._texIds = {}; // ids collected from texture defines - this._hash = ''; - } - - if ( Asset$$1 ) Material.__proto__ = Asset$$1; - Material.prototype = Object.create( Asset$$1 && Asset$$1.prototype ); - Material.prototype.constructor = Material; - - var prototypeAccessors = { hash: { configurable: true } }; - - prototypeAccessors.hash.get = function () { - return this._hash; - }; - - Material.prototype.updateHash = function updateHash (value) { - // this._hash = value || computeHash(this); - }; - - Object.defineProperties( Material.prototype, prototypeAccessors ); - - return Material; -}(Asset)); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var SpriteMaterial = (function (Material$$1) { - function SpriteMaterial() { - Material$$1.call(this, false); - - var pass = new renderer.Pass('sprite'); - pass.setDepth(false, false); - pass.setCullMode(gfx.CULL_NONE); - pass.setBlend( - gfx.BLEND_FUNC_ADD, - gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA, - gfx.BLEND_FUNC_ADD, - gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA - ); - - var mainTech = new renderer.Technique( - ['transparent'], - [ - { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer.PARAM_COLOR4 } ], - [ - pass - ] - ); - - this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer.Effect( - [ - mainTech ], - { - 'color': this._color - }, - [ - { name: 'useTexture', value: true }, - { name: 'useModel', value: false }, - { name: 'alphaTest', value: false }, - { name: 'useColor', value: true } ] - ); - - this._mainTech = mainTech; - this._texture = null; - } - - if ( Material$$1 ) SpriteMaterial.__proto__ = Material$$1; - SpriteMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); - SpriteMaterial.prototype.constructor = SpriteMaterial; - - var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; - - prototypeAccessors.effect.get = function () { - return this._effect; - }; - - prototypeAccessors.useTexture.get = function () { - return this._effect.getDefine('useTexture'); - }; - - prototypeAccessors.useTexture.set = function (val) { - this._effect.define('useTexture', val); - }; - - prototypeAccessors.useModel.get = function () { - return this._effect.getDefine('useModel'); - }; - - prototypeAccessors.useModel.set = function (val) { - this._effect.define('useModel', val); - }; - - prototypeAccessors.useColor.get = function () { - return this._effect.getDefine('useColor'); - }; - - prototypeAccessors.useColor.set = function (val) { - this._effect.define('useColor', val); - }; - - prototypeAccessors.texture.get = function () { - return this._texture; - }; - - prototypeAccessors.texture.set = function (val) { - if (this._texture !== val) { - this._texture = val; - this._effect.setProperty('texture', val.getImpl()); - this._texIds['texture'] = val.getId(); - } - }; - - prototypeAccessors.color.get = function () { - return this._color; - }; - - prototypeAccessors.color.set = function (val) { - var color = this._color; - color.r = val.r / 255; - color.g = val.g / 255; - color.b = val.b / 255; - color.a = val.a / 255; - this._effect.setProperty('color', color); - }; - - SpriteMaterial.prototype.clone = function clone () { - var copy = new SpriteMaterial(); - copy._mainTech.copy(this._mainTech); - copy.texture = this.texture; - copy.useTexture = this.useTexture; - copy.useModel = this.useModel; - copy.useColor = this.useColor; - copy.updateHash(); - return copy; - }; - - Object.defineProperties( SpriteMaterial.prototype, prototypeAccessors ); - - return SpriteMaterial; -}(Material)); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var GraySpriteMaterial = (function (Material$$1) { - function GraySpriteMaterial() { - Material$$1.call(this, false); - - var pass = new renderer.Pass('gray_sprite'); - pass.setDepth(false, false); - pass.setCullMode(gfx.CULL_NONE); - pass.setBlend( - gfx.BLEND_FUNC_ADD, - gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA, - gfx.BLEND_FUNC_ADD, - gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA - ); - - var mainTech = new renderer.Technique( - ['transparent'], - [ - { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer.PARAM_COLOR4 } ], - [ - pass - ] - ); - - this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer.Effect( - [ - mainTech ], - { - 'color': this._color - }, - [] - ); - - this._mainTech = mainTech; - this._texture = null; - } - - if ( Material$$1 ) GraySpriteMaterial.__proto__ = Material$$1; - GraySpriteMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); - GraySpriteMaterial.prototype.constructor = GraySpriteMaterial; - - var prototypeAccessors = { effect: { configurable: true },texture: { configurable: true },color: { configurable: true } }; - - prototypeAccessors.effect.get = function () { - return this._effect; - }; - - prototypeAccessors.texture.get = function () { - return this._texture; - }; - - prototypeAccessors.texture.set = function (val) { - if (this._texture !== val) { - this._texture = val; - this._effect.setProperty('texture', val.getImpl()); - this._texIds['texture'] = val.getId(); - } - }; - - prototypeAccessors.color.get = function () { - return this._color; - }; - - prototypeAccessors.color.set = function (val) { - var color = this._color; - color.r = val.r / 255; - color.g = val.g / 255; - color.b = val.b / 255; - color.a = val.a / 255; - this._effect.setProperty('color', color); - }; - - GraySpriteMaterial.prototype.clone = function clone () { - var copy = new GraySpriteMaterial(); - copy._mainTech.copy(this._mainTech); - copy.texture = this.texture; - copy.color = this.color; - copy.updateHash(); - return copy; - }; - - Object.defineProperties( GraySpriteMaterial.prototype, prototypeAccessors ); - - return GraySpriteMaterial; -}(Material)); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var StencilMaterial = (function (Material$$1) { - function StencilMaterial() { - Material$$1.call(this, false); - - this._pass = new renderer.Pass('sprite'); - this._pass.setDepth(false, false); - this._pass.setCullMode(gfx.CULL_NONE); - this._pass.setBlend( - gfx.BLEND_FUNC_ADD, - gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA, - gfx.BLEND_FUNC_ADD, - gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA - ); - - var mainTech = new renderer.Technique( - ['transparent'], - [ - { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'alphaThreshold', type: renderer.PARAM_FLOAT }, - { name: 'color', type: renderer.PARAM_COLOR4 } ], - [ - this._pass - ] - ); - - this._effect = new renderer.Effect( - [ - mainTech ], - { - 'color': {r: 1, g: 1, b: 1, a: 1} - }, - [ - { name: 'useTexture', value: true }, - { name: 'useModel', value: false }, - { name: 'alphaTest', value: true }, - { name: 'useColor', value: true } ] - ); - - this._mainTech = mainTech; - this._texture = null; - } - - if ( Material$$1 ) StencilMaterial.__proto__ = Material$$1; - StencilMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); - StencilMaterial.prototype.constructor = StencilMaterial; - - var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },useColor: { configurable: true },texture: { configurable: true },alphaThreshold: { configurable: true } }; - - prototypeAccessors.effect.get = function () { - return this._effect; - }; - - prototypeAccessors.useTexture.get = function () { - return this._effect.getDefine('useTexture'); - }; - - prototypeAccessors.useTexture.set = function (val) { - this._effect.define('useTexture', val); - }; - - prototypeAccessors.useModel.get = function () { - return this._effect.getDefine('useModel'); - }; - - prototypeAccessors.useModel.set = function (val) { - this._effect.define('useModel', val); - }; - - prototypeAccessors.useColor.get = function () { - return this._effect.getDefine('useColor'); - }; - - prototypeAccessors.useColor.set = function (val) { - this._effect.define('useColor', val); - }; - - prototypeAccessors.texture.get = function () { - return this._texture; - }; - - prototypeAccessors.texture.set = function (val) { - if (this._texture !== val) { - this._texture = val; - this._effect.setProperty('texture', val.getImpl()); - this._texIds['texture'] = val.getId(); - } - }; - - prototypeAccessors.alphaThreshold.get = function () { - return this._effect.getProperty('alphaThreshold'); - }; - - prototypeAccessors.alphaThreshold.set = function (val) { - this._effect.setProperty('alphaThreshold', val); - }; - - StencilMaterial.prototype.clone = function clone () { - var copy = new StencilMaterial(); - copy._mainTech.copy(this._mainTech); - copy.useTexture = this.useTexture; - copy.useModel = this.useModel; - copy.useColor = this.useColor; - copy.texture = this.texture; - copy.alphaThreshold = this.alphaThreshold; - copy.updateHash(); - return copy; - }; - - Object.defineProperties( StencilMaterial.prototype, prototypeAccessors ); - - return StencilMaterial; -}(Material)); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var MeshMaterial = (function (Material$$1) { - function MeshMaterial() { - Material$$1.call(this, false); - - var pass = new renderer.Pass('mesh'); - pass.setDepth(false, false); - pass.setCullMode(gfx.CULL_NONE); - pass.setBlend( - gfx.BLEND_FUNC_ADD, - gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA, - gfx.BLEND_FUNC_ADD, - gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA - ); - - var mainTech = new renderer.Technique( - ['transparent'], - [ - { name: 'texture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer.PARAM_COLOR4 }, - - { name: 'u_jointsTexture', type: renderer.PARAM_TEXTURE_2D }, - { name: 'u_jointsTextureSize', type: renderer.PARAM_FLOAT }, - { name: 'u_jointMatrices', type: renderer.PARAM_MAT4 } ], - [ - pass - ] - ); - - this._effect = new renderer.Effect( - [ - mainTech ], - { - 'color': {r: 1, g: 1, b: 1, a: 1} - }, - [ - { name: 'useTexture', value: true }, - { name: 'useModel', value: false }, - { name: 'useSkinning', value: false }, - { name: 'useJointsTexture', valu: true}, - { name: 'useAttributeColor', valu: false} ] - ); - - this._mainTech = mainTech; - this._texture = null; - this._jointsTexture = null; - this._jointsTextureSize = 0; - this._color = {r: 1, g: 1, b: 1, a: 1}; - this._jointMatrices = null; - } - - if ( Material$$1 ) MeshMaterial.__proto__ = Material$$1; - MeshMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); - MeshMaterial.prototype.constructor = MeshMaterial; - - var prototypeAccessors = { effect: { configurable: true },useModel: { configurable: true },useTexture: { configurable: true },useSkinning: { configurable: true },useJointsTexture: { configurable: true },useAttributeColor: { configurable: true },texture: { configurable: true },jointMatrices: { configurable: true },jointsTexture: { configurable: true },jointsTextureSize: { configurable: true },color: { configurable: true } }; - - prototypeAccessors.effect.get = function () { - return this._effect; - }; - - prototypeAccessors.useModel.get = function () { - return this._effect.getDefine('useModel'); - }; - - prototypeAccessors.useModel.set = function (val) { - this._effect.define('useModel', val); - }; - - prototypeAccessors.useTexture.get = function () { - return this._effect.getDefine('useTexture'); - }; - - prototypeAccessors.useTexture.set = function (val) { - this._effect.define('useTexture', val); - }; - - prototypeAccessors.useSkinning.get = function () { - return this._effect.getDefine('useSkinning'); - }; - - prototypeAccessors.useSkinning.set = function (val) { - this._effect.define('useSkinning', val); - }; - - prototypeAccessors.useJointsTexture.get = function () { - return this._effect.getDefine('useJointsTexture'); - }; - - prototypeAccessors.useJointsTexture.set = function (val) { - this._effect.define('useJointsTexture', val); - }; - - prototypeAccessors.useAttributeColor.get = function () { - return this._effect.getDefine('useAttributeColor'); - }; - - prototypeAccessors.useAttributeColor.set = function (val) { - this._effect.define('useAttributeColor', val); - }; - - prototypeAccessors.texture.get = function () { - return this._texture; - }; - - prototypeAccessors.texture.set = function (val) { - if (this._texture !== val) { - this._texture = val; - this._effect.setProperty('texture', val.getImpl()); - this._texIds['texture'] = val.getId(); - } - }; - - prototypeAccessors.jointMatrices.get = function () { - return this._jointMatrices; - }; - - prototypeAccessors.jointMatrices.set = function (val) { - this._jointMatrices = val; - this._effect.setProperty('u_jointMatrices', val); - }; - - prototypeAccessors.jointsTexture.get = function () { - return this._jointsTexture; - }; - - prototypeAccessors.jointsTexture.set = function (val) { - if (this._jointsTexture !== val) { - this._jointsTexture = val; - this._effect.setProperty('u_jointsTexture', val.getImpl()); - this._texIds['jointsTexture'] = val.getId(); - } - }; - - prototypeAccessors.jointsTextureSize.get = function () { - return this._jointsTextureSize; - }; - - prototypeAccessors.jointsTextureSize.set = function (val) { - if (this._jointsTextureSize !== val) { - this._jointsTextureSize = val; - this._effect.setProperty('u_jointsTextureSize', val); - } - }; - - prototypeAccessors.color.get = function () { - return this._effect.getProperty('color'); - }; - - prototypeAccessors.color.set = function (val) { - var color = this._color; - color.r = val.r / 255; - color.g = val.g / 255; - color.b = val.b / 255; - color.a = val.a / 255; - this._effect.setProperty('color', color); - }; - - MeshMaterial.prototype.clone = function clone () { - var copy = new MeshMaterial(); - copy.texture = this.texture; - copy.jointsTexture = this.jointsTexture; - copy.jointsTextureSize = this.jointsTextureSize; - copy.useTexture = this.useTexture; - copy.color = this.color; - copy.useModel = this.useModel; - copy.useSkinning = this.useSkinning; - copy.useJointsTexture = this.useJointsTexture; - copy.useAttributeColor = this.useAttributeColor; - copy.updateHash(); - return copy; - }; - - Object.defineProperties( MeshMaterial.prototype, prototypeAccessors ); - - return MeshMaterial; -}(Material)); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Device$2 = function Device(canvasEL) { - var ctx; - - try { - ctx = canvasEL.getContext('2d'); - } catch (err) { - console.error(err); - return; - } - - // statics - this._canvas = canvasEL; - this._ctx = ctx; - this._caps = {}; // capability - this._stats = { - drawcalls: 0, - }; - - // runtime - this._vx = this._vy = this._vw = this._vh = 0; - this._sx = this._sy = this._sw = this._sh = 0; -}; - -Device$2.prototype._restoreTexture = function _restoreTexture (unit) { -}; - -// =============================== -// Immediate Settings -// =============================== - -/** - * @method setViewport - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device$2.prototype.setViewport = function setViewport (x, y, w, h) { - if ( - this._vx !== x || - this._vy !== y || - this._vw !== w || - this._vh !== h - ) { - this._vx = x; - this._vy = y; - this._vw = w; - this._vh = h; - } -}; - -/** - * @method setScissor - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device$2.prototype.setScissor = function setScissor (x, y, w, h) { - if ( - this._sx !== x || - this._sy !== y || - this._sw !== w || - this._sh !== h - ) { - this._sx = x; - this._sy = y; - this._sw = w; - this._sh = h; - } -}; - -Device$2.prototype.clear = function clear (color) { - var ctx = this._ctx; - ctx.clearRect(this._vx, this._vy, this._vw, this._vh); - if (color && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { - ctx.fillStyle = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] +')'; - ctx.globalAlpha = color[3]; - ctx.fillRect(this._vx, this._vy, this._vw, this._vh); - } -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Texture2D$2 = function Texture2D(device, options) { - this._device = device; - - this._width = 4; - this._height = 4; - - this._image = null; - - if (options) { - if (options.width !== undefined) { - this._width = options.width; - } - if (options.height !== undefined) { - this._height = options.height; - } - - this.updateImage(options); - } -}; - -Texture2D$2.prototype.update = function update (options) { - this.updateImage(options); -}; - -Texture2D$2.prototype.updateImage = function updateImage (options) { - if (options.images && options.images[0]) { - var image = options.images[0]; - if (image && image !== this._image) { - this._image = image; - } - } -}; - -Texture2D$2.prototype.destroy = function destroy () { - this._image = null; -}; - -var canvas = { - Device: Device$2, - Texture2D: Texture2D$2 -}; - -// intenral -// deps -var Scene$2 = renderer.Scene; -var Camera$2 = renderer.Camera; -var View$2 = renderer.View; -var Texture2D$4 = gfx.Texture2D; -var Device$4 = gfx.Device; -var Model$2 = renderer.Model; -var InputAssembler$2 = renderer.InputAssembler; - -renderer.addStage('transparent'); - -var renderEngine = { - // core classes - Device: Device$4, - ForwardRenderer: ForwardRenderer, - Texture2D: Texture2D$4, - - // Canvas render support - canvas: canvas, - - // render scene - Scene: Scene$2, - Camera: Camera$2, - View: View$2, - Model: Model$2, - RenderData: RenderData, - IARenderData: IARenderData, - InputAssembler: InputAssembler$2, - - // assets - Asset: Asset, - TextureAsset: Texture$2, - Material: Material, - - // materials - SpriteMaterial: SpriteMaterial, - GraySpriteMaterial: GraySpriteMaterial, - StencilMaterial: StencilMaterial, - MeshMaterial: MeshMaterial, - - // shaders - shaders: shaders, - - // memop - RecyclePool: RecyclePool, - Pool: Pool, - - // modules - math: math, - renderer: renderer, - gfx: gfx, - - config: config, -}; - -module.exports = renderEngine; diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js deleted file mode 100644 index bc106a45b8d..00000000000 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ /dev/null @@ -1,10700 +0,0 @@ - -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - render-engine v1.2.0 - 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. - ****************************************************************************/ - - -'use strict'; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gl = window.__gl; - -var _filterGL = [ - [ gl.GL_NEAREST, gl.GL_NEAREST_MIPMAP_NEAREST, gl.GL_NEAREST_MIPMAP_LINEAR ], - [ gl.GL_LINEAR, gl.GL_LINEAR_MIPMAP_NEAREST, gl.GL_LINEAR_MIPMAP_LINEAR ] ]; - -var _textureFmtGL = [ - // TEXTURE_FMT_RGB_DXT1: 0 - { format: gl.RGB, internalFormat: gl.COMPRESSED_RGB_S3TC_DXT1_EXT, pixelType: 0, bpp: 3 }, - - // TEXTURE_FMT_RGBA_DXT1: 1 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_S3TC_DXT1_EXT, pixelType: 0, bpp: 4 }, - - // TEXTURE_FMT_RGBA_DXT3: 2 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_S3TC_DXT3_EXT, pixelType: 0, bpp: 8 }, - - // TEXTURE_FMT_RGBA_DXT5: 3 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_S3TC_DXT5_EXT, pixelType: 0, bpp: 8 }, - - // TEXTURE_FMT_RGB_ETC1: 4 - { format: gl.RGB, internalFormat: gl.COMPRESSED_RGB_ETC1_WEBGL, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5 - { format: gl.RGB, internalFormat: gl.COMPRESSED_RGB_PVRTC_2BPPV1_IMG, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, pixelType: 0, bpp:0 }, - - // TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7 - { format: gl.RGB, internalFormat: gl.COMPRESSED_RGB_PVRTC_4BPPV1_IMG, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8 - { format: gl.RGBA, internalFormat: gl.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, pixelType: null }, - - // TEXTURE_FMT_A8: 9 - { format: gl.ALPHA, internalFormat: gl.ALPHA, pixelType: gl.UNSIGNED_BYTE, bpp: 8 }, - - // TEXTURE_FMT_L8: 10 - { format: gl.LUMINANCE, internalFormat: gl.LUMINANCE, pixelType: gl.UNSIGNED_BYTE, bpp: 8 }, - - // TEXTURE_FMT_L8_A8: 11 - { format: gl.LUMINANCE_ALPHA, internalFormat: gl.LUMINANCE_ALPHA, pixelType: gl.UNSIGNED_BYTE, bpp: 16 }, - - // TEXTURE_FMT_R5_G6_B5: 12 - { format: gl.RGB, internalFormat: gl.RGB, pixelType: gl.UNSIGNED_SHORT_5_6_5, bpp: 16 }, - - // TEXTURE_FMT_R5_G5_B5_A1: 13 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.UNSIGNED_SHORT_5_5_5_1, bpp: 16 }, - - // TEXTURE_FMT_R4_G4_B4_A4: 14 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.UNSIGNED_SHORT_4_4_4_4, bpp: 16 }, - - // TEXTURE_FMT_RGB8: 15 - { format: gl.RGB, internalFormat: gl.RGB, pixelType: gl.UNSIGNED_BYTE, bpp: 24 }, - - // TEXTURE_FMT_RGBA8: 16 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.UNSIGNED_BYTE, bpp: 32 }, - - // TEXTURE_FMT_RGB16F: 17 - { format: gl.RGB, internalFormat: gl.RGB, pixelType: gl.HALF_FLOAT_OES, bpp: 0 }, - - // TEXTURE_FMT_RGBA16F: 18 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.HALF_FLOAT_OES, bpp: 0 }, - - // TEXTURE_FMT_RGB32F: 19 - { format: gl.RGB, internalFormat: gl.RGB, pixelType: gl.FLOAT, bpp: 96 }, - - // TEXTURE_FMT_RGBA32F: 20 - { format: gl.RGBA, internalFormat: gl.RGBA, pixelType: gl.FLOAT, bpp: 128 }, - - // TEXTURE_FMT_R32F: 21 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_111110F: 22 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_SRGB: 23 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_SRGBA: 24 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 }, - - // TEXTURE_FMT_D16: 25 - // TODO: fix it on android - { format: gl.DEPTH_COMPONENT, internalFormat: gl.DEPTH_COMPONENT16, pixelType: gl.UNSIGNED_SHORT }, - - // TEXTURE_FMT_D24: 26 - // { format: gl.DEPTH_COMPONENT, internalFormat: gl.DEPTH_COMPONENT24, pixelType: gl.FLOAT }, - - // TEXTURE_FMT_D24S8: 27 - { format: null, internalFormat: null, pixelType: 0, bpp: 0 } ]; - -/** - * enums - */ -var enums = { - // buffer usage - USAGE_STATIC: 35044, // gl.STATIC_DRAW - USAGE_DYNAMIC: 35048, // gl.DYNAMIC_DRAW - USAGE_STREAM: 35040, // gl.STREAM_DRAW - - // index buffer format - INDEX_FMT_UINT8: 5121, // gl.UNSIGNED_BYTE - INDEX_FMT_UINT16: 5123, // gl.UNSIGNED_SHORT - INDEX_FMT_UINT32: 5125, // gl.UNSIGNED_INT (OES_element_index_uint) - - // vertex attribute semantic - ATTR_POSITION: 'a_position', - ATTR_NORMAL: 'a_normal', - ATTR_TANGENT: 'a_tangent', - ATTR_BITANGENT: 'a_bitangent', - ATTR_WEIGHTS: 'a_weights', - ATTR_JOINTS: 'a_joints', - ATTR_COLOR: 'a_color', - ATTR_COLOR0: 'a_color0', - ATTR_COLOR1: 'a_color1', - ATTR_UV: 'a_uv', - ATTR_UV0: 'a_uv0', - ATTR_UV1: 'a_uv1', - ATTR_UV2: 'a_uv2', - ATTR_UV3: 'a_uv3', - ATTR_UV4: 'a_uv4', - ATTR_UV5: 'a_uv5', - ATTR_UV6: 'a_uv6', - ATTR_UV7: 'a_uv7', - - // vertex attribute type - ATTR_TYPE_INT8: 5120, // gl.BYTE - ATTR_TYPE_UINT8: 5121, // gl.UNSIGNED_BYTE - ATTR_TYPE_INT16: 5122, // gl.SHORT - ATTR_TYPE_UINT16: 5123, // gl.UNSIGNED_SHORT - ATTR_TYPE_INT32: 5124, // gl.INT - ATTR_TYPE_UINT32: 5125, // gl.UNSIGNED_INT - ATTR_TYPE_FLOAT32: 5126, // gl.FLOAT - - // texture filter - FILTER_NEAREST: 0, - FILTER_LINEAR: 1, - - // texture wrap mode - WRAP_REPEAT: 10497, // gl.REPEAT - WRAP_CLAMP: 33071, // gl.CLAMP_TO_EDGE - WRAP_MIRROR: 33648, // gl.MIRRORED_REPEAT - - // texture format - // compress formats - TEXTURE_FMT_RGB_DXT1: 0, - TEXTURE_FMT_RGBA_DXT1: 1, - TEXTURE_FMT_RGBA_DXT3: 2, - TEXTURE_FMT_RGBA_DXT5: 3, - TEXTURE_FMT_RGB_ETC1: 4, - TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5, - TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6, - TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7, - TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8, - - // normal formats - TEXTURE_FMT_A8: 9, - TEXTURE_FMT_L8: 10, - TEXTURE_FMT_L8_A8: 11, - TEXTURE_FMT_R5_G6_B5: 12, - TEXTURE_FMT_R5_G5_B5_A1: 13, - TEXTURE_FMT_R4_G4_B4_A4: 14, - TEXTURE_FMT_RGB8: 15, - TEXTURE_FMT_RGBA8: 16, - TEXTURE_FMT_RGB16F: 17, - TEXTURE_FMT_RGBA16F: 18, - TEXTURE_FMT_RGB32F: 19, - TEXTURE_FMT_RGBA32F: 20, - TEXTURE_FMT_R32F: 21, - TEXTURE_FMT_111110F: 22, - TEXTURE_FMT_SRGB: 23, - TEXTURE_FMT_SRGBA: 24, - - // depth formats - TEXTURE_FMT_D16: 25, - TEXTURE_FMT_D24: 26, - TEXTURE_FMT_D24S8: 27, - - // depth and stencil function - DS_FUNC_NEVER: 512, // gl.NEVER - DS_FUNC_LESS: 513, // gl.LESS - DS_FUNC_EQUAL: 514, // gl.EQUAL - DS_FUNC_LEQUAL: 515, // gl.LEQUAL - DS_FUNC_GREATER: 516, // gl.GREATER - DS_FUNC_NOTEQUAL: 517, // gl.NOTEQUAL - DS_FUNC_GEQUAL: 518, // gl.GEQUAL - DS_FUNC_ALWAYS: 519, // gl.ALWAYS - - // render-buffer format - RB_FMT_RGBA4: 32854, // gl.RGBA4 - RB_FMT_RGB5_A1: 32855, // gl.RGB5_A1 - RB_FMT_RGB565: 36194, // gl.RGB565 - RB_FMT_D16: 33189, // gl.DEPTH_COMPONENT16 - RB_FMT_S8: 36168, // gl.STENCIL_INDEX8 - RB_FMT_D24S8: 34041, // gl.DEPTH_STENCIL - - // blend-equation - BLEND_FUNC_ADD: 32774, // gl.FUNC_ADD - BLEND_FUNC_SUBTRACT: 32778, // gl.FUNC_SUBTRACT - BLEND_FUNC_REVERSE_SUBTRACT: 32779, // gl.FUNC_REVERSE_SUBTRACT - - // blend - BLEND_ZERO: 0, // gl.ZERO - BLEND_ONE: 1, // gl.ONE - BLEND_SRC_COLOR: 768, // gl.SRC_COLOR - BLEND_ONE_MINUS_SRC_COLOR: 769, // gl.ONE_MINUS_SRC_COLOR - BLEND_DST_COLOR: 774, // gl.DST_COLOR - BLEND_ONE_MINUS_DST_COLOR: 775, // gl.ONE_MINUS_DST_COLOR - BLEND_SRC_ALPHA: 770, // gl.SRC_ALPHA - BLEND_ONE_MINUS_SRC_ALPHA: 771, // gl.ONE_MINUS_SRC_ALPHA - BLEND_DST_ALPHA: 772, // gl.DST_ALPHA - BLEND_ONE_MINUS_DST_ALPHA: 773, // gl.ONE_MINUS_DST_ALPHA - BLEND_CONSTANT_COLOR: 32769, // gl.CONSTANT_COLOR - BLEND_ONE_MINUS_CONSTANT_COLOR: 32770, // gl.ONE_MINUS_CONSTANT_COLOR - BLEND_CONSTANT_ALPHA: 32771, // gl.CONSTANT_ALPHA - BLEND_ONE_MINUS_CONSTANT_ALPHA: 32772, // gl.ONE_MINUS_CONSTANT_ALPHA - BLEND_SRC_ALPHA_SATURATE: 776, // gl.SRC_ALPHA_SATURATE - - // stencil operation - STENCIL_OP_KEEP: 7680, // gl.KEEP - STENCIL_OP_ZERO: 0, // gl.ZERO - STENCIL_OP_REPLACE: 7681, // gl.REPLACE - STENCIL_OP_INCR: 7682, // gl.INCR - STENCIL_OP_INCR_WRAP: 34055, // gl.INCR_WRAP - STENCIL_OP_DECR: 7683, // gl.DECR - STENCIL_OP_DECR_WRAP: 34056, // gl.DECR_WRAP - STENCIL_OP_INVERT: 5386, // gl.INVERT - - // cull - CULL_NONE: 0, - CULL_FRONT: 1028, - CULL_BACK: 1029, - CULL_FRONT_AND_BACK: 1032, - - // primitive type - PT_POINTS: 0, // gl.POINTS - PT_LINES: 1, // gl.LINES - PT_LINE_LOOP: 2, // gl.LINE_LOOP - PT_LINE_STRIP: 3, // gl.LINE_STRIP - PT_TRIANGLES: 4, // gl.TRIANGLES - PT_TRIANGLE_STRIP: 5, // gl.TRIANGLE_STRIP - PT_TRIANGLE_FAN: 6, // gl.TRIANGLE_FAN -}; - -/** - * @method attrTypeBytes - * @param {ATTR_TYPE_*} attrType - */ -function attrTypeBytes(attrType) { - if (attrType === enums.ATTR_TYPE_INT8) { - return 1; - } else if (attrType === enums.ATTR_TYPE_UINT8) { - return 1; - } else if (attrType === enums.ATTR_TYPE_INT16) { - return 2; - } else if (attrType === enums.ATTR_TYPE_UINT16) { - return 2; - } else if (attrType === enums.ATTR_TYPE_INT32) { - return 4; - } else if (attrType === enums.ATTR_TYPE_UINT32) { - return 4; - } else if (attrType === enums.ATTR_TYPE_FLOAT32) { - return 4; - } - - console.warn(("Unknown ATTR_TYPE: " + attrType)); - return 0; -} - -/** - * @method glTextureFmt - * @param {TEXTURE_FMT_*} fmt - */ -function glTextureFmt(fmt) { - var result = _textureFmtGL[fmt]; - if (result === undefined) { - console.warn(("Unknown TEXTURE_FMT: " + fmt)); - return _textureFmtGL[enums.TEXTURE_FMT_RGBA8]; - } - - return result; -} - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gfx = window.gfx; - -// ==================== -// exports -// ==================== - -var VertexFormat = function VertexFormat(infos) { - var this$1 = this; - - this._attr2el = {}; - this._elements = []; - this._bytes = 0; - - var offset = 0; - for (var i = 0, len = infos.length; i < len; ++i) { - var info = infos[i]; - var el = { - name: info.name, - offset: offset, - stride: 0, - stream: -1, - type: info.type, - num: info.num, - normalize: (info.normalize === undefined) ? false : info.normalize, - bytes: info.num * attrTypeBytes(info.type), - }; - // log('info.num is:' + info.num + ' attrTypeBytes(info.type) is:' + attrTypeBytes(info.type)); - - this$1._attr2el[el.name] = el; - this$1._elements.push(el); - - this$1._bytes += el.bytes; - offset += el.bytes; - } - - for (var i$1 = 0, len$1 = this._elements.length; i$1 < len$1; ++i$1) { - var el$1 = this$1._elements[i$1]; - el$1.stride = this$1._bytes; - } - - this._nativeObj = new gfx.VertexFormatNative(this._elements); -}; - -/** - * @method element - * @param {string} attrName - */ -VertexFormat.prototype.element = function element (attrName) { - return this._attr2el[attrName]; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gl$1 = window.__gl; -var gfx$1 = window.gfx; - -var _tmpGetSetDesc = { - get: undefined, - set: undefined, - enumerable: true, - configurable: true -}; - -window.device = gfx$1.Device.getInstance(); -window.device._gl = window.__gl; - -//FIXME: -window.device._stats = { vb: 0 }; -window.device._caps = { - maxVextexTextures: 16, - maxFragUniforms: 1024, - maxTextureUints: 8, - maxVertexAttributes: 16, - maxDrawBuffers: 8, - maxColorAttatchments: 8 -}; - -device.setBlendColor32 = device.setBlendColor; - -var _p = gfx$1.Program.prototype; -_p._ctor = function(device, options) { - this.init(device, options.vert, options.frag); -}; - -_p = gfx$1.VertexBuffer.prototype; -_p._ctor = function(device, format, usage, data, numVertices) { - this.init(device, format._nativeObj, usage, data, numVertices); - this._nativePtr = this.self(); -}; -_tmpGetSetDesc.get = _p.getCount; -_tmpGetSetDesc.set = undefined; -Object.defineProperty(_p, "count", _tmpGetSetDesc); - -_p = gfx$1.IndexBuffer.prototype; -_p._ctor = function(device, format, usage, data, numIndices) { - this.init(device, format, usage, data, numIndices); - this._nativePtr = this.self(); -}; -_tmpGetSetDesc.get = _p.getCount; -_tmpGetSetDesc.set = undefined; -Object.defineProperty(_p, "count", _tmpGetSetDesc); - -gfx$1.VertexFormat = VertexFormat; -Object.assign(gfx$1, enums); - -function convertImages(images) { - if (images) { - for (var i = 0, len = images.length; i < len; ++i) { - var image = images[i]; - if (image !== null) { - if (image instanceof window.HTMLCanvasElement) { - if (image._data) { - images[i] = image._data._data; - } - else { - images[i] = null; - } - } - else if (image instanceof window.HTMLImageElement) { - images[i] = image._data; - } - } - } - } -} - -function convertOptions(options) { - if (options.images && options.images[0] instanceof HTMLImageElement) { - var image = options.images[0]; - options.glInternalFormat = image._glInternalFormat; - options.glFormat = image._glFormat; - options.glType = image._glType; - options.bpp = image._bpp; - options.compressed = image._compressed; - options.premultiplyAlpha = image._premultiplyAlpha; - } - else if (options.images && options.images[0] instanceof HTMLCanvasElement) { - options.glInternalFormat = gl$1.RGBA; - options.glFormat = gl$1.RGBA; - options.glType = gl$1.UNSIGNED_BYTE; - options.bpp = 32; - options.compressed = false; - } - else { - var gltf = glTextureFmt(options.format); - options.glInternalFormat = gltf.internalFormat; - options.glFormat = gltf.format; - options.glType = gltf.pixelType; - options.bpp = gltf.bpp; - options.compressed = options.glFormat >= enums.TEXTURE_FMT_RGB_DXT1 && - options.gltf <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1; - } - - convertImages(options.images); -} - -_p = gfx$1.Texture2D.prototype; -_p._ctor = function(device, options) { - convertOptions(options); - this.init(device, options); -}; -_p.destroy = function() { -}; -_p.update = function(options) { - convertOptions(options); - this.updateNative(options); -}; -_p.updateSubImage = function(option) { - var images = [option.image]; - convertImages(images); - var data = new Uint32Array(8 + - (images[0].length + 3) / 4); - - data[0] = option.x; - data[1] = option.y; - data[2] = option.width; - data[3] = option.height; - data[4] = option.level; - data[5] = option.flipY; - data[6] = false; - data[7] = images[0].length; - var imageData = new Uint8Array(data.buffer); - imageData.set(images[0], 32); - - this.updateSubImageNative(data); -}; -_tmpGetSetDesc.get = _p.getWidth; -_tmpGetSetDesc.set = undefined; -Object.defineProperty(_p, "_width", _tmpGetSetDesc); -_tmpGetSetDesc.get = _p.getHeight; -Object.defineProperty(_p, "_height", _tmpGetSetDesc); - -_p = gfx$1.FrameBuffer.prototype; -_p._ctor = function(device, width, height, options) { - this.init(device, width, height, options); -}; - -gfx$1.RB_FMT_D16 = 0x81A5; // GL_DEPTH_COMPONENT16 hack for JSB - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gfx$3 = window.gfx; - -var InputAssembler = function InputAssembler(vb, ib, pt) { - if ( pt === void 0 ) pt = gfx$3.PT_TRIANGLES; - - this._vertexBuffer = vb; - this._indexBuffer = ib; - this._primitiveType = pt; - this._start = 0; - this._count = -1; - - // TODO: instancing data - // this._stream = 0; -}; - -InputAssembler.prototype.getPrimitiveCount = function getPrimitiveCount () { - if (this._count !== -1) { - return this._count; - } - - if (this._indexBuffer) { - return this._indexBuffer.count; - } - - return this._vertexBuffer.count; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var renderer = window.renderer; -var _stageOffset = 0; -var _name2stageID = {}; - -var config = { - addStage: function (name) { - // already added - if (_name2stageID[name] !== undefined) { - return; - } - - var stageID = 1 << _stageOffset; - _name2stageID[name] = stageID; - - _stageOffset += 1; - - renderer.addStage(name); - }, - - stageID: function (name) { - var id = _name2stageID[name]; - if (id === undefined) { - return -1; - } - return id; - }, - - stageIDs: function (nameList) { - var key = 0; - for (var i = 0; i < nameList.length; ++i) { - var id = _name2stageID[nameList[i]]; - if (id !== undefined) { - key |= id; - } - } - return key; - } -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var renderer$1 = window.renderer; - -var Effect = function Effect(techniques, properties, defines) { - if ( properties === void 0 ) properties = {}; - if ( defines === void 0 ) defines = []; - - this._techniques = techniques; - this._properties = properties; - this._defines = defines; - - var techniqueObjs = []; - var techniqueObj; - for (var i = 0, len = techniques.length; i < len; ++i) { - techniqueObj = techniques[i]._nativeObj; - techniqueObjs.push(techniqueObj); - } - - this._nativeObj = new renderer$1.EffectNative(); - this._nativeObj.init(techniqueObjs, properties, defines); - this._nativePtr = this._nativeObj.self(); - - // TODO: check if params is valid for current technique??? -}; - -Effect.prototype.clear = function clear () { - this._techniques.length = 0; - this._properties = null; - this._defines.length = 0; -}; - -Effect.prototype.getTechnique = function getTechnique (stage) { - var this$1 = this; - - var stageID = config.stageID(stage); - for (var i = 0; i < this._techniques.length; ++i) { - var tech = this$1._techniques[i]; - if (tech.stageIDs & stageID) { - return tech; - } - } - - return null; -}; - -Effect.prototype.getProperty = function getProperty (name) { - return this._properties[name]; -}; - -Effect.prototype.setProperty = function setProperty (name, value) { - // TODO: check if params is valid for current technique??? - this._properties[name] = value; - this._nativeObj.setProperty(name, value); -}; - -Effect.prototype.getDefine = function getDefine (name) { - var this$1 = this; - - for (var i = 0; i < this._defines.length; ++i) { - var def = this$1._defines[i]; - if ( def.name === name ) { - return def.value; - } - } - - console.warn(("Failed to get define " + name + ", define not found.")); - return null; -}; - -Effect.prototype.define = function define (name, value) { - var this$1 = this; - - for (var i = 0; i < this._defines.length; ++i) { - var def = this$1._defines[i]; - if ( def.name === name ) { - def.value = value; - return; - } - } - - this._nativeObj.setDefine(name, value); - - console.warn(("Failed to set define " + name + ", define not found.")); -}; - -Effect.prototype.extractDefines = function extractDefines (out) { - var this$1 = this; - if ( out === void 0 ) out = {}; - - for (var i = 0; i < this._defines.length; ++i) { - var def = this$1._defines[i]; - out[def.name] = def.value; - } - - return out; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var renderer$2 = window.renderer; -var _genID = 0; - -var Technique = function Technique(stages, parameters, passes, layer) { - if ( layer === void 0 ) layer = 0; - - this._id = _genID++; - this._stageIDs = config.stageIDs(stages); - this.stageIDs = this._stageIDs; - this._parameters = parameters; // {name, type, size, val} - this._passes = passes; - this.passes = this._passes; - this._layer = layer; - this._stages = stages; - // TODO: this._version = 'webgl' or 'webgl2' // ???? - - var passesNative = []; - for (var i = 0, len = passes.length; i < len; ++i) { - passesNative.push(passes[i]._native); - } - this._nativeObj = new renderer$2.TechniqueNative(stages, parameters, passesNative, layer); - -}; - -Technique.prototype.copy = function copy (technique) { - var this$1 = this; - - this._id = technique._id; - this._stageIDs = technique._stageIDs; - - this._parameters = []; - for (var i = 0; i < technique._parameters.length; ++i) { - var parameter = technique._parameters[i]; - this$1._parameters.push({name: parameter.name, type: parameter.type}); - } - - for (var i$1 = 0; i$1 < technique._passes.length; ++i$1) { - var pass = this$1._passes[i$1]; - if (!pass) { - pass = new renderer$2.Pass(); - this$1._passes.push(pass); - } - pass.copy(technique._passes[i$1]); - } - this._passes.length = technique._passes.length; - this._layer = technique._layer; -}; - -Technique.prototype.setStages = function setStages (stages) { - this._stageIDs = config.stageIDs(stages); - this._stages = stages; - - this._nativeObj.setStages(stages); -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var gfx$4 = window.gfx; -var renderer$3 = window.renderer; - -var Pass = function Pass(name) { - this._programName = name; - - // cullmode - this._cullMode = gfx$4.CULL_BACK; - - // blending - this._blend = false; - this._blendEq = gfx$4.BLEND_FUNC_ADD; - this._blendAlphaEq = gfx$4.BLEND_FUNC_ADD; - this._blendSrc = gfx$4.BLEND_ONE; - this._blendDst = gfx$4.BLEND_ZERO; - this._blendSrcAlpha = gfx$4.BLEND_ONE; - this._blendDstAlpha = gfx$4.BLEND_ZERO; - this._blendColor = 0xffffffff; - - // depth - this._depthTest = false; - this._depthWrite = false; - this._depthFunc = gfx$4.DS_FUNC_LESS; - - // stencil - this._stencilTest = false; - // front - this._stencilFuncFront = gfx$4.DS_FUNC_ALWAYS; - this._stencilRefFront = 0; - this._stencilMaskFront = 0xff; - this._stencilFailOpFront = gfx$4.STENCIL_OP_KEEP; - this._stencilZFailOpFront = gfx$4.STENCIL_OP_KEEP; - this._stencilZPassOpFront = gfx$4.STENCIL_OP_KEEP; - this._stencilWriteMaskFront = 0xff; - // back - this._stencilFuncBack = gfx$4.DS_FUNC_ALWAYS; - this._stencilRefBack = 0; - this._stencilMaskBack = 0xff; - this._stencilFailOpBack = gfx$4.STENCIL_OP_KEEP; - this._stencilZFailOpBack = gfx$4.STENCIL_OP_KEEP; - this._stencilZPassOpBack = gfx$4.STENCIL_OP_KEEP; - this._stencilWriteMaskBack = 0xff; - - var binary = new Uint32Array(25); - binary[0] = this._cullMode; - binary[1] = this._blendEq; - binary[2] = this._blendSrc; - binary[3] = this._blendDst; - binary[4] = this._blendAlphaEq; - binary[5] = this._blendSrcAlpha; - binary[6] = this._blendDstAlpha; - binary[7] = this._blendColor; - binary[8] = this._depthTest; - binary[9] = this._depthWrite; - binary[10] = this._depthFunc; - binary[11] = this._stencilFuncFront; - binary[12] = this._stencilRefFront; - binary[13] = this._stencilMaskFront; - binary[14] = this._stencilFailOpFront; - binary[15] = this._stencilZFailOpFront; - binary[16] = this._stencilZPassOpFront; - binary[17] = this._stencilWriteMaskFront; - binary[18] = this._stencilFuncBack; - binary[19] = this._stencilRefBack; - binary[20] = this._stencilMaskBack; - binary[21] = this._stencilFailOpBack; - binary[22] = this._stencilZFailOpBack; - binary[23] = this._stencilZPassOpBack; - binary[24] = this._stencilWriteMaskBack; - this._native = new renderer$3.PassNative(); - this._native.init(this._programName, binary); -}; - -Pass.prototype.copy = function copy (pass) { - this._programName = pass._programName; - // cullmode - this._cullMode = pass._cullMode; - // blending - this._blend = pass._blend; - this._blendEq = pass._blendEq; - this._blendAlphaEq = pass._blendAlphaEq; - this._blendSrc = pass._blendSrc; - this._blendDst = pass._blendDst; - this._blendSrcAlpha = pass._blendSrcAlpha; - this._blendDstAlpha = pass._blendDstAlpha; - this._blendColor = pass._blendColor; - // depth - this._depthTest = pass._depthTest; - this._depthWrite = pass._depthWrite; - this._depthFunc = pass._depthFunc; - this._stencilTest = pass._stencilTest; - // front - this._stencilFuncFront = pass._stencilFuncFront; - this._stencilRefFront = pass._stencilRefFront; - this._stencilMaskFront = pass._stencilMaskFront; - this._stencilFailOpFront = pass._stencilFailOpFront; - this._stencilZFailOpFront = pass._stencilZFailOpFront; - this._stencilZPassOpFront = pass._stencilZPassOpFront; - this._stencilWriteMaskFront = pass._stencilWriteMaskFront; - // back - this._stencilFuncBack = pass._stencilFuncBack; - this._stencilRefBack = pass._stencilRefBack; - this._stencilMaskBack = pass._stencilMaskBack; - this._stencilFailOpBack = pass._stencilFailOpBack; - this._stencilZFailOpBack = pass._stencilZFailOpBack; - this._stencilZPassOpBack = pass._stencilZPassOpBack; - this._stencilWriteMaskBack = pass._stencilWriteMaskBack; -}; - -Pass.prototype.setCullMode = function setCullMode (cullMode) { - this._cullMode = cullMode; - - this._native.setCullMode(cullMode); -}; - -Pass.prototype.disableStecilTest = function disableStecilTest () { - this._stencilTest = false; - - this._native.disableStecilTest(); -}; - -Pass.prototype.setBlend = function setBlend ( - blendEq, - blendSrc, - blendDst, - blendAlphaEq, - blendSrcAlpha, - blendDstAlpha, - blendColor -) { - if ( blendEq === void 0 ) blendEq = gfx$4.BLEND_FUNC_ADD; - if ( blendSrc === void 0 ) blendSrc = gfx$4.BLEND_ONE; - if ( blendDst === void 0 ) blendDst = gfx$4.BLEND_ZERO; - if ( blendAlphaEq === void 0 ) blendAlphaEq = gfx$4.BLEND_FUNC_ADD; - if ( blendSrcAlpha === void 0 ) blendSrcAlpha = gfx$4.BLEND_ONE; - if ( blendDstAlpha === void 0 ) blendDstAlpha = gfx$4.BLEND_ZERO; - if ( blendColor === void 0 ) blendColor = 0xffffffff; - - this._blend = true; - this._blendEq = blendEq; - this._blendSrc = blendSrc; - this._blendDst = blendDst; - this._blendAlphaEq = blendAlphaEq; - this._blendSrcAlpha = blendSrcAlpha; - this._blendDstAlpha = blendDstAlpha; - this._blendColor = blendColor; - - this._native.setBlend(blendEq, - blendSrc, - blendDst, - blendAlphaEq, - blendSrcAlpha, - blendDstAlpha, - blendColor); -}; - -Pass.prototype.setDepth = function setDepth ( - depthTest, - depthWrite, - depthFunc -) { - if ( depthTest === void 0 ) depthTest = false; - if ( depthWrite === void 0 ) depthWrite = false; - if ( depthFunc === void 0 ) depthFunc = gfx$4.DS_FUNC_LESS; - - this._depthTest = depthTest; - this._depthWrite = depthWrite; - this._depthFunc = depthFunc; - - this._native.setDepth(depthTest, depthWrite, depthFunc); -}; - -Pass.prototype.setStencilFront = function setStencilFront ( - stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask -) { - if ( stencilFunc === void 0 ) stencilFunc = gfx$4.DS_FUNC_ALWAYS; - if ( stencilRef === void 0 ) stencilRef = 0; - if ( stencilMask === void 0 ) stencilMask = 0xff; - if ( stencilFailOp === void 0 ) stencilFailOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilZFailOp === void 0 ) stencilZFailOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilZPassOp === void 0 ) stencilZPassOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilWriteMask === void 0 ) stencilWriteMask = 0xff; - - this._stencilTest = true; - this._stencilFuncFront = stencilFunc; - this._stencilRefFront = stencilRef; - this._stencilMaskFront = stencilMask; - this._stencilFailOpFront = stencilFailOp; - this._stencilZFailOpFront = stencilZFailOp; - this._stencilZPassOpFront = stencilZPassOp; - this._stencilWriteMaskFront = stencilWriteMask; - - this._native.setStencilFront(stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask); -}; - -Pass.prototype.setStencilBack = function setStencilBack ( - stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask -) { - if ( stencilFunc === void 0 ) stencilFunc = gfx$4.DS_FUNC_ALWAYS; - if ( stencilRef === void 0 ) stencilRef = 0; - if ( stencilMask === void 0 ) stencilMask = 0xff; - if ( stencilFailOp === void 0 ) stencilFailOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilZFailOp === void 0 ) stencilZFailOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilZPassOp === void 0 ) stencilZPassOp = gfx$4.STENCIL_OP_KEEP; - if ( stencilWriteMask === void 0 ) stencilWriteMask = 0xff; - - this._stencilTest = true; - this._stencilFuncBack = stencilFunc; - this._stencilRefBack = stencilRef; - this._stencilMaskBack = stencilMask; - this._stencilFailOpBack = stencilFailOp; - this._stencilZFailOpBack = stencilZFailOp; - this._stencilZPassOpBack = stencilZPassOp; - this._stencilWriteMaskBack = stencilWriteMask; - - this._native.setStencilBack(stencilFunc, - stencilRef, - stencilMask, - stencilFailOp, - stencilZFailOp, - stencilZPassOp, - stencilWriteMask); -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Model = function Model() { - this._poolID = -1; - this._node = null; - this._inputAssemblers = []; - this._effects = []; - this._defines = []; - this._dynamicIA = false; - this._viewID = -1; - - // TODO: we calculate aabb based on vertices - // this._aabb -}; - -var prototypeAccessors = { inputAssemblerCount: { configurable: true },dynamicIA: { configurable: true },drawItemCount: { configurable: true } }; - -prototypeAccessors.inputAssemblerCount.get = function () { - return this._inputAssemblers.length; -}; - -prototypeAccessors.dynamicIA.get = function () { - return this._dynamicIA; -}; - -prototypeAccessors.drawItemCount.get = function () { - return this._dynamicIA ? 1 : this._inputAssemblers.length; -}; - -Model.prototype.setNode = function setNode (node) { - this._node = node; -}; - -Model.prototype.setDynamicIA = function setDynamicIA (enabled) { - this._dynamicIA = enabled; -}; - -Model.prototype.addInputAssembler = function addInputAssembler (ia) { - if (this._inputAssemblers.indexOf(ia) !== -1) { - return; - } - this._inputAssemblers.push(ia); -}; - -Model.prototype.clearInputAssemblers = function clearInputAssemblers () { - this._inputAssemblers.length = 0; -}; - -Model.prototype.addEffect = function addEffect (effect) { - if (this._effects.indexOf(effect) !== -1) { - return; - } - this._effects.push(effect); - - // - // let defs = Object.create(null); - // effect.extractDefines(defs); - // this._defines.push(defs); -}; - -Model.prototype.clearEffects = function clearEffects () { - this._effects.length = 0; - this._defines.length = 0; -}; - -Model.prototype.extractDrawItem = function extractDrawItem (out, index) { - if (this._dynamicIA) { - out.model = this; - out.node = this._node; - out.ia = null; - out.effect = this._effects[0]; - out.defines = out.effect.extractDefines(this._defines[0]); - - return; - } - - if (index >= this._inputAssemblers.length ) { - out.model = null; - out.node = null; - out.ia = null; - out.effect = null; - out.defines = null; - - return; - } - - out.model = this; - out.node = this._node; - out.ia = this._inputAssemblers[index]; - - var effect, defines; - if (index < this._effects.length) { - effect = this._effects[index]; - defines = this._defines[index]; - } else { - effect = this._effects[this._effects.length-1]; - defines = this._defines[this._effects.length-1]; - } - out.effect = effect; - out.defines = effect.extractDefines(defines); -}; - -Object.defineProperties( Model.prototype, prototypeAccessors ); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var renderer$4 = window.renderer; - -// projection -renderer$4.PROJ_PERSPECTIVE = 0; -renderer$4.PROJ_ORTHO = 1; - -// lights -renderer$4.LIGHT_DIRECTIONAL = 0; -renderer$4.LIGHT_POINT = 1; -renderer$4.LIGHT_SPOT = 2; - -// shadows -renderer$4.SHADOW_NONE = 0; -renderer$4.SHADOW_HARD = 1; -renderer$4.SHADOW_SOFT = 2; - -// parameter type -renderer$4.PARAM_INT = 0; -renderer$4.PARAM_INT2 = 1; -renderer$4.PARAM_INT3 = 2; -renderer$4.PARAM_INT4 = 3; -renderer$4.PARAM_FLOAT = 4; -renderer$4.PARAM_FLOAT2 = 5; -renderer$4.PARAM_FLOAT3 = 6; -renderer$4.PARAM_FLOAT4 = 7; -renderer$4.PARAM_COLOR3 = 8; -renderer$4.PARAM_COLOR4 = 9; -renderer$4.PARAM_MAT2 = 10; -renderer$4.PARAM_MAT3 = 11; -renderer$4.PARAM_MAT4 = 12; -renderer$4.PARAM_TEXTURE_2D = 13; -renderer$4.PARAM_TEXTURE_CUBE = 14; - -// clear flags -renderer$4.CLEAR_COLOR = 1; -renderer$4.CLEAR_DEPTH = 2; -renderer$4.CLEAR_STENCIL = 4; -renderer$4.InputAssembler = InputAssembler; -renderer$4.config = config; -renderer$4.Effect = Effect; -renderer$4.Technique = Technique; -renderer$4.Pass = Pass; -renderer$4.Model = Model; - -var models = []; -var sizeOfModel = 13; -var lengthOfCachedModels = 500; -// length + 500 modles(8 for each model) -var modelsData = new Float64Array(1 + lengthOfCachedModels*sizeOfModel); -var modelsData32 = new Float32Array(modelsData.buffer); -var fillModelData = function() { - if (models.length > lengthOfCachedModels) { - modelsData = new Floa64Array(1 + models.length*sizeOfModel); - lengthOfCachedModels = models.length; - modelsData32 = new Float32Array(modelsData.buffer); - } - - modelsData[0] = models.length; - var index64 = 1; - var index32 = 2; - var model; - var worldMatrix; - var ia; - for (var i = 0, len = models.length; i < len; ++i) { - model = models[i]; - - ia = model._inputAssemblers[0]; - - // 3 elements of 64 bits data - modelsData[index64++] = model._effects[0]._nativePtr; - modelsData[index64++] = ia._vertexBuffer._nativePtr; - modelsData[index64++] = ia._indexBuffer._nativePtr; - - index32 += 6; - modelsData32[index32++] = model._dynamicIA; - modelsData32[index32++] = model._viewID; - worldMatrix = model._node.getWorldRTInAB(); - modelsData32.set(worldMatrix, index32); - index32 += 16; - - modelsData32[index32++] = ia._start; - modelsData32[index32++] = ia._count; - - index64 += 10; - } -}; - -// ForwardRenderer adapter -var _p$1 = renderer$4.ForwardRenderer.prototype; -_p$1._ctor = function(device, builtin) { - this.init(device, builtin.programTemplates, builtin.defaultTexture, window.innerWidth, window.innerHeight); -}; -_p$1.render = function(scene) { - fillModelData(); - this.renderNative(scene, modelsData); - - models.length = 0; -}; -_p$1.renderCamera = function(camera, scene) { - fillModelData(); - this.renderCameraNative(camera, scene, modelsData); - - models.length = 0; -}; - -// Scene -_p$1 = renderer$4.Scene.prototype; -_p$1.addModel = function(model) { - models.push(model); -}; -_p$1.removeModel = function() {}; - -var chunks = { - 'skinning.vert': '\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}', -}; - -var templates = [ - { - name: 'gray_sprite', - vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute mediump vec2 a_uv0;\nvarying mediump vec2 uv0;\nvoid main () {\n vec4 pos = viewProj * vec4(a_position, 1);\n gl_Position = pos;\n uv0 = a_uv0;\n}', - frag: '\n \nuniform sampler2D texture;\nvarying mediump vec2 uv0;\nuniform lowp vec4 color;\nvoid main () {\n vec4 c = color * texture2D(texture, uv0);\n float gray = 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;\n gl_FragColor = vec4(gray, gray, gray, c.a);\n}', - defines: [ - ], - }, - { - name: 'mesh', - vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\n#ifdef useAttributeColor\n attribute vec4 a_color;\n varying vec4 v_color;\n#endif\n#ifdef useTexture\n attribute vec2 a_uv0;\n varying vec2 uv0;\n#endif\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useSkinning\n \nattribute vec4 a_weights;\nattribute vec4 a_joints;\n#ifdef useJointsTexture\nuniform sampler2D u_jointsTexture;\nuniform float u_jointsTextureSize;\nmat4 getBoneMatrix(const in float i) {\n float size = u_jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n y = dy * (y + 0.5);\n vec4 v1 = texture2D(u_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(u_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(u_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(u_jointsTexture, vec2(dx * (x + 3.5), y));\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 u_jointMatrices[64];\nmat4 getBoneMatrix(const in float i) {\n return u_jointMatrices[int(i)];\n}\n#endif\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n #ifdef useSkinning\n mvp = mvp * skinMatrix();\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n #ifdef useAttributeColor\n v_color = a_color;\n #endif\n gl_Position = pos;\n}', - frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying vec2 uv0;\n#endif\n#ifdef useAttributeColor\n varying vec4 v_color;\n#endif\nuniform vec4 color;\nvoid main () {\n vec4 o = color;\n \n #ifdef useAttributeColor\n o *= v_color;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n gl_FragColor = o;\n}', - defines: [ - { name: 'useTexture', }, - { name: 'useModel', }, - { name: 'useSkinning', }, - { name: 'useJointsTexture', }, - { name: 'useAttributeColor', } ], - }, - { - name: 'sprite', - vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute lowp vec4 a_color;\n#ifdef useModel\n uniform mat4 model;\n#endif\n#ifdef useTexture\n attribute mediump vec2 a_uv0;\n varying mediump vec2 uv0;\n#endif\n#ifndef useColor\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n vec4 pos = mvp * vec4(a_position, 1);\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n #ifdef useTexture\n uv0 = a_uv0;\n #endif\n gl_Position = pos;\n}', - frag: '\n \n#ifdef useTexture\n uniform sampler2D texture;\n varying mediump vec2 uv0;\n#endif\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n #ifdef useTexture\n o *= texture2D(texture, uv0);\n #endif\n #ifdef alphaTest\n if (o.a <= alphaThreshold)\n discard;\n #endif\n gl_FragColor = o;\n}', - defines: [ - { name: 'useTexture', }, - { name: 'useModel', }, - { name: 'alphaTest', }, - { name: 'useColor', } ], - } ]; - -var shaders = { - chunks: chunks, - templates: templates -}; - -// reference: https://github.com/mziccard/node-timsort - -/** - * Default minimum size of a run. - */ -var DEFAULT_MIN_MERGE = 32; - -/** - * Minimum ordered subsequece required to do galloping. - */ -var DEFAULT_MIN_GALLOPING = 7; - -/** - * Default tmp storage length. Can increase depending on the size of the - * smallest run to merge. - */ -var DEFAULT_TMP_STORAGE_LENGTH = 256; - -/** - * Pre-computed powers of 10 for efficient lexicographic comparison of - * small integers. - */ -var POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9]; - -/** - * Estimate the logarithm base 10 of a small integer. - * - * @param {number} x - The integer to estimate the logarithm of. - * @return {number} - The estimated logarithm of the integer. - */ -function log10(x) { - if (x < 1e5) { - if (x < 1e2) { - return x < 1e1 ? 0 : 1; - } - - if (x < 1e4) { - return x < 1e3 ? 2 : 3; - } - - return 4; - } - - if (x < 1e7) { - return x < 1e6 ? 5 : 6; - } - - if (x < 1e9) { - return x < 1e8 ? 7 : 8; - } - - return 9; -} - -/** - * Default alphabetical comparison of items. - * - * @param {string|object|number} a - First element to compare. - * @param {string|object|number} b - Second element to compare. - * @return {number} - A positive number if a.toString() > b.toString(), a - * negative number if .toString() < b.toString(), 0 otherwise. - */ -function alphabeticalCompare(a, b) { - if (a === b) { - return 0; - } - - if (~~a === a && ~~b === b) { - if (a === 0 || b === 0) { - return a < b ? -1 : 1; - } - - if (a < 0 || b < 0) { - if (b >= 0) { - return -1; - } - - if (a >= 0) { - return 1; - } - - a = -a; - b = -b; - } - - var al = log10(a); - var bl = log10(b); - - var t = 0; - - if (al < bl) { - a *= POWERS_OF_TEN[bl - al - 1]; - b /= 10; - t = -1; - } else if (al > bl) { - b *= POWERS_OF_TEN[al - bl - 1]; - a /= 10; - t = 1; - } - - if (a === b) { - return t; - } - - return a < b ? -1 : 1; - } - - var aStr = String(a); - var bStr = String(b); - - if (aStr === bStr) { - return 0; - } - - return aStr < bStr ? -1 : 1; -} - -/** - * Compute minimum run length for TimSort - * - * @param {number} n - The size of the array to sort. - */ -function minRunLength(n) { - var r = 0; - - while (n >= DEFAULT_MIN_MERGE) { - r |= (n & 1); - n >>= 1; - } - - return n + r; -} - -/** - * Counts the length of a monotonically ascending or strictly monotonically - * descending sequence (run) starting at array[lo] in the range [lo, hi). If - * the run is descending it is made ascending. - * - * @param {array} array - The array to reverse. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {function} compare - Item comparison function. - * @return {number} - The length of the run. - */ -function makeAscendingRun(array, lo, hi, compare) { - var runHi = lo + 1; - - if (runHi === hi) { - return 1; - } - - // Descending - if (compare(array[runHi++], array[lo]) < 0) { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { - runHi++; - } - - reverseRun(array, lo, runHi); - // Ascending - } else { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { - runHi++; - } - } - - return runHi - lo; -} - -/** - * Reverse an array in the range [lo, hi). - * - * @param {array} array - The array to reverse. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - */ -function reverseRun(array, lo, hi) { - hi--; - - while (lo < hi) { - var t = array[lo]; - array[lo++] = array[hi]; - array[hi--] = t; - } -} - -/** - * Perform the binary sort of the array in the range [lo, hi) where start is - * the first element possibly out of order. - * - * @param {array} array - The array to sort. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {number} start - First element possibly out of order. - * @param {function} compare - Item comparison function. - */ -function binaryInsertionSort(array, lo, hi, start, compare) { - if (start === lo) { - start++; - } - - for (; start < hi; start++) { - var pivot = array[start]; - - // Ranges of the array where pivot belongs - var left = lo; - var right = start; - - /* - * pivot >= array[i] for i in [lo, left) - * pivot < array[i] for i in in [right, start) - */ - while (left < right) { - var mid = (left + right) >>> 1; - - if (compare(pivot, array[mid]) < 0) { - right = mid; - } else { - left = mid + 1; - } - } - - /* - * Move elements right to make room for the pivot. If there are elements - * equal to pivot, left points to the first slot after them: this is also - * a reason for which TimSort is stable - */ - var n = start - left; - // Switch is just an optimization for small arrays - switch (n) { - case 3: - array[left + 3] = array[left + 2]; - /* falls through */ - case 2: - array[left + 2] = array[left + 1]; - /* falls through */ - case 1: - array[left + 1] = array[left]; - break; - default: - while (n > 0) { - array[left + n] = array[left + n - 1]; - n--; - } - } - - array[left] = pivot; - } -} - -/** - * Find the position at which to insert a value in a sorted range. If the range - * contains elements equal to the value the leftmost element index is returned - * (for stability). - * - * @param {number} value - Value to insert. - * @param {array} array - The array in which to insert value. - * @param {number} start - First element in the range. - * @param {number} length - Length of the range. - * @param {number} hint - The index at which to begin the search. - * @param {function} compare - Item comparison function. - * @return {number} - The index where to insert value. - */ -function gallopLeft(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) > 0) { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - lastOffset += hint; - offset += hint; - - // value <= array[start + hint] - } else { - maxOffset = hint + 1; - while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - } - - /* - * Now array[start+lastOffset] < value <= array[start+offset], so value - * belongs somewhere in the range (start + lastOffset, start + offset]. Do a - * binary search, with invariant array[start + lastOffset - 1] < value <= - * array[start + offset]. - */ - lastOffset++; - while (lastOffset < offset) { - var m = lastOffset + ((offset - lastOffset) >>> 1); - - if (compare(value, array[start + m]) > 0) { - lastOffset = m + 1; - - } else { - offset = m; - } - } - return offset; -} - -/** - * Find the position at which to insert a value in a sorted range. If the range - * contains elements equal to the value the rightmost element index is returned - * (for stability). - * - * @param {number} value - Value to insert. - * @param {array} array - The array in which to insert value. - * @param {number} start - First element in the range. - * @param {number} length - Length of the range. - * @param {number} hint - The index at which to begin the search. - * @param {function} compare - Item comparison function. - * @return {number} - The index where to insert value. - */ -function gallopRight(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) < 0) { - maxOffset = hint + 1; - - while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - - // value >= array[start + hint] - } else { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - lastOffset += hint; - offset += hint; - } - - /* - * Now array[start+lastOffset] < value <= array[start+offset], so value - * belongs somewhere in the range (start + lastOffset, start + offset]. Do a - * binary search, with invariant array[start + lastOffset - 1] < value <= - * array[start + offset]. - */ - lastOffset++; - - while (lastOffset < offset) { - var m = lastOffset + ((offset - lastOffset) >>> 1); - - if (compare(value, array[start + m]) < 0) { - offset = m; - - } else { - lastOffset = m + 1; - } - } - - return offset; -} - -var TimSort = function TimSort(array, compare) { - this.array = array; - this.compare = compare; - this.minGallop = DEFAULT_MIN_GALLOPING; - this.length = array.length; - - this.tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH; - if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) { - this.tmpStorageLength = this.length >>> 1; - } - - this.tmp = new Array(this.tmpStorageLength); - - this.stackLength = - (this.length < 120 ? 5 : - this.length < 1542 ? 10 : - this.length < 119151 ? 19 : 40); - - this.runStart = new Array(this.stackLength); - this.runLength = new Array(this.stackLength); - this.stackSize = 0; -}; - -/** - * Push a new run on TimSort's stack. - * - * @param {number} runStart - Start index of the run in the original array. - * @param {number} runLength - Length of the run; - */ -TimSort.prototype.pushRun = function pushRun (runStart, runLength) { - this.runStart[this.stackSize] = runStart; - this.runLength[this.stackSize] = runLength; - this.stackSize += 1; -}; - -/** - * Merge runs on TimSort's stack so that the following holds for all i: - * 1) runLength[i - 3] > runLength[i - 2] + runLength[i - 1] - * 2) runLength[i - 2] > runLength[i - 1] - */ -TimSort.prototype.mergeRuns = function mergeRuns () { - var this$1 = this; - - while (this.stackSize > 1) { - var n = this$1.stackSize - 2; - - if ((n >= 1 && - this$1.runLength[n - 1] <= this$1.runLength[n] + this$1.runLength[n + 1]) || - (n >= 2 && - this$1.runLength[n - 2] <= this$1.runLength[n] + this$1.runLength[n - 1])) { - - if (this$1.runLength[n - 1] < this$1.runLength[n + 1]) { - n--; - } - - } else if (this$1.runLength[n] > this$1.runLength[n + 1]) { - break; - } - this$1.mergeAt(n); - } -}; - -/** - * Merge all runs on TimSort's stack until only one remains. - */ -TimSort.prototype.forceMergeRuns = function forceMergeRuns () { - var this$1 = this; - - while (this.stackSize > 1) { - var n = this$1.stackSize - 2; - - if (n > 0 && this$1.runLength[n - 1] < this$1.runLength[n + 1]) { - n--; - } - - this$1.mergeAt(n); - } -}; - -/** - * Merge the runs on the stack at positions i and i+1. Must be always be called - * with i=stackSize-2 or i=stackSize-3 (that is, we merge on top of the stack). - * - * @param {number} i - Index of the run to merge in TimSort's stack. - */ -TimSort.prototype.mergeAt = function mergeAt (i) { - var compare = this.compare; - var array = this.array; - - var start1 = this.runStart[i]; - var length1 = this.runLength[i]; - var start2 = this.runStart[i + 1]; - var length2 = this.runLength[i + 1]; - - this.runLength[i] = length1 + length2; - - if (i === this.stackSize - 3) { - this.runStart[i + 1] = this.runStart[i + 2]; - this.runLength[i + 1] = this.runLength[i + 2]; - } - - this.stackSize--; - - /* - * Find where the first element in the second run goes in run1. Previous - * elements in run1 are already in place - */ - var k = gallopRight(array[start2], array, start1, length1, 0, compare); - start1 += k; - length1 -= k; - - if (length1 === 0) { - return; - } - - /* - * Find where the last element in the first run goes in run2. Next elements - * in run2 are already in place - */ - length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); - - if (length2 === 0) { - return; - } - - /* - * Merge remaining runs. A tmp array with length = min(length1, length2) is - * used - */ - if (length1 <= length2) { - this.mergeLow(start1, length1, start2, length2); - - } else { - this.mergeHigh(start1, length1, start2, length2); - } -}; - -/** - * Merge two adjacent runs in a stable way. The runs must be such that the - * first element of run1 is bigger than the first element in run2 and the - * last element of run1 is greater than all the elements in run2. - * The method should be called when run1.length <= run2.length as it uses - * TimSort temporary array to store run1. Use mergeHigh if run1.length > - * run2.length. - * - * @param {number} start1 - First element in run1. - * @param {number} length1 - Length of run1. - * @param {number} start2 - First element in run2. - * @param {number} length2 - Length of run2. - */ -TimSort.prototype.mergeLow = function mergeLow (start1, length1, start2, length2) { - - var compare = this.compare; - var array = this.array; - var tmp = this.tmp; - var i = 0; - - for (i = 0; i < length1; i++) { - tmp[i] = array[start1 + i]; - } - - var cursor1 = 0; - var cursor2 = start2; - var dest = start1; - - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - return; - } - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - array[dest + length2] = tmp[cursor1]; - return; - } - - var minGallop = this.minGallop; - - while (true) { - var count1 = 0; - var count2 = 0; - var exit = false; - - do { - if (compare(array[cursor2], tmp[cursor1]) < 0) { - array[dest++] = array[cursor2++]; - count2++; - count1 = 0; - - if (--length2 === 0) { - exit = true; - break; - } - - } else { - array[dest++] = tmp[cursor1++]; - count1++; - count2 = 0; - if (--length1 === 1) { - exit = true; - break; - } - } - } while ((count1 | count2) < minGallop); - - if (exit) { - break; - } - - do { - count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); - - if (count1 !== 0) { - for (i = 0; i < count1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - - dest += count1; - cursor1 += count1; - length1 -= count1; - if (length1 <= 1) { - exit = true; - break; - } - } - - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - exit = true; - break; - } - - count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); - - if (count2 !== 0) { - for (i = 0; i < count2; i++) { - array[dest + i] = array[cursor2 + i]; - } - - dest += count2; - cursor2 += count2; - length2 -= count2; - - if (length2 === 0) { - exit = true; - break; - } - } - array[dest++] = tmp[cursor1++]; - - if (--length1 === 1) { - exit = true; - break; - } - - minGallop--; - - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (minGallop < 0) { - minGallop = 0; - } - - minGallop += 2; - } - - this.minGallop = minGallop; - - if (minGallop < 1) { - this.minGallop = 1; - } - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - array[dest + length2] = tmp[cursor1]; - - } else if (length1 === 0) { - throw new Error('mergeLow preconditions were not respected'); - - } else { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - } -}; - -/** - * Merge two adjacent runs in a stable way. The runs must be such that the - * first element of run1 is bigger than the first element in run2 and the - * last element of run1 is greater than all the elements in run2. - * The method should be called when run1.length > run2.length as it uses - * TimSort temporary array to store run2. Use mergeLow if run1.length <= - * run2.length. - * - * @param {number} start1 - First element in run1. - * @param {number} length1 - Length of run1. - * @param {number} start2 - First element in run2. - * @param {number} length2 - Length of run2. - */ -TimSort.prototype.mergeHigh = function mergeHigh (start1, length1, start2, length2) { - var compare = this.compare; - var array = this.array; - var tmp = this.tmp; - var i = 0; - - for (i = 0; i < length2; i++) { - tmp[i] = array[start2 + i]; - } - - var cursor1 = start1 + length1 - 1; - var cursor2 = length2 - 1; - var dest = start2 + length2 - 1; - var customCursor = 0; - var customDest = 0; - - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - customCursor = dest - (length2 - 1); - - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - - return; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - return; - } - - var minGallop = this.minGallop; - - while (true) { - var count1 = 0; - var count2 = 0; - var exit = false; - - do { - if (compare(tmp[cursor2], array[cursor1]) < 0) { - array[dest--] = array[cursor1--]; - count1++; - count2 = 0; - if (--length1 === 0) { - exit = true; - break; - } - - } else { - array[dest--] = tmp[cursor2--]; - count2++; - count1 = 0; - if (--length2 === 1) { - exit = true; - break; - } - } - - } while ((count1 | count2) < minGallop); - - if (exit) { - break; - } - - do { - count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); - - if (count1 !== 0) { - dest -= count1; - cursor1 -= count1; - length1 -= count1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = count1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - if (length1 === 0) { - exit = true; - break; - } - } - - array[dest--] = tmp[cursor2--]; - - if (--length2 === 1) { - exit = true; - break; - } - - count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); - - if (count2 !== 0) { - dest -= count2; - cursor2 -= count2; - length2 -= count2; - customDest = dest + 1; - customCursor = cursor2 + 1; - - for (i = 0; i < count2; i++) { - array[customDest + i] = tmp[customCursor + i]; - } - - if (length2 <= 1) { - exit = true; - break; - } - } - - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - exit = true; - break; - } - - minGallop--; - - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (minGallop < 0) { - minGallop = 0; - } - - minGallop += 2; - } - - this.minGallop = minGallop; - - if (minGallop < 1) { - this.minGallop = 1; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - - } else if (length2 === 0) { - throw new Error('mergeHigh preconditions were not respected'); - - } else { - customCursor = dest - (length2 - 1); - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - } -}; - -/** - * Sort an array in the range [lo, hi) using TimSort. - * - * @param {array} array - The array to sort. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {function=} compare - Item comparison function. Default is alphabetical. - */ -function sort (array, lo, hi, compare) { - if (!Array.isArray(array)) { - throw new TypeError('Can only sort arrays'); - } - - /* - * Handle the case where a comparison function is not provided. We do - * lexicographic sorting - */ - - if (lo === undefined) { - lo = 0; - } - - if (hi === undefined) { - hi = array.length; - } - - if (compare === undefined) { - compare = alphabeticalCompare; - } - - var remaining = hi - lo; - - // The array is already sorted - if (remaining < 2) { - return; - } - - var runLength = 0; - // On small arrays binary sort can be used directly - if (remaining < DEFAULT_MIN_MERGE) { - runLength = makeAscendingRun(array, lo, hi, compare); - binaryInsertionSort(array, lo, hi, lo + runLength, compare); - return; - } - - var ts = new TimSort(array, compare); - - var minRun = minRunLength(remaining); - - do { - runLength = makeAscendingRun(array, lo, hi, compare); - if (runLength < minRun) { - var force = remaining; - if (force > minRun) { - force = minRun; - } - - binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); - runLength = force; - } - // Push new run and merge if necessary - ts.pushRun(lo, runLength); - ts.mergeRuns(); - - // Go find next run - remaining -= runLength; - lo += runLength; - - } while (remaining !== 0); - - // Force merging of remaining runs - ts.forceMergeRuns(); -} - -var FixedArray = function FixedArray(size) { - this._count = 0; - this._data = new Array(size); -}; - -var prototypeAccessors$1 = { length: { configurable: true },data: { configurable: true } }; - -FixedArray.prototype._resize = function _resize (size) { - var this$1 = this; - - if (size > this._data.length) { - for (var i = this._data.length; i < size; ++i) { - this$1._data[i] = undefined; - } - } -}; - -prototypeAccessors$1.length.get = function () { - return this._count; -}; - -prototypeAccessors$1.data.get = function () { - return this._data; -}; - -FixedArray.prototype.reset = function reset () { - var this$1 = this; - - for (var i = 0; i < this._count; ++i) { - this$1._data[i] = undefined; - } - - this._count = 0; -}; - -FixedArray.prototype.push = function push (val) { - if (this._count >= this._data.length) { - this._resize(this._data.length * 2); - } - - this._data[this._count] = val; - ++this._count; -}; - -FixedArray.prototype.pop = function pop () { - --this._count; - - if (this._count < 0) { - this._count = 0; - } - - var ret = this._data[this._count]; - this._data[this._count] = undefined; - - return ret; -}; - -FixedArray.prototype.fastRemove = function fastRemove (idx) { - if (idx >= this._count) { - return; - } - - var last = this._count - 1; - this._data[idx] = this._data[last]; - this._data[last] = undefined; - this._count -= 1; -}; - -FixedArray.prototype.indexOf = function indexOf (val) { - var idx = this._data.indexOf(val); - if (idx >= this._count) { - return -1; - } - - return idx; -}; - -FixedArray.prototype.sort = function sort$1 (cmp) { - return sort(this._data, 0, this._count, cmp); -}; - -Object.defineProperties( FixedArray.prototype, prototypeAccessors$1 ); - -var Pool = function Pool(fn, size) { - var this$1 = this; - - this._fn = fn; - this._idx = size - 1; - this._frees = new Array(size); - - for (var i = 0; i < size; ++i) { - this$1._frees[i] = fn(); - } -}; - -Pool.prototype._expand = function _expand (size) { - var this$1 = this; - - var old = this._frees; - this._frees = new Array(size); - - var len = size - old.length; - for (var i = 0; i < len; ++i) { - this$1._frees[i] = this$1._fn(); - } - - for (var i$1 = len, j = 0; i$1 < size; ++i$1, ++j) { - this$1._frees[i$1] = old[j]; - } - - this._idx += len; -}; - -Pool.prototype.alloc = function alloc () { - // create some more space (expand by 20%, minimum 1) - if (this._idx < 0) { - this._expand(Math.round(this._frees.length * 1.2) + 1); - } - - var ret = this._frees[this._idx]; - this._frees[this._idx] = null; - --this._idx; - - return ret; -}; - -Pool.prototype.free = function free (obj) { - ++this._idx; - this._frees[this._idx] = obj; -}; - -// NOTE: you must have `_prev` and `_next` field in the object returns by `fn` - -var LinkedArray = function LinkedArray(fn, size) { - this._fn = fn; - this._count = 0; - this._head = null; - this._tail = null; - - this._pool = new Pool(fn, size); -}; - -var prototypeAccessors$2 = { head: { configurable: true },tail: { configurable: true },length: { configurable: true } }; - -prototypeAccessors$2.head.get = function () { - return this._head; -}; - -prototypeAccessors$2.tail.get = function () { - return this._tail; -}; - -prototypeAccessors$2.length.get = function () { - return this._count; -}; - -LinkedArray.prototype.add = function add () { - var node = this._pool.alloc(); - - if (!this._tail) { - this._head = node; - } else { - this._tail._next = node; - node._prev = this._tail; - } - this._tail = node; - this._count += 1; - - return node; -}; - -LinkedArray.prototype.remove = function remove (node) { - if (node._prev) { - node._prev._next = node._next; - } else { - this._head = node._next; - } - - if (node._next) { - node._next._prev = node._prev; - } else { - this._tail = node._prev; - } - - node._next = null; - node._prev = null; - this._pool.free(node); - this._count -= 1; -}; - -LinkedArray.prototype.forEach = function forEach (fn, binder) { - var this$1 = this; - - var cursor = this._head; - if (!cursor) { - return; - } - - if (binder) { - fn = fn.bind(binder); - } - - var idx = 0; - var next = cursor; - - while (cursor) { - next = cursor._next; - fn(cursor, idx, this$1); - - cursor = next; - ++idx; - } -}; - -Object.defineProperties( LinkedArray.prototype, prototypeAccessors$2 ); - -var RecyclePool = function RecyclePool(fn, size) { - var this$1 = this; - - this._fn = fn; - this._count = 0; - this._data = new Array(size); - - for (var i = 0; i < size; ++i) { - this$1._data[i] = fn(); - } -}; - -var prototypeAccessors$3 = { length: { configurable: true },data: { configurable: true } }; - -prototypeAccessors$3.length.get = function () { - return this._count; -}; - -prototypeAccessors$3.data.get = function () { - return this._data; -}; - -RecyclePool.prototype.reset = function reset () { - this._count = 0; -}; - -RecyclePool.prototype.resize = function resize (size) { - var this$1 = this; - - if (size > this._data.length) { - for (var i = this._data.length; i < size; ++i) { - this$1._data[i] = this$1._fn(); - } - } -}; - -RecyclePool.prototype.add = function add () { - if (this._count >= this._data.length) { - this.resize(this._data.length * 2); - } - - return this._data[this._count++]; -}; - -RecyclePool.prototype.remove = function remove (idx) { - if (idx >= this._count) { - return; - } - - var last = this._count - 1; - var tmp = this._data[idx]; - this._data[idx] = this._data[last]; - this._data[last] = tmp; - this._count -= 1; -}; - -RecyclePool.prototype.sort = function sort$1 (cmp) { - return sort(this._data, 0, this._count, cmp); -}; - -Object.defineProperties( RecyclePool.prototype, prototypeAccessors$3 ); - -var _bufferPools = Array(8); -for (var i = 0; i < 8; ++i) { - _bufferPools[i] = []; -} - -// Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - -/** - * BaseRenderData is a core data abstraction for renderer, this is a abstract class. - * An inherited render data type should define raw vertex datas. - * User should also define the effect, vertex count and index count. - */ -var BaseRenderData = function BaseRenderData () { - this.material = null; - this.vertexCount = 0; - this.indiceCount = 0; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _pool; -var _dataPool = new Pool(function () { - return { - x: 0.0, - y: 0.0, - z: 0.0, - u: 0.0, - v: 0.0, - color: 0 - }; -}, 128); - -/** - * RenderData is most widely used render data type. - * It describes raw vertex data with a fixed data layout. - * Each vertex is described by five property: x, y, u, v, color. The data layout might be extended in the future. - * Vertex data objects are managed automatically by RenderData, user only need to set the dataLength property. - * User can also define rendering index orders for the vertex list. - */ -var RenderData = (function (BaseRenderData$$1) { - function RenderData () { - BaseRenderData$$1.call(this); - this._data = []; - this._indices = []; - - this._pivotX = 0; - this._pivotY = 0; - this._width = 0; - this._height = 0; - - this.uvDirty = true; - this.vertDirty = true; - } - - if ( BaseRenderData$$1 ) RenderData.__proto__ = BaseRenderData$$1; - RenderData.prototype = Object.create( BaseRenderData$$1 && BaseRenderData$$1.prototype ); - RenderData.prototype.constructor = RenderData; - - var prototypeAccessors = { type: { configurable: true },dataLength: { configurable: true } }; - - prototypeAccessors.type.get = function () { - return RenderData.type; - }; - - prototypeAccessors.dataLength.get = function () { - return this._data.length; - }; - - prototypeAccessors.dataLength.set = function (length) { - var data = this._data; - if (data.length !== length) { - // Free extra data - for (var i = length; i < data.length; i++) { - _dataPool.free(data[i]); - } - // Alloc needed data - for (var i$1 = data.length; i$1 < length; i$1++) { - data[i$1] = _dataPool.alloc(); - } - data.length = length; - } - }; - - RenderData.prototype.updateSizeNPivot = function updateSizeNPivot (width, height, pivotX, pivotY) { - if (width !== this._width || - height !== this._height || - pivotX !== this._pivotX || - pivotY !== this._pivotY) - { - this._width = width; - this._height = height; - this._pivotX = pivotX; - this._pivotY = pivotY; - this.vertDirty = true; - } - }; - - RenderData.alloc = function alloc () { - return _pool.alloc(); - }; - - RenderData.free = function free (data) { - if (data instanceof RenderData) { - for (var i = data.length-1; i > 0; i--) { - _dataPool.free(data._data[i]); - } - data._data.length = 0; - data._indices.length = 0; - data.material = null; - data.uvDirty = true; - data.vertDirty = true; - data.vertexCount = 0; - data.indiceCount = 0; - _pool.free(data); - } - }; - - Object.defineProperties( RenderData.prototype, prototypeAccessors ); - - return RenderData; -}(BaseRenderData)); - -RenderData.type = 'RenderData'; - -_pool = new Pool(function () { - return new RenderData(); -}, 32); - -// Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - -/** - * IARenderData is user customized render data type, user should provide the entier input assembler. - * IARenderData just defines a property `ia` for accessing the input assembler. - * It doesn't manage memory so users should manage the memory of input assembler by themselves. - */ -var IARenderData = (function (BaseRenderData$$1) { - function IARenderData () { - BaseRenderData$$1.call(this); - this.ia = null; - } - - if ( BaseRenderData$$1 ) IARenderData.__proto__ = BaseRenderData$$1; - IARenderData.prototype = Object.create( BaseRenderData$$1 && BaseRenderData$$1.prototype ); - IARenderData.prototype.constructor = IARenderData; - - var prototypeAccessors = { type: { configurable: true } }; - - prototypeAccessors.type.get = function () { - return IARenderData.type; - }; - - Object.defineProperties( IARenderData.prototype, prototypeAccessors ); - - return IARenderData; -}(BaseRenderData)); - -IARenderData.type = 'IARenderData'; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Asset = function Asset(persist) { - if ( persist === void 0 ) persist = true; - - this._loaded = false; - this._persist = persist; -}; - -Asset.prototype.unload = function unload () { - this._loaded = false; -}; - -Asset.prototype.reload = function reload () { - // TODO -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Texture = (function (Asset$$1) { - function Texture(persist) { - if ( persist === void 0 ) persist = true; - - Asset$$1.call(this, persist); - - this._texture = null; - } - - if ( Asset$$1 ) Texture.__proto__ = Asset$$1; - Texture.prototype = Object.create( Asset$$1 && Asset$$1.prototype ); - Texture.prototype.constructor = Texture; - - Texture.prototype.getImpl = function getImpl () { - return this._texture; - }; - - Texture.prototype.getId = function getId () {}; - - Texture.prototype.destroy = function destroy () { - this._texture && this._texture.destroy(); - }; - - return Texture; -}(Asset)); - -/** - * JS Implementation of MurmurHash2 - * - * @author Gary Court - * @see http://github.com/garycourt/murmurhash-js - * @author Austin Appleby - * @see http://sites.google.com/site/murmurhash/ - * - * @param {string} str ASCII only - * @param {number} seed Positive integer only - * @return {number} 32-bit positive integer hash - */ - -function murmurhash2_32_gc(str, seed) { - var - l = str.length, - h = seed ^ l, - i = 0, - k; - - while (l >= 4) { - k = - ((str.charCodeAt(i) & 0xff)) | - ((str.charCodeAt(++i) & 0xff) << 8) | - ((str.charCodeAt(++i) & 0xff) << 16) | - ((str.charCodeAt(++i) & 0xff) << 24); - - k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - k ^= k >>> 24; - k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - - h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k; - - l -= 4; - ++i; - } - - switch (l) { - case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16; - case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8; - case 1: h ^= (str.charCodeAt(i) & 0xff); - h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - } - - h ^= h >>> 13; - h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - h ^= h >>> 15; - - return h >>> 0; -} - -var renderer$6 = window.renderer; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -// function genHashCode (str) { -// var hash = 0; -// if (str.length == 0) { -// return hash; -// } -// for (var i = 0; i < str.length; i++) { -// var char = str.charCodeAt(i); -// hash = ((hash<<5)-hash)+char; -// hash = hash & hash; // Convert to 32bit integer -// } -// return hash; -// } - -function serializeDefines (defines) { - var str = ''; - for (var i = 0; i < defines.length; i++) { - str += defines[i].name + defines[i].value; - } - return str; -} - -function serializePass (pass) { - var str = pass._programName + pass._cullMode; - if (pass._blend) { - str += pass._blendEq + pass._blendAlphaEq + pass._blendSrc + pass._blendDst - + pass._blendSrcAlpha + pass._blendDstAlpha + pass._blendColor; - } - if (pass._depthTest) { - str += pass._depthWrite + pass._depthFunc; - } - if (pass._stencilTest) { - str += pass._stencilFuncFront + pass._stencilRefFront + pass._stencilMaskFront - + pass._stencilFailOpFront + pass._stencilZFailOpFront + pass._stencilZPassOpFront - + pass._stencilWriteMaskFront - + pass._stencilFuncBack + pass._stencilRefBack + pass._stencilMaskBack - + pass._stencilFailOpBack + pass._stencilZFailOpBack + pass._stencilZPassOpBack - + pass._stencilWriteMaskBack; - } - return str; -} - -function computeHash(material) { - var effect = material._effect; - var hashData = ''; - if (effect) { - var i, j, techData, param, prop, propKey; - - // effect._defines - hashData += serializeDefines(effect._defines); - // effect._techniques - for (i = 0; i < effect._techniques.length; i++) { - techData = effect._techniques[i]; - // technique.stageIDs - hashData += techData.stageIDs; - // technique._layer - // hashData += + techData._layer + "_"; - // technique.passes - for (j = 0; j < techData.passes.length; j++) { - hashData += serializePass(techData.passes[j]); - } - //technique._parameters - for (j = 0; j < techData._parameters.length; j++) { - param = techData._parameters[j]; - propKey = param.name; - prop = effect._properties[propKey]; - if (!prop) { - continue; - } - switch(param.type) { - case renderer$6.PARAM_INT: - case renderer$6.PARAM_FLOAT: - hashData += prop + ';'; - break; - case renderer$6.PARAM_INT2: - case renderer$6.PARAM_FLOAT2: - hashData += prop.x + ',' + prop.y + ';'; - break; - case renderer$6.PARAM_INT4: - case renderer$6.PARAM_FLOAT4: - hashData += prop.x + ',' + prop.y + ',' + prop.z + ',' + prop.w + ';'; - break; - case renderer$6.PARAM_COLOR4: - hashData += prop.r + ',' + prop.g + ',' + prop.b + ',' + prop.a + ';'; - break; - case renderer$6.PARAM_MAT2: - hashData += prop.m00 + ',' + prop.m01 + ',' + prop.m02 + ',' + prop.m03 + ';'; - break; - case renderer$6.PARAM_TEXTURE_2D: - case renderer$6.PARAM_TEXTURE_CUBE: - hashData += material._texIds[propKey] + ';'; - break; - case renderer$6.PARAM_INT3: - case renderer$6.PARAM_FLOAT3: - case renderer$6.PARAM_COLOR3: - case renderer$6.PARAM_MAT3: - case renderer$6.PARAM_MAT4: - hashData += JSON.stringify(prop) + ';'; - break; - default: - break; - } - } - } - } - return hashData ? murmurhash2_32_gc(hashData, 666) : hashData; -} - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Material = (function (Asset$$1) { - function Material(persist) { - if ( persist === void 0 ) persist = false; - - Asset$$1.call(this, persist); - - this._effect = null; // renderer.Effect - this._texIds = {}; // ids collected from texture defines - this._hash = ''; - } - - if ( Asset$$1 ) Material.__proto__ = Asset$$1; - Material.prototype = Object.create( Asset$$1 && Asset$$1.prototype ); - Material.prototype.constructor = Material; - - var prototypeAccessors = { hash: { configurable: true } }; - - prototypeAccessors.hash.get = function () { - return this._hash; - }; - - Material.prototype.updateHash = function updateHash (value) { - this._hash = value || computeHash(this); - }; - - Object.defineProperties( Material.prototype, prototypeAccessors ); - - return Material; -}(Asset)); - -var gfx$5 = window.gfx; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var SpriteMaterial = (function (Material$$1) { - function SpriteMaterial() { - Material$$1.call(this, false); - - var pass = new renderer$6.Pass('sprite'); - pass.setDepth(false, false); - pass.setCullMode(gfx$5.CULL_NONE); - pass.setBlend( - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA, - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA - ); - - var mainTech = new renderer$6.Technique( - ['transparent'], - [ - { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer$6.PARAM_COLOR4 } ], - [ - pass - ] - ); - - this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer$6.Effect( - [ - mainTech ], - { - 'color': this._color - }, - [ - { name: 'useTexture', value: true }, - { name: 'useModel', value: false }, - { name: 'alphaTest', value: false }, - { name: 'useColor', value: true } ] - ); - - this._mainTech = mainTech; - this._texture = null; - } - - if ( Material$$1 ) SpriteMaterial.__proto__ = Material$$1; - SpriteMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); - SpriteMaterial.prototype.constructor = SpriteMaterial; - - var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },useColor: { configurable: true },texture: { configurable: true },color: { configurable: true } }; - - prototypeAccessors.effect.get = function () { - return this._effect; - }; - - prototypeAccessors.useTexture.get = function () { - return this._effect.getDefine('useTexture'); - }; - - prototypeAccessors.useTexture.set = function (val) { - this._effect.define('useTexture', val); - }; - - prototypeAccessors.useModel.get = function () { - return this._effect.getDefine('useModel'); - }; - - prototypeAccessors.useModel.set = function (val) { - this._effect.define('useModel', val); - }; - - prototypeAccessors.useColor.get = function () { - return this._effect.getDefine('useColor'); - }; - - prototypeAccessors.useColor.set = function (val) { - this._effect.define('useColor', val); - }; - - prototypeAccessors.texture.get = function () { - return this._texture; - }; - - prototypeAccessors.texture.set = function (val) { - if (this._texture !== val) { - this._texture = val; - this._effect.setProperty('texture', val.getImpl()); - this._texIds['texture'] = val.getId(); - } - }; - - prototypeAccessors.color.get = function () { - return this._color; - }; - - prototypeAccessors.color.set = function (val) { - var color = this._color; - color.r = val.r / 255; - color.g = val.g / 255; - color.b = val.b / 255; - color.a = val.a / 255; - this._effect.setProperty('color', color); - }; - - SpriteMaterial.prototype.clone = function clone () { - var copy = new SpriteMaterial(); - copy._mainTech.copy(this._mainTech); - copy.texture = this.texture; - copy.useTexture = this.useTexture; - copy.useModel = this.useModel; - copy.useColor = this.useColor; - copy.updateHash(); - return copy; - }; - - Object.defineProperties( SpriteMaterial.prototype, prototypeAccessors ); - - return SpriteMaterial; -}(Material)); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var GraySpriteMaterial = (function (Material$$1) { - function GraySpriteMaterial() { - Material$$1.call(this, false); - - var pass = new renderer$6.Pass('gray_sprite'); - pass.setDepth(false, false); - pass.setCullMode(gfx$5.CULL_NONE); - pass.setBlend( - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA, - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA - ); - - var mainTech = new renderer$6.Technique( - ['transparent'], - [ - { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, - { name: 'color', type: renderer$6.PARAM_COLOR4 } ], - [ - pass - ] - ); - - this._color = {r: 1, g: 1, b: 1, a: 1}; - this._effect = new renderer$6.Effect( - [ - mainTech ], - { - 'color': this._color - }, - [] - ); - - this._mainTech = mainTech; - this._texture = null; - } - - if ( Material$$1 ) GraySpriteMaterial.__proto__ = Material$$1; - GraySpriteMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); - GraySpriteMaterial.prototype.constructor = GraySpriteMaterial; - - var prototypeAccessors = { effect: { configurable: true },texture: { configurable: true },color: { configurable: true } }; - - prototypeAccessors.effect.get = function () { - return this._effect; - }; - - prototypeAccessors.texture.get = function () { - return this._texture; - }; - - prototypeAccessors.texture.set = function (val) { - if (this._texture !== val) { - this._texture = val; - this._effect.setProperty('texture', val.getImpl()); - this._texIds['texture'] = val.getId(); - } - }; - - prototypeAccessors.color.get = function () { - return this._color; - }; - - prototypeAccessors.color.set = function (val) { - var color = this._color; - color.r = val.r / 255; - color.g = val.g / 255; - color.b = val.b / 255; - color.a = val.a / 255; - this._effect.setProperty('color', color); - }; - - GraySpriteMaterial.prototype.clone = function clone () { - var copy = new GraySpriteMaterial(); - copy._mainTech.copy(this._mainTech); - copy.texture = this.texture; - copy.color = this.color; - copy.updateHash(); - return copy; - }; - - Object.defineProperties( GraySpriteMaterial.prototype, prototypeAccessors ); - - return GraySpriteMaterial; -}(Material)); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var StencilMaterial = (function (Material$$1) { - function StencilMaterial() { - Material$$1.call(this, false); - - this._pass = new renderer$6.Pass('sprite'); - this._pass.setDepth(false, false); - this._pass.setCullMode(gfx$5.CULL_NONE); - this._pass.setBlend( - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA, - gfx$5.BLEND_FUNC_ADD, - gfx$5.BLEND_SRC_ALPHA, gfx$5.BLEND_ONE_MINUS_SRC_ALPHA - ); - - var mainTech = new renderer$6.Technique( - ['transparent'], - [ - { name: 'texture', type: renderer$6.PARAM_TEXTURE_2D }, - { name: 'alphaThreshold', type: renderer$6.PARAM_FLOAT }, - { name: 'color', type: renderer$6.PARAM_COLOR4 } ], - [ - this._pass - ] - ); - - this._effect = new renderer$6.Effect( - [ - mainTech ], - { - 'color': {r: 1, g: 1, b: 1, a: 1} - }, - [ - { name: 'useTexture', value: true }, - { name: 'useModel', value: false }, - { name: 'alphaTest', value: true }, - { name: 'useColor', value: true } ] - ); - - this._mainTech = mainTech; - this._texture = null; - } - - if ( Material$$1 ) StencilMaterial.__proto__ = Material$$1; - StencilMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); - StencilMaterial.prototype.constructor = StencilMaterial; - - var prototypeAccessors = { effect: { configurable: true },useTexture: { configurable: true },useModel: { configurable: true },useColor: { configurable: true },texture: { configurable: true },alphaThreshold: { configurable: true } }; - - prototypeAccessors.effect.get = function () { - return this._effect; - }; - - prototypeAccessors.useTexture.get = function () { - return this._effect.getDefine('useTexture'); - }; - - prototypeAccessors.useTexture.set = function (val) { - this._effect.define('useTexture', val); - }; - - prototypeAccessors.useModel.get = function () { - return this._effect.getDefine('useModel'); - }; - - prototypeAccessors.useModel.set = function (val) { - this._effect.define('useModel', val); - }; - - prototypeAccessors.useColor.get = function () { - return this._effect.getDefine('useColor'); - }; - - prototypeAccessors.useColor.set = function (val) { - this._effect.define('useColor', val); - }; - - prototypeAccessors.texture.get = function () { - return this._texture; - }; - - prototypeAccessors.texture.set = function (val) { - if (this._texture !== val) { - this._texture = val; - this._effect.setProperty('texture', val.getImpl()); - this._texIds['texture'] = val.getId(); - } - }; - - prototypeAccessors.alphaThreshold.get = function () { - return this._effect.getProperty('alphaThreshold'); - }; - - prototypeAccessors.alphaThreshold.set = function (val) { - this._effect.setProperty('alphaThreshold', val); - }; - - StencilMaterial.prototype.clone = function clone () { - var copy = new StencilMaterial(); - copy._mainTech.copy(this._mainTech); - copy.useTexture = this.useTexture; - copy.useModel = this.useModel; - copy.useColor = this.useColor; - copy.texture = this.texture; - copy.alphaThreshold = this.alphaThreshold; - copy.updateHash(); - return copy; - }; - - Object.defineProperties( StencilMaterial.prototype, prototypeAccessors ); - - return StencilMaterial; -}(Material)); - -var _d2r = Math.PI / 180.0; -var _r2d = 180.0 / Math.PI; - -/** - * @property {number} EPSILON - */ -var EPSILON = 0.000001; - -/** - * Tests whether or not the arguments have approximately the same value, within an absolute - * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less - * than or equal to 1.0, and a relative tolerance is used for larger values) - * - * @param {Number} a The first number to test. - * @param {Number} b The second number to test. - * @returns {Boolean} True if the numbers are approximately equal, false otherwise. - */ -function equals(a, b) { - return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b)); -} - -/** - * Tests whether or not the arguments have approximately the same value by given maxDiff - * - * @param {Number} a The first number to test. - * @param {Number} b The second number to test. - * @param {Number} maxDiff Maximum difference. - * @returns {Boolean} True if the numbers are approximately equal, false otherwise. - */ -function approx(a, b, maxDiff) { - maxDiff = maxDiff || EPSILON; - return Math.abs(a - b) <= maxDiff; -} - -/** - * Clamps a value between a minimum float and maximum float value. - * - * @method clamp - * @param {number} val - * @param {number} min - * @param {number} max - * @return {number} - */ -function clamp(val, min, max) { - return val < min ? min : val > max ? max : val; -} - -/** - * Clamps a value between 0 and 1. - * - * @method clamp01 - * @param {number} val - * @return {number} - */ -function clamp01(val) { - return val < 0 ? 0 : val > 1 ? 1 : val; -} - -/** - * @method lerp - * @param {number} from - * @param {number} to - * @param {number} ratio - the interpolation coefficient - * @return {number} - */ -function lerp(from, to, ratio) { - return from + (to - from) * ratio; -} - -/** -* Convert Degree To Radian -* -* @param {Number} a Angle in Degrees -*/ -function toRadian(a) { - return a * _d2r; -} - -/** -* Convert Radian To Degree -* -* @param {Number} a Angle in Radian -*/ -function toDegree(a) { - return a * _r2d; -} - -/** -* @method random -*/ -var random = Math.random; - -/** - * Returns a floating-point random number between min (inclusive) and max (exclusive). - * - * @method randomRange - * @param {number} min - * @param {number} max - * @return {number} the random number - */ -function randomRange(min, max) { - return Math.random() * (max - min) + min; -} - -/** - * Returns a random integer between min (inclusive) and max (exclusive). - * - * @method randomRangeInt - * @param {number} min - * @param {number} max - * @return {number} the random integer - */ -function randomRangeInt(min, max) { - return Math.floor(randomRange(min, max)); -} - -/** - * Returns the next power of two for the value - * - * @method nextPow2 - * @param {number} val - * @return {number} the the next power of two - */ -function nextPow2(val) { - --val; - val = (val >> 1) | val; - val = (val >> 2) | val; - val = (val >> 4) | val; - val = (val >> 8) | val; - val = (val >> 16) | val; - ++val; - - return val; -} - -/** - * Bit twiddling hacks for JavaScript. - * - * Author: Mikola Lysenko - * - * Ported from Stanford bit twiddling hack library: - * http://graphics.stanford.edu/~seander/bithacks.html - */ - -// Number of bits in an integer -var INT_BITS = 32; -var INT_MAX = 0x7fffffff; -var INT_MIN = -1<<(INT_BITS-1); - -/** - * Returns -1, 0, +1 depending on sign of x - * - * @param {number} v - * @returns {number} - */ -function sign(v) { - return (v > 0) - (v < 0); -} - -/** - * Computes absolute value of integer - * - * @param {number} v - * @returns {number} - */ -function abs(v) { - var mask = v >> (INT_BITS-1); - return (v ^ mask) - mask; -} - -/** - * Computes minimum of integers x and y - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function min(x, y) { - return y ^ ((x ^ y) & -(x < y)); -} - -/** - * Computes maximum of integers x and y - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function max(x, y) { - return x ^ ((x ^ y) & -(x < y)); -} - -/** - * Checks if a number is a power of two - * - * @param {number} v - * @returns {boolean} - */ -function isPow2(v) { - return !(v & (v-1)) && (!!v); -} - -/** - * Computes log base 2 of v - * - * @param {number} v - * @returns {number} - */ -function log2(v) { - var r, shift; - r = (v > 0xFFFF) << 4; v >>>= r; - shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; - return r | (v >> 1); -} - -/** - * Computes log base 10 of v - * - * @param {number} v - * @returns {number} - */ -function log10$1(v) { - return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : - (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : - (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; -} - -/** - * Counts number of bits - * - * @param {number} v - * @returns {number} - */ -function popCount(v) { - v = v - ((v >>> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); - return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; -} - -/** - * Counts number of trailing zeros - * - * @param {number} v - * @returns {number} - */ -function countTrailingZeros(v) { - var c = 32; - v &= -v; - if (v) { c--; } - if (v & 0x0000FFFF) { c -= 16; } - if (v & 0x00FF00FF) { c -= 8; } - if (v & 0x0F0F0F0F) { c -= 4; } - if (v & 0x33333333) { c -= 2; } - if (v & 0x55555555) { c -= 1; } - return c; -} - -/** - * Rounds to next power of 2 - * - * @param {number} v - * @returns {number} - */ -function nextPow2$1(v) { - v += v === 0; - --v; - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v + 1; -} - -/** - * Rounds down to previous power of 2 - * - * @param {number} v - * @returns {number} - */ -function prevPow2(v) { - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v - (v>>>1); -} - -/** - * Computes parity of word - * - * @param {number} v - * @returns {number} - */ -function parity(v) { - v ^= v >>> 16; - v ^= v >>> 8; - v ^= v >>> 4; - v &= 0xf; - return (0x6996 >>> v) & 1; -} - -var REVERSE_TABLE = new Array(256); - -(function(tab) { - for(var i=0; i<256; ++i) { - var v = i, r = i, s = 7; - for (v >>>= 1; v; v >>>= 1) { - r <<= 1; - r |= v & 1; - --s; - } - tab[i] = (r << s) & 0xff; - } -})(REVERSE_TABLE); - -/** - * Reverse bits in a 32 bit word - * - * @param {number} v - * @returns {number} - */ -function reverse(v) { - return (REVERSE_TABLE[v & 0xff] << 24) | - (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | - (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | - REVERSE_TABLE[(v >>> 24) & 0xff]; -} - -/** - * Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function interleave2(x, y) { - x &= 0xFFFF; - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y &= 0xFFFF; - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -/** - * Extracts the nth interleaved component - * - * @param {number} v - * @param {number} n - * @returns {number} - */ -function deinterleave2(v, n) { - v = (v >>> n) & 0x55555555; - v = (v | (v >>> 1)) & 0x33333333; - v = (v | (v >>> 2)) & 0x0F0F0F0F; - v = (v | (v >>> 4)) & 0x00FF00FF; - v = (v | (v >>> 16)) & 0x000FFFF; - return (v << 16) >> 16; -} - -/** - * Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes - * - * @param {number} x - * @param {number} y - * @param {number} z - * @returns {number} - */ -function interleave3(x, y, z) { - x &= 0x3FF; - x = (x | (x<<16)) & 4278190335; - x = (x | (x<<8)) & 251719695; - x = (x | (x<<4)) & 3272356035; - x = (x | (x<<2)) & 1227133513; - - y &= 0x3FF; - y = (y | (y<<16)) & 4278190335; - y = (y | (y<<8)) & 251719695; - y = (y | (y<<4)) & 3272356035; - y = (y | (y<<2)) & 1227133513; - x |= (y << 1); - - z &= 0x3FF; - z = (z | (z<<16)) & 4278190335; - z = (z | (z<<8)) & 251719695; - z = (z | (z<<4)) & 3272356035; - z = (z | (z<<2)) & 1227133513; - - return x | (z << 2); -} - -/** - * Extracts nth interleaved component of a 3-tuple - * - * @param {number} v - * @param {number} n - * @returns {number} - */ -function deinterleave3(v, n) { - v = (v >>> n) & 1227133513; - v = (v | (v>>>2)) & 3272356035; - v = (v | (v>>>4)) & 251719695; - v = (v | (v>>>8)) & 4278190335; - v = (v | (v>>>16)) & 0x3FF; - return (v<<22)>>22; -} - -/** - * Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) - * - * @param {number} v - * @returns {number} - */ -function nextCombination(v) { - var t = v | (v - 1); - return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); -} - -var bits_ = Object.freeze({ - INT_BITS: INT_BITS, - INT_MAX: INT_MAX, - INT_MIN: INT_MIN, - sign: sign, - abs: abs, - min: min, - max: max, - isPow2: isPow2, - log2: log2, - log10: log10$1, - popCount: popCount, - countTrailingZeros: countTrailingZeros, - nextPow2: nextPow2$1, - prevPow2: prevPow2, - parity: parity, - reverse: reverse, - interleave2: interleave2, - deinterleave2: deinterleave2, - interleave3: interleave3, - deinterleave3: deinterleave3, - nextCombination: nextCombination -}); - -var _tmp = new Array(2); - -var _vec2 = function _vec2(x, y) { - this.x = x; - this.y = y; -}; - -_vec2.prototype.toJSON = function toJSON () { - _tmp[0] = this.x; - _tmp[1] = this.y; - - return _tmp; -}; - -/** - * @class 2 Dimensional Vector - * @name vec2 - */ -var vec2 = {}; - -/** - * Creates a new, empty vec2 - * - * @returns {vec2} a new 2D vector - */ -vec2.create = function () { - return new _vec2(0, 0); -}; - -/** - * Creates a new vec2 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @returns {vec2} a new 2D vector - */ -vec2.new = function (x, y) { - return new _vec2(x, y); -}; - -/** - * Creates a new vec2 initialized with values from an existing vector - * - * @param {vec2} a vector to clone - * @returns {vec2} a new 2D vector - */ -vec2.clone = function (a) { - return new _vec2(a.x, a.y); -}; - -/** - * Copy the values from one vec2 to another - * - * @param {vec2} out the receiving vector - * @param {vec2} a the source vector - * @returns {vec2} out - */ -vec2.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - return out; -}; - -/** - * Set the components of a vec2 to the given values - * - * @param {vec2} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @returns {vec2} out - */ -vec2.set = function (out, x, y) { - out.x = x; - out.y = y; - return out; -}; - -/** - * Adds two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - return out; -}; - -/** - * Alias for {@link vec2.subtract} - * @function - */ -vec2.sub = vec2.subtract; - -/** - * Multiplies two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - return out; -}; - -/** - * Alias for {@link vec2.multiply} - * @function - */ -vec2.mul = vec2.multiply; - -/** - * Divides two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - return out; -}; - -/** - * Alias for {@link vec2.divide} - * @function - */ -vec2.div = vec2.divide; - -/** - * Math.ceil the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to ceil - * @returns {vec2} out - */ -vec2.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - return out; -}; - -/** - * Math.floor the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to floor - * @returns {vec2} out - */ -vec2.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - return out; -}; - -/** - * Returns the minimum of two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - return out; -}; - -/** - * Returns the maximum of two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - return out; -}; - -/** - * Math.round the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to round - * @returns {vec2} out - */ -vec2.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - return out; -}; - -/** - * Scales a vec2 by a scalar number - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec2} out - */ -vec2.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - return out; -}; - -/** - * Adds two vec2's after scaling the second operand by a scalar value - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec2} out - */ -vec2.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} distance between a and b - */ -vec2.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y; - return Math.sqrt(x * x + y * y); -}; - -/** - * Alias for {@link vec2.distance} - * @function - */ -vec2.dist = vec2.distance; - -/** - * Calculates the squared euclidian distance between two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} squared distance between a and b - */ -vec2.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y; - return x * x + y * y; -}; - -/** - * Alias for {@link vec2.squaredDistance} - * @function - */ -vec2.sqrDist = vec2.squaredDistance; - -/** - * Calculates the length of a vec2 - * - * @param {vec2} a vector to calculate length of - * @returns {Number} length of a - */ -vec2.length = function (a) { - var x = a.x, - y = a.y; - return Math.sqrt(x * x + y * y); -}; - -/** - * Alias for {@link vec2.length} - * @function - */ -vec2.len = vec2.length; - -/** - * Calculates the squared length of a vec2 - * - * @param {vec2} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec2.squaredLength = function (a) { - var x = a.x, - y = a.y; - return x * x + y * y; -}; - -/** - * Alias for {@link vec2.squaredLength} - * @function - */ -vec2.sqrLen = vec2.squaredLength; - -/** - * Negates the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to negate - * @returns {vec2} out - */ -vec2.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - return out; -}; - -/** - * Returns the inverse of the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to invert - * @returns {vec2} out - */ -vec2.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - return out; -}; - -/** - * Returns the inverse of the components of a vec2 safely - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to invert - * @returns {vec2} out - */ -vec2.inverseSafe = function (out, a) { - var x = a.x, - y = a.y; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / a.y; - } - - return out; -}; - -/** - * Normalize a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to normalize - * @returns {vec2} out - */ -vec2.normalize = function (out, a) { - var x = a.x, - y = a.y; - var len = x * x + y * y; - if (len > 0) { - //TODO: evaluate use of glm_invsqrt here? - len = 1 / Math.sqrt(len); - out.x = a.x * len; - out.y = a.y * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} dot product of a and b - */ -vec2.dot = function (a, b) { - return a.x * b.x + a.y * b.y; -}; - -/** - * Computes the cross product of two vec2's - * Note that the cross product must by definition produce a 3D vector - * - * @param {vec3} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec3} out - */ -vec2.cross = function (out, a, b) { - var z = a.x * b.y - a.y * b.x; - out.x = out.y = 0; - out.z = z; - return out; -}; - -/** - * Performs a linear interpolation between two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec2} out - */ -vec2.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec2} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec2} out - */ -vec2.random = function (out, scale) { - scale = scale || 1.0; - var r = random() * 2.0 * Math.PI; - out.x = Math.cos(r) * scale; - out.y = Math.sin(r) * scale; - return out; -}; - -/** - * Transforms the vec2 with a mat2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat2} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat2 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m02 * y; - out.y = m.m01 * x + m.m03 * y; - return out; -}; - -/** - * Transforms the vec2 with a mat23 - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat23} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat23 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m02 * y + m.m04; - out.y = m.m01 * x + m.m03 * y + m.m05; - return out; -}; - -/** - * Transforms the vec2 with a mat3 - * 3rd vector component is implicitly '1' - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat3} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat3 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m03 * y + m.m06; - out.y = m.m01 * x + m.m04 * y + m.m07; - return out; -}; - -/** - * Transforms the vec2 with a mat4 - * 3rd vector component is implicitly '0' - * 4th vector component is implicitly '1' - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat4 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m04 * y + m.m12; - out.y = m.m01 * x + m.m05 * y + m.m13; - return out; -}; - -/** - * Perform some operation over an array of vec2s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec2.forEach = (function () { - var vec = vec2.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 2; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; - } - - return a; - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec2} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec2.str = function (a) { - return ("vec2(" + (a.x) + ", " + (a.y) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec2} v - * @returns {array} - */ -vec2.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - - return out; -}; - -/** - * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===) - * - * @param {vec2} a The first vector. - * @param {vec2} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec2.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec2} a The first vector. - * @param {vec2} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec2.equals = function (a, b) { - var a0 = a.x, a1 = a.y; - var b0 = b.x, b1 = b.y; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1))); -}; - -var _tmp$1 = new Array(3); - -var _vec3 = function _vec3(x, y, z) { - this.x = x; - this.y = y; - this.z = z; -}; - -_vec3.prototype.toJSON = function toJSON () { - _tmp$1[0] = this.x; - _tmp$1[1] = this.y; - _tmp$1[2] = this.z; - - return _tmp$1; -}; - -/** - * @class 3 Dimensional Vector - * @name vec3 - */ -var vec3 = {}; - -/** - * Creates a new, empty vec3 - * - * @returns {vec3} a new 3D vector - */ -vec3.create = function () { - return new _vec3(0, 0, 0); -}; - -/** - * Creates a new vec3 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} a new 3D vector - */ -vec3.new = function (x, y, z) { - return new _vec3(x, y, z); -}; - -/** - * Creates a new vec3 initialized with values from an existing vector - * - * @param {vec3} a vector to clone - * @returns {vec3} a new 3D vector - */ -vec3.clone = function (a) { - return new _vec3(a.x, a.y, a.z); -}; - -/** - * Copy the values from one vec3 to another - * - * @param {vec3} out the receiving vector - * @param {vec3} a the source vector - * @returns {vec3} out - */ -vec3.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - out.z = a.z; - return out; -}; - -/** - * Set the components of a vec3 to the given values - * - * @param {vec3} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} out - */ -vec3.set = function (out, x, y, z) { - out.x = x; - out.y = y; - out.z = z; - return out; -}; - -/** - * Adds two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - out.z = a.z + b.z; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; - return out; -}; - -/** - * Alias for {@link vec3.subtract} - * @function - */ -vec3.sub = vec3.subtract; - -/** - * Multiplies two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - out.z = a.z * b.z; - return out; -}; - -/** - * Alias for {@link vec3.multiply} - * @function - */ -vec3.mul = vec3.multiply; - -/** - * Divides two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - out.z = a.z / b.z; - return out; -}; - -/** - * Alias for {@link vec3.divide} - * @function - */ -vec3.div = vec3.divide; - -/** - * Math.ceil the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to ceil - * @returns {vec3} out - */ -vec3.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - out.z = Math.ceil(a.z); - return out; -}; - -/** - * Math.floor the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to floor - * @returns {vec3} out - */ -vec3.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - out.z = Math.floor(a.z); - return out; -}; - -/** - * Returns the minimum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - out.z = Math.min(a.z, b.z); - return out; -}; - -/** - * Returns the maximum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - out.z = Math.max(a.z, b.z); - return out; -}; - -/** - * Math.round the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to round - * @returns {vec3} out - */ -vec3.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - out.z = Math.round(a.z); - return out; -}; - -/** - * Scales a vec3 by a scalar number - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec3} out - */ -vec3.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - out.z = a.z * b; - return out; -}; - -/** - * Adds two vec3's after scaling the second operand by a scalar value - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec3} out - */ -vec3.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - out.z = a.z + (b.z * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} distance between a and b - */ -vec3.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z; - return Math.sqrt(x * x + y * y + z * z); -}; - -/** - * Alias for {@link vec3.distance} - * @function - */ -vec3.dist = vec3.distance; - -/** - * Calculates the squared euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} squared distance between a and b - */ -vec3.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z; - return x * x + y * y + z * z; -}; - -/** - * Alias for {@link vec3.squaredDistance} - * @function - */ -vec3.sqrDist = vec3.squaredDistance; - -/** - * Calculates the length of a vec3 - * - * @param {vec3} a vector to calculate length of - * @returns {Number} length of a - */ -vec3.length = function (a) { - var x = a.x, - y = a.y, - z = a.z; - return Math.sqrt(x * x + y * y + z * z); -}; - -/** - * Alias for {@link vec3.length} - * @function - */ -vec3.len = vec3.length; - -/** - * Calculates the squared length of a vec3 - * - * @param {vec3} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec3.squaredLength = function (a) { - var x = a.x, - y = a.y, - z = a.z; - return x * x + y * y + z * z; -}; - -/** - * Alias for {@link vec3.squaredLength} - * @function - */ -vec3.sqrLen = vec3.squaredLength; - -/** - * Negates the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to negate - * @returns {vec3} out - */ -vec3.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - return out; -}; - -/** - * Returns the inverse of the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to invert - * @returns {vec3} out - */ -vec3.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - out.z = 1.0 / a.z; - return out; -}; - -/** - * Returns the inverse of the components of a vec3 safely - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to invert - * @returns {vec3} out - */ -vec3.inverseSafe = function (out, a) { - var x = a.x, - y = a.y, - z = a.z; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / y; - } - - if (Math.abs(z) < EPSILON) { - out.z = 0; - } else { - out.z = 1.0 / z; - } - - return out; -}; - -/** - * Normalize a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to normalize - * @returns {vec3} out - */ -vec3.normalize = function (out, a) { - var x = a.x, - y = a.y, - z = a.z; - - var len = x * x + y * y + z * z; - if (len > 0) { - //TODO: evaluate use of glm_invsqrt here? - len = 1 / Math.sqrt(len); - out.x = x * len; - out.y = y * len; - out.z = z * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} dot product of a and b - */ -vec3.dot = function (a, b) { - return a.x * b.x + a.y * b.y + a.z * b.z; -}; - -/** - * Computes the cross product of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.cross = function (out, a, b) { - var ax = a.x, ay = a.y, az = a.z, - bx = b.x, by = b.y, bz = b.z; - - out.x = ay * bz - az * by; - out.y = az * bx - ax * bz; - out.z = ax * by - ay * bx; - return out; -}; - -/** - * Performs a linear interpolation between two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y, - az = a.z; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - out.z = az + t * (b.z - az); - return out; -}; - -/** - * Performs a hermite interpolation with two control points - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {vec3} c the third operand - * @param {vec3} d the fourth operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.hermite = function (out, a, b, c, d, t) { - var factorTimes2 = t * t, - factor1 = factorTimes2 * (2 * t - 3) + 1, - factor2 = factorTimes2 * (t - 2) + t, - factor3 = factorTimes2 * (t - 1), - factor4 = factorTimes2 * (3 - 2 * t); - - out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; - out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; - out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; - - return out; -}; - -/** - * Performs a bezier interpolation with two control points - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {vec3} c the third operand - * @param {vec3} d the fourth operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.bezier = function (out, a, b, c, d, t) { - var inverseFactor = 1 - t, - inverseFactorTimesTwo = inverseFactor * inverseFactor, - factorTimes2 = t * t, - factor1 = inverseFactorTimesTwo * inverseFactor, - factor2 = 3 * t * inverseFactorTimesTwo, - factor3 = 3 * factorTimes2 * inverseFactor, - factor4 = factorTimes2 * t; - - out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; - out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; - out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; - - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec3} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec3} out - */ -vec3.random = function (out, scale) { - scale = scale || 1.0; - - var r = random() * 2.0 * Math.PI; - var z = (random() * 2.0) - 1.0; - var zScale = Math.sqrt(1.0 - z * z) * scale; - - out.x = Math.cos(r) * zScale; - out.y = Math.sin(r) * zScale; - out.z = z * scale; - return out; -}; - -/** - * Transforms the vec3 with a mat4. - * 4th vector component is implicitly '1' - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec3} out - */ -vec3.transformMat4 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z, - w = m.m03 * x + m.m07 * y + m.m11 * z + m.m15; - w = w || 1.0; - out.x = (m.m00 * x + m.m04 * y + m.m08 * z + m.m12) / w; - out.y = (m.m01 * x + m.m05 * y + m.m09 * z + m.m13) / w; - out.z = (m.m02 * x + m.m06 * y + m.m10 * z + m.m14) / w; - return out; -}; - -/** - * Transforms the vec3 with a mat3. - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m the 3x3 matrix to transform with - * @returns {vec3} out - */ -vec3.transformMat3 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z; - out.x = x * m.m00 + y * m.m03 + z * m.m06; - out.y = x * m.m01 + y * m.m04 + z * m.m07; - out.z = x * m.m02 + y * m.m05 + z * m.m08; - return out; -}; - -/** - * Transforms the vec3 with a quat - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec3} out - */ -vec3.transformQuat = function (out, a, q) { - // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations - - var x = a.x, y = a.y, z = a.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vec - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - - // calculate result * inverse quat - out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - return out; -}; - -/** - * Rotate a 3D vector around the x-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateX = function (out, a, b, c) { - var p = [], r = []; - // Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.x; - r.y = p.y * Math.cos(c) - p.z * Math.sin(c); - r.z = p.y * Math.sin(c) + p.z * Math.cos(c); - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Rotate a 3D vector around the y-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateY = function (out, a, b, c) { - var p = [], r = []; - //Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.z * Math.sin(c) + p.x * Math.cos(c); - r.y = p.y; - r.z = p.z * Math.cos(c) - p.x * Math.sin(c); - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Rotate a 3D vector around the z-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateZ = function (out, a, b, c) { - var p = [], r = []; - //Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.x * Math.cos(c) - p.y * Math.sin(c); - r.y = p.x * Math.sin(c) + p.y * Math.cos(c); - r.z = p.z; - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Perform some operation over an array of vec3s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec3.forEach = (function () { - var vec = vec3.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 3; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; vec.z = a[i + 2]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; a[i + 2] = vec.z; - } - - return a; - }; -})(); - -/** - * Get the angle between two 3D vectors - * @param {vec3} a The first operand - * @param {vec3} b The second operand - * @returns {Number} The angle in radians - */ -vec3.angle = (function () { - var tempA = vec3.create(); - var tempB = vec3.create(); - - return function (a, b) { - vec3.copy(tempA, a); - vec3.copy(tempB, b); - - vec3.normalize(tempA, tempA); - vec3.normalize(tempB, tempB); - - var cosine = vec3.dot(tempA, tempB); - - if (cosine > 1.0) { - return 0; - } - - if (cosine < -1.0) { - return Math.PI; - } - - return Math.acos(cosine); - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec3} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec3.str = function (a) { - return ("vec3(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec3} v - * @returns {array} - */ -vec3.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - out[2] = v.z; - - return out; -}; - -/** - * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec3.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y && a.z === b.z; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec3.equals = function (a, b) { - var a0 = a.x, a1 = a.y, a2 = a.z; - var b0 = b.x, b1 = b.y, b2 = b.z; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); -}; - -var _tmp$2 = new Array(4); - -var _vec4 = function _vec4(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; -}; - -_vec4.prototype.toJSON = function toJSON () { - _tmp$2[0] = this.x; - _tmp$2[1] = this.y; - _tmp$2[2] = this.z; - _tmp$2[3] = this.w; - - return _tmp$2; -}; - -/** - * @class 4 Dimensional Vector - * @name vec4 - */ -var vec4 = {}; - -/** - * Creates a new, empty vec4 - * - * @returns {vec4} a new 4D vector - */ -vec4.create = function () { - return new _vec4(0, 0, 0, 0); -}; - -/** - * Creates a new vec4 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} a new 4D vector - */ -vec4.new = function (x, y, z, w) { - return new _vec4(x, y, z, w); -}; - -/** - * Creates a new vec4 initialized with values from an existing vector - * - * @param {vec4} a vector to clone - * @returns {vec4} a new 4D vector - */ -vec4.clone = function (a) { - return new _vec4(a.x, a.y, a.z, a.w); -}; - -/** - * Copy the values from one vec4 to another - * - * @param {vec4} out the receiving vector - * @param {vec4} a the source vector - * @returns {vec4} out - */ -vec4.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - out.z = a.z; - out.w = a.w; - return out; -}; - -/** - * Set the components of a vec4 to the given values - * - * @param {vec4} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} out - */ -vec4.set = function (out, x, y, z, w) { - out.x = x; - out.y = y; - out.z = z; - out.w = w; - return out; -}; - -/** - * Adds two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - out.z = a.z + b.z; - out.w = a.w + b.w; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; - out.w = a.w - b.w; - return out; -}; - -/** - * Alias for {@link vec4.subtract} - * @function - */ -vec4.sub = vec4.subtract; - -/** - * Multiplies two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - out.z = a.z * b.z; - out.w = a.w * b.w; - return out; -}; - -/** - * Alias for {@link vec4.multiply} - * @function - */ -vec4.mul = vec4.multiply; - -/** - * Divides two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - out.z = a.z / b.z; - out.w = a.w / b.w; - return out; -}; - -/** - * Alias for {@link vec4.divide} - * @function - */ -vec4.div = vec4.divide; - -/** - * Math.ceil the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to ceil - * @returns {vec4} out - */ -vec4.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - out.z = Math.ceil(a.z); - out.w = Math.ceil(a.w); - return out; -}; - -/** - * Math.floor the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to floor - * @returns {vec4} out - */ -vec4.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - out.z = Math.floor(a.z); - out.w = Math.floor(a.w); - return out; -}; - -/** - * Returns the minimum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - out.z = Math.min(a.z, b.z); - out.w = Math.min(a.w, b.w); - return out; -}; - -/** - * Returns the maximum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - out.z = Math.max(a.z, b.z); - out.w = Math.max(a.w, b.w); - return out; -}; - -/** - * Math.round the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to round - * @returns {vec4} out - */ -vec4.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - out.z = Math.round(a.z); - out.w = Math.round(a.w); - return out; -}; - -/** - * Scales a vec4 by a scalar number - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec4} out - */ -vec4.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - out.z = a.z * b; - out.w = a.w * b; - return out; -}; - -/** - * Adds two vec4's after scaling the second operand by a scalar value - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec4} out - */ -vec4.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - out.z = a.z + (b.z * scale); - out.w = a.w + (b.w * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} distance between a and b - */ -vec4.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z, - w = b.w - a.w; - return Math.sqrt(x * x + y * y + z * z + w * w); -}; - -/** - * Alias for {@link vec4.distance} - * @function - */ -vec4.dist = vec4.distance; - -/** - * Calculates the squared euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} squared distance between a and b - */ -vec4.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z, - w = b.w - a.w; - return x * x + y * y + z * z + w * w; -}; - -/** - * Alias for {@link vec4.squaredDistance} - * @function - */ -vec4.sqrDist = vec4.squaredDistance; - -/** - * Calculates the length of a vec4 - * - * @param {vec4} a vector to calculate length of - * @returns {Number} length of a - */ -vec4.length = function (a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - return Math.sqrt(x * x + y * y + z * z + w * w); -}; - -/** - * Alias for {@link vec4.length} - * @function - */ -vec4.len = vec4.length; - -/** - * Calculates the squared length of a vec4 - * - * @param {vec4} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec4.squaredLength = function (a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - return x * x + y * y + z * z + w * w; -}; - -/** - * Alias for {@link vec4.squaredLength} - * @function - */ -vec4.sqrLen = vec4.squaredLength; - -/** - * Negates the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to negate - * @returns {vec4} out - */ -vec4.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - out.w = -a.w; - return out; -}; - -/** - * Returns the inverse of the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to invert - * @returns {vec4} out - */ -vec4.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - out.z = 1.0 / a.z; - out.w = 1.0 / a.w; - return out; -}; - -/** - * Returns the inverse of the components of a vec4 safely - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to invert - * @returns {vec4} out - */ -vec4.inverseSafe = function (out, a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / y; - } - - if (Math.abs(z) < EPSILON) { - out.z = 0; - } else { - out.z = 1.0 / z; - } - - if (Math.abs(w) < EPSILON) { - out.w = 0; - } else { - out.w = 1.0 / w; - } - - return out; -}; - -/** - * Normalize a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to normalize - * @returns {vec4} out - */ -vec4.normalize = function (out, a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - var len = x * x + y * y + z * z + w * w; - if (len > 0) { - len = 1 / Math.sqrt(len); - out.x = x * len; - out.y = y * len; - out.z = z * len; - out.w = w * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} dot product of a and b - */ -vec4.dot = function (a, b) { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -}; - -/** - * Performs a linear interpolation between two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec4} out - */ -vec4.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y, - az = a.z, - aw = a.w; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - out.z = az + t * (b.z - az); - out.w = aw + t * (b.w - aw); - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec4} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec4} out - */ -vec4.random = function (out, scale) { - scale = scale || 1.0; - - //TODO: This is a pretty awful way of doing this. Find something better. - out.x = random(); - out.y = random(); - out.z = random(); - out.w = random(); - vec4.normalize(out, out); - vec4.scale(out, out, scale); - return out; -}; - -/** - * Transforms the vec4 with a mat4. - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec4} out - */ -vec4.transformMat4 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z, w = a.w; - out.x = m.m00 * x + m.m04 * y + m.m08 * z + m.m12 * w; - out.y = m.m01 * x + m.m05 * y + m.m09 * z + m.m13 * w; - out.z = m.m02 * x + m.m06 * y + m.m10 * z + m.m14 * w; - out.w = m.m03 * x + m.m07 * y + m.m11 * z + m.m15 * w; - return out; -}; - -/** - * Transforms the vec4 with a quat - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec4} out - */ -vec4.transformQuat = function (out, a, q) { - var x = a.x, y = a.y, z = a.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vec - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - - // calculate result * inverse quat - out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - out.w = a.w; - return out; -}; - -/** - * Perform some operation over an array of vec4s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec4.forEach = (function () { - var vec = vec4.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 4; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; vec.z = a[i + 2]; vec.w = a[i + 3]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; a[i + 2] = vec.z; a[i + 3] = vec.w; - } - - return a; - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec4} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec4.str = function (a) { - return ("vec4(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ", " + (a.w) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec4} v - * @returns {array} - */ -vec4.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - out[2] = v.z; - out[3] = v.w; - - return out; -}; - -/** - * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) - * - * @param {vec4} a The first vector. - * @param {vec4} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec4.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y && a.z === b.z && a.w === b.w; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec4} a The first vector. - * @param {vec4} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec4.equals = function (a, b) { - var a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; - var b0 = b.x, b1 = b.y, b2 = b.z, b3 = b.w; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); -}; - -var _tmp$3 = new Array(9); - -var _mat3 = function _mat3(m00, m01, m02, m03, m04, m05, m06, m07, m08) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; - this.m06 = m06; - this.m07 = m07; - this.m08 = m08; -}; - -_mat3.prototype.toJSON = function toJSON () { - _tmp$3[0] = this.m00; - _tmp$3[1] = this.m01; - _tmp$3[2] = this.m02; - _tmp$3[3] = this.m03; - _tmp$3[4] = this.m04; - _tmp$3[5] = this.m05; - _tmp$3[6] = this.m06; - _tmp$3[7] = this.m07; - _tmp$3[8] = this.m08; - - return _tmp$3; -}; - -/** - * @class 3x3 Matrix - * @name mat3 - * - * NOTE: we use column-major matrix for all matrix calculation. - * - * This may lead to some confusion when referencing OpenGL documentation, - * however, which represents out all matricies in column-major format. - * This means that while in code a matrix may be typed out as: - * - * [1, 0, 0, 0, - * 0, 1, 0, 0, - * 0, 0, 1, 0, - * x, y, z, 0] - * - * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) - * is written as: - * - * 1 0 0 x - * 0 1 0 y - * 0 0 1 z - * 0 0 0 0 - * - * Please rest assured, however, that they are the same thing! - * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the - * apparent lack of consistency between the memory layout and the documentation. - */ -var mat3 = {}; - -/** - * Creates a new identity mat3 - * - * @returns {mat3} a new 3x3 matrix - */ -mat3.create = function () { - return new _mat3( - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - ); -}; - -/** - * Create a new mat3 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m10 Component in column 1, row 0 position (index 3) - * @param {Number} m11 Component in column 1, row 1 position (index 4) - * @param {Number} m12 Component in column 1, row 2 position (index 5) - * @param {Number} m20 Component in column 2, row 0 position (index 6) - * @param {Number} m21 Component in column 2, row 1 position (index 7) - * @param {Number} m22 Component in column 2, row 2 position (index 8) - * @returns {mat3} A new mat3 - */ -mat3.new = function (m00, m01, m02, m10, m11, m12, m20, m21, m22) { - return new _mat3( - m00, m01, m02, - m10, m11, m12, - m20, m21, m22 - ); -}; - -/** - * Creates a new mat3 initialized with values from an existing matrix - * - * @param {mat3} a matrix to clone - * @returns {mat3} a new 3x3 matrix - */ -mat3.clone = function (a) { - return new _mat3( - a.m00, a.m01, a.m02, - a.m03, a.m04, a.m05, - a.m06, a.m07, a.m08 - ); -}; - -/** - * Copy the values from one mat3 to another - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - return out; -}; - -/** - * Set the components of a mat3 to the given values - * - * @param {mat3} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m10 Component in column 1, row 0 position (index 3) - * @param {Number} m11 Component in column 1, row 1 position (index 4) - * @param {Number} m12 Component in column 1, row 2 position (index 5) - * @param {Number} m20 Component in column 2, row 0 position (index 6) - * @param {Number} m21 Component in column 2, row 1 position (index 7) - * @param {Number} m22 Component in column 2, row 2 position (index 8) - * @returns {mat3} out - */ -mat3.set = function (out, m00, m01, m02, m10, m11, m12, m20, m21, m22) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m02; - out.m03 = m10; - out.m04 = m11; - out.m05 = m12; - out.m06 = m20; - out.m07 = m21; - out.m08 = m22; - return out; -}; - -/** - * Set a mat3 to the identity matrix - * - * @param {mat3} out the receiving matrix - * @returns {mat3} out - */ -mat3.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 1; - out.m05 = 0; - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Transpose the values of a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a01 = a.m01, a02 = a.m02, a12 = a.m05; - out.m01 = a.m03; - out.m02 = a.m06; - out.m03 = a01; - out.m05 = a.m07; - out.m06 = a02; - out.m07 = a12; - } else { - out.m00 = a.m00; - out.m01 = a.m03; - out.m02 = a.m06; - out.m03 = a.m01; - out.m04 = a.m04; - out.m05 = a.m07; - out.m06 = a.m02; - out.m07 = a.m05; - out.m08 = a.m08; - } - - return out; -}; - -/** - * Inverts a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.invert = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var b01 = a22 * a11 - a12 * a21; - var b11 = -a22 * a10 + a12 * a20; - var b21 = a21 * a10 - a11 * a20; - - // Calculate the determinant - var det = a00 * b01 + a01 * b11 + a02 * b21; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = b01 * det; - out.m01 = (-a22 * a01 + a02 * a21) * det; - out.m02 = (a12 * a01 - a02 * a11) * det; - out.m03 = b11 * det; - out.m04 = (a22 * a00 - a02 * a20) * det; - out.m05 = (-a12 * a00 + a02 * a10) * det; - out.m06 = b21 * det; - out.m07 = (-a21 * a00 + a01 * a20) * det; - out.m08 = (a11 * a00 - a01 * a10) * det; - return out; -}; - -/** - * Calculates the adjugate of a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.adjoint = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - out.m00 = (a11 * a22 - a12 * a21); - out.m01 = (a02 * a21 - a01 * a22); - out.m02 = (a01 * a12 - a02 * a11); - out.m03 = (a12 * a20 - a10 * a22); - out.m04 = (a00 * a22 - a02 * a20); - out.m05 = (a02 * a10 - a00 * a12); - out.m06 = (a10 * a21 - a11 * a20); - out.m07 = (a01 * a20 - a00 * a21); - out.m08 = (a00 * a11 - a01 * a10); - return out; -}; - -/** - * Calculates the determinant of a mat3 - * - * @param {mat3} a the source matrix - * @returns {Number} determinant of a - */ -mat3.determinant = function (a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); -}; - -/** - * Multiplies two mat3's - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.multiply = function (out, a, b) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var b00 = b.m00, b01 = b.m01, b02 = b.m02; - var b10 = b.m03, b11 = b.m04, b12 = b.m05; - var b20 = b.m06, b21 = b.m07, b22 = b.m08; - - out.m00 = b00 * a00 + b01 * a10 + b02 * a20; - out.m01 = b00 * a01 + b01 * a11 + b02 * a21; - out.m02 = b00 * a02 + b01 * a12 + b02 * a22; - - out.m03 = b10 * a00 + b11 * a10 + b12 * a20; - out.m04 = b10 * a01 + b11 * a11 + b12 * a21; - out.m05 = b10 * a02 + b11 * a12 + b12 * a22; - - out.m06 = b20 * a00 + b21 * a10 + b22 * a20; - out.m07 = b20 * a01 + b21 * a11 + b22 * a21; - out.m08 = b20 * a02 + b21 * a12 + b22 * a22; - return out; -}; - -/** - * Alias for {@link mat3.multiply} - * @function - */ -mat3.mul = mat3.multiply; - -/** - * Translate a mat3 by the given vector - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to translate - * @param {vec2} v vector to translate by - * @returns {mat3} out - */ -mat3.translate = function (out, a, v) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - var x = v.x, y = v.y; - - out.m00 = a00; - out.m01 = a01; - out.m02 = a02; - - out.m03 = a10; - out.m04 = a11; - out.m05 = a12; - - out.m06 = x * a00 + y * a10 + a20; - out.m07 = x * a01 + y * a11 + a21; - out.m08 = x * a02 + y * a12 + a22; - return out; -}; - -/** - * Rotates a mat3 by the given angle - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat3} out - */ -mat3.rotate = function (out, a, rad) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var s = Math.sin(rad); - var c = Math.cos(rad); - - out.m00 = c * a00 + s * a10; - out.m01 = c * a01 + s * a11; - out.m02 = c * a02 + s * a12; - - out.m03 = c * a10 - s * a00; - out.m04 = c * a11 - s * a01; - out.m05 = c * a12 - s * a02; - - out.m06 = a20; - out.m07 = a21; - out.m08 = a22; - return out; -}; - -/** - * Scales the mat3 by the dimensions in the given vec2 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to rotate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat3} out - **/ -mat3.scale = function (out, a, v) { - var x = v.x, y = v.y; - - out.m00 = x * a.m00; - out.m01 = x * a.m01; - out.m02 = x * a.m02; - - out.m03 = y * a.m03; - out.m04 = y * a.m04; - out.m05 = y * a.m05; - - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - return out; -}; - -/** - * Copies the upper-left 3x3 values into the given mat3. - * - * @param {mat3} out the receiving 3x3 matrix - * @param {mat4} a the source 4x4 matrix - * @returns {mat3} out - */ -mat3.fromMat4 = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m04; - out.m04 = a.m05; - out.m05 = a.m06; - out.m06 = a.m08; - out.m07 = a.m09; - out.m08 = a.m10; - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.translate(dest, dest, vec); - * - * @param {mat3} out mat3 receiving operation result - * @param {vec2} v Translation vector - * @returns {mat3} out - */ -mat3.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 1; - out.m05 = 0; - out.m06 = v.x; - out.m07 = v.y; - out.m08 = 1; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.rotate(dest, dest, rad); - * - * @param {mat3} out mat3 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat3} out - */ -mat3.fromRotation = function (out, rad) { - var s = Math.sin(rad), c = Math.cos(rad); - - out.m00 = c; - out.m01 = s; - out.m02 = 0; - - out.m03 = -s; - out.m04 = c; - out.m05 = 0; - - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.scale(dest, dest, vec); - * - * @param {mat3} out mat3 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat3} out - */ -mat3.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - - out.m03 = 0; - out.m04 = v.y; - out.m05 = 0; - - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Copies the values from a mat2d into a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat2d} a the matrix to copy - * @returns {mat3} out - **/ -mat3.fromMat2d = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = 0; - - out.m03 = a.m02; - out.m04 = a.m03; - out.m05 = 0; - - out.m06 = a.m04; - out.m07 = a.m05; - out.m08 = 1; - return out; -}; - -/** -* Calculates a 3x3 matrix from the given quaternion -* -* @param {mat3} out mat3 receiving operation result -* @param {quat} q Quaternion to create matrix from -* -* @returns {mat3} out -*/ -mat3.fromQuat = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var yx = y * x2; - var yy = y * y2; - var zx = z * x2; - var zy = z * y2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - yy - zz; - out.m03 = yx - wz; - out.m06 = zx + wy; - - out.m01 = yx + wz; - out.m04 = 1 - xx - zz; - out.m07 = zy - wx; - - out.m02 = zx - wy; - out.m05 = zy + wx; - out.m08 = 1 - xx - yy; - - return out; -}; - -/** -* Calculates a 3x3 matrix from view direction and up direction -* -* @param {mat3} out mat3 receiving operation result -* @param {vec3} view view direction (must be normalized) -* @param {vec3} [up] up direction, default is (0,1,0) (must be normalized) -* -* @returns {mat3} out -*/ -mat3.fromViewUp = (function () { - var default_up = vec3.new(0, 1, 0); - var x = vec3.create(); - var y = vec3.create(); - - return function (out, view, up) { - if (vec3.sqrLen(view) < EPSILON * EPSILON) { - mat3.identity(out); - return out; - } - - up = up || default_up; - vec3.cross(x, up, view); - - if (vec3.sqrLen(x) < EPSILON * EPSILON) { - mat3.identity(out); - return out; - } - - vec3.cross(y, view, x); - mat3.set(out, - x.x, x.y, x.z, - y.x, y.y, y.z, - view.x, view.y, view.z - ); - - return out; - }; -})(); - -/** -* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix -* -* @param {mat3} out mat3 receiving operation result -* @param {mat4} a Mat4 to derive the normal matrix from -* -* @returns {mat3} out -*/ -mat3.normalFromMat4 = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out.m01 = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out.m02 = (a10 * b10 - a11 * b08 + a13 * b06) * det; - - out.m03 = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out.m04 = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out.m05 = (a01 * b08 - a00 * b10 - a03 * b06) * det; - - out.m06 = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out.m07 = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out.m08 = (a30 * b04 - a31 * b02 + a33 * b00) * det; - - return out; -}; - -/** - * Returns a string representation of a mat3 - * - * @param {mat3} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat3.str = function (a) { - return ("mat3(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ", " + (a.m06) + ", " + (a.m07) + ", " + (a.m08) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat3} m - * @returns {array} - */ -mat3.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - out[6] = m.m06; - out[7] = m.m07; - out[8] = m.m08; - - return out; -}; - -/** - * Returns Frobenius norm of a mat3 - * - * @param {mat3} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat3.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2))); -}; - -/** - * Adds two mat3's - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - out.m06 = a.m06 + b.m06; - out.m07 = a.m07 + b.m07; - out.m08 = a.m08 + b.m08; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - out.m06 = a.m06 - b.m06; - out.m07 = a.m07 - b.m07; - out.m08 = a.m08 - b.m08; - return out; -}; - -/** - * Alias for {@link mat3.subtract} - * @function - */ -mat3.sub = mat3.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat3} out - */ -mat3.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - out.m06 = a.m06 * b; - out.m07 = a.m07 * b; - out.m08 = a.m08 * b; - return out; -}; - -/** - * Adds two mat3's after multiplying each element of the second operand by a scalar value. - * - * @param {mat3} out the receiving vector - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat3} out - */ -mat3.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - out.m06 = a.m06 + (b.m06 * scale); - out.m07 = a.m07 + (b.m07 * scale); - out.m08 = a.m08 + (b.m08 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat3} a The first matrix. - * @param {mat3} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat3.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && - a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05 && - a.m06 === b.m06 && a.m07 === b.m07 && a.m08 === b.m08; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat3} a The first matrix. - * @param {mat3} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat3.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, a8 = a.m08; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, b8 = b.m08; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && - Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && - Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && - Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) - ); -}; - -var _tmp$4 = new Array(4); - -var _quat = function _quat(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; -}; - -_quat.prototype.toJSON = function toJSON () { - _tmp$4[0] = this.x; - _tmp$4[1] = this.y; - _tmp$4[2] = this.z; - _tmp$4[3] = this.w; - - return _tmp$4; -}; - -/** - * @class Quaternion - * @name quat - */ -var quat = {}; - -/** - * Creates a new identity quat - * - * @returns {quat} a new quaternion - */ -quat.create = function () { - return new _quat(0, 0, 0, 1); -}; - -/** - * Creates a new quat initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {quat} a new quaternion - * @function - */ -quat.new = function (x, y, z, w) { - return new _quat(x, y, z, w); -}; - -/** - * Creates a new quat initialized with values from an existing quaternion - * - * @param {quat} a quaternion to clone - * @returns {quat} a new quaternion - * @function - */ -quat.clone = function (a) { - return new _quat(a.x, a.y, a.z, a.w); -}; - -/** - * Copy the values from one quat to another - * - * @param {quat} out the receiving quaternion - * @param {quat} a the source quaternion - * @returns {quat} out - * @function - */ -quat.copy = vec4.copy; - -/** - * Set the components of a quat to the given values - * - * @param {quat} out the receiving quaternion - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {quat} out - * @function - */ -quat.set = vec4.set; - -/** - * Set a quat to the identity quaternion - * - * @param {quat} out the receiving quaternion - * @returns {quat} out - */ -quat.identity = function (out) { - out.x = 0; - out.y = 0; - out.z = 0; - out.w = 1; - return out; -}; - -/** - * Sets a quaternion to represent the shortest rotation from one - * vector to another. - * - * Both vectors are assumed to be unit length. - * - * @param {quat} out the receiving quaternion. - * @param {vec3} a the initial vector - * @param {vec3} b the destination vector - * @returns {quat} out - */ -quat.rotationTo = (function () { - var tmpvec3 = vec3.create(); - var xUnitVec3 = vec3.new(1, 0, 0); - var yUnitVec3 = vec3.new(0, 1, 0); - - return function (out, a, b) { - var dot = vec3.dot(a, b); - if (dot < -0.999999) { - vec3.cross(tmpvec3, xUnitVec3, a); - if (vec3.length(tmpvec3) < 0.000001) { - vec3.cross(tmpvec3, yUnitVec3, a); - } - vec3.normalize(tmpvec3, tmpvec3); - quat.fromAxisAngle(out, tmpvec3, Math.PI); - return out; - } else if (dot > 0.999999) { - out.x = 0; - out.y = 0; - out.z = 0; - out.w = 1; - return out; - } else { - vec3.cross(tmpvec3, a, b); - out.x = tmpvec3.x; - out.y = tmpvec3.y; - out.z = tmpvec3.z; - out.w = 1 + dot; - return quat.normalize(out, out); - } - }; -})(); - -/** - * Gets the rotation axis and angle for a given - * quaternion. If a quaternion is created with - * fromAxisAngle, this method will return the same - * values as providied in the original parameter list - * OR functionally equivalent values. - * Example: The quaternion formed by axis [0, 0, 1] and - * angle -90 is the same as the quaternion formed by - * [0, 0, 1] and 270. This method favors the latter. - * @param {vec3} out_axis Vector receiving the axis of rotation - * @param {quat} q Quaternion to be decomposed - * @return {Number} Angle, in radians, of the rotation - */ -quat.getAxisAngle = function (out_axis, q) { - var rad = Math.acos(q.w) * 2.0; - var s = Math.sin(rad / 2.0); - if (s != 0.0) { - out_axis.x = q.x / s; - out_axis.y = q.y / s; - out_axis.z = q.z / s; - } else { - // If s is zero, return any axis (no rotation - axis does not matter) - out_axis.x = 1; - out_axis.y = 0; - out_axis.z = 0; - } - return rad; -}; - -/** - * Multiplies two quat's - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @returns {quat} out - */ -quat.multiply = function (out, a, b) { - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = b.x, by = b.y, bz = b.z, bw = b.w; - - out.x = ax * bw + aw * bx + ay * bz - az * by; - out.y = ay * bw + aw * by + az * bx - ax * bz; - out.z = az * bw + aw * bz + ax * by - ay * bx; - out.w = aw * bw - ax * bx - ay * by - az * bz; - return out; -}; - -/** - * Alias for {@link quat.multiply} - * @function - */ -quat.mul = quat.multiply; - -/** - * Scales a quat by a scalar number - * - * @param {quat} out the receiving vector - * @param {quat} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {quat} out - * @function - */ -quat.scale = vec4.scale; - -/** - * Rotates a quaternion by the given angle about the X axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateX = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw + aw * bx; - out.y = ay * bw + az * bx; - out.z = az * bw - ay * bx; - out.w = aw * bw - ax * bx; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the Y axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateY = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - by = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw - az * by; - out.y = ay * bw + aw * by; - out.z = az * bw + ax * by; - out.w = aw * bw - ay * by; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the Z axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateZ = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bz = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw + ay * bz; - out.y = ay * bw - ax * bz; - out.z = az * bw + aw * bz; - out.w = aw * bw - az * bz; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the axis in world space - * - * @param {quat} out quat receiving operation result - * @param {quat} rot quat to rotate - * @param {vec3} axis the axis around which to rotate in world space - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateAround = (function () { - var v3_tmp = vec3.create(); - var q_tmp = quat.create(); - - return function (out, rot, axis, rad) { - // get inv-axis (local to rot) - quat.invert(q_tmp, rot); - vec3.transformQuat(v3_tmp, axis, q_tmp); - // rotate by inv-axis - quat.fromAxisAngle(q_tmp, v3_tmp, rad); - quat.mul(out, rot, q_tmp); - - return out; - }; -})(); - -/** - * Rotates a quaternion by the given angle about the axis in local space - * - * @param {quat} out quat receiving operation result - * @param {quat} rot quat to rotate - * @param {vec3} axis the axis around which to rotate in local space - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateAroundLocal = (function () { - var q_tmp = quat.create(); - - return function (out, rot, axis, rad) { - quat.fromAxisAngle(q_tmp, axis, rad); - quat.mul(out, rot, q_tmp); - - return out; - }; -})(); - -/** - * Calculates the W component of a quat from the X, Y, and Z components. - * Assumes that quaternion is 1 unit in length. - * Any existing W component will be ignored. - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate W component of - * @returns {quat} out - */ -quat.calculateW = function (out, a) { - var x = a.x, y = a.y, z = a.z; - - out.x = x; - out.y = y; - out.z = z; - out.w = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); - return out; -}; - -/** - * Calculates the dot product of two quat's - * - * @param {quat} a the first operand - * @param {quat} b the second operand - * @returns {Number} dot product of a and b - * @function - */ -quat.dot = vec4.dot; - -/** - * Performs a linear interpolation between two quat's - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {quat} out - * @function - */ -quat.lerp = vec4.lerp; - -/** - * Performs a spherical linear interpolation between two quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {quat} out - */ -quat.slerp = function (out, a, b, t) { - // benchmarks: - // http://jsperf.com/quaternion-slerp-implementations - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = b.x, by = b.y, bz = b.z, bw = b.w; - - var omega, cosom, sinom, scale0, scale1; - - // calc cosine - cosom = ax * bx + ay * by + az * bz + aw * bw; - // adjust signs (if necessary) - if (cosom < 0.0) { - cosom = -cosom; - bx = - bx; - by = - by; - bz = - bz; - bw = - bw; - } - // calculate coefficients - if ((1.0 - cosom) > 0.000001) { - // standard case (slerp) - omega = Math.acos(cosom); - sinom = Math.sin(omega); - scale0 = Math.sin((1.0 - t) * omega) / sinom; - scale1 = Math.sin(t * omega) / sinom; - } else { - // "from" and "to" quaternions are very close - // ... so we can do a linear interpolation - scale0 = 1.0 - t; - scale1 = t; - } - // calculate final values - out.x = scale0 * ax + scale1 * bx; - out.y = scale0 * ay + scale1 * by; - out.z = scale0 * az + scale1 * bz; - out.w = scale0 * aw + scale1 * bw; - - return out; -}; - -/** - * Performs a spherical linear interpolation with two control points - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {quat} c the third operand - * @param {quat} d the fourth operand - * @param {Number} t interpolation amount - * @returns {quat} out - */ -quat.sqlerp = (function () { - var temp1 = quat.create(); - var temp2 = quat.create(); - - return function (out, a, b, c, d, t) { - quat.slerp(temp1, a, d, t); - quat.slerp(temp2, b, c, t); - quat.slerp(out, temp1, temp2, 2 * t * (1 - t)); - - return out; - }; -}()); - -/** - * Calculates the inverse of a quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate inverse of - * @returns {quat} out - */ -quat.invert = function (out, a) { - var a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; - var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3; - var invDot = dot ? 1.0 / dot : 0; - - // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 - - out.x = -a0 * invDot; - out.y = -a1 * invDot; - out.z = -a2 * invDot; - out.w = a3 * invDot; - return out; -}; - -/** - * Calculates the conjugate of a quat - * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate conjugate of - * @returns {quat} out - */ -quat.conjugate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - out.w = a.w; - return out; -}; - -/** - * Calculates the length of a quat - * - * @param {quat} a vector to calculate length of - * @returns {Number} length of a - * @function - */ -quat.length = vec4.length; - -/** - * Alias for {@link quat.length} - * @function - */ -quat.len = quat.length; - -/** - * Calculates the squared length of a quat - * - * @param {quat} a vector to calculate squared length of - * @returns {Number} squared length of a - * @function - */ -quat.squaredLength = vec4.squaredLength; - -/** - * Alias for {@link quat.squaredLength} - * @function - */ -quat.sqrLen = quat.squaredLength; - -/** - * Normalize a quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a quaternion to normalize - * @returns {quat} out - * @function - */ -quat.normalize = vec4.normalize; - -/** - * Sets the specified quaternion with values corresponding to the given - * axes. Each axis is a vec3 and is expected to be unit length and - * perpendicular to all other specified axes. - * - * @param {vec3} xAxis the vector representing the local "right" direction - * @param {vec3} yAxis the vector representing the local "up" direction - * @param {vec3} zAxis the vector representing the viewing direction - * @returns {quat} out - */ -quat.fromAxes = (function () { - var matr = mat3.create(); - - return function (out, xAxis, yAxis, zAxis) { - mat3.set( - matr, - xAxis.x, xAxis.y, xAxis.z, - yAxis.x, yAxis.y, yAxis.z, - zAxis.x, zAxis.y, zAxis.z - ); - return quat.normalize(out, quat.fromMat3(out, matr)); - }; -})(); - -/** -* Calculates a quaternion from view direction and up direction -* -* @param {quat} out mat3 receiving operation result -* @param {vec3} view view direction (must be normalized) -* @param {vec3} [up] up direction, default is (0,1,0) (must be normalized) -* -* @returns {quat} out -*/ -quat.fromViewUp = (function () { - var matr = mat3.create(); - - return function (out, view, up) { - mat3.fromViewUp(matr, view, up); - if (!matr) { - return null; - } - - return quat.normalize(out, quat.fromMat3(out, matr)); - }; -})(); - -/** - * Sets a quat from the given angle and rotation axis, - * then returns it. - * - * @param {quat} out the receiving quaternion - * @param {vec3} axis the axis around which to rotate - * @param {Number} rad the angle in radians - * @returns {quat} out - **/ -quat.fromAxisAngle = function (out, axis, rad) { - rad = rad * 0.5; - var s = Math.sin(rad); - out.x = s * axis.x; - out.y = s * axis.y; - out.z = s * axis.z; - out.w = Math.cos(rad); - return out; -}; - -/** - * Creates a quaternion from the given 3x3 rotation matrix. - * - * NOTE: The resultant quaternion is not normalized, so you should be sure - * to renormalize the quaternion yourself where necessary. - * - * @param {quat} out the receiving quaternion - * @param {mat3} m rotation matrix - * @returns {quat} out - * @function - */ -quat.fromMat3 = function (out, m) { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - - var m00 = m.m00, m01 = m.m03, m02 = m.m06, - m10 = m.m01, m11 = m.m04, m12 = m.m07, - m20 = m.m02, m21 = m.m05, m22 = m.m08; - - var trace = m00 + m11 + m22; - - if (trace > 0) { - var s = 0.5 / Math.sqrt(trace + 1.0); - - out.w = 0.25 / s; - out.x = (m21 - m12) * s; - out.y = (m02 - m20) * s; - out.z = (m10 - m01) * s; - - } else if ((m00 > m11) && (m00 > m22)) { - var s$1 = 2.0 * Math.sqrt(1.0 + m00 - m11 - m22); - - out.w = (m21 - m12) / s$1; - out.x = 0.25 * s$1; - out.y = (m01 + m10) / s$1; - out.z = (m02 + m20) / s$1; - - } else if (m11 > m22) { - var s$2 = 2.0 * Math.sqrt(1.0 + m11 - m00 - m22); - - out.w = (m02 - m20) / s$2; - out.x = (m01 + m10) / s$2; - out.y = 0.25 * s$2; - out.z = (m12 + m21) / s$2; - - } else { - var s$3 = 2.0 * Math.sqrt(1.0 + m22 - m00 - m11); - - out.w = (m10 - m01) / s$3; - out.x = (m02 + m20) / s$3; - out.y = (m12 + m21) / s$3; - out.z = 0.25 * s$3; - } - - return out; -}; - -/** - * Creates a quaternion from the given euler angle x, y, z. - * - * @param {quat} out the receiving quaternion - * @param {x} Angle to rotate around X axis in degrees. - * @param {y} Angle to rotate around Y axis in degrees. - * @param {z} Angle to rotate around Z axis in degrees. - * @returns {quat} out - * @function - */ -quat.fromEuler = function (out, x, y, z) { - var halfToRad = 0.5 * Math.PI / 180.0; - x *= halfToRad; - y *= halfToRad; - z *= halfToRad; - - var sx = Math.sin(x); - var cx = Math.cos(x); - var sy = Math.sin(y); - var cy = Math.cos(y); - var sz = Math.sin(z); - var cz = Math.cos(z); - - out.x = sx * cy * cz + cx * sy * sz; - out.y = cx * sy * cz + sx * cy * sz; - out.z = cx * cy * sz - sx * sy * cz; - out.w = cx * cy * cz - sx * sy * sz; - - return out; -}; - -/** - * Convert a quaternion back to euler angle (in degrees). - * - * @param {vec3} out - Euler angle stored as a vec3 - * @param {number} q - the quaternion to be converted - * @returns {vec3} out. - */ -quat.toEuler = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var heading, attitude, bank; - var test = x * y + z * w; - if (test > 0.499) { // singularity at north pole - heading = 2 * Math.atan2(x,w); - attitude = Math.PI/2; - bank = 0; - } - if (test < -0.499) { // singularity at south pole - heading = -2 * Math.atan2(x,w); - attitude = - Math.PI/2; - bank = 0; - } - if(isNaN(heading)){ - var sqx = x*x; - var sqy = y*y; - var sqz = z*z; - heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // heading - attitude = Math.asin(2*test); // attitude - bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank - } - - out.y = toDegree(heading); - out.z = toDegree(attitude); - out.x = toDegree(bank); - - return out; -} - -/** - * Returns a string representation of a quatenion - * - * @param {quat} a vector to represent as a string - * @returns {String} string representation of the vector - */ -quat.str = function (a) { - return ("quat(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ", " + (a.w) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {quat} q - * @returns {array} - */ -quat.array = function (out, q) { - out[0] = q.x; - out[1] = q.y; - out[2] = q.z; - out[3] = q.w; - - return out; -}; - -/** - * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===) - * - * @param {quat} a The first quaternion. - * @param {quat} b The second quaternion. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -quat.exactEquals = vec4.exactEquals; - -/** - * Returns whether or not the quaternions have approximately the same elements in the same position. - * - * @param {quat} a The first vector. - * @param {quat} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -quat.equals = vec4.equals; - -var _tmp$5 = new Array(4); - -var _mat2 = function _mat2(m00, m01, m02, m03) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; -}; - -_mat2.prototype.toJSON = function toJSON () { - _tmp$5[0] = this.m00; - _tmp$5[1] = this.m01; - _tmp$5[2] = this.m02; - _tmp$5[3] = this.m03; - - return _tmp$5; -}; - -/** - * @class 2x2 Matrix - * @name mat2 - */ -var mat2 = {}; - -/** - * Creates a new identity mat2 - * - * @returns {mat2} a new 2x2 matrix - */ -mat2.create = function() { - return new _mat2(1, 0, 0, 1); -}; - -/** - * Create a new mat2 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m10 Component in column 1, row 0 position (index 2) - * @param {Number} m11 Component in column 1, row 1 position (index 3) - * @returns {mat2} out A new 2x2 matrix - */ -mat2.new = function (m00, m01, m10, m11) { - return new _mat2(m00, m01, m10, m11); -}; - -/** - * Creates a new mat2 initialized with values from an existing matrix - * - * @param {mat2} a matrix to clone - * @returns {mat2} a new 2x2 matrix - */ -mat2.clone = function (a) { - return new _mat2(a.m00, a.m01, a.m02, a.m03); -}; - -/** - * Copy the values from one mat2 to another - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - return out; -}; - -/** - * Set a mat2 to the identity matrix - * - * @param {mat2} out the receiving matrix - * @returns {mat2} out - */ -mat2.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - return out; -}; - -/** - * Set the components of a mat2 to the given values - * - * @param {mat2} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m10 Component in column 1, row 0 position (index 2) - * @param {Number} m11 Component in column 1, row 1 position (index 3) - * @returns {mat2} out - */ -mat2.set = function (out, m00, m01, m10, m11) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m10; - out.m03 = m11; - return out; -}; - - -/** - * Transpose the values of a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a1 = a.m01; - out.m01 = a.m02; - out.m02 = a1; - } else { - out.m00 = a.m00; - out.m01 = a.m02; - out.m02 = a.m01; - out.m03 = a.m03; - } - - return out; -}; - -/** - * Inverts a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.invert = function (out, a) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - - // Calculate the determinant - var det = a0 * a3 - a2 * a1; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = a3 * det; - out.m01 = -a1 * det; - out.m02 = -a2 * det; - out.m03 = a0 * det; - - return out; -}; - -/** - * Calculates the adjugate of a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.adjoint = function (out, a) { - // Caching this value is nessecary if out == a - var a0 = a.m00; - out.m00 = a.m03; - out.m01 = -a.m01; - out.m02 = -a.m02; - out.m03 = a0; - - return out; -}; - -/** - * Calculates the determinant of a mat2 - * - * @param {mat2} a the source matrix - * @returns {Number} determinant of a - */ -mat2.determinant = function (a) { - return a.m00 * a.m03 - a.m02 * a.m01; -}; - -/** - * Multiplies two mat2's - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.multiply = function (out, a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - out.m00 = a0 * b0 + a2 * b1; - out.m01 = a1 * b0 + a3 * b1; - out.m02 = a0 * b2 + a2 * b3; - out.m03 = a1 * b2 + a3 * b3; - return out; -}; - -/** - * Alias for {@link mat2.multiply} - * @function - */ -mat2.mul = mat2.multiply; - -/** - * Rotates a mat2 by the given angle - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat2} out - */ -mat2.rotate = function (out, a, rad) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = a0 * c + a2 * s; - out.m01 = a1 * c + a3 * s; - out.m02 = a0 * -s + a2 * c; - out.m03 = a1 * -s + a3 * c; - return out; -}; - -/** - * Scales the mat2 by the dimensions in the given vec2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to rotate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat2} out - **/ -mat2.scale = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - v0 = v.x, v1 = v.y; - out.m00 = a0 * v0; - out.m01 = a1 * v0; - out.m02 = a2 * v1; - out.m03 = a3 * v1; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat2.identity(dest); - * mat2.rotate(dest, dest, rad); - * - * @param {mat2} out mat2 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat2} out - */ -mat2.fromRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = c; - out.m01 = s; - out.m02 = -s; - out.m03 = c; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat2.identity(dest); - * mat2.scale(dest, dest, vec); - * - * @param {mat2} out mat2 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat2} out - */ -mat2.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - out.m03 = v.y; - return out; -}; - -/** - * Returns a string representation of a mat2 - * - * @param {mat2} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat2.str = function (a) { - return ("mat2(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat2} m - * @returns {array} - */ -mat2.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - - return out; -}; - -/** - * Returns Frobenius norm of a mat2 - * - * @param {mat2} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat2.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2))); -}; - -/** - * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix - * @param {mat2} L the lower triangular matrix - * @param {mat2} D the diagonal matrix - * @param {mat2} U the upper triangular matrix - * @param {mat2} a the input matrix to factorize - */ - -mat2.LDU = function (L, D, U, a) { - L.m02 = a.m02 / a.m00; - U.m00 = a.m00; - U.m01 = a.m01; - U.m03 = a.m03 - L.m02 * U.m01; -}; - -/** - * Adds two mat2's - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - return out; -}; - -/** - * Alias for {@link mat2.subtract} - * @function - */ -mat2.sub = mat2.subtract; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat2} a The first matrix. - * @param {mat2} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat2.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat2} a The first matrix. - * @param {mat2} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat2.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) - ); -}; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat2} out - */ -mat2.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - return out; -}; - -/** - * Adds two mat2's after multiplying each element of the second operand by a scalar value. - * - * @param {mat2} out the receiving vector - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat2} out - */ -mat2.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - return out; -}; - -var _tmp$6 = new Array(6); - -var _mat23 = function _mat23(m00, m01, m02, m03, m04, m05) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; -}; - -_mat23.prototype.toJSON = function toJSON () { - _tmp$6[0] = this.m00; - _tmp$6[1] = this.m01; - _tmp$6[2] = this.m02; - _tmp$6[3] = this.m03; - _tmp$6[4] = this.m04; - _tmp$6[5] = this.m05; - - return _tmp$6; -}; - -/** - * @class 2x3 Matrix - * @name mat23 - * - * @description - * A mat23 contains six elements defined as: - *
- * [a, c, tx,
- *  b, d, ty]
- * 
- * This is a short form for the 3x3 matrix: - *
- * [a, c, tx,
- *  b, d, ty,
- *  0, 0, 1]
- * 
- * The last row is ignored so the array is shorter and operations are faster. - */ -var mat23 = {}; - -/** - * Creates a new identity mat23 - * - * @returns {mat23} a new 2x3 matrix - */ -mat23.create = function () { - return new _mat23( - 1, 0, - 0, 1, - 0, 0 - ); -}; - -/** - * Create a new mat23 with the given values - * - * @param {Number} a Component A (index 0) - * @param {Number} b Component B (index 1) - * @param {Number} c Component C (index 2) - * @param {Number} d Component D (index 3) - * @param {Number} tx Component TX (index 4) - * @param {Number} ty Component TY (index 5) - * @returns {mat23} A new mat23 - */ -mat23.new = function (a, b, c, d, tx, ty) { - return new _mat23( - a, b, - c, d, - tx, ty - ); -}; - -/** - * Creates a new mat23 initialized with values from an existing matrix - * - * @param {mat23} a matrix to clone - * @returns {mat23} a new 2x3 matrix - */ -mat23.clone = function (a) { - return new _mat23( - a.m00, a.m01, - a.m02, a.m03, - a.m04, a.m05 - ); -}; - -/** - * Copy the values from one mat23 to another - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the source matrix - * @returns {mat23} out - */ -mat23.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - return out; -}; - -/** - * Set a mat23 to the identity matrix - * - * @param {mat23} out the receiving matrix - * @returns {mat23} out - */ -mat23.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Set the components of a mat23 to the given values - * - * @param {mat23} out the receiving matrix - * @param {Number} a Component A (index 0) - * @param {Number} b Component B (index 1) - * @param {Number} c Component C (index 2) - * @param {Number} d Component D (index 3) - * @param {Number} tx Component TX (index 4) - * @param {Number} ty Component TY (index 5) - * @returns {mat23} out - */ -mat23.set = function (out, a, b, c, d, tx, ty) { - out.m00 = a; - out.m01 = b; - out.m02 = c; - out.m03 = d; - out.m04 = tx; - out.m05 = ty; - return out; -}; - -/** - * Inverts a mat23 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the source matrix - * @returns {mat23} out - */ -mat23.invert = function (out, a) { - var aa = a.m00, ab = a.m01, ac = a.m02, ad = a.m03, - atx = a.m04, aty = a.m05; - - var det = aa * ad - ab * ac; - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = ad * det; - out.m01 = -ab * det; - out.m02 = -ac * det; - out.m03 = aa * det; - out.m04 = (ac * aty - ad * atx) * det; - out.m05 = (ab * atx - aa * aty) * det; - return out; -}; - -/** - * Calculates the determinant of a mat23 - * - * @param {mat23} a the source matrix - * @returns {Number} determinant of a - */ -mat23.determinant = function (a) { - return a.m00 * a.m03 - a.m01 * a.m02; -}; - -/** - * Multiplies two mat23's - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.multiply = function (out, a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; - out.m00 = a0 * b0 + a2 * b1; - out.m01 = a1 * b0 + a3 * b1; - out.m02 = a0 * b2 + a2 * b3; - out.m03 = a1 * b2 + a3 * b3; - out.m04 = a0 * b4 + a2 * b5 + a4; - out.m05 = a1 * b4 + a3 * b5 + a5; - return out; -}; - -/** - * Alias for {@link mat23.multiply} - * @function - */ -mat23.mul = mat23.multiply; - -/** - * Rotates a mat23 by the given angle - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat23} out - */ -mat23.rotate = function (out, a, rad) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = a0 * c + a2 * s; - out.m01 = a1 * c + a3 * s; - out.m02 = a0 * -s + a2 * c; - out.m03 = a1 * -s + a3 * c; - out.m04 = a4; - out.m05 = a5; - return out; -}; - -/** - * Scales the mat23 by the dimensions in the given vec2 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to translate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat23} out - **/ -mat23.scale = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - v0 = v.x, v1 = v.y; - out.m00 = a0 * v0; - out.m01 = a1 * v0; - out.m02 = a2 * v1; - out.m03 = a3 * v1; - out.m04 = a4; - out.m05 = a5; - return out; -}; - -/** - * Translates the mat23 by the dimensions in the given vec2 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to translate - * @param {vec2} v the vec2 to translate the matrix by - * @returns {mat23} out - **/ -mat23.translate = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - v0 = v.x, v1 = v.y; - out.m00 = a0; - out.m01 = a1; - out.m02 = a2; - out.m03 = a3; - out.m04 = a0 * v0 + a2 * v1 + a4; - out.m05 = a1 * v0 + a3 * v1 + a5; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.rotate(dest, dest, rad); - * - * @param {mat23} out mat23 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat23} out - */ -mat23.fromRotation = function (out, rad) { - var s = Math.sin(rad), c = Math.cos(rad); - out.m00 = c; - out.m01 = s; - out.m02 = -s; - out.m03 = c; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.scale(dest, dest, vec); - * - * @param {mat23} out mat23 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat23} out - */ -mat23.fromScaling = function (out, v) { - out.m00 = v.m00; - out.m01 = 0; - out.m02 = 0; - out.m03 = v.m01; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.translate(dest, dest, vec); - * - * @param {mat23} out mat23 receiving operation result - * @param {vec2} v Translation vector - * @returns {mat23} out - */ -mat23.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - out.m04 = v.x; - out.m05 = v.y; - return out; -}; - -/** - * Returns a string representation of a mat23 - * - * @param {mat23} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat23.str = function (a) { - return ("mat23(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat23} m - * @returns {array} - */ -mat23.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - - return out; -}; - -/** - * Returns typed array to 16 float array - * - * @param {array} out - * @param {mat23} m - * @returns {array} - */ -mat23.array4x4 = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = 0; - out[3] = 0; - out[4] = m.m02; - out[5] = m.m03; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 1; - out[11] = 0; - out[12] = m.m04; - out[13] = m.m05; - out[14] = 0; - out[15] = 1; - - return out; -}; - -/** - * Returns Frobenius norm of a mat23 - * - * @param {mat23} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat23.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + 1)); -}; - -/** - * Adds two mat23's - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - return out; -}; - -/** - * Alias for {@link mat23.subtract} - * @function - */ -mat23.sub = mat23.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat23} out - */ -mat23.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - return out; -}; - -/** - * Adds two mat23's after multiplying each element of the second operand by a scalar value. - * - * @param {mat23} out the receiving vector - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat23} out - */ -mat23.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat23} a The first matrix. - * @param {mat23} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat23.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat23} a The first matrix. - * @param {mat23} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat23.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) - ); -}; - -var _tmp$7 = new Array(16); - -var _mat4 = function _mat4( - m00, m01, m02, m03, - m04, m05, m06, m07, - m08, m09, m10, m11, - m12, m13, m14, m15 -) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; - this.m06 = m06; - this.m07 = m07; - this.m08 = m08; - this.m09 = m09; - this.m10 = m10; - this.m11 = m11; - this.m12 = m12; - this.m13 = m13; - this.m14 = m14; - this.m15 = m15; -}; - -_mat4.prototype.toJSON = function toJSON () { - _tmp$7[0] = this.m00; - _tmp$7[1] = this.m01; - _tmp$7[2] = this.m02; - _tmp$7[3] = this.m03; - _tmp$7[4] = this.m04; - _tmp$7[5] = this.m05; - _tmp$7[6] = this.m06; - _tmp$7[7] = this.m07; - _tmp$7[8] = this.m08; - _tmp$7[9] = this.m09; - _tmp$7[10] = this.m10; - _tmp$7[11] = this.m11; - _tmp$7[12] = this.m12; - _tmp$7[13] = this.m13; - _tmp$7[14] = this.m14; - _tmp$7[15] = this.m15; - - return _tmp$7; -}; - -/** - * @class 4x4 Matrix - * @name mat4 - * - * NOTE: we use column-major matrix for all matrix calculation. - * - * This may lead to some confusion when referencing OpenGL documentation, - * however, which represents out all matricies in column-major format. - * This means that while in code a matrix may be typed out as: - * - * [1, 0, 0, 0, - * 0, 1, 0, 0, - * 0, 0, 1, 0, - * x, y, z, 0] - * - * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) - * is written as: - * - * 1 0 0 x - * 0 1 0 y - * 0 0 1 z - * 0 0 0 0 - * - * Please rest assured, however, that they are the same thing! - * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the - * apparent lack of consistency between the memory layout and the documentation. - */ -var mat4 = {}; - -/** - * Creates a new identity mat4 - * - * @returns {mat4} a new 4x4 matrix - */ -mat4.create = function () { - return new _mat4( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ); -}; - -/** - * Create a new mat4 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m03 Component in column 0, row 3 position (index 3) - * @param {Number} m10 Component in column 1, row 0 position (index 4) - * @param {Number} m11 Component in column 1, row 1 position (index 5) - * @param {Number} m12 Component in column 1, row 2 position (index 6) - * @param {Number} m13 Component in column 1, row 3 position (index 7) - * @param {Number} m20 Component in column 2, row 0 position (index 8) - * @param {Number} m21 Component in column 2, row 1 position (index 9) - * @param {Number} m22 Component in column 2, row 2 position (index 10) - * @param {Number} m23 Component in column 2, row 3 position (index 11) - * @param {Number} m30 Component in column 3, row 0 position (index 12) - * @param {Number} m31 Component in column 3, row 1 position (index 13) - * @param {Number} m32 Component in column 3, row 2 position (index 14) - * @param {Number} m33 Component in column 3, row 3 position (index 15) - * @returns {mat4} A new mat4 - */ -mat4.new = function (m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { - return new _mat4( - m00, m01, m02, m03, - m10, m11, m12, m13, - m20, m21, m22, m23, - m30, m31, m32, m33 - ); -}; - -/** - * Creates a new mat4 initialized with values from an existing matrix - * - * @param {mat4} a matrix to clone - * @returns {mat4} a new 4x4 matrix - */ -mat4.clone = function (a) { - return new _mat4( - a.m00, a.m01, a.m02, a.m03, - a.m04, a.m05, a.m06, a.m07, - a.m08, a.m09, a.m10, a.m11, - a.m12, a.m13, a.m14, a.m15 - ); -}; - -/** - * Copy the values from one mat4 to another - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - out.m09 = a.m09; - out.m10 = a.m10; - out.m11 = a.m11; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - return out; -}; - -/** - * Set the components of a mat4 to the given values - * - * @param {mat4} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m03 Component in column 0, row 3 position (index 3) - * @param {Number} m10 Component in column 1, row 0 position (index 4) - * @param {Number} m11 Component in column 1, row 1 position (index 5) - * @param {Number} m12 Component in column 1, row 2 position (index 6) - * @param {Number} m13 Component in column 1, row 3 position (index 7) - * @param {Number} m20 Component in column 2, row 0 position (index 8) - * @param {Number} m21 Component in column 2, row 1 position (index 9) - * @param {Number} m22 Component in column 2, row 2 position (index 10) - * @param {Number} m23 Component in column 2, row 3 position (index 11) - * @param {Number} m30 Component in column 3, row 0 position (index 12) - * @param {Number} m31 Component in column 3, row 1 position (index 13) - * @param {Number} m32 Component in column 3, row 2 position (index 14) - * @param {Number} m33 Component in column 3, row 3 position (index 15) - * @returns {mat4} out - */ -mat4.set = function (out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m02; - out.m03 = m03; - out.m04 = m10; - out.m05 = m11; - out.m06 = m12; - out.m07 = m13; - out.m08 = m20; - out.m09 = m21; - out.m10 = m22; - out.m11 = m23; - out.m12 = m30; - out.m13 = m31; - out.m14 = m32; - out.m15 = m33; - return out; -}; - - -/** - * Set a mat4 to the identity matrix - * - * @param {mat4} out the receiving matrix - * @returns {mat4} out - */ -mat4.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Transpose the values of a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a01 = a.m01, a02 = a.m02, a03 = a.m03, - a12 = a.m06, a13 = a.m07, - a23 = a.m11; - - out.m01 = a.m04; - out.m02 = a.m08; - out.m03 = a.m12; - out.m04 = a01; - out.m06 = a.m09; - out.m07 = a.m13; - out.m08 = a02; - out.m09 = a12; - out.m11 = a.m14; - out.m12 = a03; - out.m13 = a13; - out.m14 = a23; - } else { - out.m00 = a.m00; - out.m01 = a.m04; - out.m02 = a.m08; - out.m03 = a.m12; - out.m04 = a.m01; - out.m05 = a.m05; - out.m06 = a.m09; - out.m07 = a.m13; - out.m08 = a.m02; - out.m09 = a.m06; - out.m10 = a.m10; - out.m11 = a.m14; - out.m12 = a.m03; - out.m13 = a.m07; - out.m14 = a.m11; - out.m15 = a.m15; - } - - return out; -}; - -/** - * Inverts a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.invert = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out.m01 = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out.m02 = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out.m03 = (a22 * b04 - a21 * b05 - a23 * b03) * det; - out.m04 = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out.m05 = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out.m06 = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out.m07 = (a20 * b05 - a22 * b02 + a23 * b01) * det; - out.m08 = (a10 * b10 - a11 * b08 + a13 * b06) * det; - out.m09 = (a01 * b08 - a00 * b10 - a03 * b06) * det; - out.m10 = (a30 * b04 - a31 * b02 + a33 * b00) * det; - out.m11 = (a21 * b02 - a20 * b04 - a23 * b00) * det; - out.m12 = (a11 * b07 - a10 * b09 - a12 * b06) * det; - out.m13 = (a00 * b09 - a01 * b07 + a02 * b06) * det; - out.m14 = (a31 * b01 - a30 * b03 - a32 * b00) * det; - out.m15 = (a20 * b03 - a21 * b01 + a22 * b00) * det; - - return out; -}; - -/** - * Calculates the adjugate of a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.adjoint = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - out.m00 = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); - out.m01 = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); - out.m02 = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); - out.m03 = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); - out.m04 = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); - out.m05 = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); - out.m06 = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); - out.m07 = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); - out.m08 = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); - out.m09 = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); - out.m10 = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); - out.m11 = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); - out.m12 = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); - out.m13 = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); - out.m14 = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); - out.m15 = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); - return out; -}; - -/** - * Calculates the determinant of a mat4 - * - * @param {mat4} a the source matrix - * @returns {Number} determinant of a - */ -mat4.determinant = function (a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; -}; - -/** - * Multiplies two mat4's explicitly - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.multiply = function (out, a, b) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - // Cache only the current line of the second matrix - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - out.m00 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m01 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m02 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m03 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m04; b1 = b.m05; b2 = b.m06; b3 = b.m07; - out.m04 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m05 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m06 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m07 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m08; b1 = b.m09; b2 = b.m10; b3 = b.m11; - out.m08 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m09 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m10 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m11 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m12; b1 = b.m13; b2 = b.m14; b3 = b.m15; - out.m12 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m13 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m14 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m15 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - return out; -}; - -/** - * Alias for {@link mat4.multiply} - * @function - */ -mat4.mul = mat4.multiply; - -/** - * Translate a mat4 by the given vector - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to translate - * @param {vec3} v vector to translate by - * @returns {mat4} out - */ -mat4.translate = function (out, a, v) { - var x = v.x, y = v.y, z = v.z, - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23; - - if (a === out) { - out.m12 = a.m00 * x + a.m04 * y + a.m08 * z + a.m12; - out.m13 = a.m01 * x + a.m05 * y + a.m09 * z + a.m13; - out.m14 = a.m02 * x + a.m06 * y + a.m10 * z + a.m14; - out.m15 = a.m03 * x + a.m07 * y + a.m11 * z + a.m15; - } else { - a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; - a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; - a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; - - out.m00 = a00; out.m01 = a01; out.m02 = a02; out.m03 = a03; - out.m04 = a10; out.m05 = a11; out.m06 = a12; out.m07 = a13; - out.m08 = a20; out.m09 = a21; out.m10 = a22; out.m11 = a23; - - out.m12 = a00 * x + a10 * y + a20 * z + a.m12; - out.m13 = a01 * x + a11 * y + a21 * z + a.m13; - out.m14 = a02 * x + a12 * y + a22 * z + a.m14; - out.m15 = a03 * x + a13 * y + a23 * z + a.m15; - } - - return out; -}; - -/** - * Scales the mat4 by the dimensions in the given vec3 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to scale - * @param {vec3} v the vec3 to scale the matrix by - * @returns {mat4} out - **/ -mat4.scale = function (out, a, v) { - var x = v.x, y = v.y, z = v.z; - - out.m00 = a.m00 * x; - out.m01 = a.m01 * x; - out.m02 = a.m02 * x; - out.m03 = a.m03 * x; - out.m04 = a.m04 * y; - out.m05 = a.m05 * y; - out.m06 = a.m06 * y; - out.m07 = a.m07 * y; - out.m08 = a.m08 * z; - out.m09 = a.m09 * z; - out.m10 = a.m10 * z; - out.m11 = a.m11 * z; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - return out; -}; - -/** - * Rotates a mat4 by the given angle around the given axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @param {vec3} axis the axis to rotate around - * @returns {mat4} out - */ -mat4.rotate = function (out, a, rad, axis) { - var x = axis.x, y = axis.y, z = axis.z; - var s, c, t, - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23, - b00, b01, b02, - b10, b11, b12, - b20, b21, b22; - - var len = Math.sqrt(x * x + y * y + z * z); - - if (Math.abs(len) < EPSILON) { - return null; - } - - len = 1 / len; - x *= len; - y *= len; - z *= len; - - s = Math.sin(rad); - c = Math.cos(rad); - t = 1 - c; - - a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; - a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; - a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; - - // Construct the elements of the rotation matrix - b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; - b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; - b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; - - // Perform rotation-specific matrix multiplication - out.m00 = a00 * b00 + a10 * b01 + a20 * b02; - out.m01 = a01 * b00 + a11 * b01 + a21 * b02; - out.m02 = a02 * b00 + a12 * b01 + a22 * b02; - out.m03 = a03 * b00 + a13 * b01 + a23 * b02; - out.m04 = a00 * b10 + a10 * b11 + a20 * b12; - out.m05 = a01 * b10 + a11 * b11 + a21 * b12; - out.m06 = a02 * b10 + a12 * b11 + a22 * b12; - out.m07 = a03 * b10 + a13 * b11 + a23 * b12; - out.m08 = a00 * b20 + a10 * b21 + a20 * b22; - out.m09 = a01 * b20 + a11 * b21 + a21 * b22; - out.m10 = a02 * b20 + a12 * b21 + a22 * b22; - out.m11 = a03 * b20 + a13 * b21 + a23 * b22; - - // If the source and destination differ, copy the unchanged last row - if (a !== out) { - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - return out; -}; - -/** - * Rotates a matrix by the given angle around the X axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateX = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a10 = a.m04, - a11 = a.m05, - a12 = a.m06, - a13 = a.m07, - a20 = a.m08, - a21 = a.m09, - a22 = a.m10, - a23 = a.m11; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m04 = a10 * c + a20 * s; - out.m05 = a11 * c + a21 * s; - out.m06 = a12 * c + a22 * s; - out.m07 = a13 * c + a23 * s; - out.m08 = a20 * c - a10 * s; - out.m09 = a21 * c - a11 * s; - out.m10 = a22 * c - a12 * s; - out.m11 = a23 * c - a13 * s; - - return out; -}; - -/** - * Rotates a matrix by the given angle around the Y axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateY = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a.m00, - a01 = a.m01, - a02 = a.m02, - a03 = a.m03, - a20 = a.m08, - a21 = a.m09, - a22 = a.m10, - a23 = a.m11; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m00 = a00 * c - a20 * s; - out.m01 = a01 * c - a21 * s; - out.m02 = a02 * c - a22 * s; - out.m03 = a03 * c - a23 * s; - out.m08 = a00 * s + a20 * c; - out.m09 = a01 * s + a21 * c; - out.m10 = a02 * s + a22 * c; - out.m11 = a03 * s + a23 * c; - - return out; -}; - -/** - * Rotates a matrix by the given angle around the Z axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateZ = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a.m00, - a01 = a.m01, - a02 = a.m02, - a03 = a.m03, - a10 = a.m04, - a11 = a.m05, - a12 = a.m06, - a13 = a.m07; - - // If the source and destination differ, copy the unchanged last row - if (a !== out) { - out.m08 = a.m08; - out.m09 = a.m09; - out.m10 = a.m10; - out.m11 = a.m11; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m00 = a00 * c + a10 * s; - out.m01 = a01 * c + a11 * s; - out.m02 = a02 * c + a12 * s; - out.m03 = a03 * c + a13 * s; - out.m04 = a10 * c - a00 * s; - out.m05 = a11 * c - a01 * s; - out.m06 = a12 * c - a02 * s; - out.m07 = a13 * c - a03 * s; - - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, dest, vec); - * - * @param {mat4} out mat4 receiving operation result - * @param {vec3} v Translation vector - * @returns {mat4} out - */ -mat4.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.scale(dest, dest, vec); - * - * @param {mat4} out mat4 receiving operation result - * @param {vec3} v Scaling vector - * @returns {mat4} out - */ -mat4.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = v.y; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = v.z; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a given angle around a given axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotate(dest, dest, rad, axis); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @param {vec3} axis the axis to rotate around - * @returns {mat4} out - */ -mat4.fromRotation = function (out, rad, axis) { - var x = axis.x, y = axis.y, z = axis.z; - var len = Math.sqrt(x * x + y * y + z * z); - var s, c, t; - - if (Math.abs(len) < EPSILON) { - return null; - } - - len = 1 / len; - x *= len; - y *= len; - z *= len; - - s = Math.sin(rad); - c = Math.cos(rad); - t = 1 - c; - - // Perform rotation-specific matrix multiplication - out.m00 = x * x * t + c; - out.m01 = y * x * t + z * s; - out.m02 = z * x * t - y * s; - out.m03 = 0; - out.m04 = x * y * t - z * s; - out.m05 = y * y * t + c; - out.m06 = z * y * t + x * s; - out.m07 = 0; - out.m08 = x * z * t + y * s; - out.m09 = y * z * t - x * s; - out.m10 = z * z * t + c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the X axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateX(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromXRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = c; - out.m06 = s; - out.m07 = 0; - out.m08 = 0; - out.m09 = -s; - out.m10 = c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the Y axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateY(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromYRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = c; - out.m01 = 0; - out.m02 = -s; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = s; - out.m09 = 0; - out.m10 = c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the Z axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateZ(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromZRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = c; - out.m01 = s; - out.m02 = 0; - out.m03 = 0; - out.m04 = -s; - out.m05 = c; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a quaternion rotation and vector translation - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @returns {mat4} out - */ -mat4.fromRT = function (out, q, v) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - (yy + zz); - out.m01 = xy + wz; - out.m02 = xz - wy; - out.m03 = 0; - out.m04 = xy - wz; - out.m05 = 1 - (xx + zz); - out.m06 = yz + wx; - out.m07 = 0; - out.m08 = xz + wy; - out.m09 = yz - wx; - out.m10 = 1 - (xx + yy); - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - - return out; -}; - -/** - * Returns the translation vector component of a transformation - * matrix. If a matrix is built with fromRT, - * the returned vector will be the same as the translation vector - * originally supplied. - * @param {vec3} out Vector to receive translation component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {vec3} out - */ -mat4.getTranslation = function (out, mat) { - out.x = mat.m12; - out.y = mat.m13; - out.z = mat.m14; - - return out; -}; - -/** - * Returns the scaling factor component of a transformation - * matrix. If a matrix is built with fromRTS - * with a normalized Quaternion paramter, the returned vector will be - * the same as the scaling vector - * originally supplied. - * @param {vec3} out Vector to receive scaling factor component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {vec3} out - */ -mat4.getScaling = function (out, mat) { - var m11 = mat.m00, - m12 = mat.m01, - m13 = mat.m02, - m21 = mat.m04, - m22 = mat.m05, - m23 = mat.m06, - m31 = mat.m08, - m32 = mat.m09, - m33 = mat.m10; - - out.x = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13); - out.y = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23); - out.z = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33); - - return out; -}; - -/** - * Returns a quaternion representing the rotational component - * of a transformation matrix. If a matrix is built with - * fromRT, the returned quaternion will be the - * same as the quaternion originally supplied. - * @param {quat} out Quaternion to receive the rotation component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {quat} out - */ -mat4.getRotation = function (out, mat) { - // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - var trace = mat.m00 + mat.m05 + mat.m10; - var S = 0; - - if (trace > 0) { - S = Math.sqrt(trace + 1.0) * 2; - out.w = 0.25 * S; - out.x = (mat.m06 - mat.m09) / S; - out.y = (mat.m08 - mat.m02) / S; - out.z = (mat.m01 - mat.m04) / S; - } else if ((mat.m00 > mat.m05) & (mat.m00 > mat.m10)) { - S = Math.sqrt(1.0 + mat.m00 - mat.m05 - mat.m10) * 2; - out.w = (mat.m06 - mat.m09) / S; - out.x = 0.25 * S; - out.y = (mat.m01 + mat.m04) / S; - out.z = (mat.m08 + mat.m02) / S; - } else if (mat.m05 > mat.m10) { - S = Math.sqrt(1.0 + mat.m05 - mat.m00 - mat.m10) * 2; - out.w = (mat.m08 - mat.m02) / S; - out.x = (mat.m01 + mat.m04) / S; - out.y = 0.25 * S; - out.z = (mat.m06 + mat.m09) / S; - } else { - S = Math.sqrt(1.0 + mat.m10 - mat.m00 - mat.m05) * 2; - out.w = (mat.m01 - mat.m04) / S; - out.x = (mat.m08 + mat.m02) / S; - out.y = (mat.m06 + mat.m09) / S; - out.z = 0.25 * S; - } - - return out; -}; - -/** - * Creates a matrix from a quaternion rotation, vector translation and vector scale - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * mat4.scale(dest, scale) - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @param {vec3} s Scaling vector - * @returns {mat4} out - */ -mat4.fromRTS = function (out, q, v, s) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - var sx = s.x; - var sy = s.y; - var sz = s.z; - - out.m00 = (1 - (yy + zz)) * sx; - out.m01 = (xy + wz) * sx; - out.m02 = (xz - wy) * sx; - out.m03 = 0; - out.m04 = (xy - wz) * sy; - out.m05 = (1 - (xx + zz)) * sy; - out.m06 = (yz + wx) * sy; - out.m07 = 0; - out.m08 = (xz + wy) * sz; - out.m09 = (yz - wx) * sz; - out.m10 = (1 - (xx + yy)) * sz; - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - - return out; -}; - -/** - * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * mat4.translate(dest, origin); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * mat4.scale(dest, scale) - * mat4.translate(dest, negativeOrigin); - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @param {vec3} s Scaling vector - * @param {vec3} o The origin vector around which to scale and rotate - * @returns {mat4} out - */ -mat4.fromRTSOrigin = function (out, q, v, s, o) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - var sx = s.x; - var sy = s.y; - var sz = s.z; - - var ox = o.x; - var oy = o.y; - var oz = o.z; - - out.m00 = (1 - (yy + zz)) * sx; - out.m01 = (xy + wz) * sx; - out.m02 = (xz - wy) * sx; - out.m03 = 0; - out.m04 = (xy - wz) * sy; - out.m05 = (1 - (xx + zz)) * sy; - out.m06 = (yz + wx) * sy; - out.m07 = 0; - out.m08 = (xz + wy) * sz; - out.m09 = (yz - wx) * sz; - out.m10 = (1 - (xx + yy)) * sz; - out.m11 = 0; - out.m12 = v.x + ox - (out.m00 * ox + out.m04 * oy + out.m08 * oz); - out.m13 = v.y + oy - (out.m01 * ox + out.m05 * oy + out.m09 * oz); - out.m14 = v.z + oz - (out.m02 * ox + out.m06 * oy + out.m10 * oz); - out.m15 = 1; - - return out; -}; - -/** - * Calculates a 4x4 matrix from the given quaternion - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Quaternion to create matrix from - * - * @returns {mat4} out - */ -mat4.fromQuat = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var yx = y * x2; - var yy = y * y2; - var zx = z * x2; - var zy = z * y2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - yy - zz; - out.m01 = yx + wz; - out.m02 = zx - wy; - out.m03 = 0; - - out.m04 = yx - wz; - out.m05 = 1 - xx - zz; - out.m06 = zy + wx; - out.m07 = 0; - - out.m08 = zx + wy; - out.m09 = zy - wx; - out.m10 = 1 - xx - yy; - out.m11 = 0; - - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - - return out; -}; - -/** - * Generates a frustum matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {Number} left Left bound of the frustum - * @param {Number} right Right bound of the frustum - * @param {Number} bottom Bottom bound of the frustum - * @param {Number} top Top bound of the frustum - * @param {Number} near Near bound of the frustum - * @param {Number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.frustum = function (out, left, right, bottom, top, near, far) { - var rl = 1 / (right - left); - var tb = 1 / (top - bottom); - var nf = 1 / (near - far); - - out.m00 = (near * 2) * rl; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = (near * 2) * tb; - out.m06 = 0; - out.m07 = 0; - out.m08 = (right + left) * rl; - out.m09 = (top + bottom) * tb; - out.m10 = (far + near) * nf; - out.m11 = -1; - out.m12 = 0; - out.m13 = 0; - out.m14 = (far * near * 2) * nf; - out.m15 = 0; - return out; -}; - -/** - * Generates a perspective projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} fovy Vertical field of view in radians - * @param {number} aspect Aspect ratio. typically viewport width/height - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.perspective = function (out, fovy, aspect, near, far) { - var f = 1.0 / Math.tan(fovy / 2); - var nf = 1 / (near - far); - - out.m00 = f / aspect; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = f; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = (far + near) * nf; - out.m11 = -1; - out.m12 = 0; - out.m13 = 0; - out.m14 = (2 * far * near) * nf; - out.m15 = 0; - return out; -}; - -/** - * Generates a perspective projection matrix with the given field of view. - * This is primarily useful for generating projection matrices to be used - * with the still experiemental WebVR API. - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.perspectiveFromFieldOfView = function (out, fov, near, far) { - var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0); - var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0); - var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0); - var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0); - var xScale = 2.0 / (leftTan + rightTan); - var yScale = 2.0 / (upTan + downTan); - - out.m00 = xScale; - out.m01 = 0.0; - out.m02 = 0.0; - out.m03 = 0.0; - out.m04 = 0.0; - out.m05 = yScale; - out.m06 = 0.0; - out.m07 = 0.0; - out.m08 = -((leftTan - rightTan) * xScale * 0.5); - out.m09 = ((upTan - downTan) * yScale * 0.5); - out.m10 = far / (near - far); - out.m11 = -1.0; - out.m12 = 0.0; - out.m13 = 0.0; - out.m14 = (far * near) / (near - far); - out.m15 = 0.0; - return out; -}; - -/** - * Generates a orthogonal projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} left Left bound of the frustum - * @param {number} right Right bound of the frustum - * @param {number} bottom Bottom bound of the frustum - * @param {number} top Top bound of the frustum - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.ortho = function (out, left, right, bottom, top, near, far) { - var lr = 1 / (left - right); - var bt = 1 / (bottom - top); - var nf = 1 / (near - far); - out.m00 = -2 * lr; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = -2 * bt; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 2 * nf; - out.m11 = 0; - out.m12 = (left + right) * lr; - out.m13 = (top + bottom) * bt; - out.m14 = (far + near) * nf; - out.m15 = 1; - return out; -}; - -/** - * Generates a look-at matrix with the given eye position, focal point, and up axis - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {vec3} eye Position of the viewer - * @param {vec3} center Point the viewer is looking at - * @param {vec3} up vec3 pointing up - * @returns {mat4} out - */ -mat4.lookAt = function (out, eye, center, up) { - var x0, x1, x2, y0, y1, y2, z0, z1, z2, len; - var eyex = eye.x; - var eyey = eye.y; - var eyez = eye.z; - var upx = up.x; - var upy = up.y; - var upz = up.z; - var centerx = center.x; - var centery = center.y; - var centerz = center.z; - - if ( - Math.abs(eyex - centerx) < EPSILON && - Math.abs(eyey - centery) < EPSILON && - Math.abs(eyez - centerz) < EPSILON - ) { - return mat4.identity(out); - } - - z0 = eyex - centerx; - z1 = eyey - centery; - z2 = eyez - centerz; - - len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); - z0 *= len; - z1 *= len; - z2 *= len; - - x0 = upy * z2 - upz * z1; - x1 = upz * z0 - upx * z2; - x2 = upx * z1 - upy * z0; - len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); - if (!len) { - x0 = 0; - x1 = 0; - x2 = 0; - } else { - len = 1 / len; - x0 *= len; - x1 *= len; - x2 *= len; - } - - y0 = z1 * x2 - z2 * x1; - y1 = z2 * x0 - z0 * x2; - y2 = z0 * x1 - z1 * x0; - - len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); - if (!len) { - y0 = 0; - y1 = 0; - y2 = 0; - } else { - len = 1 / len; - y0 *= len; - y1 *= len; - y2 *= len; - } - - out.m00 = x0; - out.m01 = y0; - out.m02 = z0; - out.m03 = 0; - out.m04 = x1; - out.m05 = y1; - out.m06 = z1; - out.m07 = 0; - out.m08 = x2; - out.m09 = y2; - out.m10 = z2; - out.m11 = 0; - out.m12 = -(x0 * eyex + x1 * eyey + x2 * eyez); - out.m13 = -(y0 * eyex + y1 * eyey + y2 * eyez); - out.m14 = -(z0 * eyex + z1 * eyey + z2 * eyez); - out.m15 = 1; - - return out; -}; - -/** - * Returns a string representation of a mat4 - * - * @param {mat4} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat4.str = function (a) { - return ("mat4(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ", " + (a.m06) + ", " + (a.m07) + ", " + (a.m08) + ", " + (a.m09) + ", " + (a.m10) + ", " + (a.m11) + ", " + (a.m12) + ", " + (a.m13) + ", " + (a.m14) + ", " + (a.m15) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat4} m - * @returns {array} - */ -mat4.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - out[6] = m.m06; - out[7] = m.m07; - out[8] = m.m08; - out[9] = m.m09; - out[10] = m.m10; - out[11] = m.m11; - out[12] = m.m12; - out[13] = m.m13; - out[14] = m.m14; - out[15] = m.m15; - - return out; -}; - -/** - * Returns Frobenius norm of a mat4 - * - * @param {mat4} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat4.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2) + Math.pow(a.m09, 2) + Math.pow(a.m10, 2) + Math.pow(a.m11, 2) + Math.pow(a.m12, 2) + Math.pow(a.m13, 2) + Math.pow(a.m14, 2) + Math.pow(a.m15, 2))) -}; - -/** - * Adds two mat4's - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - out.m06 = a.m06 + b.m06; - out.m07 = a.m07 + b.m07; - out.m08 = a.m08 + b.m08; - out.m09 = a.m09 + b.m09; - out.m10 = a.m10 + b.m10; - out.m11 = a.m11 + b.m11; - out.m12 = a.m12 + b.m12; - out.m13 = a.m13 + b.m13; - out.m14 = a.m14 + b.m14; - out.m15 = a.m15 + b.m15; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - out.m06 = a.m06 - b.m06; - out.m07 = a.m07 - b.m07; - out.m08 = a.m08 - b.m08; - out.m09 = a.m09 - b.m09; - out.m10 = a.m10 - b.m10; - out.m11 = a.m11 - b.m11; - out.m12 = a.m12 - b.m12; - out.m13 = a.m13 - b.m13; - out.m14 = a.m14 - b.m14; - out.m15 = a.m15 - b.m15; - return out; -}; - -/** - * Alias for {@link mat4.subtract} - * @function - */ -mat4.sub = mat4.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat4} out - */ -mat4.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - out.m06 = a.m06 * b; - out.m07 = a.m07 * b; - out.m08 = a.m08 * b; - out.m09 = a.m09 * b; - out.m10 = a.m10 * b; - out.m11 = a.m11 * b; - out.m12 = a.m12 * b; - out.m13 = a.m13 * b; - out.m14 = a.m14 * b; - out.m15 = a.m15 * b; - return out; -}; - -/** - * Adds two mat4's after multiplying each element of the second operand by a scalar value. - * - * @param {mat4} out the receiving vector - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat4} out - */ -mat4.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - out.m06 = a.m06 + (b.m06 * scale); - out.m07 = a.m07 + (b.m07 * scale); - out.m08 = a.m08 + (b.m08 * scale); - out.m09 = a.m09 + (b.m09 * scale); - out.m10 = a.m10 + (b.m10 * scale); - out.m11 = a.m11 + (b.m11 * scale); - out.m12 = a.m12 + (b.m12 * scale); - out.m13 = a.m13 + (b.m13 * scale); - out.m14 = a.m14 + (b.m14 * scale); - out.m15 = a.m15 + (b.m15 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat4} a The first matrix. - * @param {mat4} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat4.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && - a.m04 === b.m04 && a.m05 === b.m05 && a.m06 === b.m06 && a.m07 === b.m07 && - a.m08 === b.m08 && a.m09 === b.m09 && a.m10 === b.m10 && a.m11 === b.m11 && - a.m12 === b.m12 && a.m13 === b.m13 && a.m14 === b.m14 && a.m15 === b.m15; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat4} a The first matrix. - * @param {mat4} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat4.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, - a8 = a.m08, a9 = a.m09, a10 = a.m10, a11 = a.m11, - a12 = a.m12, a13 = a.m13, a14 = a.m14, a15 = a.m15; - - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, - b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, - b8 = b.m08, b9 = b.m09, b10 = b.m10, b11 = b.m11, - b12 = b.m12, b13 = b.m13, b14 = b.m14, b15 = b.m15; - - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && - Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && - Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && - Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && - Math.abs(a9 - b9) <= EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && - Math.abs(a10 - b10) <= EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && - Math.abs(a11 - b11) <= EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && - Math.abs(a12 - b12) <= EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && - Math.abs(a13 - b13) <= EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && - Math.abs(a14 - b14) <= EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && - Math.abs(a15 - b15) <= EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15)) - ); -}; - -var _tmp$8 = new Array(3); - -var _color3 = function _color3(r, g, b) { - this.r = r; - this.g = g; - this.b = b; -}; - -_color3.prototype.toJSON = function toJSON () { - _tmp$8[0] = this.r; - _tmp$8[1] = this.g; - _tmp$8[2] = this.b; - - return _tmp$8; -}; - -/** - * @class Color - * @name color3 - */ -var color3 = {}; - -/** - * Creates a new color - * - * @returns {color3} a new color - */ -color3.create = function () { - return new _color3(1, 1, 1); -}; - -/** - * Creates a new color initialized with the given values - * - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @returns {color3} a new color - * @function - */ -color3.new = function (r, g, b) { - return new _color3(r, g, b); -}; - -/** - * Creates a new color initialized with values from an existing quaternion - * - * @param {color3} a color to clone - * @returns {color3} a new color - * @function - */ -color3.clone = function (a) { - return new _color3(a.r, a.g, a.b, a.a); -}; - -/** - * Copy the values from one color to another - * - * @param {color3} out the receiving color - * @param {color3} a the source color - * @returns {color3} out - * @function - */ -color3.copy = function (out, a) { - out.r = a.r; - out.g = a.g; - out.b = a.b; - return out; -}; - -/** - * Set the components of a color to the given values - * - * @param {color3} out the receiving color - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @returns {color3} out - * @function - */ -color3.set = function (out, r, g, b) { - out.r = r; - out.g = g; - out.b = b; - return out; -}; - -/** - * Set from hex - * - * @param {color3} out the receiving color - * @param {Number} hex - * @returns {color3} out - * @function - */ -color3.fromHex = function (out, hex) { - var r = ((hex >> 16)) / 255.0; - var g = ((hex >> 8) & 0xff) / 255.0; - var b = ((hex) & 0xff) / 255.0; - - out.r = r; - out.g = g; - out.b = b; - return out; -}; - -/** - * Adds two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - * @function - */ -color3.add = function (out, a, b) { - out.r = a.r + b.r; - out.g = a.g + b.g; - out.b = a.b + b.b; - return out; -}; - -/** - * Subtracts color b from color a - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - */ -color3.subtract = function (out, a, b) { - out.r = a.r - b.r; - out.g = a.g - b.g; - out.b = a.b - b.b; - return out; -}; - -/** - * Alias for {@link color3.subtract} - * @function - */ -color3.sub = color3.subtract; - -/** - * Multiplies two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - * @function - */ -color3.multiply = function (out, a, b) { - out.r = a.r * b.r; - out.g = a.g * b.g; - out.b = a.b * b.b; - return out; -}; - -/** - * Alias for {@link color3.multiply} - * @function - */ -color3.mul = color3.multiply; - -/** - * Divides two color's - * - * @param {color3} out the receiving vector - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - */ -color3.divide = function (out, a, b) { - out.r = a.r / b.r; - out.g = a.g / b.g; - out.b = a.b / b.b; - return out; -}; - -/** - * Alias for {@link color3.divide} - * @function - */ -color3.div = color3.divide; - - -/** - * Scales a color by a scalar number - * - * @param {color3} out the receiving vector - * @param {color3} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {color3} out - * @function - */ -color3.scale = function (out, a, b) { - out.r = a.r * b; - out.g = a.g * b; - out.b = a.b * b; - return out; -}; - -/** - * Performs a linear interpolation between two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {color3} out - * @function - */ -color3.lerp = function (out, a, b, t) { - var ar = a.r, - ag = a.g, - ab = a.b; - out.r = ar + t * (b.r - ar); - out.g = ag + t * (b.g - ag); - out.b = ab + t * (b.b - ab); - return out; -}; - -/** - * Returns a string representation of a color - * - * @param {color3} a vector to represent as a string - * @returns {String} string representation of the vector - */ -color3.str = function (a) { - return ("color3(" + (a.r) + ", " + (a.g) + ", " + (a.b) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {color3} a - * @returns {array} - */ -color3.array = function (out, a) { - out[0] = a.r; - out[1] = a.g; - out[2] = a.b; - - return out; -}; - -/** - * Returns whether or not the color have exactly the same elements in the same position (when compared with ===) - * - * @param {color3} a The first color3. - * @param {color3} b The second color3. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color3.exactEquals = function (a, b) { - return a.r === b.r && a.g === b.g && a.b === b.b; -}; - -/** - * Returns whether or not the colors have approximately the same elements in the same position. - * - * @param {color3} a The first color3. - * @param {color3} b The second color3. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color3.equals = function (a, b) { - var a0 = a.r, a1 = a.g, a2 = a.b; - var b0 = b.r, b1 = b.g, b2 = b.b; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); -}; - -/** - * Returns the hex value - * - * @param {color3} a The color - * @returns {Number} - */ -color3.hex = function (a) { - return (a.r * 255) << 16 | (a.g * 255) << 8 | (a.b * 255); -}; - -var _tmp$9 = new Array(4); - -var _color4 = function _color4(r, g, b, a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; -}; - -_color4.prototype.toJSON = function toJSON () { - _tmp$9[0] = this.r; - _tmp$9[1] = this.g; - _tmp$9[2] = this.b; - _tmp$9[3] = this.a; - - return _tmp$9; -}; - -/** - * @class Color - * @name color4 - */ -var color4 = {}; - -/** - * Creates a new color - * - * @returns {color4} a new color - */ -color4.create = function () { - return new _color4(1, 1, 1, 1); -}; - -/** - * Creates a new color initialized with the given values - * - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @param {Number} a alpha component - * @returns {color4} a new color - * @function - */ -color4.new = function (r, g, b, a) { - return new _color4(r, g, b, a); -}; - -/** - * Creates a new color initialized with values from an existing quaternion - * - * @param {color4} a color to clone - * @returns {color4} a new color - * @function - */ -color4.clone = function (a) { - return new _color4(a.r, a.g, a.b, a.a); -}; - -/** - * Copy the values from one color to another - * - * @param {color4} out the receiving color - * @param {color4} a the source color - * @returns {color4} out - * @function - */ -color4.copy = function (out, a) { - out.r = a.r; - out.g = a.g; - out.b = a.b; - out.a = a.a; - return out; -}; - -/** - * Set the components of a color to the given values - * - * @param {color4} out the receiving color - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @param {Number} a alpha component - * @returns {color4} out - * @function - */ -color4.set = function (out, r, g, b, a) { - out.r = r; - out.g = g; - out.b = b; - out.a = a; - return out; -}; - -/** - * Set from hex - * - * @param {color4} out the receiving color - * @param {Number} hex - * @returns {color4} out - * @function - */ -color4.fromHex = function (out, hex) { - var r = ((hex >> 24)) / 255.0; - var g = ((hex >> 16) & 0xff) / 255.0; - var b = ((hex >> 8) & 0xff) / 255.0; - var a = ((hex) & 0xff) / 255.0; - - out.r = r; - out.g = g; - out.b = b; - out.a = a; - return out; -}; - -/** - * Adds two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - * @function - */ -color4.add = function (out, a, b) { - out.r = a.r + b.r; - out.g = a.g + b.g; - out.b = a.b + b.b; - out.a = a.a + b.a; - return out; -}; - -/** - * Subtracts color b from color a - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - */ -color4.subtract = function (out, a, b) { - out.r = a.r - b.r; - out.g = a.g - b.g; - out.b = a.b - b.b; - out.a = a.a - b.a; - return out; -}; - -/** - * Alias for {@link color4.subtract} - * @function - */ -color4.sub = color4.subtract; - -/** - * Multiplies two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - * @function - */ -color4.multiply = function (out, a, b) { - out.r = a.r * b.r; - out.g = a.g * b.g; - out.b = a.b * b.b; - out.a = a.a * b.a; - return out; -}; - -/** - * Alias for {@link color4.multiply} - * @function - */ -color4.mul = color4.multiply; - -/** - * Divides two color's - * - * @param {color4} out the receiving vector - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - */ -color4.divide = function (out, a, b) { - out.r = a.r / b.r; - out.g = a.g / b.g; - out.b = a.b / b.b; - out.a = a.a / b.a; - return out; -}; - -/** - * Alias for {@link color4.divide} - * @function - */ -color4.div = color4.divide; - - -/** - * Scales a color by a scalar number - * - * @param {color4} out the receiving vector - * @param {color4} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {color4} out - * @function - */ -color4.scale = function (out, a, b) { - out.r = a.r * b; - out.g = a.g * b; - out.b = a.b * b; - out.a = a.a * b; - return out; -}; - -/** - * Performs a linear interpolation between two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {color4} out - * @function - */ -color4.lerp = function (out, a, b, t) { - var ar = a.r, - ag = a.g, - ab = a.b, - aa = a.a; - out.r = ar + t * (b.r - ar); - out.g = ag + t * (b.g - ag); - out.b = ab + t * (b.b - ab); - out.a = aa + t * (b.a - aa); - return out; -}; - -/** - * Returns a string representation of a color - * - * @param {color4} a vector to represent as a string - * @returns {String} string representation of the vector - */ -color4.str = function (a) { - return ("color4(" + (a.r) + ", " + (a.g) + ", " + (a.b) + ", " + (a.a) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {color4} a - * @returns {array} - */ -color4.array = function (out, a) { - out[0] = a.r; - out[1] = a.g; - out[2] = a.b; - out[3] = a.a; - - return out; -}; - -/** - * Returns whether or not the color have exactly the same elements in the same position (when compared with ===) - * - * @param {color4} a The first color4. - * @param {color4} b The second color4. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color4.exactEquals = function (a, b) { - return a.r === b.r && a.g === b.g && a.b === b.b && a.a === b.a; -}; - -/** - * Returns whether or not the colors have approximately the same elements in the same position. - * - * @param {color4} a The first color4. - * @param {color4} b The second color4. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color4.equals = function (a, b) { - var a0 = a.r, a1 = a.g, a2 = a.b, a3 = a.a; - var b0 = b.r, b1 = b.g, b2 = b.b, b3 = b.a; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); -}; - -/** - * Returns the hex value - * - * @param {color4} a The color - * @returns {Number} - */ -color4.hex = function (a) { - return ((a.r * 255) << 24 | (a.g * 255) << 16 | (a.b * 255) << 8 | a.a * 255) >>> 0; -}; - -// NOTE: there is no syntax for: export {* as bits} from './lib/bits'; -var bits = bits_; - - - -var math = Object.freeze({ - bits: bits, - vec2: vec2, - vec3: vec3, - vec4: vec4, - quat: quat, - mat2: mat2, - mat23: mat23, - mat3: mat3, - mat4: mat4, - color3: color3, - color4: color4, - EPSILON: EPSILON, - equals: equals, - approx: approx, - clamp: clamp, - clamp01: clamp01, - lerp: lerp, - toRadian: toRadian, - toDegree: toDegree, - random: random, - randomRange: randomRange, - randomRangeInt: randomRangeInt, - nextPow2: nextPow2 -}); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Device = function Device(canvasEL) { - var ctx; - - try { - ctx = canvasEL.getContext('2d'); - } catch (err) { - console.error(err); - return; - } - - // statics - this._canvas = canvasEL; - this._ctx = ctx; - this._caps = {}; // capability - this._stats = { - drawcalls: 0, - }; - - // runtime - this._vx = this._vy = this._vw = this._vh = 0; - this._sx = this._sy = this._sw = this._sh = 0; -}; - -Device.prototype._restoreTexture = function _restoreTexture (unit) { -}; - -// =============================== -// Immediate Settings -// =============================== - -/** - * @method setViewport - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device.prototype.setViewport = function setViewport (x, y, w, h) { - if ( - this._vx !== x || - this._vy !== y || - this._vw !== w || - this._vh !== h - ) { - this._vx = x; - this._vy = y; - this._vw = w; - this._vh = h; - } -}; - -/** - * @method setScissor - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device.prototype.setScissor = function setScissor (x, y, w, h) { - if ( - this._sx !== x || - this._sy !== y || - this._sw !== w || - this._sh !== h - ) { - this._sx = x; - this._sy = y; - this._sw = w; - this._sh = h; - } -}; - -Device.prototype.clear = function clear (color) { - var ctx = this._ctx; - ctx.clearRect(this._vx, this._vy, this._vw, this._vh); - if (color && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { - ctx.fillStyle = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] +')'; - ctx.globalAlpha = color[3]; - ctx.fillRect(this._vx, this._vy, this._vw, this._vh); - } -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Texture2D = function Texture2D(device, options) { - this._device = device; - - this._width = 4; - this._height = 4; - - this._image = null; - - if (options) { - if (options.width !== undefined) { - this._width = options.width; - } - if (options.height !== undefined) { - this._height = options.height; - } - - this.updateImage(options); - } -}; - -Texture2D.prototype.update = function update (options) { - this.updateImage(options); -}; - -Texture2D.prototype.updateImage = function updateImage (options) { - if (options.images && options.images[0]) { - var image = options.images[0]; - if (image && image !== this._image) { - this._image = image; - } - } -}; - -Texture2D.prototype.destroy = function destroy () { - this._image = null; -}; - -var canvas = { - Device: Device, - Texture2D: Texture2D -}; - -// intenral -// deps -// Add stage to renderer -renderer$4.config.addStage('transparent'); - -var renderEngine = { - // core classes - Device: gfx$1.Device, - ForwardRenderer: renderer$4.ForwardRenderer, - Texture2D: gfx$1.Texture2D, - - // Canvas render support - canvas: canvas, - - // render scene - Scene: renderer$4.Scene, - Camera: renderer$4.Camera, - View: renderer$4.View, - Model: renderer$4.Model, - RenderData: RenderData, - IARenderData: IARenderData, - InputAssembler: renderer$4.InputAssembler, - - // assets - Asset: Asset, - TextureAsset: Texture, - Material: Material, - - // materials - SpriteMaterial: SpriteMaterial, - GraySpriteMaterial: GraySpriteMaterial, - StencilMaterial: StencilMaterial, - - // shaders - shaders: shaders, - - // memop - RecyclePool: RecyclePool, - Pool: Pool, - - // modules - math: math, - renderer: renderer$4, - gfx: gfx$1, -}; - -module.exports = renderEngine; diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index b016a0e6b9d..4a9da97fe28 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -4,13 +4,12 @@ const WORLD_TRANSFORM = 1 << 1; const TRANSFORM = LOCAL_TRANSFORM | WORLD_TRANSFORM; const UPDATE_RENDER_DATA = 1 << 2; const OPACITY = 1 << 3; -const COLOR = 1 << 4; -const RENDER = 1 << 5; -const CUSTOM_IA_RENDER = 1 << 6; -const CHILDREN = 1 << 7; -const POST_UPDATE_RENDER_DATA = 1 << 8; -const POST_RENDER = 1 << 9; -const FINAL = 1 << 10; +const RENDER = 1 << 4; +const CUSTOM_IA_RENDER = 1 << 5; +const CHILDREN = 1 << 6; +const POST_UPDATE_RENDER_DATA = 1 << 7; +const POST_RENDER = 1 << 8; +const FINAL = 1 << 9; let _batcher; let _cullingMask = 0; @@ -46,20 +45,12 @@ _proto._worldTransform = function (node) { _batcher.worldMatDirty --; }; -_proto._color = function (node) { - let comp = node._renderComponent; - if (comp) { - comp._updateColor(); - } - else { - node._renderFlag &= ~COLOR; - } - this._next._func(node); -}; - _proto._opacity = function (node) { _batcher.parentOpacityDirty++; + let comp = node._renderComponent; + if (comp && comp._updateColor) comp._updateColor(); + node._renderFlag &= ~OPACITY; this._next._func(node); @@ -93,7 +84,7 @@ _proto._children = function (node) { batcher.parentOpacity *= (node._opacity / 255); let worldTransformFlag = batcher.worldMatDirty ? WORLD_TRANSFORM : 0; - let worldOpacityFlag = batcher.parentOpacityDirty ? COLOR : 0; + let worldOpacityFlag = batcher.parentOpacityDirty ? OPACITY : 0; let children = node._children; for (let i = 0, l = children.length; i < l; i++) { @@ -149,9 +140,6 @@ function createFlow (flag, next) { case WORLD_TRANSFORM: flow._func = flow._worldTransform; break; - case COLOR: - flow._func = flow._color; - break; case OPACITY: flow._func = flow._opacity; break; @@ -234,7 +222,6 @@ RenderFlow.FLAG_DONOTHING = DONOTHING; RenderFlow.FLAG_LOCAL_TRANSFORM = LOCAL_TRANSFORM; RenderFlow.FLAG_WORLD_TRANSFORM = WORLD_TRANSFORM; RenderFlow.FLAG_TRANSFORM = TRANSFORM; -RenderFlow.FLAG_COLOR = COLOR; RenderFlow.FLAG_OPACITY = OPACITY; RenderFlow.FLAG_UPDATE_RENDER_DATA = UPDATE_RENDER_DATA; RenderFlow.FLAG_RENDER = RENDER; diff --git a/cocos2d/core/renderer/webgl/assemblers/assembler.js b/cocos2d/core/renderer/webgl/assemblers/assembler.js index 5d3942e6812..c8a893e886b 100644 --- a/cocos2d/core/renderer/webgl/assemblers/assembler.js +++ b/cocos2d/core/renderer/webgl/assemblers/assembler.js @@ -24,6 +24,5 @@ ****************************************************************************/ module.exports = { - useModel: false, datas: [] }; \ No newline at end of file diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js index 76946c8a764..66598b2ee9c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js @@ -1,12 +1,36 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 InputAssembler from '../../../../../renderer/core/input-assembler'; +import IARenderData from '../../../../../renderer/render-data/ia-render-data'; const Helper = require('../../../../graphics/helper'); const PointFlags = require('../../../../graphics/types').PointFlags; const MeshBuffer = require('../../mesh-buffer'); const vfmtPosColor = require('../../vertex-format').vfmtPosColor; const renderer = require('../../../index'); -const renderEngine = renderer.renderEngine; -const IARenderData = renderEngine.IARenderData; -const InputAssembler = renderEngine.InputAssembler; let Point = cc.Class({ name: 'cc.GraphicsPoint', diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/index.js b/cocos2d/core/renderer/webgl/assemblers/graphics/index.js index 1d3b65a0adc..489a7cef4e4 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/index.js @@ -63,7 +63,6 @@ function clamp (v, min, max) { } let graphicsAssembler = { - useModel: true, createImpl (graphics) { return new Impl(graphics); }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js index d26c4e6b942..980edcc0a1b 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js @@ -27,11 +27,9 @@ const Sprite = require('../../../../../components/CCSprite'); const FillType = Sprite.FillType; const utils = require('../utils'); -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { - useModel: false, updateRenderData (sprite) { utils.packToDynamicAtlas(sprite); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js index 50d39bf7016..51f50b5974c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js @@ -24,12 +24,9 @@ ****************************************************************************/ const utils = require('../utils'); -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { - useModel: false, - createData (sprite) { return sprite.requestRenderData(); }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js index f72f229302f..be12b7abcaf 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js @@ -25,7 +25,6 @@ const utils = require('../utils'); -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); const fillVertices = require('../../utils').fillVertices; const PI_2 = Math.PI * 2; @@ -213,8 +212,6 @@ function _generateUV (progressX, progressY, data, offset) { } module.exports = { - useModel: false, - createData (sprite) { return sprite.requestRenderData(); }, diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js index 94b7e094c7b..a56ccc80c46 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js @@ -24,11 +24,7 @@ ****************************************************************************/ const utils = require('../utils'); -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); - module.exports = { - useModel: false, - updateRenderData (sprite) { utils.packToDynamicAtlas(sprite); diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js index 4c988a1861b..71d2621f598 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js @@ -24,11 +24,8 @@ ****************************************************************************/ const utils = require('../utils'); -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { - useModel: false, - createData (sprite) { let renderData = sprite.requestRenderData(); // 0-4 for local verts diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js index 5a1aefdf465..ab156f98e0f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js @@ -24,11 +24,8 @@ ****************************************************************************/ const utils = require('../utils'); -const dynamicAtlasManager = require('../../../../utils/dynamic-atlas/manager'); module.exports = { - useModel: false, - vertexOffset: 5, uvOffset: 2, colorOffset: 4, diff --git a/cocos2d/core/renderer/webgl/mesh-buffer.js b/cocos2d/core/renderer/webgl/mesh-buffer.js index 0d49d4bc915..c68d2691205 100644 --- a/cocos2d/core/renderer/webgl/mesh-buffer.js +++ b/cocos2d/core/renderer/webgl/mesh-buffer.js @@ -1,5 +1,29 @@ -const renderEngine = require('../render-engine'); -const gfx = renderEngine.gfx; +/**************************************************************************** + Copyright (c) 2017-2018 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 gfx from '../../../renderer/gfx'; let MeshBuffer = cc.Class({ name: 'cc.MeshBuffer', diff --git a/cocos2d/core/renderer/webgl/model-batcher.js b/cocos2d/core/renderer/webgl/model-batcher.js index 7acc6fea986..1f809f63ee7 100644 --- a/cocos2d/core/renderer/webgl/model-batcher.js +++ b/cocos2d/core/renderer/webgl/model-batcher.js @@ -23,23 +23,23 @@ THE SOFTWARE. ****************************************************************************/ -const renderEngine = require('../render-engine'); const vertexFormat = require('./vertex-format'); const defaultVertexFormat = vertexFormat.vfmtPosUvColor; const vfmt3D = vertexFormat.vfmt3D; const StencilManager = require('./stencil-manager'); const QuadBuffer = require('./quad-buffer'); const MeshBuffer = require('./mesh-buffer'); +const Material = require('../../assets/material/CCMaterial'); let idGenerater = new (require('../../platform/id-generater'))('VertextFormat'); -const RecyclePool = renderEngine.RecyclePool; -const InputAssembler = renderEngine.InputAssembler; +import InputAssembler from '../../../renderer/core/input-assembler'; +import RecyclePool from '../../../renderer/memop/recycle-pool'; +import Model from '../../../renderer/scene/model'; let _buffers = {}; -const empty_material = new renderEngine.Material(); -empty_material.updateHash(); +const empty_material = new Material(); var ModelBatcher = function (device, renderScene) { this._renderScene = renderScene; @@ -55,7 +55,7 @@ var ModelBatcher = function (device, renderScene) { }, 16); this._modelPool = new RecyclePool(function () { - return new renderEngine.Model(); + return new Model(); }, 16); // buffers @@ -74,6 +74,8 @@ var ModelBatcher = function (device, renderScene) { this.parentOpacity = 1; this.parentOpacityDirty = 0; this.worldMatDirty = 0; + + this.customProperties = null; }; ModelBatcher.prototype = { @@ -88,8 +90,8 @@ ModelBatcher.prototype = { let models = this._batchedModels; for (let i = 0; i < models.length; ++i) { // remove from scene - models[i].clearInputAssemblers(); - models[i].clearEffects(); + models[i].setInputAssembler(null); + models[i].setEffect(null); scene.removeModel(models[i]); } this._modelPool.reset(); @@ -112,6 +114,8 @@ ModelBatcher.prototype = { // reset stencil manager's cache this._stencilMgr.reset(); + + this.customProperties = null; }, _flush () { @@ -125,6 +129,7 @@ ModelBatcher.prototype = { } let effect = material.effect; + if (!effect) return; // Generate ia let ia = this._iaPool.add(); @@ -142,8 +147,8 @@ ModelBatcher.prototype = { model.sortKey = this._sortKey++; model._cullingMask = this.cullingMask; model.setNode(this.node); - model.addEffect(effect); - model.addInputAssembler(ia); + model.setEffect(effect, this.customProperties); + model.setInputAssembler(ia); this._renderScene.addModel(model); @@ -160,9 +165,11 @@ ModelBatcher.prototype = { } this.material = material; + let effect = material.effect; + if (!effect) return; // Check stencil state and modify pass - let effect = this._stencilMgr.handleEffect(material.effect); + effect = this._stencilMgr.handleEffect(effect); // Generate model let model = this._modelPool.add(); @@ -170,19 +177,19 @@ ModelBatcher.prototype = { model.sortKey = this._sortKey++; model._cullingMask = this.cullingMask; model.setNode(this.node); - model.addEffect(effect); - model.addInputAssembler(iaRenderData.ia); + model.setEffect(effect, this.customProperties); + model.setInputAssembler(iaRenderData.ia); this._renderScene.addModel(model); }, _commitComp (comp, assembler, cullingMask) { let material = comp.sharedMaterials[0]; - if ((material && material._hash !== this.material._hash) || + if ((material && material.getHash() !== this.material.getHash()) || this.cullingMask !== cullingMask) { this._flush(); - this.node = assembler.useModel ? comp.node : this._dummyNode; + this.node = material.getDefine('_USE_MODEL') ? comp.node : this._dummyNode; this.material = material; this.cullingMask = cullingMask; } @@ -194,7 +201,7 @@ ModelBatcher.prototype = { this._flush(); this.cullingMask = cullingMask; this.material = comp.sharedMaterials[0] || empty_material; - this.node = assembler.useModel ? comp.node : this._dummyNode; + this.node = this.material.getDefine('_USE_MODEL') ? comp.node : this._dummyNode; assembler.renderIA(comp, this); }, diff --git a/cocos2d/core/renderer/webgl/quad-buffer.js b/cocos2d/core/renderer/webgl/quad-buffer.js index b5835f8f6c2..36600834c81 100644 --- a/cocos2d/core/renderer/webgl/quad-buffer.js +++ b/cocos2d/core/renderer/webgl/quad-buffer.js @@ -1,3 +1,28 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 MeshBuffer = require('./mesh-buffer'); let QuadBuffer = cc.Class({ diff --git a/cocos2d/core/renderer/webgl/stencil-manager.js b/cocos2d/core/renderer/webgl/stencil-manager.js index 6b2af07086c..b464ba78ddc 100644 --- a/cocos2d/core/renderer/webgl/stencil-manager.js +++ b/cocos2d/core/renderer/webgl/stencil-manager.js @@ -23,8 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -const renderEngine = require('../render-engine'); -const gfx = renderEngine.gfx; +import gfx from '../../../renderer/gfx'; // Stage types var Stage = cc.Enum({ @@ -59,13 +58,13 @@ StencilManager.prototype = { }, handleEffect (effect) { - let technique = effect.getTechnique('transparent'); + let technique = effect.getDefaultTechnique(); let passes = technique.passes; if (this.stage === Stage.DISABLED) { for (let i = 0; i < passes.length; ++i) { let pass = passes[i]; if (pass._stencilTest) { - pass.disableStencilTest(); + pass._stencilTest = false; } } return effect; @@ -105,8 +104,8 @@ StencilManager.prototype = { for (let i = 0; i < passes.length; ++i) { let pass = passes[i]; - pass.setStencilFront(func, ref, stencilMask, failOp, zFailOp, zPassOp, writeMask); - pass.setStencilBack(func, ref, stencilMask, failOp, zFailOp, zPassOp, writeMask); + pass.setStencilFront(true, func, ref, stencilMask, failOp, zFailOp, zPassOp, writeMask); + pass.setStencilBack(true, func, ref, stencilMask, failOp, zFailOp, zPassOp, writeMask); } return effect; }, diff --git a/cocos2d/core/renderer/webgl/vertex-format.js b/cocos2d/core/renderer/webgl/vertex-format.js index 94351122408..bc26bccc255 100644 --- a/cocos2d/core/renderer/webgl/vertex-format.js +++ b/cocos2d/core/renderer/webgl/vertex-format.js @@ -23,8 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -const renderEngine = require('../render-engine'); -const gfx = renderEngine.gfx; +import gfx from '../../../renderer/gfx'; var vfmt3D = new gfx.VertexFormat([ { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 3 }, diff --git a/cocos2d/core/utils/math-pools.js b/cocos2d/core/utils/math-pools.js index a65a2d0d851..9cf7021e3b0 100644 --- a/cocos2d/core/utils/math-pools.js +++ b/cocos2d/core/utils/math-pools.js @@ -24,20 +24,20 @@ ****************************************************************************/ const js = require('../platform/js'); -const renderEngine = require('../renderer/render-engine'); // const Vec2 = require('../value-types/vec2'); // const Vec3 = require('../value-types/vec3'); // const Quat = require('../value-types/quat'); -const math = renderEngine.math; + +import { mat4, quat } from '../vmath'; var mat4Pool = new js.Pool(128); mat4Pool.get = function () { var matrix = this._get(); if (matrix) { - math.mat4.identity(matrix); + mat4.identity(matrix); } else { - matrix = math.mat4.create(); + matrix = mat4.create(); } return matrix; }; @@ -68,15 +68,15 @@ mat4Pool.get = function () { var quatPool = new js.Pool(64); quatPool.get = function () { - var quat = this._get(); - if (quat) { - quat.x = quat.y = quat.z = 0; - quat.w = 1; + var q = this._get(); + if (q) { + q.x = q.y = q.z = 0; + q.w = 1; } else { - quat = math.quat.create(); + q = quat.create(); } - return quat; + return q; }; module.exports = { diff --git a/cocos2d/core/utils/prefab-helper.js b/cocos2d/core/utils/prefab-helper.js index 075e2e23365..3a03bf2b788 100644 --- a/cocos2d/core/utils/prefab-helper.js +++ b/cocos2d/core/utils/prefab-helper.js @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -var math = require("../renderer").renderEngine.math; +import { quat } from '../vmath'; cc._PrefabInfo = cc.Class({ name: 'cc.PrefabInfo', @@ -124,7 +124,7 @@ module.exports = { node._active = _active; node._position.x = x; node._position.y = y; - math.quat.copy(node._quat, _quat); + quat.copy(node._quat, _quat); node._localZOrder = _localZOrder; node._globalZOrder = _globalZOrder; } diff --git a/cocos2d/core/value-types/index.js b/cocos2d/core/value-types/index.js index 3b5ae993366..edcc79a8d1e 100644 --- a/cocos2d/core/value-types/index.js +++ b/cocos2d/core/value-types/index.js @@ -26,11 +26,12 @@ require('./value-type'); -cc.vmath = require('../renderer/render-engine').math; +cc.vmath = require('../vmath').default; module.exports = { Vec2: require('./vec2'), Vec3: require('./vec3'), + Vec4: require('./vec4'), Quat: require('./quat'), Mat4: require('./mat4'), Size: require('./size'), diff --git a/cocos2d/core/value-types/mat4.js b/cocos2d/core/value-types/mat4.js index 2e4e7d940de..c458363024b 100644 --- a/cocos2d/core/value-types/mat4.js +++ b/cocos2d/core/value-types/mat4.js @@ -26,8 +26,8 @@ const ValueType = require('./value-type'); const js = require('../platform/js'); const CCClass = require('../platform/CCClass'); -const math = require('../renderer/render-engine').math; -const mat4 = math.mat4; + +import { mat4 } from '../vmath'; /** * !#en Representation of 4*4 matrix. diff --git a/cocos2d/core/value-types/quat.js b/cocos2d/core/value-types/quat.js index aeeca3b04d2..dd5b858d0a4 100644 --- a/cocos2d/core/value-types/quat.js +++ b/cocos2d/core/value-types/quat.js @@ -26,6 +26,7 @@ const ValueType = require('./value-type'); const js = require('../platform/js'); const CCClass = require('../platform/CCClass'); +const quat = require('../vmath/quat'); /** * !#en Representation of 2D vectors and points. @@ -123,7 +124,7 @@ proto.equals = function (other) { * @return {Vec3} */ proto.toEuler = function (out) { - cc.vmath.quat.toEuler(out, this); + quat.toEuler(out, this); return out; }; @@ -135,7 +136,7 @@ proto.toEuler = function (out) { * @return {Quat} */ proto.fromEuler = function (euler) { - cc.vmath.quat.fromEuler(this, euler.x, euler.y, euler.z); + quat.fromEuler(this, euler.x, euler.y, euler.z); return this; }; @@ -149,7 +150,21 @@ proto.fromEuler = function (euler) { */ proto.lerp = function (to, ratio, out) { out = out || new cc.Quat(); - cc.vmath.quat.slerp(out, this, to, ratio); + quat.slerp(out, this, to, ratio); + return out; +}; + +/** + * !#en Calculate the multiply result between this quaternion and another one + * !#zh 计算四元数乘积的结果 + * @member lerp + * @param {Quat} to + * @param {Number} ratio + * @param {Quat} out + */ +proto.mul = function (other, out) { + out = out || new cc.Quat(); + quat.mul(out, this, other); return out; }; diff --git a/cocos2d/core/value-types/vec2.js b/cocos2d/core/value-types/vec2.js index 8ba14000d14..caef562c29c 100644 --- a/cocos2d/core/value-types/vec2.js +++ b/cocos2d/core/value-types/vec2.js @@ -24,10 +24,11 @@ THE SOFTWARE. ****************************************************************************/ +import { vec2 } from '../vmath'; + const ValueType = require('./value-type'); const js = require('../platform/js'); const CCClass = require('../platform/CCClass'); -const math = require('../renderer/render-engine').math; const misc = require('../utils/misc'); /** @@ -589,7 +590,7 @@ proto.project = function (vector) { */ proto.transformMat4 = function (m, out) { out = out || new Vec2(); - math.vec2.transformMat4(out, this, m); + vec2.transformMat4(out, this, m); }; //_serialize: function () { diff --git a/cocos2d/core/value-types/vec3.js b/cocos2d/core/value-types/vec3.js index 4bbf3e7694e..a845fcf7122 100644 --- a/cocos2d/core/value-types/vec3.js +++ b/cocos2d/core/value-types/vec3.js @@ -24,10 +24,11 @@ THE SOFTWARE. ****************************************************************************/ +import { vec3 } from '../vmath'; + const ValueType = require('./value-type'); const js = require('../platform/js'); const CCClass = require('../platform/CCClass'); -const math = require('../renderer/render-engine').math; const misc = require('../utils/misc'); /** @@ -157,7 +158,7 @@ proto.toString = function () { */ proto.lerp = function (to, ratio, out) { out = out || new Vec3(); - math.vec3.lerp(out, this, to, ratio); + vec3.lerp(out, this, to, ratio); return out; }; @@ -385,7 +386,7 @@ proto.dot = function (vector) { */ proto.cross = function (vector, out) { out = out || new Vec3(); - math.vec3.cross(out, this, vector) + vec3.cross(out, this, vector) return out; }; @@ -420,7 +421,7 @@ proto.magSqr = function () { * @chainable */ proto.normalizeSelf = function () { - math.vec3.normalize(this, this); + vec3.normalize(this, this); return this; }; @@ -439,7 +440,7 @@ proto.normalizeSelf = function () { */ proto.normalize = function (out) { out = out || new Vec3(); - math.vec3.normalize(out, this); + vec3.normalize(out, this); return out; }; @@ -452,7 +453,7 @@ proto.normalize = function (out) { */ proto.transformMat4 = function (m, out) { out = out || new Vec3(); - math.vec3.transformMat4(out, this, m); + vec3.transformMat4(out, this, m); }; /** diff --git a/cocos2d/core/value-types/vec4.js b/cocos2d/core/value-types/vec4.js new file mode 100644 index 00000000000..b39b4f1d897 --- /dev/null +++ b/cocos2d/core/value-types/vec4.js @@ -0,0 +1,504 @@ +/**************************************************************************** + Copyright (c) 2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://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 ValueType from './value-type'; +import CCClass from '../platform/CCClass'; +import {vec4} from '../vmath'; +import {clampf} from '../utils/misc'; + +/** + * !#en Representation of 3D vectors and points. + * !#zh 表示 3D 向量和坐标 + * + * @class Vec4 + * @extends ValueType + */ +class Vec4 extends ValueType { + /** + * !#en + * Constructor + * see {{#crossLink "cc/vec4:method"}}cc.v4{{/crossLink}} + * !#zh + * 构造函数,可查看 {{#crossLink "cc/vec4:method"}}cc.v4{{/crossLink}} + * @method constructor + * @param {number} [x=0] + * @param {number} [y=0] + * @param {number} [z=0] + * @param {number} [w=0] + */ + constructor (x, y, z, w) { + super(); + if (x && typeof x === 'object') { + w = x.w; + z = x.z; + y = x.y; + x = x.x; + } + /** + * @property {Number} x + */ + this.x = x || 0; + /** + * @property {Number} y + */ + this.y = y || 0; + /** + * @property {Number} z + */ + this.z = z || 0; + /** + * @property {Number} z + */ + this.w = w || 0; + } + + /** + * !#en clone a Vec4 value + * !#zh 克隆一个 Vec4 值 + * @method clone + * @return {Vec4} + */ + clone () { + return new Vec4(this.x, this.y, this.z, this.w); + } + + /** + * !#en Set the current vector value with the given vector. + * !#zh 用另一个向量设置当前的向量对象值。 + * @method set + * @param {Vec4} newValue - !#en new value to set. !#zh 要设置的新值 + * @return {Vec4} returns this + * @chainable + */ + set (newValue) { + this.x = newValue.x; + this.y = newValue.y; + this.z = newValue.z; + this.w = newValue.w; + return this; + } + + /** + * !#en Check whether the vector equals another one + * !#zh 当前的向量是否与指定的向量相等。 + * @method equals + * @param {Vec4} other + * @return {Boolean} + */ + equals (other) { + return other && this.x === other.x && this.y === other.y && this.z === other.z && this.w === other.w; + } + + + /** + * !#en Check whether two vector equal with some degree of variance. + * !#zh + * 近似判断两个点是否相等。
+ * 判断 2 个向量是否在指定数值的范围之内,如果在则返回 true,反之则返回 false。 + * @method fuzzyEquals + * @param {Vec4} other + * @param {Number} variance + * @return {Boolean} + */ + fuzzyEquals (other, variance) { + if (this.x - variance <= other.x && other.x <= this.x + variance) { + if (this.y - variance <= other.y && other.y <= this.y + variance) { + if (this.z - variance <= other.z && other.z <= this.z + variance) { + if (this.w - variance <= other.w && other.w <= this.w + variance) + return true; + } + } + } + return false; + } + + /** + * !#en Transform to string with vector informations + * !#zh 转换为方便阅读的字符串。 + * @method toString + * @return {string} + */ + toString () { + return "(" + + this.x.toFixed(2) + ", " + + this.y.toFixed(2) + ", " + + this.z.toFixed(2) + ", " + + this.w.toFixed(2) + ")"; + } + + /** + * !#en Calculate linear interpolation result between this vector and another one with given ratio + * !#zh 线性插值。 + * @method lerp + * @param {Vec4} to + * @param {number} ratio - the interpolation coefficient + * @param {Vec4} [out] - optional, the receiving vector, you can pass the same vec4 to save result to itself, if not provided, a new vec4 will be created + * @return {Vec4} + */ + lerp (to, ratio, out) { + out = out || new Vec4(); + vec4.lerp(out, this, to, ratio); + return out; + } + + /** + * !#en Clamp the vector between from float and to float. + * !#zh + * 返回指定限制区域后的向量。
+ * 向量大于 max_inclusive 则返回 max_inclusive。
+ * 向量小于 min_inclusive 则返回 min_inclusive。
+ * 否则返回自身。 + * @method clampf + * @param {Vec4} min_inclusive + * @param {Vec4} max_inclusive + * @return {Vec4} + */ + clampf (min_inclusive, max_inclusive) { + this.x = clampf(this.x, min_inclusive.x, max_inclusive.x); + this.y = clampf(this.y, min_inclusive.y, max_inclusive.y); + this.z = clampf(this.z, min_inclusive.z, max_inclusive.z); + this.w = clampf(this.w, min_inclusive.w, max_inclusive.w); + return this; + } + + /** + * !#en Adds this vector. If you want to save result to another vector, use add() instead. + * !#zh 向量加法。如果你想保存结果到另一个向量,使用 add() 代替。 + * @method addSelf + * @param {Vec4} vector + * @return {Vec4} returns this + * @chainable + */ + addSelf (vector) { + this.x += vector.x; + this.y += vector.y; + this.z += vector.z; + this.w += vector.w; + return this; + } + + /** + * !#en Adds two vectors, and returns the new result. + * !#zh 向量加法,并返回新结果。 + * @method add + * @param {Vec4} vector + * @param {Vec4} [out] - optional, the receiving vector, you can pass the same vec4 to save result to itself, if not provided, a new vec4 will be created + * @return {Vec4} the result + */ + add (vector, out) { + out = out || new Vec4(); + out.x = this.x + vector.x; + out.y = this.y + vector.y; + out.z = this.z + vector.z; + out.w = this.w + vector.w; + return out; + } + + /** + * !#en Subtracts one vector from this. If you want to save result to another vector, use sub() instead. + * !#zh 向量减法。如果你想保存结果到另一个向量,可使用 sub() 代替。 + * @method subSelf + * @param {Vec4} vector + * @return {Vec4} returns this + * @chainable + */ + subSelf (vector) { + this.x -= vector.x; + this.y -= vector.y; + this.z -= vector.z; + this.w -= vector.w; + return this; + } + + /** + * !#en Subtracts one vector from this, and returns the new result. + * !#zh 向量减法,并返回新结果。 + * @method sub + * @param {Vec4} vector + * @param {Vec4} [out] - optional, the receiving vector, you can pass the same vec4 to save result to itself, if not provided, a new vec4 will be created + * @return {Vec4} the result + */ + sub (vector, out) { + out = out || new Vec4(); + out.x = this.x - vector.x; + out.y = this.y - vector.y; + out.z = this.z - vector.z; + out.w = this.w - vector.w; + return out; + } + + /** + * !#en Multiplies this by a number. If you want to save result to another vector, use mul() instead. + * !#zh 缩放当前向量。如果你想结果保存到另一个向量,可使用 mul() 代替。 + * @method mulSelf + * @param {number} num + * @return {Vec4} returns this + * @chainable + */ + mulSelf (num) { + this.x *= num; + this.y *= num; + this.z *= num; + this.w *= num; + return this; + } + + /** + * !#en Multiplies by a number, and returns the new result. + * !#zh 缩放向量,并返回新结果。 + * @method mul + * @param {number} num + * @param {Vec4} [out] - optional, the receiving vector, you can pass the same vec4 to save result to itself, if not provided, a new vec4 will be created + * @return {Vec4} the result + */ + mul (num, out) { + out = out || new Vec4(); + out.x = this.x * num; + out.y = this.y * num; + out.z = this.z * num; + out.w = this.w * num; + return out; + } + + /** + * !#en Multiplies two vectors. + * !#zh 分量相乘。 + * @method scaleSelf + * @param {Vec4} vector + * @return {Vec4} returns this + * @chainable + */ + scaleSelf (vector) { + this.x *= vector.x; + this.y *= vector.y; + this.z *= vector.z; + this.w *= vector.w; + return this; + } + + /** + * !#en Multiplies two vectors, and returns the new result. + * !#zh 分量相乘,并返回新的结果。 + * @method scale + * @param {Vec4} vector + * @param {Vec4} [out] - optional, the receiving vector, you can pass the same vec4 to save result to itself, if not provided, a new vec4 will be created + * @return {Vec4} the result + */ + scale (vector, out) { + out = out || new Vec4(); + out.x = this.x * vector.x; + out.y = this.y * vector.y; + out.z = this.z * vector.z; + out.w = this.w * vector.w; + return out; + } + + /** + * !#en Divides by a number. If you want to save result to another vector, use div() instead. + * !#zh 向量除法。如果你想结果保存到另一个向量,可使用 div() 代替。 + * @method divSelf + * @param {Vec4} vector + * @return {Vec4} returns this + * @chainable + */ + divSelf (num) { + this.x /= num; + this.y /= num; + this.z /= num; + this.w /= num; + return this; + } + + /** + * !#en Divides by a number, and returns the new result. + * !#zh 向量除法,并返回新的结果。 + * @method div + * @param {Vec4} vector + * @param {Vec4} [out] - optional, the receiving vector, you can pass the same vec4 to save result to itself, if not provided, a new vec4 will be created + * @return {Vec4} the result + */ + div (num, out) { + out = out || new Vec4(); + out.x = this.x / num; + out.y = this.y / num; + out.z = this.z / num; + out.w = this.w / num; + return out; + } + + /** + * !#en Negates the components. If you want to save result to another vector, use neg() instead. + * !#zh 向量取反。如果你想结果保存到另一个向量,可使用 neg() 代替。 + * @method negSelf + * @return {Vec4} returns this + * @chainable + */ + negSelf () { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + this.w = -this.w; + return this; + } + + /** + * !#en Negates the components, and returns the new result. + * !#zh 返回取反后的新向量。 + * @method neg + * @param {Vec4} [out] - optional, the receiving vector, you can pass the same vec4 to save result to itself, if not provided, a new vec4 will be created + * @return {Vec4} the result + */ + neg (out) { + out = out || new Vec4(); + out.x = -this.x; + out.y = -this.y; + out.z = -this.z; + out.w = -this.w; + return out; + } + + /** + * !#en Dot product + * !#zh 当前向量与指定向量进行点乘。 + * @method dot + * @param {Vec4} [vector] + * @return {number} the result + */ + dot (vector) { + return this.x * vector.x + this.y * vector.y + this.z * vector.z + this.w * vector.w; + } + + /** + * !#en Cross product + * !#zh 当前向量与指定向量进行叉乘。 + * @method cross + * @param {Vec4} vector + * @param {Vec4} [out] + * @return {Vec4} the result + */ + cross (vector, out) { + out = out || new Vec4(); + vec4.cross(out, this, vector); + return out; + } + + /** + * !#en Returns the length of this vector. + * !#zh 返回该向量的长度。 + * @method mag + * @return {number} the result + * @example + * var v = cc.v4(10, 10); + * v.mag(); // return 14.142135623730951; + */ + mag () { + let x = this.x, + y = this.y, + z = this.z, + w = this.w; + return Math.sqrt(x * x + y * y + z * z + w * w); + } + + /** + * !#en Returns the squared length of this vector. + * !#zh 返回该向量的长度平方。 + * @method magSqr + * @return {number} the result + */ + magSqr () { + let x = this.x, + y = this.y, + z = this.z, + w = this.w; + return x * x + y * y + z * z + w * w; + } + + /** + * !#en Make the length of this vector to 1. + * !#zh 向量归一化,让这个向量的长度为 1。 + * @method normalizeSelf + * @return {Vec4} returns this + * @chainable + */ + normalizeSelf () { + vec4.normalize(this, this); + return this; + } + + /** + * !#en + * Returns this vector with a magnitude of 1.
+ *
+ * Note that the current vector is unchanged and a new normalized vector is returned. If you want to normalize the current vector, use normalizeSelf function. + * !#zh + * 返回归一化后的向量。
+ *
+ * 注意,当前向量不变,并返回一个新的归一化向量。如果你想来归一化当前向量,可使用 normalizeSelf 函数。 + * @method normalize + * @param {Vec4} [out] - optional, the receiving vector, you can pass the same vec4 to save result to itself, if not provided, a new vec4 will be created + * @return {Vec4} result + */ + normalize (out) { + out = out || new Vec4(); + vec4.normalize(out, this); + return out; + } + + /** + * Transforms the vec4 with a mat4. 4th vector component is implicitly '1' + * @method transformMat4 + * @param {mat4} m matrix to transform with + * @param {vec4} [out] the receiving vector, you can pass the same vec4 to save result to itself, if not provided, a new vec4 will be created + * @returns {vec4} out + */ + transformMat4 (m, out) { + out = out || new Vec4(); + vec4.transformMat4(out, this, m); + return out; + } +} + +CCClass.fastDefine('cc.Vec4', Vec4, { x: 0, y: 0, z: 0, w: 0 }); + +/** + * !#en The convenience method to create a new {{#crossLink "Vec4"}}cc.Vec4{{/crossLink}}. + * !#zh 通过该简便的函数进行创建 {{#crossLink "Vec4"}}cc.Vec4{{/crossLink}} 对象。 + * @method v4 + * @param {Number|Object} [x=0] + * @param {Number} [y=0] + * @param {Number} [z=0] + * @return {Vec4} + * @example + * var v1 = cc.v4(); + * var v2 = cc.v4(0, 0, 0); + * var v3 = cc.v4(v2); + * var v4 = cc.v4({x: 100, y: 100, z: 0}); + */ +cc.v4 = function v4 (x, y, z, w) { + return new Vec4(x, y, z, w); +}; + +module.exports = cc.Vec4 = Vec4; diff --git a/cocos2d/core/vmath/bits.js b/cocos2d/core/vmath/bits.js new file mode 100644 index 00000000000..c9aa4b49ff1 --- /dev/null +++ b/cocos2d/core/vmath/bits.js @@ -0,0 +1,307 @@ +/** + * Bit twiddling hacks for JavaScript. + * + * Author: Mikola Lysenko + * + * Ported from Stanford bit twiddling hack library: + * http://graphics.stanford.edu/~seander/bithacks.html + */ + +'use strict'; + +// Number of bits in an integer +/** + * @ignore + */ +export const INT_BITS = 32; +/** + * @ignore + */ +export const INT_MAX = 0x7fffffff; +/** + * @ignore + */ +export const INT_MIN = -1<<(INT_BITS-1); + +/** + * Returns -1, 0, +1 depending on sign of x + * + * @param {number} v + * @returns {number} + */ +export function sign(v) { + return (v > 0) - (v < 0); +} + +/** + * Computes absolute value of integer + * + * @param {number} v + * @returns {number} + */ +export function abs(v) { + let mask = v >> (INT_BITS-1); + return (v ^ mask) - mask; +} + +/** + * Computes minimum of integers x and y + * + * @param {number} x + * @param {number} y + * @returns {number} + */ +export function min(x, y) { + return y ^ ((x ^ y) & -(x < y)); +} + +/** + * Computes maximum of integers x and y + * + * @param {number} x + * @param {number} y + * @returns {number} + */ +export function max(x, y) { + return x ^ ((x ^ y) & -(x < y)); +} + +/** + * Checks if a number is a power of two + * + * @param {number} v + * @returns {boolean} + */ +export function isPow2(v) { + return !(v & (v-1)) && (!!v); +} + +/** + * Computes log base 2 of v + * + * @param {number} v + * @returns {number} + */ +export function log2(v) { + let r, shift; + r = (v > 0xFFFF) << 4; v >>>= r; + shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; + shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; + shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; + return r | (v >> 1); +} + +/** + * Computes log base 10 of v + * + * @param {number} v + * @returns {number} + */ +export function log10(v) { + return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : + (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : + (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; +} + +/** + * Counts number of bits + * + * @param {number} v + * @returns {number} + */ +export function popCount(v) { + v = v - ((v >>> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); + return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; +} + +/** + * Counts number of trailing zeros + * + * @param {number} v + * @returns {number} + */ +export function countTrailingZeros(v) { + let c = 32; + v &= -v; + if (v) c--; + if (v & 0x0000FFFF) c -= 16; + if (v & 0x00FF00FF) c -= 8; + if (v & 0x0F0F0F0F) c -= 4; + if (v & 0x33333333) c -= 2; + if (v & 0x55555555) c -= 1; + return c; +} + +/** + * Rounds to next power of 2 + * + * @param {number} v + * @returns {number} + */ +export function nextPow2(v) { + v += v === 0; + --v; + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v + 1; +} + +/** + * Rounds down to previous power of 2 + * + * @param {number} v + * @returns {number} + */ +export function prevPow2(v) { + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v - (v>>>1); +} + +/** + * Computes parity of word + * + * @param {number} v + * @returns {number} + */ +export function parity(v) { + v ^= v >>> 16; + v ^= v >>> 8; + v ^= v >>> 4; + v &= 0xf; + return (0x6996 >>> v) & 1; +} + +/** + * @ignore + */ +const REVERSE_TABLE = new Array(256); + +(function(tab) { + for(let i=0; i<256; ++i) { + let v = i, r = i, s = 7; + for (v >>>= 1; v; v >>>= 1) { + r <<= 1; + r |= v & 1; + --s; + } + tab[i] = (r << s) & 0xff; + } +})(REVERSE_TABLE); + +/** + * Reverse bits in a 32 bit word + * + * @param {number} v + * @returns {number} + */ +export function reverse(v) { + return (REVERSE_TABLE[v & 0xff] << 24) | + (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | + (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | + REVERSE_TABLE[(v >>> 24) & 0xff]; +} + +/** + * Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes + * + * @param {number} x + * @param {number} y + * @returns {number} + */ +export function interleave2(x, y) { + x &= 0xFFFF; + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y &= 0xFFFF; + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +/** + * Extracts the nth interleaved component + * + * @param {number} v + * @param {number} n + * @returns {number} + */ +export function deinterleave2(v, n) { + v = (v >>> n) & 0x55555555; + v = (v | (v >>> 1)) & 0x33333333; + v = (v | (v >>> 2)) & 0x0F0F0F0F; + v = (v | (v >>> 4)) & 0x00FF00FF; + v = (v | (v >>> 16)) & 0x000FFFF; + return (v << 16) >> 16; +} + +/** + * Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes + * + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {number} + */ +export function interleave3(x, y, z) { + x &= 0x3FF; + x = (x | (x<<16)) & 4278190335; + x = (x | (x<<8)) & 251719695; + x = (x | (x<<4)) & 3272356035; + x = (x | (x<<2)) & 1227133513; + + y &= 0x3FF; + y = (y | (y<<16)) & 4278190335; + y = (y | (y<<8)) & 251719695; + y = (y | (y<<4)) & 3272356035; + y = (y | (y<<2)) & 1227133513; + x |= (y << 1); + + z &= 0x3FF; + z = (z | (z<<16)) & 4278190335; + z = (z | (z<<8)) & 251719695; + z = (z | (z<<4)) & 3272356035; + z = (z | (z<<2)) & 1227133513; + + return x | (z << 2); +} + +/** + * Extracts nth interleaved component of a 3-tuple + * + * @param {number} v + * @param {number} n + * @returns {number} + */ +export function deinterleave3(v, n) { + v = (v >>> n) & 1227133513; + v = (v | (v>>>2)) & 3272356035; + v = (v | (v>>>4)) & 251719695; + v = (v | (v>>>8)) & 4278190335; + v = (v | (v>>>16)) & 0x3FF; + return (v<<22)>>22; +} + +/** + * Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) + * + * @param {number} v + * @returns {number} + */ +export function nextCombination(v) { + let t = v | (v - 1); + return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); +} \ No newline at end of file diff --git a/cocos2d/core/vmath/color3.js b/cocos2d/core/vmath/color3.js new file mode 100644 index 00000000000..77ef9d72c01 --- /dev/null +++ b/cocos2d/core/vmath/color3.js @@ -0,0 +1,283 @@ +import { EPSILON } from './utils'; + +/** + * Represents a color with red(r), green(g), blue(b) component of that color. + */ +class color3 { + /** + * Creates a color, with components specified separately. + * + * @param {number} r - Value assigned to r component. + * @param {number} g - Value assigned to g component. + * @param {number} b - Value assigned to b component. + */ + constructor(r = 1, g = 1, b = 1) { + /** + * The r component. + * @type {number} + * */ + this.r = r; + + /** + * The g component. + * @type {number} + * */ + this.g = g; + + /** + * The b component. + * @type {number} + * */ + this.b = b; + } + + /** + * Creates a color, with components specified separately, or a black color if not specified + * + * @param {number} r - Value assigned to r component. + * @param {number} g - Value assigned to g component. + * @param {number} b - Value assigned to b component. + * @return {color3} The newly created color. + */ + static create(r = 1, g = 1, b = 1) { + return new color3(r, g, b); + } + + /** + * Clone a color. + * + * @param {color3} a - Color to clone. + * @returns {color3} The newly created color. + */ + static clone(a) { + return new color3(a.r, a.g, a.b); + } + + /** + * Copy content of a color into another. + * + * @param {color3} out - The color to modified. + * @param {color3} a - The specified color. + * @returns {color3} out. + */ + static copy(out, a) { + out.r = a.r; + out.g = a.g; + out.b = a.b; + return out; + } + + /** + * Set the components of a color to the given values. + * + * @param {color3} out - The color to modified. + * @param {number} r - Value assigned to r component. + * @param {number} g - Value assigned to g component. + * @param {number} b - Value assigned to b component. + * @returns {color3} out. + */ + static set(out, r, g, b) { + out.r = r; + out.g = g; + out.b = b; + return out; + } + + /** + * Converts the hexadecimal formal color into rgb formal. + * + * @param {color3} out - Color to store result. + * @param {Number} hex - The color's hexadecimal formal. + * @returns {color3} out. + * @function + */ + static fromHex(out, hex) { + let r = ((hex >> 16)) / 255.0; + let g = ((hex >> 8) & 0xff) / 255.0; + let b = ((hex) & 0xff) / 255.0; + + out.r = r; + out.g = g; + out.b = b; + return out; + } + + /** + * Add components of two colors, respectively. + * + * @param {color3} out - Color to store result. + * @param {color3} a - The first operand. + * @param {color3} b - The second operand. + * @returns {color3} out. + */ + static add(out, a, b) { + out.r = a.r + b.r; + out.g = a.g + b.g; + out.b = a.b + b.b; + return out; + } + + /** + * Subtract components of color b from components of color a, respectively. + * + * @param {color3} out - Color to store result. + * @param {color3} a - The a. + * @param {color3} b - The b. + * @returns {color3} out. + */ + static subtract(out, a, b) { + out.r = a.r - b.r; + out.g = a.g - b.g; + out.b = a.b - b.b; + return out; + } + + /** + * Alias of {@link color3.subtract}. + */ + static sub(out, a, b) { + return color3.subtract(out, a, b); + } + + /** + * Multiply components of two colors, respectively. + * + * @param {color3} out - Color to store result. + * @param {color3} a - The first operand. + * @param {color3} b - The second operand. + * @returns {color3} out. + */ + static multiply(out, a, b) { + out.r = a.r * b.r; + out.g = a.g * b.g; + out.b = a.b * b.b; + return out; + } + + /** + * Alias of {@link color3.multiply}. + */ + static mul(out, a, b) { + return color3.multiply(out, a, b); + } + + /** + * Divide components of color a by components of color b, respectively. + * + * @param {color3} out - Color to store result. + * @param {color3} a - The first operand. + * @param {color3} b - The second operand. + * @returns {color3} out. + */ + static divide(out, a, b) { + out.r = a.r / b.r; + out.g = a.g / b.g; + out.b = a.b / b.b; + return out; + } + + /** + * Alias of {@link color3.divide}. + */ + static div(out, a, b) { + return color3.divide(out, a, b); + } + + /** + * Scales a color by a number. + * + * @param {color3} out - Color to store result. + * @param {color3} a - Color to scale. + * @param {number} b - The scale number. + * @returns {color3} out. + */ + static scale(out, a, b) { + out.r = a.r * b; + out.g = a.g * b; + out.b = a.b * b; + return out; + } + + /** + * Performs a linear interpolation between two colors. + * + * @param {color3} out - Color to store result. + * @param {color3} a - The first operand. + * @param {color3} b - The second operand. + * @param {Number} t - The interpolation coefficient. + * @returns {color3} out. + */ + static lerp(out, a, b, t) { + let ar = a.r, + ag = a.g, + ab = a.b; + out.r = ar + t * (b.r - ar); + out.g = ag + t * (b.g - ag); + out.b = ab + t * (b.b - ab); + return out; + } + + /** + * Returns string representation of a color. + * + * @param {color3} a - The color. + * @returns {String} - String representation of this color. + */ + static str(a) { + return `color3(${a.r}, ${a.g}, ${a.b})`; + } + + /** + * Store components of a color into array. + * + * @param {Array} out - Array to store result. + * @param {color3} a - The color. + * @returns {Array} out. + */ + static array(out, a) { + let scale = a instanceof cc.Color ? 1 / 255 : 1; + out[0] = a.r * scale; + out[1] = a.g * scale; + out[2] = a.b * scale; + + return out; + } + + /** + * Returns whether the specified colors are equal. (Compared using ===) + * + * @param {color3} a - The first color. + * @param {color3} b - The second color. + * @returns {Boolean} True if the colors are equal, false otherwise. + */ + static exactEquals(a, b) { + return a.r === b.r && a.g === b.g && a.b === b.b; + } + + /** + * Returns whether the specified colors are approximately equal. + * + * @param {color3} a - The first color. + * @param {color3} b - The second color. + * @returns {Boolean} True if the colors are approximately equal, false otherwise. + */ + static equals(a, b) { + let a0 = a.r, a1 = a.g, a2 = a.b; + let b0 = b.r, b1 = b.g, b2 = b.b; + return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); + } + + /** + * Converts a color's rgb formal into the hexadecimal one. + * + * @param {color3} a - The color. + * @returns {Number} - The color's hexadecimal formal. + */ + static hex(a) { + return (a.r * 255) << 16 | (a.g * 255) << 8 | (a.b * 255); + } +} + +export default color3; \ No newline at end of file diff --git a/cocos2d/core/vmath/color4.js b/cocos2d/core/vmath/color4.js new file mode 100644 index 00000000000..975af8cf3b2 --- /dev/null +++ b/cocos2d/core/vmath/color4.js @@ -0,0 +1,306 @@ +import { EPSILON } from './utils'; + +/** + * Represents a color with red(r), green(g), blue(b) component of that color and + * and an extra alpha(a) component indicating how opaque this color is. + */ +class color4 { + /** + * Creates a color, with components specified separately. + * + * @param {number} r - Value assigned to r component. + * @param {number} g - Value assigned to g component. + * @param {number} b - Value assigned to b component. + * @param {number} a - Value assigned to a component. + */ + constructor(r = 1, g = 1, b = 1, a = 1) { + /** + * The r component. + * @type {number} + * */ + this.r = r; + + /** + * The g component. + * @type {number} + * */ + this.g = g; + + /** + * The b component. + * @type {number} + * */ + this.b = b; + + /** + * The a component. + * @type {number} + * */ + this.a = a; + } + + /** + * Creates a white color, or components specified separately. + * + * @param {number} r - Value assigned to r component. + * @param {number} g - Value assigned to g component. + * @param {number} b - Value assigned to b component. + * @param {number} a - Value assigned to a component. + * @return {color4} The newly created color. + */ + static create(r = 1, g = 1, b = 1, a = 1) { + return new color4(r, g, b, a); + } + + /** + * Clone a color. + * + * @param {color4} a - Color to clone. + * @returns {color4} The newly created color. + */ + static clone(a) { + return new color4(a.r, a.g, a.b, a.a); + } + + /** + * Copy content of a color into another. + * + * @param {color4} out - The color to modified. + * @param {color4} a - The specified color. + * @returns {color4} out. + */ + static copy(out, a) { + out.r = a.r; + out.g = a.g; + out.b = a.b; + out.a = a.a; + return out; + } + + /** + * Set the components of a color to the given values. + * + * @param {color4} out - The color to modified. + * @param {number} r - Value assigned to r component. + * @param {number} g - Value assigned to g component. + * @param {number} b - Value assigned to b component. + * @param {number} a - Value assigned to a component. + * @returns {color4} out. + */ + static set(out, r, g, b, a) { + out.r = r; + out.g = g; + out.b = b; + out.a = a; + return out; + } + + /** + * Converts the hexadecimal formal color into rgb formal. + * + * @param {color4} out - Color to store result. + * @param {Number} hex - The color's hexadecimal formal. + * @returns {color4} out. + * @function + */ + static fromHex(out, hex) { + let r = ((hex >> 24)) / 255.0; + let g = ((hex >> 16) & 0xff) / 255.0; + let b = ((hex >> 8) & 0xff) / 255.0; + let a = ((hex) & 0xff) / 255.0; + + out.r = r; + out.g = g; + out.b = b; + out.a = a; + return out; + } + + /** + * Add components of two colors, respectively. + * + * @param {color4} out - Color to store result. + * @param {color4} a - The first operand. + * @param {color4} b - The second operand. + * @returns {color4} out. + */ + static add(out, a, b) { + out.r = a.r + b.r; + out.g = a.g + b.g; + out.b = a.b + b.b; + out.a = a.a + b.a; + return out; + } + + /** + * Subtract components of color b from components of color a, respectively. + * + * @param {color4} out - Color to store result. + * @param {color4} a - The a. + * @param {color4} b - The b. + * @returns {color4} out. + */ + static subtract(out, a, b) { + out.r = a.r - b.r; + out.g = a.g - b.g; + out.b = a.b - b.b; + out.a = a.a - b.a; + return out; + } + + /** + * Alias of {@link color4.subtract}. + */ + static sub(out, a, b) { + return color4.subtract(out, a, b); + } + + /** + * Multiply components of two colors, respectively. + * + * @param {color4} out - Color to store result. + * @param {color4} a - The first operand. + * @param {color4} b - The second operand. + * @returns {color4} out. + */ + static multiply(out, a, b) { + out.r = a.r * b.r; + out.g = a.g * b.g; + out.b = a.b * b.b; + out.a = a.a * b.a; + return out; + } + + /** + * Alias of {@link color4.multiply}. + */ + static mul(out, a, b) { + return color4.multiply(out, a, b); + } + + /** + * Divide components of color a by components of color b, respectively. + * + * @param {color4} out - Color to store result. + * @param {color4} a - The first operand. + * @param {color4} b - The second operand. + * @returns {color4} out. + */ + static divide(out, a, b) { + out.r = a.r / b.r; + out.g = a.g / b.g; + out.b = a.b / b.b; + out.a = a.a / b.a; + return out; + } + + /** + * Alias of {@link color4.divide}. + */ + static div(out, a, b) { + return color4.divide(out, a, b); + } + + /** + * Scales a color by a number. + * + * @param {color4} out - Color to store result. + * @param {color4} a - Color to scale. + * @param {number} b - The scale number. + * @returns {color4} out. + */ + static scale(out, a, b) { + out.r = a.r * b; + out.g = a.g * b; + out.b = a.b * b; + out.a = a.a * b; + return out; + } + + /** + * Performs a linear interpolation between two colors. + * + * @param {color4} out - Color to store result. + * @param {color4} a - The first operand. + * @param {color4} b - The second operand. + * @param {Number} t - The interpolation coefficient. + * @returns {color4} out. + */ + static lerp(out, a, b, t) { + let ar = a.r, + ag = a.g, + ab = a.b, + aa = a.a; + out.r = ar + t * (b.r - ar); + out.g = ag + t * (b.g - ag); + out.b = ab + t * (b.b - ab); + out.a = aa + t * (b.a - aa); + return out; + } + + /** + * Returns string representation of a color. + * + * @param {color4} a - The color. + * @returns {String} - String representation of this color. + */ + static str(a) { + return `color4(${a.r}, ${a.g}, ${a.b}, ${a.a})`; + } + + /** + * Store components of a color into array. + * + * @param {Array} out - Array to store result. + * @param {color4} a - The color. + * @returns {Array} out. + */ + static array(out, a) { + let scale = (a instanceof cc.Color || a.a > 1) ? 1 / 255 : 1; + out[0] = a.r * scale; + out[1] = a.g * scale; + out[2] = a.b * scale; + out[3] = a.a * scale; + + return out; + } + + /** + * Returns whether the specified colors are equal. (Compared using ===) + * + * @param {color4} a - The first color. + * @param {color4} b - The second color. + * @returns {Boolean} True if the colors are equal, false otherwise. + */ + static exactEquals(a, b) { + return a.r === b.r && a.g === b.g && a.b === b.b && a.a === b.a; + } + + /** + * Returns whether the specified colors are approximately equal. + * + * @param {color4} a - The first color. + * @param {color4} b - The second color. + * @returns {Boolean} True if the colors are approximately equal, false otherwise. + */ + static equals(a, b) { + let a0 = a.r, a1 = a.g, a2 = a.b, a3 = a.a; + let b0 = b.r, b1 = b.g, b2 = b.b, b3 = b.a; + return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && + Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); + } + + /** + * Converts a color's rgb formal into the hexadecimal one. + * + * @param {color4} a - The color. + * @returns {Number} - The color's hexadecimal formal. + */ + static hex(a) { + return ((a.r * 255) << 24 | (a.g * 255) << 16 | (a.b * 255) << 8 | a.a * 255) >>> 0; + } +} + +export default color4; \ No newline at end of file diff --git a/cocos2d/core/vmath/index.js b/cocos2d/core/vmath/index.js new file mode 100644 index 00000000000..2d129c25026 --- /dev/null +++ b/cocos2d/core/vmath/index.js @@ -0,0 +1,22 @@ +export * from './utils'; + +// NOTE: there is no syntax for: export {* as bits} from './lib/bits'; +import * as bits_ from './bits'; +/** + * Export module bits. + */ +export let bits = bits_; + +import vec2 from './vec2'; +import vec3 from './vec3'; +import vec4 from './vec4'; +import quat from './quat'; +import mat2 from './mat2'; +import mat23 from './mat23'; +import mat3 from './mat3'; +import mat4 from './mat4'; +import color3 from './color3'; +import color4 from './color4'; + +export { vec2, vec3, vec4, quat, mat2, mat23, mat3, mat4, color3, color4 }; +export default { vec2, vec3, vec4, quat, mat2, mat23, mat3, mat4, color3, color4 }; diff --git a/cocos2d/core/vmath/mat2.js b/cocos2d/core/vmath/mat2.js new file mode 100644 index 00000000000..2466c532686 --- /dev/null +++ b/cocos2d/core/vmath/mat2.js @@ -0,0 +1,443 @@ +import { EPSILON } from './utils'; + +/** + * Mathematical 2x2 matrix. + */ +class mat2 { + /** + * Creates a matrix, with elements specified separately. + * + * @param {Number} m00 - Value assigned to element at column 0 row 0. + * @param {Number} m01 - Value assigned to element at column 0 row 1. + * @param {Number} m02 - Value assigned to element at column 1 row 0. + * @param {Number} m03 - Value assigned to element at column 1 row 1. + */ + constructor(m00 = 1, m01 = 0, m02 = 0, m03 = 1) { + /** + * The element at column 0 row 0. + * @type {number} + * */ + this.m00 = m00; + + /** + * The element at column 0 row 1. + * @type {number} + * */ + this.m01 = m01; + + /** + * The element at column 1 row 0. + * @type {number} + * */ + this.m02 = m02; + + /** + * The element at column 1 row 1. + * @type {number} + * */ + this.m03 = m03; + } + + /** + * Creates a matrix, with elements specified separately. + * + * @param {Number} m00 - Value assigned to element at column 0 row 0. + * @param {Number} m01 - Value assigned to element at column 0 row 1. + * @param {Number} m02 - Value assigned to element at column 1 row 0. + * @param {Number} m03 - Value assigned to element at column 1 row 1. + * @returns {mat2} The newly created matrix. + */ + static create(m00 = 1, m01 = 0, m02 = 0, m03 = 1) { + return new mat2(m00, m01, m02, m03); + } + + /** + * Clone a matrix. + * + * @param {mat2} a - Matrix to clone. + * @returns {mat2} The newly created matrix. + */ + static clone(a) { + return new mat2(a.m00, a.m01, a.m02, a.m03); + } + + /** + * Copy content of a matrix into another. + * + * @param {mat2} out - Matrix to modified. + * @param {mat2} a - The specified matrix. + * @returns {mat2} out. + */ + static copy(out, a) { + out.m00 = a.m00; + out.m01 = a.m01; + out.m02 = a.m02; + out.m03 = a.m03; + return out; + } + + /** + * Sets a matrix as identity matrix. + * + * @param {mat2} out - Matrix to modified. + * @returns {mat2} out. + */ + static identity(out) { + out.m00 = 1; + out.m01 = 0; + out.m02 = 0; + out.m03 = 1; + return out; + } + + /** + * Sets the elements of a matrix to the given values. + * + * @param {mat2} out - The matrix to modified. + * @param {Number} m00 - Value assigned to element at column 0 row 0. + * @param {Number} m01 - Value assigned to element at column 0 row 1. + * @param {Number} m10 - Value assigned to element at column 1 row 0. + * @param {Number} m11 - Value assigned to element at column 1 row 1. + * @returns {mat2} out. + */ + static set(out, m00, m01, m10, m11) { + out.m00 = m00; + out.m01 = m01; + out.m02 = m10; + out.m03 = m11; + return out; + } + + + /** + * Transposes a matrix. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - Matrix to transpose. + * @returns {mat2} out. + */ + static transpose(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + let a1 = a.m01; + out.m01 = a.m02; + out.m02 = a1; + } else { + out.m00 = a.m00; + out.m01 = a.m02; + out.m02 = a.m01; + out.m03 = a.m03; + } + + return out; + } + + /** + * Inverts a matrix. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - Matrix to invert. + * @returns {mat2} out. + */ + static invert(out, a) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; + + // Calculate the determinant + let det = a0 * a3 - a2 * a1; + + if (!det) { + return null; + } + det = 1.0 / det; + + out.m00 = a3 * det; + out.m01 = -a1 * det; + out.m02 = -a2 * det; + out.m03 = a0 * det; + + return out; + } + + /** + * Calculates the adjugate of a matrix. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - Matrix to calculate. + * @returns {mat2} out. + */ + static adjoint(out, a) { + // Caching this value is nessecary if out == a + let a0 = a.m00; + out.m00 = a.m03; + out.m01 = -a.m01; + out.m02 = -a.m02; + out.m03 = a0; + + return out; + } + + /** + * Calculates the determinant of a matrix. + * + * @param {mat2} a - Matrix to calculate. + * @returns {Number} Determinant of a. + */ + static determinant(a) { + return a.m00 * a.m03 - a.m02 * a.m01; + } + + /** + * Multiply two matrices explicitly. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - The first operand. + * @param {mat2} b - The second operand. + * @returns {mat2} out. + */ + static multiply(out, a, b) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; + let b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; + out.m00 = a0 * b0 + a2 * b1; + out.m01 = a1 * b0 + a3 * b1; + out.m02 = a0 * b2 + a2 * b3; + out.m03 = a1 * b2 + a3 * b3; + return out; + } + + /** + * Alias of {@link mat2.multiply}. + */ + static mul(out, a, b) { + return mat2.multiply(out, a, b); + } + + /** + * Rotates a matrix by the given angle. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - Matrix to rotate. + * @param {Number} rad - The rotation angle. + * @returns {mat2} out + */ + static rotate(out, a, rad) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, + s = Math.sin(rad), + c = Math.cos(rad); + out.m00 = a0 * c + a2 * s; + out.m01 = a1 * c + a3 * s; + out.m02 = a0 * -s + a2 * c; + out.m03 = a1 * -s + a3 * c; + return out; + } + + /** + * Scales the matrix given by a scale vector. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - Matrix to scale. + * @param {vec2} v - The scale vector. + * @returns {mat2} out + **/ + static scale(out, a, v) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, + v0 = v.x, v1 = v.y; + out.m00 = a0 * v0; + out.m01 = a1 * v0; + out.m02 = a2 * v1; + out.m03 = a3 * v1; + return out; + } + + /** + * Creates a matrix from a given angle. + * This is equivalent to (but much faster than): + * + * mat2.set(dest, 1, 0, 0, 1); + * mat2.rotate(dest, dest, rad); + * + * @param {mat2} out - Matrix to store result. + * @param {Number} rad - The rotation angle. + * @returns {mat2} out. + */ + static fromRotation(out, rad) { + let s = Math.sin(rad), + c = Math.cos(rad); + out.m00 = c; + out.m01 = s; + out.m02 = -s; + out.m03 = c; + return out; + } + + /** + * Creates a matrix from a scale vector. + * This is equivalent to (but much faster than): + * + * mat2.set(dest, 1, 0, 0, 1); + * mat2.scale(dest, dest, vec); + * + * @param {mat2} out - Matrix to store result. + * @param {vec2} v - Scale vector. + * @returns {mat2} out. + */ + static fromScaling(out, v) { + out.m00 = v.x; + out.m01 = 0; + out.m02 = 0; + out.m03 = v.y; + return out; + } + + /** + * Returns a string representation of a matrix. + * + * @param {mat2} a - The matrix. + * @returns {String} String representation of this matrix. + */ + static str(a) { + return `mat2(${a.m00}, ${a.m01}, ${a.m02}, ${a.m03})`; + } + + /** + * Store elements of a matrix into array. + * + * @param {array} out - Array to store result. + * @param {mat2} m - The matrix. + * @returns {Array} out. + */ + static array(out, m) { + out[0] = m.m00; + out[1] = m.m01; + out[2] = m.m02; + out[3] = m.m03; + + return out; + } + + /** + * Returns Frobenius norm of a matrix. + * + * @param {mat2} a - Matrix to calculate Frobenius norm of. + * @returns {Number} - The frobenius norm. + */ + static frob(a) { + return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2))); + } + + /** + * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix. + * @param {mat2} L - The lower triangular matrix. + * @param {mat2} D - The diagonal matrix. + * @param {mat2} U - The upper triangular matrix. + * @param {mat2} a - The input matrix to factorize. + */ + static LDU(L, D, U, a) { + L.m02 = a.m02 / a.m00; + U.m00 = a.m00; + U.m01 = a.m01; + U.m03 = a.m03 - L.m02 * U.m01; + } + + /** + * Adds two matrices. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - The first operand. + * @param {mat2} b - The second operand. + * @returns {mat2} out. + */ + static add(out, a, b) { + out.m00 = a.m00 + b.m00; + out.m01 = a.m01 + b.m01; + out.m02 = a.m02 + b.m02; + out.m03 = a.m03 + b.m03; + return out; + } + + /** + * Subtracts matrix b from matrix a. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - The first operand. + * @param {mat2} b - The second operand. + * @returns {mat2} out. + */ + static subtract(out, a, b) { + out.m00 = a.m00 - b.m00; + out.m01 = a.m01 - b.m01; + out.m02 = a.m02 - b.m02; + out.m03 = a.m03 - b.m03; + return out; + } + + /** + * Alias of {@link mat2.subtract}. + */ + static sub(out, a, b) { + return mat2.subtract(out, a, b); + } + + /** + * Returns whether the specified matrices are equal. (Compared using ===) + * + * @param {mat2} a - The first matrix. + * @param {mat2} b - The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ + static exactEquals(a, b) { + return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03; + } + + /** + * Returns whether the specified matrices are approximately equal. + * + * @param {mat2} a - The first matrix. + * @param {mat2} b - The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ + static equals(a, b) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; + let b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; + return ( + Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && + Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) + ); + } + + /** + * Multiply each element of a matrix by a scalar number. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - Matrix to scale + * @param {Number} b - The scale number. + * @returns {mat2} out. + */ + static multiplyScalar(out, a, b) { + out.m00 = a.m00 * b; + out.m01 = a.m01 * b; + out.m02 = a.m02 * b; + out.m03 = a.m03 * b; + return out; + } + + /** + * Adds two matrices after multiplying each element of the second operand by a scalar number. + * + * @param {mat2} out - Matrix to store result. + * @param {mat2} a - The first operand. + * @param {mat2} b - The second operand. + * @param {Number} scale - The scale number. + * @returns {mat2} out. + */ + static multiplyScalarAndAdd(out, a, b, scale) { + out.m00 = a.m00 + (b.m00 * scale); + out.m01 = a.m01 + (b.m01 * scale); + out.m02 = a.m02 + (b.m02 * scale); + out.m03 = a.m03 + (b.m03 * scale); + return out; + } +} + +export default mat2; \ No newline at end of file diff --git a/cocos2d/core/vmath/mat23.js b/cocos2d/core/vmath/mat23.js new file mode 100644 index 00000000000..4c89ec8a8f1 --- /dev/null +++ b/cocos2d/core/vmath/mat23.js @@ -0,0 +1,547 @@ +import { EPSILON } from './utils'; + +/** + * Mathematical 2x3 matrix. + * + * A mat23 contains six elements defined as: + *
+ * [a, c, tx,
+ *  b, d, ty]
+ * 
+ * This is a short form for the 3x3 matrix: + *
+ * [a, c, tx,
+ *  b, d, ty,
+ *  0, 0, 1]
+ * 
+ * The last row is ignored so the array is shorter and operations are faster. + */ +class mat23 { + /** + * Creates a matrix, with elements specified separately. + * + * @param {Number} m00 - Value assigned to element a. + * @param {Number} m01 - Value assigned to element b. + * @param {Number} m02 - Value assigned to element c. + * @param {Number} m03 - Value assigned to element d. + * @param {Number} m04 - Value assigned to element tx. + * @param {Number} m05 - Value assigned to element ty. + */ + constructor(m00 = 1, m01 = 0, m02 = 0, m03 = 1, m04 = 0, m05 = 0) { + /** + * The element a. + * @type {number} + * */ + this.m00 = m00; + + /** + * The element b. + * @type {number} + * */ + this.m01 = m01; + + /** + * The element c. + * @type {number} + * */ + this.m02 = m02; + + /** + * The element d. + * @type {number} + * */ + this.m03 = m03; + + /** + * The element tx. + * @type {number} + * */ + this.m04 = m04; + + /** + * The element ty. + * @type {number} + * */ + this.m05 = m05; + } + + /** + * Creates a matrix, with elements specified separately. + * + * @param {Number} m00 - Value assigned to element a. + * @param {Number} m01 - Value assigned to element b. + * @param {Number} m02 - Value assigned to element c. + * @param {Number} m03 - Value assigned to element d. + * @param {Number} m04 - Value assigned to element tx. + * @param {Number} m05 - Value assigned to element ty. + * @returns {mat23} The newly created matrix. + */ + static create(m00 = 1, m01 = 0, m02 = 0, m03 = 1, m04 = 0, m05 = 0) { + return new mat23(m00, m01, m02, m03, m04, m05); + } + + /** + * Clone a matrix. + * + * @param {mat23} a - Matrix to clone. + * @returns {mat23} The newly created matrix. + */ + static clone(a) { + return new mat23( + a.m00, a.m01, + a.m02, a.m03, + a.m04, a.m05 + ); + } + + /** + * Copy content of a matrix into another. + * + * @param {mat23} out - Matrix to modified. + * @param {mat23} a - The specified matrix. + * @returns {mat23} out. + */ + static copy(out, a) { + out.m00 = a.m00; + out.m01 = a.m01; + out.m02 = a.m02; + out.m03 = a.m03; + out.m04 = a.m04; + out.m05 = a.m05; + return out; + } + + /** + * Sets a matrix as identity matrix. + * + * @param {mat23} out - Matrix to modified. + * @returns {mat23} out. + */ + static identity(out) { + out.m00 = 1; + out.m01 = 0; + out.m02 = 0; + out.m03 = 1; + out.m04 = 0; + out.m05 = 0; + return out; + } + + /** + * Sets the elements of a matrix to the given values. + * + * @param {mat23} out - The matrix to modified. + * @param {Number} a - Value assigned to element a. + * @param {Number} b - Value assigned to element b. + * @param {Number} c - Value assigned to element c. + * @param {Number} d - Value assigned to element d. + * @param {Number} tx - Value assigned to element tx. + * @param {Number} ty - Value assigned to element ty. + * @returns {mat23} out. + */ + static set(out, a, b, c, d, tx, ty) { + out.m00 = a; + out.m01 = b; + out.m02 = c; + out.m03 = d; + out.m04 = tx; + out.m05 = ty; + return out; + } + + /** + * Inverts a matrix. + * + * @param {mat23} out - Matrix to store result. + * @param {mat23} a - Matrix to invert. + * @returns {mat23} out. + */ + static invert(out, a) { + let aa = a.m00, ab = a.m01, ac = a.m02, ad = a.m03, + atx = a.m04, aty = a.m05; + + let det = aa * ad - ab * ac; + if (!det) { + return null; + } + det = 1.0 / det; + + out.m00 = ad * det; + out.m01 = -ab * det; + out.m02 = -ac * det; + out.m03 = aa * det; + out.m04 = (ac * aty - ad * atx) * det; + out.m05 = (ab * atx - aa * aty) * det; + return out; + } + + /** + * Calculates the determinant of a matrix. + * + * @param {mat23} a - Matrix to calculate. + * @returns {Number} Determinant of a. + */ + static determinant(a) { + return a.m00 * a.m03 - a.m01 * a.m02; + } + + /** + * Multiply two matrices explicitly. + * + * @param {mat23} out - Matrix to store result. + * @param {mat23} a - The first operand. + * @param {mat23} b - The second operand. + * @returns {mat23} out. + */ + static multiply(out, a, b) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, + b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; + out.m00 = a0 * b0 + a2 * b1; + out.m01 = a1 * b0 + a3 * b1; + out.m02 = a0 * b2 + a2 * b3; + out.m03 = a1 * b2 + a3 * b3; + out.m04 = a0 * b4 + a2 * b5 + a4; + out.m05 = a1 * b4 + a3 * b5 + a5; + return out; + } + + /** + * Alias of {@link mat23.multiply}. + */ + static mul(out, a, b) { + return mat23.multiply(out, a, b); + } + + /** + * Rotates a matrix by the given angle. + * + * @param {mat23} out - Matrix to store result. + * @param {mat23} a - Matrix to rotate. + * @param {Number} rad - The rotation angle. + * @returns {mat23} out + */ + static rotate(out, a, rad) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, + s = Math.sin(rad), + c = Math.cos(rad); + out.m00 = a0 * c + a2 * s; + out.m01 = a1 * c + a3 * s; + out.m02 = a0 * -s + a2 * c; + out.m03 = a1 * -s + a3 * c; + out.m04 = a4; + out.m05 = a5; + return out; + } + + /** + * Multiply a matrix with a scale matrix given by a scale vector. + * + * @param {mat23} out - Matrix to store result. + * @param {mat23} a - Matrix to multiply. + * @param {vec2} v - The scale vector. + * @returns {mat23} out + **/ + static scale(out, a, v) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, + v0 = v.x, v1 = v.y; + out.m00 = a0 * v0; + out.m01 = a1 * v0; + out.m02 = a2 * v1; + out.m03 = a3 * v1; + out.m04 = a4; + out.m05 = a5; + return out; + } + + /** + * Multiply a matrix with a translation matrix given by a translation offset. + * + * @param {mat23} out - Matrix to store result. + * @param {mat23} a - Matrix to multiply. + * @param {vec2} v - The translation offset. + * @returns {mat23} out. + */ + static translate(out, a, v) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, + v0 = v.x, v1 = v.y; + out.m00 = a0; + out.m01 = a1; + out.m02 = a2; + out.m03 = a3; + out.m04 = a0 * v0 + a2 * v1 + a4; + out.m05 = a1 * v0 + a3 * v1 + a5; + return out; + } + + /** + * Creates a matrix from a given angle. + * This is equivalent to (but much faster than): + * + * mat23.identity(dest); + * mat23.rotate(dest, dest, rad); + * + * @param {mat23} out - Matrix to store result. + * @param {Number} rad - The rotation angle. + * @returns {mat23} out. + */ + static fromRotation(out, rad) { + let s = Math.sin(rad), c = Math.cos(rad); + out.m00 = c; + out.m01 = s; + out.m02 = -s; + out.m03 = c; + out.m04 = 0; + out.m05 = 0; + return out; + } + + /** + * Creates a matrix from a scale vector. + * This is equivalent to (but much faster than): + * + * mat23.identity(dest); + * mat23.scale(dest, dest, vec); + * + * @param {mat23} out - Matrix to store result. + * @param {vec2} v - Scale vector. + * @returns {mat23} out. + */ + static fromScaling(out, v) { + out.m00 = v.m00; + out.m01 = 0; + out.m02 = 0; + out.m03 = v.m01; + out.m04 = 0; + out.m05 = 0; + return out; + } + + /** + * Creates a matrix from a translation offset. + * This is equivalent to (but much faster than): + * + * mat23.identity(dest); + * mat23.translate(dest, dest, vec); + * + * @param {mat23} out - Matrix to store result. + * @param {vec2} v - The translation offset. + * @returns {mat23} out. + */ + static fromTranslation(out, v) { + out.m00 = 1; + out.m01 = 0; + out.m02 = 0; + out.m03 = 1; + out.m04 = v.x; + out.m05 = v.y; + return out; + } + + /** + * Creates a matrix from a rotation, translation offset and scale vector. + * This is equivalent to (but faster than): + * + * mat23.identity(dest); + * mat23.translate(dest, vec); + * let tmp = mat23.create(); + * mat23.fromRotation(tmp, rot); + * mat23.multiply(dest, dest, tmp); + * mat23.fromScaling(tmp, scale); + * mat23.multiply(dest, dest, tmp); + * + * @param {mat23} out - Matrix to store result. + * @param {number} r - Rotation radian. + * @param {vec2} t - Translation offset. + * @param {vec2} s - Scale vector. + * @returns {mat23} out. + */ + static fromRTS(out, r, t, s) { + let sr = Math.sin(r), cr = Math.cos(r); + out.m00 = cr * s.x; + out.m01 = sr * s.x; + out.m02 = -sr * s.y; + out.m03 = cr * s.y; + out.m04 = t.x; + out.m05 = t.y; + return out; + } + + /** + * Returns a string representation of a matrix. + * + * @param {mat23} a - The matrix. + * @returns {String} String representation of this matrix. + */ + static str(a) { + return `mat23(${a.m00}, ${a.m01}, ${a.m02}, ${a.m03}, ${a.m04}, ${a.m05})`; + } + + /** + * Store elements of a matrix into array. + * + * @param {array} out - Array to store result. + * @param {mat23} m - The matrix. + * @returns {Array} out. + */ + static array(out, m) { + out[0] = m.m00; + out[1] = m.m01; + out[2] = m.m02; + out[3] = m.m03; + out[4] = m.m04; + out[5] = m.m05; + + return out; + } + + /** + * Store elements of a matrix into 16 floats array. + * + * @param {array} out + * @param {mat23} m + * @returns {array} + */ + static array4x4(out, m) { + out[0] = m.m00; + out[1] = m.m01; + out[2] = 0; + out[3] = 0; + out[4] = m.m02; + out[5] = m.m03; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + out[12] = m.m04; + out[13] = m.m05; + out[14] = 0; + out[15] = 1; + + return out; + } + + /** + * Returns Frobenius norm of a matrix. + * + * @param {mat23} a - Matrix to calculate Frobenius norm of. + * @returns {Number} - The frobenius norm. + */ + static frob(a) { + return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + 1)); + } + + /** + * Adds two matrices. + * + * @param {mat23} out - Matrix to store result. + * @param {mat23} a - The first operand. + * @param {mat23} b - The second operand. + * @returns {mat23} out. + */ + static add(out, a, b) { + out.m00 = a.m00 + b.m00; + out.m01 = a.m01 + b.m01; + out.m02 = a.m02 + b.m02; + out.m03 = a.m03 + b.m03; + out.m04 = a.m04 + b.m04; + out.m05 = a.m05 + b.m05; + return out; + } + + /** + * Subtracts matrix b from matrix a. + * + * @param {mat23} out - Matrix to store result. + * @param {mat23} a - The first operand. + * @param {mat23} b - The second operand. + * @returns {mat23} out. + */ + static subtract(out, a, b) { + out.m00 = a.m00 - b.m00; + out.m01 = a.m01 - b.m01; + out.m02 = a.m02 - b.m02; + out.m03 = a.m03 - b.m03; + out.m04 = a.m04 - b.m04; + out.m05 = a.m05 - b.m05; + return out; + } + + /** + * Alias of {@link mat23.subtract}. + */ + static sub(out, a, b) { + return mat23.subtract(out, a, b); + } + + /** + * Multiply each element of a matrix by a scalar number. + * + * @param {mat23} out - Matrix to store result. + * @param {mat23} a - Matrix to scale + * @param {Number} b - The scale number. + * @returns {mat23} out. + */ + static multiplyScalar(out, a, b) { + out.m00 = a.m00 * b; + out.m01 = a.m01 * b; + out.m02 = a.m02 * b; + out.m03 = a.m03 * b; + out.m04 = a.m04 * b; + out.m05 = a.m05 * b; + return out; + } + + /** + * Adds two matrices after multiplying each element of the second operand by a scalar number. + * + * @param {mat23} out - Matrix to store result. + * @param {mat23} a - The first operand. + * @param {mat23} b - The second operand. + * @param {Number} scale - The scale number. + * @returns {mat23} out. + */ + static multiplyScalarAndAdd(out, a, b, scale) { + out.m00 = a.m00 + (b.m00 * scale); + out.m01 = a.m01 + (b.m01 * scale); + out.m02 = a.m02 + (b.m02 * scale); + out.m03 = a.m03 + (b.m03 * scale); + out.m04 = a.m04 + (b.m04 * scale); + out.m05 = a.m05 + (b.m05 * scale); + return out; + } + + /** + * Returns whether the specified matrices are equal. (Compared using ===) + * + * @param {mat23} a - The first matrix. + * @param {mat23} b - The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ + static exactEquals(a, b) { + return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05; + } + + /** + * Returns whether the specified matrices are approximately equal. + * + * @param {mat23} a - The first matrix. + * @param {mat23} b - The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ + static equals(a, b) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05; + let b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; + return ( + Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && + Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && + Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && + Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) + ); + } +} + +export default mat23; \ No newline at end of file diff --git a/cocos2d/core/vmath/mat3.js b/cocos2d/core/vmath/mat3.js new file mode 100644 index 00000000000..a87eeba5f47 --- /dev/null +++ b/cocos2d/core/vmath/mat3.js @@ -0,0 +1,851 @@ +import { EPSILON } from './utils'; +import vec3 from './vec3'; + +/** + * Mathematical 3x3 matrix. + * + * NOTE: we use column-major matrix for all matrix calculation. + * + * This may lead to some confusion when referencing OpenGL documentation, + * however, which represents out all matricies in column-major format. + * This means that while in code a matrix may be typed out as: + * + * [1, 0, 0, 0, + * 0, 1, 0, 0, + * 0, 0, 1, 0, + * x, y, z, 0] + * + * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) + * is written as: + * + * 1 0 0 x + * 0 1 0 y + * 0 0 1 z + * 0 0 0 0 + * + * Please rest assured, however, that they are the same thing! + * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the + * apparent lack of consistency between the memory layout and the documentation. + */ +class mat3 { + /** + * Creates a matrix, with elements specified separately. + * + * @param {Number} m00 - Value assigned to element at column 0 row 0. + * @param {Number} m01 - Value assigned to element at column 0 row 1. + * @param {Number} m02 - Value assigned to element at column 0 row 2. + * @param {Number} m03 - Value assigned to element at column 1 row 0. + * @param {Number} m04 - Value assigned to element at column 1 row 1. + * @param {Number} m05 - Value assigned to element at column 1 row 2. + * @param {Number} m06 - Value assigned to element at column 2 row 0. + * @param {Number} m07 - Value assigned to element at column 2 row 1. + * @param {Number} m08 - Value assigned to element at column 2 row 2. + */ + constructor( + m00 = 1, m01 = 0, m02 = 0, + m03 = 0, m04 = 1, m05 = 0, + m06 = 0, m07 = 0, m08 = 1 + ) { + /** + * The element at column 0 row 0. + * @type {number} + * */ + this.m00 = m00; + + /** + * The element at column 0 row 1. + * @type {number} + * */ + this.m01 = m01; + + /** + * The element at column 0 row 2. + * @type {number} + * */ + this.m02 = m02; + + /** + * The element at column 1 row 0. + * @type {number} + * */ + this.m03 = m03; + + /** + * The element at column 1 row 1. + * @type {number} + * */ + this.m04 = m04; + + /** + * The element at column 1 row 2. + * @type {number} + * */ + this.m05 = m05; + + /** + * The element at column 2 row 0. + * @type {number} + * */ + this.m06 = m06; + + /** + * The element at column 2 row 1. + * @type {number} + * */ + this.m07 = m07; + + /** + * The element at column 2 row 2. + * @type {number} + * */ + this.m08 = m08; + } + + /** + * Creates a matrix, with elements specified separately. + * + * @param {Number} m00 - Value assigned to element at column 0 row 0. + * @param {Number} m01 - Value assigned to element at column 0 row 1. + * @param {Number} m02 - Value assigned to element at column 0 row 2. + * @param {Number} m03 - Value assigned to element at column 1 row 0. + * @param {Number} m04 - Value assigned to element at column 1 row 1. + * @param {Number} m05 - Value assigned to element at column 1 row 2. + * @param {Number} m06 - Value assigned to element at column 2 row 0. + * @param {Number} m07 - Value assigned to element at column 2 row 1. + * @param {Number} m08 - Value assigned to element at column 2 row 2. + * @returns {mat3} The newly created matrix. + */ + static create(m00 = 1, m01 = 0, m02 = 0, m03 = 0, m04 = 1, m05 = 0, m06 = 0, m07 = 0, m08 = 1) { + return new mat3(m00, m01, m02, m03, m04, m05, m06, m07, m08); + } + + /** + * Clone a matrix. + * + * @param {mat3} a - Matrix to clone. + * @returns {mat3} The newly created matrix. + */ + static clone(a) { + return new mat3( + a.m00, a.m01, a.m02, + a.m03, a.m04, a.m05, + a.m06, a.m07, a.m08 + ); + } + + /** + * Copy content of a matrix into another. + * + * @param {mat3} out - Matrix to modified. + * @param {mat3} a - The specified matrix. + * @returns {mat3} out. + */ + static copy(out, a) { + out.m00 = a.m00; + out.m01 = a.m01; + out.m02 = a.m02; + out.m03 = a.m03; + out.m04 = a.m04; + out.m05 = a.m05; + out.m06 = a.m06; + out.m07 = a.m07; + out.m08 = a.m08; + return out; + } + + /** + * Sets the elements of a matrix to the given values. + * + * @param {mat3} out - The matrix to modified. + * @param {Number} m00 - Value assigned to element at column 0 row 0. + * @param {Number} m01 - Value assigned to element at column 0 row 1. + * @param {Number} m02 - Value assigned to element at column 0 row 2. + * @param {Number} m10 - Value assigned to element at column 1 row 0. + * @param {Number} m11 - Value assigned to element at column 1 row 1. + * @param {Number} m12 - Value assigned to element at column 1 row 2. + * @param {Number} m20 - Value assigned to element at column 2 row 0. + * @param {Number} m21 - Value assigned to element at column 2 row 1. + * @param {Number} m22 - Value assigned to element at column 2 row 2. + * @returns {mat3} out. + */ + static set(out, m00, m01, m02, m10, m11, m12, m20, m21, m22) { + out.m00 = m00; + out.m01 = m01; + out.m02 = m02; + out.m03 = m10; + out.m04 = m11; + out.m05 = m12; + out.m06 = m20; + out.m07 = m21; + out.m08 = m22; + return out; + } + + /** + * return an identity matrix. + * + * @returns {mat3} out. + */ + static identity(out) { + out.m00 = 1; + out.m01 = 0; + out.m02 = 0; + out.m03 = 0; + out.m04 = 1; + out.m05 = 0; + out.m06 = 0; + out.m07 = 0; + out.m08 = 1; + return out; + } + + /** + * Transposes a matrix. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - Matrix to transpose. + * @returns {mat3} out. + */ + static transpose(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + let a01 = a.m01, a02 = a.m02, a12 = a.m05; + out.m01 = a.m03; + out.m02 = a.m06; + out.m03 = a01; + out.m05 = a.m07; + out.m06 = a02; + out.m07 = a12; + } else { + out.m00 = a.m00; + out.m01 = a.m03; + out.m02 = a.m06; + out.m03 = a.m01; + out.m04 = a.m04; + out.m05 = a.m07; + out.m06 = a.m02; + out.m07 = a.m05; + out.m08 = a.m08; + } + + return out; + } + + /** + * Inverts a matrix. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - Matrix to invert. + * @returns {mat3} out. + */ + static invert(out, a) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, + a10 = a.m03, a11 = a.m04, a12 = a.m05, + a20 = a.m06, a21 = a.m07, a22 = a.m08; + + let b01 = a22 * a11 - a12 * a21; + let b11 = -a22 * a10 + a12 * a20; + let b21 = a21 * a10 - a11 * a20; + + // Calculate the determinant + let det = a00 * b01 + a01 * b11 + a02 * b21; + + if (!det) { + return null; + } + det = 1.0 / det; + + out.m00 = b01 * det; + out.m01 = (-a22 * a01 + a02 * a21) * det; + out.m02 = (a12 * a01 - a02 * a11) * det; + out.m03 = b11 * det; + out.m04 = (a22 * a00 - a02 * a20) * det; + out.m05 = (-a12 * a00 + a02 * a10) * det; + out.m06 = b21 * det; + out.m07 = (-a21 * a00 + a01 * a20) * det; + out.m08 = (a11 * a00 - a01 * a10) * det; + return out; + } + + /** + * Calculates the adjugate of a matrix. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - Matrix to calculate. + * @returns {mat3} out. + */ + static adjoint(out, a) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, + a10 = a.m03, a11 = a.m04, a12 = a.m05, + a20 = a.m06, a21 = a.m07, a22 = a.m08; + + out.m00 = (a11 * a22 - a12 * a21); + out.m01 = (a02 * a21 - a01 * a22); + out.m02 = (a01 * a12 - a02 * a11); + out.m03 = (a12 * a20 - a10 * a22); + out.m04 = (a00 * a22 - a02 * a20); + out.m05 = (a02 * a10 - a00 * a12); + out.m06 = (a10 * a21 - a11 * a20); + out.m07 = (a01 * a20 - a00 * a21); + out.m08 = (a00 * a11 - a01 * a10); + return out; + } + + /** + * Calculates the determinant of a matrix. + * + * @param {mat3} a - Matrix to calculate. + * @returns {Number} Determinant of a. + */ + static determinant(a) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, + a10 = a.m03, a11 = a.m04, a12 = a.m05, + a20 = a.m06, a21 = a.m07, a22 = a.m08; + + return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); + } + + /** + * Multiply two matrices explicitly. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - The first operand. + * @param {mat3} b - The second operand. + * @returns {mat3} out. + */ + static multiply(out, a, b) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, + a10 = a.m03, a11 = a.m04, a12 = a.m05, + a20 = a.m06, a21 = a.m07, a22 = a.m08; + + let b00 = b.m00, b01 = b.m01, b02 = b.m02; + let b10 = b.m03, b11 = b.m04, b12 = b.m05; + let b20 = b.m06, b21 = b.m07, b22 = b.m08; + + out.m00 = b00 * a00 + b01 * a10 + b02 * a20; + out.m01 = b00 * a01 + b01 * a11 + b02 * a21; + out.m02 = b00 * a02 + b01 * a12 + b02 * a22; + + out.m03 = b10 * a00 + b11 * a10 + b12 * a20; + out.m04 = b10 * a01 + b11 * a11 + b12 * a21; + out.m05 = b10 * a02 + b11 * a12 + b12 * a22; + + out.m06 = b20 * a00 + b21 * a10 + b22 * a20; + out.m07 = b20 * a01 + b21 * a11 + b22 * a21; + out.m08 = b20 * a02 + b21 * a12 + b22 * a22; + return out; + } + + /** + * Alias of {@link mat3.multiply}. + */ + static mul(out, a, b) { + return mat3.multiply(out, a, b); + } + + /** + * Multiply a matrix with a translation matrix given by a translation offset. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - Matrix to multiply. + * @param {vec2} v - The translation offset. + * @returns {mat3} out. + */ + static translate(out, a, v) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, + a10 = a.m03, a11 = a.m04, a12 = a.m05, + a20 = a.m06, a21 = a.m07, a22 = a.m08; + let x = v.x, y = v.y; + + out.m00 = a00; + out.m01 = a01; + out.m02 = a02; + + out.m03 = a10; + out.m04 = a11; + out.m05 = a12; + + out.m06 = x * a00 + y * a10 + a20; + out.m07 = x * a01 + y * a11 + a21; + out.m08 = x * a02 + y * a12 + a22; + return out; + } + + /** + * Rotates a matrix by the given angle. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - Matrix to rotate. + * @param {Number} rad - The rotation angle. + * @returns {mat3} out + */ + static rotate(out, a, rad) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, + a10 = a.m03, a11 = a.m04, a12 = a.m05, + a20 = a.m06, a21 = a.m07, a22 = a.m08; + + let s = Math.sin(rad); + let c = Math.cos(rad); + + out.m00 = c * a00 + s * a10; + out.m01 = c * a01 + s * a11; + out.m02 = c * a02 + s * a12; + + out.m03 = c * a10 - s * a00; + out.m04 = c * a11 - s * a01; + out.m05 = c * a12 - s * a02; + + out.m06 = a20; + out.m07 = a21; + out.m08 = a22; + return out; + } + + /** + * Multiply a matrix with a scale matrix given by a scale vector. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - Matrix to multiply. + * @param {vec2} v - The scale vector. + * @returns {mat3} out + **/ + static scale(out, a, v) { + let x = v.x, y = v.y; + + out.m00 = x * a.m00; + out.m01 = x * a.m01; + out.m02 = x * a.m02; + + out.m03 = y * a.m03; + out.m04 = y * a.m04; + out.m05 = y * a.m05; + + out.m06 = a.m06; + out.m07 = a.m07; + out.m08 = a.m08; + return out; + } + + /** + * Copies the upper-left 3x3 values of a 4x4 matrix into a 3x3 matrix. + * + * @param {mat3} out - Matrix to store result. + * @param {mat4} a - The 4x4 matrix. + * @returns {mat3} out. + */ + static fromMat4(out, a) { + out.m00 = a.m00; + out.m01 = a.m01; + out.m02 = a.m02; + out.m03 = a.m04; + out.m04 = a.m05; + out.m05 = a.m06; + out.m06 = a.m08; + out.m07 = a.m09; + out.m08 = a.m10; + return out; + } + + /** + * Creates a matrix from a translation offset. + * This is equivalent to (but much faster than): + * + * mat3.identity(dest); + * mat3.translate(dest, dest, vec); + * + * @param {mat3} out - Matrix to store result. + * @param {vec2} v - The translation offset. + * @returns {mat3} out. + */ + static fromTranslation(out, v) { + out.m00 = 1; + out.m01 = 0; + out.m02 = 0; + out.m03 = 0; + out.m04 = 1; + out.m05 = 0; + out.m06 = v.x; + out.m07 = v.y; + out.m08 = 1; + return out; + } + + /** + * Creates a matrix from a given angle. + * This is equivalent to (but much faster than): + * + * mat3.identity(dest); + * mat3.rotate(dest, dest, rad); + * + * @param {mat3} out - Matrix to store result. + * @param {Number} rad - The rotation angle. + * @returns {mat3} out. + */ + static fromRotation(out, rad) { + let s = Math.sin(rad), c = Math.cos(rad); + + out.m00 = c; + out.m01 = s; + out.m02 = 0; + + out.m03 = -s; + out.m04 = c; + out.m05 = 0; + + out.m06 = 0; + out.m07 = 0; + out.m08 = 1; + return out; + } + + /** + * Creates a matrix from a scale vector. + * This is equivalent to (but much faster than): + * + * mat3.identity(dest); + * mat3.scale(dest, dest, vec); + * + * @param {mat3} out - Matrix to store result. + * @param {vec2} v - Scale vector. + * @returns {mat3} out. + */ + static fromScaling(out, v) { + out.m00 = v.x; + out.m01 = 0; + out.m02 = 0; + + out.m03 = 0; + out.m04 = v.y; + out.m05 = 0; + + out.m06 = 0; + out.m07 = 0; + out.m08 = 1; + return out; + } + + /** + * Copies the values from a 2x3 matrix into a 3x3 matrix. + * + * @param {mat3} out - Matrix to store result. + * @param {mat23} a - The 2x3 matrix. + * @returns {mat3} out. + **/ + static fromMat2d(out, a) { + out.m00 = a.m00; + out.m01 = a.m01; + out.m02 = 0; + + out.m03 = a.m02; + out.m04 = a.m03; + out.m05 = 0; + + out.m06 = a.m04; + out.m07 = a.m05; + out.m08 = 1; + return out; + } + + /** + * Calculates a 3x3 matrix from the given quaternion. + * + * @param {mat3} out - Matrix to store result. + * @param {quat} q - The quaternion. + * + * @returns {mat3} out. + */ + static fromQuat(out, q) { + let x = q.x, y = q.y, z = q.z, w = q.w; + let x2 = x + x; + let y2 = y + y; + let z2 = z + z; + + let xx = x * x2; + let yx = y * x2; + let yy = y * y2; + let zx = z * x2; + let zy = z * y2; + let zz = z * z2; + let wx = w * x2; + let wy = w * y2; + let wz = w * z2; + + out.m00 = 1 - yy - zz; + out.m03 = yx - wz; + out.m06 = zx + wy; + + out.m01 = yx + wz; + out.m04 = 1 - xx - zz; + out.m07 = zy - wx; + + out.m02 = zx - wy; + out.m05 = zy + wx; + out.m08 = 1 - xx - yy; + + return out; + } + + /** + * Calculates a 3x3 matrix from view direction and up direction. + * + * @param {mat3} out - Matrix to store result. + * @param {vec3} view - View direction (must be normalized). + * @param {vec3} [up] - Up direction, default is (0,1,0) (must be normalized). + * + * @returns {mat3} out + */ + static fromViewUp(out, view, up) { + let _fromViewUpIIFE = (function () { + let default_up = vec3.create(0, 1, 0); + let x = vec3.create(0, 0, 0); + let y = vec3.create(0, 0, 0); + + return function (out, view, up) { + if (vec3.sqrMag(view) < EPSILON * EPSILON) { + mat3.identity(out); + return out; + } + + up = up || default_up; + vec3.normalize(x, vec3.cross(x, up, view)); + + if (vec3.sqrMag(x) < EPSILON * EPSILON) { + mat3.identity(out); + return out; + } + + vec3.cross(y, view, x); + mat3.set( + out, + x.x, x.y, x.z, + y.x, y.y, y.z, + view.x, view.y, view.z + ); + + return out; + }; + })(); + return _fromViewUpIIFE(out, view, up); + } + + /** + * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix. + * + * @param {mat3} out - Matrix to store result. + * @param {mat4} a - A 4x4 matrix to derive the normal matrix from. + * + * @returns {mat3} out. + */ + static normalFromMat4(out, a) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, + a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, + a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, + a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; + + let b00 = a00 * a11 - a01 * a10; + let b01 = a00 * a12 - a02 * a10; + let b02 = a00 * a13 - a03 * a10; + let b03 = a01 * a12 - a02 * a11; + let b04 = a01 * a13 - a03 * a11; + let b05 = a02 * a13 - a03 * a12; + let b06 = a20 * a31 - a21 * a30; + let b07 = a20 * a32 - a22 * a30; + let b08 = a20 * a33 - a23 * a30; + let b09 = a21 * a32 - a22 * a31; + let b10 = a21 * a33 - a23 * a31; + let b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + + if (!det) { + return null; + } + det = 1.0 / det; + + out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out.m01 = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out.m02 = (a10 * b10 - a11 * b08 + a13 * b06) * det; + + out.m03 = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out.m04 = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out.m05 = (a01 * b08 - a00 * b10 - a03 * b06) * det; + + out.m06 = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out.m07 = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out.m08 = (a30 * b04 - a31 * b02 + a33 * b00) * det; + + return out; + } + + /** + * Returns a string representation of a matrix. + * + * @param {mat3} a - The matrix. + * @returns {String} String representation of this matrix. + */ + static str(a) { + return `mat3(${a.m00}, ${a.m01}, ${a.m02}, ${a.m03}, ${a.m04}, ${a.m05}, ${a.m06}, ${a.m07}, ${a.m08})`; + } + + /** + * Store elements of a matrix into array. + * + * @param {array} out - Array to store result. + * @param {mat3} m - The matrix. + * @returns {Array} out. + */ + static array(out, m) { + out[0] = m.m00; + out[1] = m.m01; + out[2] = m.m02; + out[3] = m.m03; + out[4] = m.m04; + out[5] = m.m05; + out[6] = m.m06; + out[7] = m.m07; + out[8] = m.m08; + + return out; + } + + /** + * Returns Frobenius norm of a matrix. + * + * @param {mat3} a - Matrix to calculate Frobenius norm of. + * @returns {Number} - The frobenius norm. + */ + static frob(a) { + return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2))); + } + + /** + * Adds two matrices. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - The first operand. + * @param {mat3} b - The second operand. + * @returns {mat3} out. + */ + static add(out, a, b) { + out.m00 = a.m00 + b.m00; + out.m01 = a.m01 + b.m01; + out.m02 = a.m02 + b.m02; + out.m03 = a.m03 + b.m03; + out.m04 = a.m04 + b.m04; + out.m05 = a.m05 + b.m05; + out.m06 = a.m06 + b.m06; + out.m07 = a.m07 + b.m07; + out.m08 = a.m08 + b.m08; + return out; + } + + /** + * Subtracts matrix b from matrix a. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - The first operand. + * @param {mat3} b - The second operand. + * @returns {mat3} out. + */ + static subtract(out, a, b) { + out.m00 = a.m00 - b.m00; + out.m01 = a.m01 - b.m01; + out.m02 = a.m02 - b.m02; + out.m03 = a.m03 - b.m03; + out.m04 = a.m04 - b.m04; + out.m05 = a.m05 - b.m05; + out.m06 = a.m06 - b.m06; + out.m07 = a.m07 - b.m07; + out.m08 = a.m08 - b.m08; + return out; + } + + /** + * Alias of {@link mat3.subtract}. + */ + static sub(out, a, b) { + return mat3.subtract(out, a, b); + } + + /** + * Multiply each element of a matrix by a scalar number. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - Matrix to scale + * @param {Number} b - The scale number. + * @returns {mat3} out. + */ + static multiplyScalar(out, a, b) { + out.m00 = a.m00 * b; + out.m01 = a.m01 * b; + out.m02 = a.m02 * b; + out.m03 = a.m03 * b; + out.m04 = a.m04 * b; + out.m05 = a.m05 * b; + out.m06 = a.m06 * b; + out.m07 = a.m07 * b; + out.m08 = a.m08 * b; + return out; + } + + /** + * Adds two matrices after multiplying each element of the second operand by a scalar number. + * + * @param {mat3} out - Matrix to store result. + * @param {mat3} a - The first operand. + * @param {mat3} b - The second operand. + * @param {Number} scale - The scale number. + * @returns {mat3} out. + */ + static multiplyScalarAndAdd(out, a, b, scale) { + out.m00 = a.m00 + (b.m00 * scale); + out.m01 = a.m01 + (b.m01 * scale); + out.m02 = a.m02 + (b.m02 * scale); + out.m03 = a.m03 + (b.m03 * scale); + out.m04 = a.m04 + (b.m04 * scale); + out.m05 = a.m05 + (b.m05 * scale); + out.m06 = a.m06 + (b.m06 * scale); + out.m07 = a.m07 + (b.m07 * scale); + out.m08 = a.m08 + (b.m08 * scale); + return out; + } + + /** + * Returns whether the specified matrices are equal. (Compared using ===) + * + * @param {mat3} a - The first matrix. + * @param {mat3} b - The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ + static exactEquals(a, b) { + return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && + a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05 && + a.m06 === b.m06 && a.m07 === b.m07 && a.m08 === b.m08; + } + + /** + * Returns whether the specified matrices are approximately equal. + * + * @param {mat3} a - The first matrix. + * @param {mat3} b - The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ + static equals(a, b) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, a8 = a.m08; + let b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, b8 = b.m08; + return ( + Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && + Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && + Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && + Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && + Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && + Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && + Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) + ); + } +} + +export default mat3; \ No newline at end of file diff --git a/cocos2d/core/vmath/mat4.js b/cocos2d/core/vmath/mat4.js new file mode 100644 index 00000000000..08568f3d9be --- /dev/null +++ b/cocos2d/core/vmath/mat4.js @@ -0,0 +1,1729 @@ +import { EPSILON } from './utils'; + +/** + * Mathematical 4x4 matrix. + * + * NOTE: we use column-major matrix for all matrix calculation. + * + * This may lead to some confusion when referencing OpenGL documentation, + * however, which represents out all matricies in column-major format. + * This means that while in code a matrix may be typed out as: + * + * [1, 0, 0, 0, + * 0, 1, 0, 0, + * 0, 0, 1, 0, + * x, y, z, 0] + * + * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) + * is written as: + * + * 1 0 0 x + * 0 1 0 y + * 0 0 1 z + * 0 0 0 0 + * + * Please rest assured, however, that they are the same thing! + * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the + * apparent lack of consistency between the memory layout and the documentation. + */ +class mat4 { + /** + * Creates a matrix, with elements specified separately. + * + * @param {Number} m00 - Value assigned to element at column 0 row 0. + * @param {Number} m01 - Value assigned to element at column 0 row 1. + * @param {Number} m02 - Value assigned to element at column 0 row 2. + * @param {Number} m03 - Value assigned to element at column 0 row 3. + * @param {Number} m04 - Value assigned to element at column 1 row 0. + * @param {Number} m05 - Value assigned to element at column 1 row 1. + * @param {Number} m06 - Value assigned to element at column 1 row 2. + * @param {Number} m07 - Value assigned to element at column 1 row 3. + * @param {Number} m08 - Value assigned to element at column 2 row 0. + * @param {Number} m09 - Value assigned to element at column 2 row 1. + * @param {Number} m10 - Value assigned to element at column 2 row 2. + * @param {Number} m11 - Value assigned to element at column 2 row 3. + * @param {Number} m12 - Value assigned to element at column 3 row 0. + * @param {Number} m13 - Value assigned to element at column 3 row 1. + * @param {Number} m14 - Value assigned to element at column 3 row 2. + * @param {Number} m15 - Value assigned to element at column 3 row 3. + */ + constructor( + m00 = 1, m01 = 0, m02 = 0, m03 = 0, + m04 = 0, m05 = 1, m06 = 0, m07 = 0, + m08 = 0, m09 = 0, m10 = 1, m11 = 0, + m12 = 0, m13 = 0, m14 = 0, m15 = 1 + ) { + /** + * The element at column 0 row 0. + * @type {number} + * */ + this.m00 = m00; + + /** + * The element at column 0 row 1. + * @type {number} + * */ + this.m01 = m01; + + /** + * The element at column 0 row 2. + * @type {number} + * */ + this.m02 = m02; + + /** + * The element at column 0 row 3. + * @type {number} + * */ + this.m03 = m03; + + /** + * The element at column 1 row 0. + * @type {number} + * */ + this.m04 = m04; + + /** + * The element at column 1 row 1. + * @type {number} + * */ + this.m05 = m05; + + /** + * The element at column 1 row 2. + * @type {number} + * */ + this.m06 = m06; + + /** + * The element at column 1 row 3. + * @type {number} + * */ + this.m07 = m07; + + /** + * The element at column 2 row 0. + * @type {number} + * */ + this.m08 = m08; + + /** + * The element at column 2 row 1. + * @type {number} + * */ + this.m09 = m09; + + /** + * The element at column 2 row 2. + * @type {number} + * */ + this.m10 = m10; + + /** + * The element at column 2 row 3. + * @type {number} + * */ + this.m11 = m11; + + /** + * The element at column 3 row 0. + * @type {number} + * */ + this.m12 = m12; + + /** + * The element at column 3 row 1. + * @type {number} + * */ + this.m13 = m13; + + /** + * The element at column 3 row 2. + * @type {number} + * */ + this.m14 = m14; + + /** + * The element at column 3 row 3. + * @type {number} + * */ + this.m15 = m15; + } + + /** + * Creates a matrix, with elements specified separately. + * + * @param {Number} m00 - Value assigned to element at column 0 row 0. + * @param {Number} m01 - Value assigned to element at column 0 row 1. + * @param {Number} m02 - Value assigned to element at column 0 row 2. + * @param {Number} m03 - Value assigned to element at column 0 row 3. + * @param {Number} m04 - Value assigned to element at column 1 row 0. + * @param {Number} m05 - Value assigned to element at column 1 row 1. + * @param {Number} m06 - Value assigned to element at column 1 row 2. + * @param {Number} m07 - Value assigned to element at column 1 row 3. + * @param {Number} m08 - Value assigned to element at column 2 row 0. + * @param {Number} m09 - Value assigned to element at column 2 row 1. + * @param {Number} m10 - Value assigned to element at column 2 row 2. + * @param {Number} m11 - Value assigned to element at column 2 row 3. + * @param {Number} m12 - Value assigned to element at column 3 row 0. + * @param {Number} m13 - Value assigned to element at column 3 row 1. + * @param {Number} m14 - Value assigned to element at column 3 row 2. + * @param {Number} m15 - Value assigned to element at column 3 row 3. + * @returns {mat4} The newly created matrix. + */ + static create( + m00 = 1, m01 = 0, m02 = 0, m03 = 0, + m04 = 0, m05 = 1, m06 = 0, m07 = 0, + m08 = 0, m09 = 0, m10 = 1, m11 = 0, + m12 = 0, m13 = 0, m14 = 0, m15 = 1 + ) { + return new mat4( + m00, m01, m02, m03, + m04, m05, m06, m07, + m08, m09, m10, m11, + m12, m13, m14, m15); + } + + /** + * Clone a matrix. + * + * @param {mat4} a - Matrix to clone. + * @returns {mat4} The newly created matrix. + */ + static clone(a) { + return new mat4( + a.m00, a.m01, a.m02, a.m03, + a.m04, a.m05, a.m06, a.m07, + a.m08, a.m09, a.m10, a.m11, + a.m12, a.m13, a.m14, a.m15 + ); + } + + /** + * Copy content of a matrix into another. + * + * @param {mat4} out - Matrix to modified. + * @param {mat4} a - The specified matrix. + * @returns {mat4} out. + */ + static copy(out, a) { + out.m00 = a.m00; + out.m01 = a.m01; + out.m02 = a.m02; + out.m03 = a.m03; + out.m04 = a.m04; + out.m05 = a.m05; + out.m06 = a.m06; + out.m07 = a.m07; + out.m08 = a.m08; + out.m09 = a.m09; + out.m10 = a.m10; + out.m11 = a.m11; + out.m12 = a.m12; + out.m13 = a.m13; + out.m14 = a.m14; + out.m15 = a.m15; + return out; + } + + /** + * Sets the elements of a matrix to the given values. + * + * @param {mat4} out - The matrix to modified. + * @param {Number} m00 - Value assigned to element at column 0 row 0. + * @param {Number} m01 - Value assigned to element at column 0 row 1. + * @param {Number} m02 - Value assigned to element at column 0 row 2. + * @param {Number} m03 - Value assigned to element at column 0 row 3. + * @param {Number} m10 - Value assigned to element at column 1 row 0. + * @param {Number} m11 - Value assigned to element at column 1 row 1. + * @param {Number} m12 - Value assigned to element at column 1 row 2. + * @param {Number} m13 - Value assigned to element at column 1 row 3. + * @param {Number} m20 - Value assigned to element at column 2 row 0. + * @param {Number} m21 - Value assigned to element at column 2 row 1. + * @param {Number} m22 - Value assigned to element at column 2 row 2. + * @param {Number} m23 - Value assigned to element at column 2 row 3. + * @param {Number} m30 - Value assigned to element at column 3 row 0. + * @param {Number} m31 - Value assigned to element at column 3 row 1. + * @param {Number} m32 - Value assigned to element at column 3 row 2. + * @param {Number} m33 - Value assigned to element at column 3 row 3. + * @returns {mat4} out. + */ + static set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { + out.m00 = m00; + out.m01 = m01; + out.m02 = m02; + out.m03 = m03; + out.m04 = m10; + out.m05 = m11; + out.m06 = m12; + out.m07 = m13; + out.m08 = m20; + out.m09 = m21; + out.m10 = m22; + out.m11 = m23; + out.m12 = m30; + out.m13 = m31; + out.m14 = m32; + out.m15 = m33; + return out; + } + + + /** + * Sets a matrix as identity matrix. + * + * @param {mat4} out - Matrix to modified. + * @returns {mat4} out. + */ + static identity(out) { + out.m00 = 1; + out.m01 = 0; + out.m02 = 0; + out.m03 = 0; + out.m04 = 0; + out.m05 = 1; + out.m06 = 0; + out.m07 = 0; + out.m08 = 0; + out.m09 = 0; + out.m10 = 1; + out.m11 = 0; + out.m12 = 0; + out.m13 = 0; + out.m14 = 0; + out.m15 = 1; + return out; + } + + /** + * Transposes a matrix. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to transpose. + * @returns {mat4} out. + */ + static transpose(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + let a01 = a.m01, a02 = a.m02, a03 = a.m03, + a12 = a.m06, a13 = a.m07, + a23 = a.m11; + + out.m01 = a.m04; + out.m02 = a.m08; + out.m03 = a.m12; + out.m04 = a01; + out.m06 = a.m09; + out.m07 = a.m13; + out.m08 = a02; + out.m09 = a12; + out.m11 = a.m14; + out.m12 = a03; + out.m13 = a13; + out.m14 = a23; + } else { + out.m00 = a.m00; + out.m01 = a.m04; + out.m02 = a.m08; + out.m03 = a.m12; + out.m04 = a.m01; + out.m05 = a.m05; + out.m06 = a.m09; + out.m07 = a.m13; + out.m08 = a.m02; + out.m09 = a.m06; + out.m10 = a.m10; + out.m11 = a.m14; + out.m12 = a.m03; + out.m13 = a.m07; + out.m14 = a.m11; + out.m15 = a.m15; + } + + return out; + } + + /** + * Inverts a matrix. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to invert. + * @returns {mat4} out. + */ + static invert(out, a) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, + a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, + a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, + a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; + + let b00 = a00 * a11 - a01 * a10; + let b01 = a00 * a12 - a02 * a10; + let b02 = a00 * a13 - a03 * a10; + let b03 = a01 * a12 - a02 * a11; + let b04 = a01 * a13 - a03 * a11; + let b05 = a02 * a13 - a03 * a12; + let b06 = a20 * a31 - a21 * a30; + let b07 = a20 * a32 - a22 * a30; + let b08 = a20 * a33 - a23 * a30; + let b09 = a21 * a32 - a22 * a31; + let b10 = a21 * a33 - a23 * a31; + let b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + + if (!det) { + return null; + } + det = 1.0 / det; + + out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out.m01 = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out.m02 = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out.m03 = (a22 * b04 - a21 * b05 - a23 * b03) * det; + out.m04 = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out.m05 = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out.m06 = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out.m07 = (a20 * b05 - a22 * b02 + a23 * b01) * det; + out.m08 = (a10 * b10 - a11 * b08 + a13 * b06) * det; + out.m09 = (a01 * b08 - a00 * b10 - a03 * b06) * det; + out.m10 = (a30 * b04 - a31 * b02 + a33 * b00) * det; + out.m11 = (a21 * b02 - a20 * b04 - a23 * b00) * det; + out.m12 = (a11 * b07 - a10 * b09 - a12 * b06) * det; + out.m13 = (a00 * b09 - a01 * b07 + a02 * b06) * det; + out.m14 = (a31 * b01 - a30 * b03 - a32 * b00) * det; + out.m15 = (a20 * b03 - a21 * b01 + a22 * b00) * det; + + return out; + } + + /** + * Calculates the adjugate of a matrix. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to calculate. + * @returns {mat4} out. + */ + static adjoint(out, a) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, + a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, + a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, + a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; + + out.m00 = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); + out.m01 = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); + out.m02 = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); + out.m03 = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); + out.m04 = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); + out.m05 = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); + out.m06 = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); + out.m07 = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); + out.m08 = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); + out.m09 = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); + out.m10 = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); + out.m11 = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); + out.m12 = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); + out.m13 = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); + out.m14 = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); + out.m15 = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); + return out; + } + + /** + * Calculates the determinant of a matrix. + * + * @param {mat4} a - Matrix to calculate. + * @returns {Number} Determinant of a. + */ + static determinant(a) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, + a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, + a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, + a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; + + let b00 = a00 * a11 - a01 * a10; + let b01 = a00 * a12 - a02 * a10; + let b02 = a00 * a13 - a03 * a10; + let b03 = a01 * a12 - a02 * a11; + let b04 = a01 * a13 - a03 * a11; + let b05 = a02 * a13 - a03 * a12; + let b06 = a20 * a31 - a21 * a30; + let b07 = a20 * a32 - a22 * a30; + let b08 = a20 * a33 - a23 * a30; + let b09 = a21 * a32 - a22 * a31; + let b10 = a21 * a33 - a23 * a31; + let b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + } + + /** + * Multiply two matrices explicitly. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - The first operand. + * @param {mat4} b - The second operand. + * @returns {mat4} out. + */ + static multiply(out, a, b) { + let a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, + a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, + a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, + a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; + + // Cache only the current line of the second matrix + let b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; + out.m00 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + out.m01 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + out.m02 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + out.m03 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; + + b0 = b.m04; b1 = b.m05; b2 = b.m06; b3 = b.m07; + out.m04 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + out.m05 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + out.m06 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + out.m07 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; + + b0 = b.m08; b1 = b.m09; b2 = b.m10; b3 = b.m11; + out.m08 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + out.m09 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + out.m10 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + out.m11 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; + + b0 = b.m12; b1 = b.m13; b2 = b.m14; b3 = b.m15; + out.m12 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + out.m13 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + out.m14 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + out.m15 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; + return out; + } + + /** + * Alias of {@link mat4.multiply}. + */ + static mul(out, a, b) { + return mat4.multiply(out, a, b); + } + + /** + * Multiply a matrix with a translation matrix given by a translation offset. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to multiply. + * @param {vec3} v - The translation offset. + * @returns {mat4} out. + */ + static translate(out, a, v) { + let x = v.x, y = v.y, z = v.z, + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23; + + if (a === out) { + out.m12 = a.m00 * x + a.m04 * y + a.m08 * z + a.m12; + out.m13 = a.m01 * x + a.m05 * y + a.m09 * z + a.m13; + out.m14 = a.m02 * x + a.m06 * y + a.m10 * z + a.m14; + out.m15 = a.m03 * x + a.m07 * y + a.m11 * z + a.m15; + } else { + a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; + a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; + a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; + + out.m00 = a00; out.m01 = a01; out.m02 = a02; out.m03 = a03; + out.m04 = a10; out.m05 = a11; out.m06 = a12; out.m07 = a13; + out.m08 = a20; out.m09 = a21; out.m10 = a22; out.m11 = a23; + + out.m12 = a00 * x + a10 * y + a20 * z + a.m12; + out.m13 = a01 * x + a11 * y + a21 * z + a.m13; + out.m14 = a02 * x + a12 * y + a22 * z + a.m14; + out.m15 = a03 * x + a13 * y + a23 * z + a.m15; + } + + return out; + } + + /** + * Multiply a matrix with a scale matrix given by a scale vector. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to multiply. + * @param {vec3} v - The scale vector. + * @returns {mat4} out + **/ + static scale(out, a, v) { + let x = v.x, y = v.y, z = v.z; + + out.m00 = a.m00 * x; + out.m01 = a.m01 * x; + out.m02 = a.m02 * x; + out.m03 = a.m03 * x; + out.m04 = a.m04 * y; + out.m05 = a.m05 * y; + out.m06 = a.m06 * y; + out.m07 = a.m07 * y; + out.m08 = a.m08 * z; + out.m09 = a.m09 * z; + out.m10 = a.m10 * z; + out.m11 = a.m11 * z; + out.m12 = a.m12; + out.m13 = a.m13; + out.m14 = a.m14; + out.m15 = a.m15; + return out; + } + + /** + * Multiply a matrix with a rotation matrix denotes by the rotation around arbitrary axis. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to multiply. + * @param {Number} rad - The rotation angle. + * @param {vec3} axis - The rotation axis. + * @returns {mat4} out. + */ + static rotate(out, a, rad, axis) { + let x = axis.x, y = axis.y, z = axis.z; + let s, c, t, + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23, + b00, b01, b02, + b10, b11, b12, + b20, b21, b22; + + let len = Math.sqrt(x * x + y * y + z * z); + + if (Math.abs(len) < EPSILON) { + return null; + } + + len = 1 / len; + x *= len; + y *= len; + z *= len; + + s = Math.sin(rad); + c = Math.cos(rad); + t = 1 - c; + + a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; + a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; + a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; + + // Construct the elements of the rotation matrix + b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; + b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; + b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; + + // Perform rotation-specific matrix multiplication + out.m00 = a00 * b00 + a10 * b01 + a20 * b02; + out.m01 = a01 * b00 + a11 * b01 + a21 * b02; + out.m02 = a02 * b00 + a12 * b01 + a22 * b02; + out.m03 = a03 * b00 + a13 * b01 + a23 * b02; + out.m04 = a00 * b10 + a10 * b11 + a20 * b12; + out.m05 = a01 * b10 + a11 * b11 + a21 * b12; + out.m06 = a02 * b10 + a12 * b11 + a22 * b12; + out.m07 = a03 * b10 + a13 * b11 + a23 * b12; + out.m08 = a00 * b20 + a10 * b21 + a20 * b22; + out.m09 = a01 * b20 + a11 * b21 + a21 * b22; + out.m10 = a02 * b20 + a12 * b21 + a22 * b22; + out.m11 = a03 * b20 + a13 * b21 + a23 * b22; + + // If the source and destination differ, copy the unchanged last row + if (a !== out) { + out.m12 = a.m12; + out.m13 = a.m13; + out.m14 = a.m14; + out.m15 = a.m15; + } + + return out; + } + + /** + * Multiply a matrix with a rotation matrix denotes by the rotation around x-axis. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to multiply. + * @param {Number} rad - The rotation angle. + * @returns {mat4} out. + */ + static rotateX(out, a, rad) { + let s = Math.sin(rad), + c = Math.cos(rad), + a10 = a.m04, + a11 = a.m05, + a12 = a.m06, + a13 = a.m07, + a20 = a.m08, + a21 = a.m09, + a22 = a.m10, + a23 = a.m11; + + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out.m00 = a.m00; + out.m01 = a.m01; + out.m02 = a.m02; + out.m03 = a.m03; + out.m12 = a.m12; + out.m13 = a.m13; + out.m14 = a.m14; + out.m15 = a.m15; + } + + // Perform axis-specific matrix multiplication + out.m04 = a10 * c + a20 * s; + out.m05 = a11 * c + a21 * s; + out.m06 = a12 * c + a22 * s; + out.m07 = a13 * c + a23 * s; + out.m08 = a20 * c - a10 * s; + out.m09 = a21 * c - a11 * s; + out.m10 = a22 * c - a12 * s; + out.m11 = a23 * c - a13 * s; + + return out; + } + + /** + * Multiply a matrix with a rotation matrix denotes by the rotation around y-axis. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to multiply. + * @param {Number} rad - The rotation angle. + * @returns {mat4} out. + */ + static rotateY(out, a, rad) { + let s = Math.sin(rad), + c = Math.cos(rad), + a00 = a.m00, + a01 = a.m01, + a02 = a.m02, + a03 = a.m03, + a20 = a.m08, + a21 = a.m09, + a22 = a.m10, + a23 = a.m11; + + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out.m04 = a.m04; + out.m05 = a.m05; + out.m06 = a.m06; + out.m07 = a.m07; + out.m12 = a.m12; + out.m13 = a.m13; + out.m14 = a.m14; + out.m15 = a.m15; + } + + // Perform axis-specific matrix multiplication + out.m00 = a00 * c - a20 * s; + out.m01 = a01 * c - a21 * s; + out.m02 = a02 * c - a22 * s; + out.m03 = a03 * c - a23 * s; + out.m08 = a00 * s + a20 * c; + out.m09 = a01 * s + a21 * c; + out.m10 = a02 * s + a22 * c; + out.m11 = a03 * s + a23 * c; + + return out; + } + + /** + * Multiply a matrix with a rotation matrix denotes by the rotation around z-axis. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to multiply. + * @param {Number} rad - The rotation angle. + * @returns {mat4} out. + */ + static rotateZ(out, a, rad) { + let s = Math.sin(rad), + c = Math.cos(rad), + a00 = a.m00, + a01 = a.m01, + a02 = a.m02, + a03 = a.m03, + a10 = a.m04, + a11 = a.m05, + a12 = a.m06, + a13 = a.m07; + + // If the source and destination differ, copy the unchanged last row + if (a !== out) { + out.m08 = a.m08; + out.m09 = a.m09; + out.m10 = a.m10; + out.m11 = a.m11; + out.m12 = a.m12; + out.m13 = a.m13; + out.m14 = a.m14; + out.m15 = a.m15; + } + + // Perform axis-specific matrix multiplication + out.m00 = a00 * c + a10 * s; + out.m01 = a01 * c + a11 * s; + out.m02 = a02 * c + a12 * s; + out.m03 = a03 * c + a13 * s; + out.m04 = a10 * c - a00 * s; + out.m05 = a11 * c - a01 * s; + out.m06 = a12 * c - a02 * s; + out.m07 = a13 * c - a03 * s; + + return out; + } + + /** + * Create a translation matrix from a translation offset. + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.translate(dest, dest, vec); + * + * @param {mat4} out - Matrix to store result. + * @param {vec3} v - The translation offset. + * @returns {mat4} out. + */ + static fromTranslation(out, v) { + out.m00 = 1; + out.m01 = 0; + out.m02 = 0; + out.m03 = 0; + out.m04 = 0; + out.m05 = 1; + out.m06 = 0; + out.m07 = 0; + out.m08 = 0; + out.m09 = 0; + out.m10 = 1; + out.m11 = 0; + out.m12 = v.x; + out.m13 = v.y; + out.m14 = v.z; + out.m15 = 1; + return out; + } + + /** + * Creates a scale matrix from a scale vector. + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.scale(dest, dest, vec); + * + * @param {mat4} out - Matrix to store result. + * @param {vec3} v - The scale vector. + * @returns {mat4} out. + */ + static fromScaling(out, v) { + out.m00 = v.x; + out.m01 = 0; + out.m02 = 0; + out.m03 = 0; + out.m04 = 0; + out.m05 = v.y; + out.m06 = 0; + out.m07 = 0; + out.m08 = 0; + out.m09 = 0; + out.m10 = v.z; + out.m11 = 0; + out.m12 = 0; + out.m13 = 0; + out.m14 = 0; + out.m15 = 1; + return out; + } + + /** + * Creates a rotation matrix from the rotation around arbitrary axis. + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.rotate(dest, dest, rad, axis); + * + * @param {mat4} out - Matrix to store result. + * @param {Number} rad - The rotation angle. + * @param {vec3} axis - The rotation axis. + * @returns {mat4} out. + */ + static fromRotation(out, rad, axis) { + let x = axis.x, y = axis.y, z = axis.z; + let len = Math.sqrt(x * x + y * y + z * z); + let s, c, t; + + if (Math.abs(len) < EPSILON) { + return null; + } + + len = 1 / len; + x *= len; + y *= len; + z *= len; + + s = Math.sin(rad); + c = Math.cos(rad); + t = 1 - c; + + // Perform rotation-specific matrix multiplication + out.m00 = x * x * t + c; + out.m01 = y * x * t + z * s; + out.m02 = z * x * t - y * s; + out.m03 = 0; + out.m04 = x * y * t - z * s; + out.m05 = y * y * t + c; + out.m06 = z * y * t + x * s; + out.m07 = 0; + out.m08 = x * z * t + y * s; + out.m09 = y * z * t - x * s; + out.m10 = z * z * t + c; + out.m11 = 0; + out.m12 = 0; + out.m13 = 0; + out.m14 = 0; + out.m15 = 1; + return out; + } + + /** + * Creates a rotation matrix from the rotation around x-axis. + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.rotateX(dest, dest, rad); + * + * @param {mat4} out - Matrix to store result. + * @param {Number} rad - The rotation angle. + * @returns {mat4} out. + */ + static fromXRotation(out, rad) { + let s = Math.sin(rad), + c = Math.cos(rad); + + // Perform axis-specific matrix multiplication + out.m00 = 1; + out.m01 = 0; + out.m02 = 0; + out.m03 = 0; + out.m04 = 0; + out.m05 = c; + out.m06 = s; + out.m07 = 0; + out.m08 = 0; + out.m09 = -s; + out.m10 = c; + out.m11 = 0; + out.m12 = 0; + out.m13 = 0; + out.m14 = 0; + out.m15 = 1; + return out; + } + + /** + * Creates a rotation matrix from the rotation around y-axis. + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.rotateY(dest, dest, rad); + * + * @param {mat4} out - Matrix to store result. + * @param {Number} rad - The rotation angle. + * @returns {mat4} out. + */ + static fromYRotation(out, rad) { + let s = Math.sin(rad), + c = Math.cos(rad); + + // Perform axis-specific matrix multiplication + out.m00 = c; + out.m01 = 0; + out.m02 = -s; + out.m03 = 0; + out.m04 = 0; + out.m05 = 1; + out.m06 = 0; + out.m07 = 0; + out.m08 = s; + out.m09 = 0; + out.m10 = c; + out.m11 = 0; + out.m12 = 0; + out.m13 = 0; + out.m14 = 0; + out.m15 = 1; + return out; + } + + /** + * Creates a rotation matrix from the rotation around z-axis. + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.rotateZ(dest, dest, rad); + * + * @param {mat4} out - Matrix to store result. + * @param {Number} rad - The rotation angle. + * @returns {mat4} out. + */ + static fromZRotation(out, rad) { + let s = Math.sin(rad), + c = Math.cos(rad); + + // Perform axis-specific matrix multiplication + out.m00 = c; + out.m01 = s; + out.m02 = 0; + out.m03 = 0; + out.m04 = -s; + out.m05 = c; + out.m06 = 0; + out.m07 = 0; + out.m08 = 0; + out.m09 = 0; + out.m10 = 1; + out.m11 = 0; + out.m12 = 0; + out.m13 = 0; + out.m14 = 0; + out.m15 = 1; + return out; + } + + /** + * Creates a matrix from a quaternion rotation and a translation offset. + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.translate(dest, vec); + * let quatMat = mat4.create(); + * quat.toMat4(quat, quatMat); + * mat4.multiply(dest, quatMat); + * + * @param {mat4} out - Matrix to store result. + * @param {quat} q - Rotation quaternion. + * @param {vec3} v - Translation vector. + * @returns {mat4} out. + */ + static fromRT(out, q, v) { + // Quaternion math + let x = q.x, y = q.y, z = q.z, w = q.w; + let x2 = x + x; + let y2 = y + y; + let z2 = z + z; + + let xx = x * x2; + let xy = x * y2; + let xz = x * z2; + let yy = y * y2; + let yz = y * z2; + let zz = z * z2; + let wx = w * x2; + let wy = w * y2; + let wz = w * z2; + + out.m00 = 1 - (yy + zz); + out.m01 = xy + wz; + out.m02 = xz - wy; + out.m03 = 0; + out.m04 = xy - wz; + out.m05 = 1 - (xx + zz); + out.m06 = yz + wx; + out.m07 = 0; + out.m08 = xz + wy; + out.m09 = yz - wx; + out.m10 = 1 - (xx + yy); + out.m11 = 0; + out.m12 = v.x; + out.m13 = v.y; + out.m14 = v.z; + out.m15 = 1; + + return out; + } + + /** + * Returns the translation vector component of a transformation + * matrix. If a matrix is built with fromRT, + * the returned vector will be the same as the translation offset + * originally supplied. + * @param {vec3} out - Vector to store result. + * @param {mat4} mat - Matrix to be decomposed. + * @return {vec3} out. + */ + static getTranslation(out, mat) { + out.x = mat.m12; + out.y = mat.m13; + out.z = mat.m14; + + return out; + } + + /** + * Returns the scale component of a transformation + * matrix. If a matrix is built with fromRTS + * with a normalized Quaternion parameter, the returned vector will be + * the same as the scale vector + * originally supplied. + * @param {vec3} out - Vector to store result. + * @param {mat4} mat - Matrix to be decomposed. + * @return {vec3} out. + */ + static getScaling(out, mat) { + let m11 = mat.m00, + m12 = mat.m01, + m13 = mat.m02, + m21 = mat.m04, + m22 = mat.m05, + m23 = mat.m06, + m31 = mat.m08, + m32 = mat.m09, + m33 = mat.m10; + + out.x = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13); + out.y = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23); + out.z = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33); + + return out; + } + + /** + * Returns a quaternion representing the rotational component + * of a transformation matrix. If a matrix is built with + * fromRT, the returned quaternion will be the + * same as the quaternion originally supplied. + * @param {quat} out - Quaternion to store result. + * @param {mat4} mat - Matrix to be decomposed. + * @return {quat} out. + */ + static getRotation(out, mat) { + // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm + let trace = mat.m00 + mat.m05 + mat.m10; + let S = 0; + + if (trace > 0) { + S = Math.sqrt(trace + 1.0) * 2; + out.w = 0.25 * S; + out.x = (mat.m06 - mat.m09) / S; + out.y = (mat.m08 - mat.m02) / S; + out.z = (mat.m01 - mat.m04) / S; + } else if ((mat.m00 > mat.m05) & (mat.m00 > mat.m10)) { + S = Math.sqrt(1.0 + mat.m00 - mat.m05 - mat.m10) * 2; + out.w = (mat.m06 - mat.m09) / S; + out.x = 0.25 * S; + out.y = (mat.m01 + mat.m04) / S; + out.z = (mat.m08 + mat.m02) / S; + } else if (mat.m05 > mat.m10) { + S = Math.sqrt(1.0 + mat.m05 - mat.m00 - mat.m10) * 2; + out.w = (mat.m08 - mat.m02) / S; + out.x = (mat.m01 + mat.m04) / S; + out.y = 0.25 * S; + out.z = (mat.m06 + mat.m09) / S; + } else { + S = Math.sqrt(1.0 + mat.m10 - mat.m00 - mat.m05) * 2; + out.w = (mat.m01 - mat.m04) / S; + out.x = (mat.m08 + mat.m02) / S; + out.y = (mat.m06 + mat.m09) / S; + out.z = 0.25 * S; + } + + return out; + } + + /** + * Creates a matrix from a quaternion rotation, translation offset and scale vector. + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.translate(dest, vec); + * let quatMat = mat4.create(); + * quat.toMat4(quat, quatMat); + * mat4.multiply(dest, quatMat); + * mat4.scale(dest, scale) + * + * @param {mat4} out mat4 - Matrix to store result. + * @param {quat} q - Rotation quaternion. + * @param {vec3} v - Translation offset. + * @param {vec3} s - Scale vector. + * @returns {mat4} out. + */ + static fromRTS(out, q, v, s) { + // Quaternion math + let x = q.x, y = q.y, z = q.z, w = q.w; + let x2 = x + x; + let y2 = y + y; + let z2 = z + z; + + let xx = x * x2; + let xy = x * y2; + let xz = x * z2; + let yy = y * y2; + let yz = y * z2; + let zz = z * z2; + let wx = w * x2; + let wy = w * y2; + let wz = w * z2; + let sx = s.x; + let sy = s.y; + let sz = s.z; + + out.m00 = (1 - (yy + zz)) * sx; + out.m01 = (xy + wz) * sx; + out.m02 = (xz - wy) * sx; + out.m03 = 0; + out.m04 = (xy - wz) * sy; + out.m05 = (1 - (xx + zz)) * sy; + out.m06 = (yz + wx) * sy; + out.m07 = 0; + out.m08 = (xz + wy) * sz; + out.m09 = (yz - wx) * sz; + out.m10 = (1 - (xx + yy)) * sz; + out.m11 = 0; + out.m12 = v.x; + out.m13 = v.y; + out.m14 = v.z; + out.m15 = 1; + + return out; + } + + /** + * Creates a matrix from a quaternion rotation, translation offset and scale vector, rotating and scaling around the given origin. + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.translate(dest, vec); + * mat4.translate(dest, origin); + * let quatMat = mat4.create(); + * quat.toMat4(quat, quatMat); + * mat4.multiply(dest, quatMat); + * mat4.scale(dest, scale) + * mat4.translate(dest, negativeOrigin); + * + * @param {mat4} out mat4 - Matrix to store result. + * @param {quat} q - Rotation quaternion. + * @param {vec3} v - Translation offset. + * @param {vec3} s - Scale vector. + * @param {vec3} o The origin vector around which to scale and rotate. + * @returns {mat4} out. + */ + static fromRTSOrigin(out, q, v, s, o) { + // Quaternion math + let x = q.x, y = q.y, z = q.z, w = q.w; + let x2 = x + x; + let y2 = y + y; + let z2 = z + z; + + let xx = x * x2; + let xy = x * y2; + let xz = x * z2; + let yy = y * y2; + let yz = y * z2; + let zz = z * z2; + let wx = w * x2; + let wy = w * y2; + let wz = w * z2; + + let sx = s.x; + let sy = s.y; + let sz = s.z; + + let ox = o.x; + let oy = o.y; + let oz = o.z; + + out.m00 = (1 - (yy + zz)) * sx; + out.m01 = (xy + wz) * sx; + out.m02 = (xz - wy) * sx; + out.m03 = 0; + out.m04 = (xy - wz) * sy; + out.m05 = (1 - (xx + zz)) * sy; + out.m06 = (yz + wx) * sy; + out.m07 = 0; + out.m08 = (xz + wy) * sz; + out.m09 = (yz - wx) * sz; + out.m10 = (1 - (xx + yy)) * sz; + out.m11 = 0; + out.m12 = v.x + ox - (out.m00 * ox + out.m04 * oy + out.m08 * oz); + out.m13 = v.y + oy - (out.m01 * ox + out.m05 * oy + out.m09 * oz); + out.m14 = v.z + oz - (out.m02 * ox + out.m06 * oy + out.m10 * oz); + out.m15 = 1; + + return out; + } + + /** + * Calculates a 4x4 matrix from the given quaternion. + * + * @param {mat4} out mat4 - Matrix to store result. + * @param {quat} q - Quaternion to create matrix from. + * + * @returns {mat4} out. + */ + static fromQuat(out, q) { + let x = q.x, y = q.y, z = q.z, w = q.w; + let x2 = x + x; + let y2 = y + y; + let z2 = z + z; + + let xx = x * x2; + let yx = y * x2; + let yy = y * y2; + let zx = z * x2; + let zy = z * y2; + let zz = z * z2; + let wx = w * x2; + let wy = w * y2; + let wz = w * z2; + + out.m00 = 1 - yy - zz; + out.m01 = yx + wz; + out.m02 = zx - wy; + out.m03 = 0; + + out.m04 = yx - wz; + out.m05 = 1 - xx - zz; + out.m06 = zy + wx; + out.m07 = 0; + + out.m08 = zx + wy; + out.m09 = zy - wx; + out.m10 = 1 - xx - yy; + out.m11 = 0; + + out.m12 = 0; + out.m13 = 0; + out.m14 = 0; + out.m15 = 1; + + return out; + } + + /** + * Generates a frustum matrix with the given bounds. + * + * @param {mat4} out mat4 - Matrix to store result. + * @param {Number} left - Left bound of the frustum. + * @param {Number} right - Right bound of the frustum. + * @param {Number} bottom - Bottom bound of the frustum. + * @param {Number} top - Top bound of the frustum. + * @param {Number} near - Near bound of the frustum. + * @param {Number} far - Far bound of the frustum. + * @returns {mat4} out. + */ + static frustum(out, left, right, bottom, top, near, far) { + let rl = 1 / (right - left); + let tb = 1 / (top - bottom); + let nf = 1 / (near - far); + + out.m00 = (near * 2) * rl; + out.m01 = 0; + out.m02 = 0; + out.m03 = 0; + out.m04 = 0; + out.m05 = (near * 2) * tb; + out.m06 = 0; + out.m07 = 0; + out.m08 = (right + left) * rl; + out.m09 = (top + bottom) * tb; + out.m10 = (far + near) * nf; + out.m11 = -1; + out.m12 = 0; + out.m13 = 0; + out.m14 = (far * near * 2) * nf; + out.m15 = 0; + return out; + } + + /** + * Generates a perspective projection matrix with the given bounds. + * + * @param {mat4} out - Matrix to store result. + * @param {number} fovy - Vertical field of view in radians. + * @param {number} aspect - Aspect ratio. typically viewport width/height. + * @param {number} near - Near bound of the frustum. + * @param {number} far - Far bound of the frustum. + * @returns {mat4} out. + */ + static perspective(out, fovy, aspect, near, far) { + let f = 1.0 / Math.tan(fovy / 2); + let nf = 1 / (near - far); + + out.m00 = f / aspect; + out.m01 = 0; + out.m02 = 0; + out.m03 = 0; + out.m04 = 0; + out.m05 = f; + out.m06 = 0; + out.m07 = 0; + out.m08 = 0; + out.m09 = 0; + out.m10 = (far + near) * nf; + out.m11 = -1; + out.m12 = 0; + out.m13 = 0; + out.m14 = (2 * far * near) * nf; + out.m15 = 0; + return out; + } + + /** + * Generates a perspective projection matrix with the given field of view. + * This is primarily useful for generating projection matrices to be used + * with the still experiemental WebVR API. + * + * @param {mat4} out - Matrix to store result. + * @param {Object} fov - Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees. + * @param {number} near - Near bound of the frustum. + * @param {number} far - Far bound of the frustum. + * @returns {mat4} out. + */ + static perspectiveFromFieldOfView(out, fov, near, far) { + let upTan = Math.tan(fov.upDegrees * Math.PI / 180.0); + let downTan = Math.tan(fov.downDegrees * Math.PI / 180.0); + let leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0); + let rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0); + let xScale = 2.0 / (leftTan + rightTan); + let yScale = 2.0 / (upTan + downTan); + + out.m00 = xScale; + out.m01 = 0.0; + out.m02 = 0.0; + out.m03 = 0.0; + out.m04 = 0.0; + out.m05 = yScale; + out.m06 = 0.0; + out.m07 = 0.0; + out.m08 = -((leftTan - rightTan) * xScale * 0.5); + out.m09 = ((upTan - downTan) * yScale * 0.5); + out.m10 = far / (near - far); + out.m11 = -1.0; + out.m12 = 0.0; + out.m13 = 0.0; + out.m14 = (far * near) / (near - far); + out.m15 = 0.0; + return out; + } + + /** + * Generates a orthogonal projection matrix with the given bounds. + * + * @param {mat4} out - Matrix to store result. + * @param {number} left - Left bound of the frustum. + * @param {number} right - Right bound of the frustum. + * @param {number} bottom - Bottom bound of the frustum. + * @param {number} top - Top bound of the frustum. + * @param {number} near - Near bound of the frustum. + * @param {number} far - Far bound of the frustum. + * @returns {mat4} out. + */ + static ortho(out, left, right, bottom, top, near, far) { + let lr = 1 / (left - right); + let bt = 1 / (bottom - top); + let nf = 1 / (near - far); + out.m00 = -2 * lr; + out.m01 = 0; + out.m02 = 0; + out.m03 = 0; + out.m04 = 0; + out.m05 = -2 * bt; + out.m06 = 0; + out.m07 = 0; + out.m08 = 0; + out.m09 = 0; + out.m10 = 2 * nf; + out.m11 = 0; + out.m12 = (left + right) * lr; + out.m13 = (top + bottom) * bt; + out.m14 = (far + near) * nf; + out.m15 = 1; + return out; + } + + /** + * Generates a look-at matrix with the given eye position, focal point, and up axis. + * `eye - center` mustn't be zero vector or parallel to `up` + * + * @param {mat4} out - Matrix to store result. + * @param {vec3} eye - Position of the viewer. + * @param {vec3} center - Point the viewer is looking at. + * @param {vec3} up - Vector pointing up. + * @returns {mat4} out + */ + static lookAt(out, eye, center, up) { + let x0, x1, x2, y0, y1, y2, z0, z1, z2, len; + let eyex = eye.x; + let eyey = eye.y; + let eyez = eye.z; + let upx = up.x; + let upy = up.y; + let upz = up.z; + let centerx = center.x; + let centery = center.y; + let centerz = center.z; + + z0 = eyex - centerx; + z1 = eyey - centery; + z2 = eyez - centerz; + + len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); + z0 *= len; + z1 *= len; + z2 *= len; + + x0 = upy * z2 - upz * z1; + x1 = upz * z0 - upx * z2; + x2 = upx * z1 - upy * z0; + len = 1 / Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); + x0 *= len; + x1 *= len; + x2 *= len; + + y0 = z1 * x2 - z2 * x1; + y1 = z2 * x0 - z0 * x2; + y2 = z0 * x1 - z1 * x0; + + out.m00 = x0; + out.m01 = y0; + out.m02 = z0; + out.m03 = 0; + out.m04 = x1; + out.m05 = y1; + out.m06 = z1; + out.m07 = 0; + out.m08 = x2; + out.m09 = y2; + out.m10 = z2; + out.m11 = 0; + out.m12 = -(x0 * eyex + x1 * eyey + x2 * eyez); + out.m13 = -(y0 * eyex + y1 * eyey + y2 * eyez); + out.m14 = -(z0 * eyex + z1 * eyey + z2 * eyez); + out.m15 = 1; + + return out; + } + + /** + * Returns a string representation of a matrix. + * + * @param {mat4} a - The matrix. + * @returns {String} String representation of this matrix. + */ + static str(a) { + return `mat4(${a.m00}, ${a.m01}, ${a.m02}, ${a.m03}, ${a.m04}, ${a.m05}, ${a.m06}, ${a.m07}, ${a.m08}, ${a.m09}, ${a.m10}, ${a.m11}, ${a.m12}, ${a.m13}, ${a.m14}, ${a.m15})`; + } + + /** + * Store elements of a matrix into array. + * + * @param {array} out - Array to store result. + * @param {mat4} m - The matrix. + * @returns {Array} out. + */ + static array(out, m) { + out[0] = m.m00; + out[1] = m.m01; + out[2] = m.m02; + out[3] = m.m03; + out[4] = m.m04; + out[5] = m.m05; + out[6] = m.m06; + out[7] = m.m07; + out[8] = m.m08; + out[9] = m.m09; + out[10] = m.m10; + out[11] = m.m11; + out[12] = m.m12; + out[13] = m.m13; + out[14] = m.m14; + out[15] = m.m15; + + return out; + } + + /** + * Returns Frobenius norm of a matrix. + * + * @param {mat4} a - Matrix to calculate Frobenius norm of. + * @returns {Number} - The frobenius norm. + */ + static frob(a) { + return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2) + Math.pow(a.m09, 2) + Math.pow(a.m10, 2) + Math.pow(a.m11, 2) + Math.pow(a.m12, 2) + Math.pow(a.m13, 2) + Math.pow(a.m14, 2) + Math.pow(a.m15, 2))) + } + + /** + * Adds two matrices. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - The first operand. + * @param {mat4} b - The second operand. + * @returns {mat4} out. + */ + static add(out, a, b) { + out.m00 = a.m00 + b.m00; + out.m01 = a.m01 + b.m01; + out.m02 = a.m02 + b.m02; + out.m03 = a.m03 + b.m03; + out.m04 = a.m04 + b.m04; + out.m05 = a.m05 + b.m05; + out.m06 = a.m06 + b.m06; + out.m07 = a.m07 + b.m07; + out.m08 = a.m08 + b.m08; + out.m09 = a.m09 + b.m09; + out.m10 = a.m10 + b.m10; + out.m11 = a.m11 + b.m11; + out.m12 = a.m12 + b.m12; + out.m13 = a.m13 + b.m13; + out.m14 = a.m14 + b.m14; + out.m15 = a.m15 + b.m15; + return out; + } + + /** + * Subtracts matrix b from matrix a. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - The first operand. + * @param {mat4} b - The second operand. + * @returns {mat4} out. + */ + static subtract(out, a, b) { + out.m00 = a.m00 - b.m00; + out.m01 = a.m01 - b.m01; + out.m02 = a.m02 - b.m02; + out.m03 = a.m03 - b.m03; + out.m04 = a.m04 - b.m04; + out.m05 = a.m05 - b.m05; + out.m06 = a.m06 - b.m06; + out.m07 = a.m07 - b.m07; + out.m08 = a.m08 - b.m08; + out.m09 = a.m09 - b.m09; + out.m10 = a.m10 - b.m10; + out.m11 = a.m11 - b.m11; + out.m12 = a.m12 - b.m12; + out.m13 = a.m13 - b.m13; + out.m14 = a.m14 - b.m14; + out.m15 = a.m15 - b.m15; + return out; + } + + /** + * Alias of {@link mat4.subtract}. + */ + static sub(out, a, b) { + return mat4.subtract(out, a, b); + } + + /** + * Multiply each element of a matrix by a scalar number. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - Matrix to scale + * @param {Number} b - The scale number. + * @returns {mat4} out. + */ + static multiplyScalar(out, a, b) { + out.m00 = a.m00 * b; + out.m01 = a.m01 * b; + out.m02 = a.m02 * b; + out.m03 = a.m03 * b; + out.m04 = a.m04 * b; + out.m05 = a.m05 * b; + out.m06 = a.m06 * b; + out.m07 = a.m07 * b; + out.m08 = a.m08 * b; + out.m09 = a.m09 * b; + out.m10 = a.m10 * b; + out.m11 = a.m11 * b; + out.m12 = a.m12 * b; + out.m13 = a.m13 * b; + out.m14 = a.m14 * b; + out.m15 = a.m15 * b; + return out; + } + + /** + * Adds two matrices after multiplying each element of the second operand by a scalar number. + * + * @param {mat4} out - Matrix to store result. + * @param {mat4} a - The first operand. + * @param {mat4} b - The second operand. + * @param {Number} scale - The scale number. + * @returns {mat4} out. + */ + static multiplyScalarAndAdd(out, a, b, scale) { + out.m00 = a.m00 + (b.m00 * scale); + out.m01 = a.m01 + (b.m01 * scale); + out.m02 = a.m02 + (b.m02 * scale); + out.m03 = a.m03 + (b.m03 * scale); + out.m04 = a.m04 + (b.m04 * scale); + out.m05 = a.m05 + (b.m05 * scale); + out.m06 = a.m06 + (b.m06 * scale); + out.m07 = a.m07 + (b.m07 * scale); + out.m08 = a.m08 + (b.m08 * scale); + out.m09 = a.m09 + (b.m09 * scale); + out.m10 = a.m10 + (b.m10 * scale); + out.m11 = a.m11 + (b.m11 * scale); + out.m12 = a.m12 + (b.m12 * scale); + out.m13 = a.m13 + (b.m13 * scale); + out.m14 = a.m14 + (b.m14 * scale); + out.m15 = a.m15 + (b.m15 * scale); + return out; + } + + /** + * Returns whether the specified matrices are equal. (Compared using ===) + * + * @param {mat4} a - The first matrix. + * @param {mat4} b - The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ + static exactEquals(a, b) { + return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && + a.m04 === b.m04 && a.m05 === b.m05 && a.m06 === b.m06 && a.m07 === b.m07 && + a.m08 === b.m08 && a.m09 === b.m09 && a.m10 === b.m10 && a.m11 === b.m11 && + a.m12 === b.m12 && a.m13 === b.m13 && a.m14 === b.m14 && a.m15 === b.m15; + } + + /** + * Returns whether the specified matrices are approximately equal. + * + * @param {mat4} a - The first matrix. + * @param {mat4} b - The second matrix. + * @returns {Boolean} True if the matrices are equal, false otherwise. + */ + static equals(a, b) { + let a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, + a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, + a8 = a.m08, a9 = a.m09, a10 = a.m10, a11 = a.m11, + a12 = a.m12, a13 = a.m13, a14 = a.m14, a15 = a.m15; + + let b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, + b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, + b8 = b.m08, b9 = b.m09, b10 = b.m10, b11 = b.m11, + b12 = b.m12, b13 = b.m13, b14 = b.m14, b15 = b.m15; + + return ( + Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && + Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && + Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && + Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && + Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && + Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && + Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && + Math.abs(a9 - b9) <= EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && + Math.abs(a10 - b10) <= EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && + Math.abs(a11 - b11) <= EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && + Math.abs(a12 - b12) <= EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && + Math.abs(a13 - b13) <= EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && + Math.abs(a14 - b14) <= EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && + Math.abs(a15 - b15) <= EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15)) + ); + } +} + +export default mat4; \ No newline at end of file diff --git a/cocos2d/core/vmath/quat.js b/cocos2d/core/vmath/quat.js new file mode 100644 index 00000000000..7876482bba5 --- /dev/null +++ b/cocos2d/core/vmath/quat.js @@ -0,0 +1,822 @@ +import vec3 from './vec3'; +import vec4 from './vec4'; +import mat3 from './mat3'; +import { toDegree } from './utils'; + +let halfToRad = 0.5 * Math.PI / 180.0; + +/** + * Mathematical quaternion. + * + * A quaternion is a hypercomplex number represented by w + xi + yj + zk, where + * x, y, z and w are real numbers(called here its components), and i, j, and k are the fundamental quaternion units. + */ +class quat { + /** + * Creates a quaternion, with components specified separately. + * + * @param {number} x - Value assigned to x component. + * @param {number} y - Value assigned to y component. + * @param {number} z - Value assigned to z component. + * @param {number} w - Value assigned to w component. + */ + constructor(x = 0, y = 0, z = 0, w = 1) { + /** + * The x component. + * @type {number} + * */ + this.x = x; + + /** + * The y component. + * @type {number} + * */ + this.y = y; + + /** + * The z component. + * @type {number} + * */ + this.z = z; + + /** + * The w component. + * @type {number} + * */ + this.w = w; + } + + /** + * Creates a quaternion, with components specified separately. + * + * @param {number} x - Value assigned to x component. + * @param {number} y - Value assigned to y component. + * @param {number} z - Value assigned to z component. + * @param {number} w - Value assigned to w component. + * @return {quat} The newly created quaternion. + */ + static create(x = 0, y = 0, z = 0, w = 1) { + return new quat(x, y, z, w); + } + + /** + * Clone a quaternion. + * + * @param {quat} a - Quaternion to clone. + * @returns {quat} The newly created quaternion. + */ + static clone(a) { + return new quat(a.x, a.y, a.z, a.w); + } + + /** + * Copy content of a quaternion into another. + * + * @param {quat} out - Quaternion to modified. + * @param {quat} a - The specified quaternion. + * @returns {quat} out. + */ + static copy(out, a) { + return vec4.copy(out, a); + } + + /** + * Sets the components of a quaternion to the given values. + * + * @param {quat} out - The quaternion to modified. + * @param {Number} x - Value set to x component. + * @param {Number} y - Value set to y component. + * @param {Number} z - Value set to z component. + * @param {Number} w - Value set to w component. + * @returns {quat} out. + */ + static set(out, x, y, z, w) { + out.x = x; + out.y = y; + out.z = z; + out.w = w; + return out; + } + + /** + * Sets a quaternion as identity quaternion. + * + * @param {quat} out - Quaternion to set. + * @returns {quat} out. + */ + static identity(out) { + out.x = 0; + out.y = 0; + out.z = 0; + out.w = 1; + return out; + } + + /** + * Sets a quaternion to represent the shortest rotation from one + * vector to another. + * + * Both vectors are assumed to be unit length. + * + * @param {quat} out - Quaternion to set. + * @param {vec3} a - The initial vector. + * @param {vec3} b - The destination vector. + * @returns {quat} out. + */ + static rotationTo(out, a, b) { + let rotationToIIFE = (function () { + let tmpvec3 = vec3.create(0, 0, 0); + let xUnitVec3 = vec3.create(1, 0, 0); + let yUnitVec3 = vec3.create(0, 1, 0); + + return function (out, a, b) { + let dot = vec3.dot(a, b); + if (dot < -0.999999) { + vec3.cross(tmpvec3, xUnitVec3, a); + if (vec3.magnitude(tmpvec3) < 0.000001) { + vec3.cross(tmpvec3, yUnitVec3, a); + } + vec3.normalize(tmpvec3, tmpvec3); + quat.fromAxisAngle(out, tmpvec3, Math.PI); + return out; + } else if (dot > 0.999999) { + out.x = 0; + out.y = 0; + out.z = 0; + out.w = 1; + return out; + } else { + vec3.cross(tmpvec3, a, b); + out.x = tmpvec3.x; + out.y = tmpvec3.y; + out.z = tmpvec3.z; + out.w = 1 + dot; + return quat.normalize(out, out); + } + }; + })(); + + return rotationToIIFE(out, a, b); + } + + /** + * Gets the rotation axis and angle for a given + * quaternion. If a quaternion is created with + * fromAxisAngle, this method will return the same + * values as provided in the original parameter list + * OR functionally equivalent values. + * Example: The quaternion formed by axis [0, 0, 1] and + * angle -90 is the same as the quaternion formed by + * [0, 0, 1] and 270. This method favors the latter. + * @param {vec3} out_axis - Vector to store the rotation axis. + * @param {quat} q - Quaternion to be decomposed. + * @return {Number} - Angle, in radians, of the rotation. + */ + static getAxisAngle(out_axis, q) { + let rad = Math.acos(q.w) * 2.0; + let s = Math.sin(rad / 2.0); + if (s != 0.0) { + out_axis.x = q.x / s; + out_axis.y = q.y / s; + out_axis.z = q.z / s; + } else { + // If s is zero, return any axis (no rotation - axis does not matter) + out_axis.x = 1; + out_axis.y = 0; + out_axis.z = 0; + } + return rad; + } + + /** + * Multiply two quaternions. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - The first operand. + * @param {quat} b - The second operand. + * @returns {quat} out. + */ + static multiply(out, a, b) { + let ax = a.x, ay = a.y, az = a.z, aw = a.w, + bx = b.x, by = b.y, bz = b.z, bw = b.w; + + out.x = ax * bw + aw * bx + ay * bz - az * by; + out.y = ay * bw + aw * by + az * bx - ax * bz; + out.z = az * bw + aw * bz + ax * by - ay * bx; + out.w = aw * bw - ax * bx - ay * by - az * bz; + return out; + } + + /** + * Alias of {@link quat.multiply}. + */ + static mul(out, a, b) { + return quat.multiply(out, a, b); + } + + /** + * Scales a quaternion with a number. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - Quaternion to scale. + * @param {quat} b - The scale number. + * @returns {quat} out. + * */ + static scale(out, a, b) { + out.x = a.x * b; + out.y = a.y * b; + out.z = a.z * b; + out.w = a.w * b; + return out; + } + + /** + * Rotates a quaternion by the given angle about the X axis. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - Quaternion to rotate. + * @param {number} rad - Angle (in radians) to rotate. + * @returns {quat} out. + */ + static rotateX(out, a, rad) { + rad *= 0.5; + + let ax = a.x, ay = a.y, az = a.z, aw = a.w, + bx = Math.sin(rad), bw = Math.cos(rad); + + out.x = ax * bw + aw * bx; + out.y = ay * bw + az * bx; + out.z = az * bw - ay * bx; + out.w = aw * bw - ax * bx; + return out; + } + + /** + * Rotates a quaternion by the given angle about the Y axis. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - Quaternion to rotate. + * @param {number} rad - Angle (in radians) to rotate. + * @returns {quat} out. + */ + static rotateY(out, a, rad) { + rad *= 0.5; + + let ax = a.x, ay = a.y, az = a.z, aw = a.w, + by = Math.sin(rad), bw = Math.cos(rad); + + out.x = ax * bw - az * by; + out.y = ay * bw + aw * by; + out.z = az * bw + ax * by; + out.w = aw * bw - ay * by; + return out; + } + + /** + * Rotates a quaternion by the given angle about the Z axis. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - Quaternion to rotate. + * @param {number} rad - Angle (in radians) to rotate. + * @returns {quat} out. + */ + static rotateZ(out, a, rad) { + rad *= 0.5; + + let ax = a.x, ay = a.y, az = a.z, aw = a.w, + bz = Math.sin(rad), bw = Math.cos(rad); + + out.x = ax * bw + ay * bz; + out.y = ay * bw - ax * bz; + out.z = az * bw + aw * bz; + out.w = aw * bw - az * bz; + return out; + } + + /** + * Rotates a quaternion by the given angle about a world space axis. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} rot - Quaternion to rotate. + * @param {vec3} axis - The axis around which to rotate in world space. + * @param {number} rad - Angle (in radians) to rotate. + * @returns {quat} out. + */ + static rotateAround(out, rot, axis, rad) { + let rotateAroundIIFE = (function () { + let v3_tmp = vec3.create(0, 0, 0); + let q_tmp = quat.create(); + + return function (out, rot, axis, rad) { + // get inv-axis (local to rot) + quat.invert(q_tmp, rot); + vec3.transformQuat(v3_tmp, axis, q_tmp); + // rotate by inv-axis + quat.fromAxisAngle(q_tmp, v3_tmp, rad); + quat.mul(out, rot, q_tmp); + + return out; + }; + })(); + return rotateAroundIIFE(out, rot, axis, rad); + } + + /** + * Rotates a quaternion by the given angle about a local space axis. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} rot - Quaternion to rotate. + * @param {vec3} axis - The axis around which to rotate in local space. + * @param {number} rad - Angle (in radians) to rotate. + * @returns {quat} out. + */ + static rotateAroundLocal(out, rot, axis, rad) { + let rotateAroundLocalIIFE = (function () { + let q_tmp = quat.create(); + + return function (out, rot, axis, rad) { + quat.fromAxisAngle(q_tmp, axis, rad); + quat.mul(out, rot, q_tmp); + + return out; + }; + })(); + + return rotateAroundLocalIIFE(out, rot, axis, rad); + } + + /** + * Calculates the W component of a quaternion from the X, Y, and Z components. + * Assumes that quaternion is 1 unit in length. + * Any existing W component will be ignored. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - Quaternion to calculate W. + * @returns {quat} out. + */ + static calculateW(out, a) { + let x = a.x, y = a.y, z = a.z; + + out.x = x; + out.y = y; + out.z = z; + out.w = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); + return out; + } + + /** + * Calculates the dot product of two quaternions. + * + * @param {quat} a - The first operand. + * @param {quat} b - The second operand. + * @returns {Number} - The dot product of a and b. + */ + static dot(a, b) { + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; + } + + /** + * Performs a linear interpolation between two quaternions. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - The first operand. + * @param {quat} b - The second operand. + * @param {Number} t - The interpolation coefficient. + * @returns {quat} out. + */ + static lerp(out, a, b, t) { + let ax = a.x, + ay = a.y, + az = a.z, + aw = a.w; + out.x = ax + t * (b.x - ax); + out.y = ay + t * (b.y - ay); + out.z = az + t * (b.z - az); + out.w = aw + t * (b.w - aw); + return out; + } + + /** + * Performs a spherical linear interpolation between two quaternions. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - The first operand. + * @param {quat} b - The second operand. + * @param {Number} t - The interpolation coefficient. + * @returns {quat} out. + */ + static slerp(out, a, b, t) { + // benchmarks: + // http://jsperf.com/quaternion-slerp-implementations + + let ax = a.x, ay = a.y, az = a.z, aw = a.w, + bx = b.x, by = b.y, bz = b.z, bw = b.w; + + let omega, cosom, sinom, scale0, scale1; + + // calc cosine + cosom = ax * bx + ay * by + az * bz + aw * bw; + // adjust signs (if necessary) + if (cosom < 0.0) { + cosom = -cosom; + bx = -bx; + by = -by; + bz = -bz; + bw = -bw; + } + // calculate coefficients + if ((1.0 - cosom) > 0.000001) { + // standard case (slerp) + omega = Math.acos(cosom); + sinom = Math.sin(omega); + scale0 = Math.sin((1.0 - t) * omega) / sinom; + scale1 = Math.sin(t * omega) / sinom; + } else { + // "from" and "to" quaternions are very close + // ... so we can do a linear interpolation + scale0 = 1.0 - t; + scale1 = t; + } + // calculate final values + out.x = scale0 * ax + scale1 * bx; + out.y = scale0 * ay + scale1 * by; + out.z = scale0 * az + scale1 * bz; + out.w = scale0 * aw + scale1 * bw; + + return out; + } + + /** + * Performs a spherical linear interpolation with two control points. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - The first operand. + * @param {quat} b - The second operand. + * @param {quat} c - The third operand. + * @param {quat} d - The fourth operand. + * @param {Number} t - The interpolation coefficient. + * @returns {quat} out + */ + static sqlerp(out, a, b, c, d, t) { + let sqlerpIIFE = (function () { + let temp1 = quat.create(); + let temp2 = quat.create(); + + return function (out, a, b, c, d, t) { + quat.slerp(temp1, a, d, t); + quat.slerp(temp2, b, c, t); + quat.slerp(out, temp1, temp2, 2 * t * (1 - t)); + + return out; + }; + }()); + return sqlerpIIFE(out, a, b, c, d, t); + } + + /** + * Calculates the inverse of a quaternion. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - Quaternion to calculate inverse of. + * @returns {quat} out. + */ + static invert(out, a) { + let a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; + let dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3; + let invDot = dot ? 1.0 / dot : 0; + + // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 + + out.x = -a0 * invDot; + out.y = -a1 * invDot; + out.z = -a2 * invDot; + out.w = a3 * invDot; + return out; + } + + /** + * Calculates the conjugate of a quaternion. + * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - Quaternion to calculate conjugate of. + * @returns {quat} out. + */ + static conjugate(out, a) { + out.x = -a.x; + out.y = -a.y; + out.z = -a.z; + out.w = a.w; + return out; + } + + /** + * Calculates the length of a quaternion. + * + * @param {quat} a - The quaternion. + * @returns {Number} Length of the quaternion. + */ + static magnitude(a) { + let x = a.x, + y = a.y, + z = a.z, + w = a.w; + return Math.sqrt(x * x + y * y + z * z + w * w); + } + + /** + *Alias of {@link quat.magnitude}. + */ + static mag(a) { + return quat.magnitude(a); + } + + /** + * Calculates the squared length of a quaternion. + * + * @param {quat} a - The quaternion. + * @returns {Number} Squared length of the quaternion. + */ + static squaredMagnitude(a) { + let x = a.x, + y = a.y, + z = a.z, + w = a.w; + return x * x + y * y + z * z + w * w; + } + + /** + *Alias of {@link quat.squaredMagnitude} + */ + static sqrMag(a) { + return quat.squaredMagnitude(a); + } + + /** + * Normalizes a quaternion. + * + * @param {quat} out - Quaternion to store result. + * @param {quat} a - Quaternion to normalize. + * @returns {quat} out. + * @function + */ + static normalize(out, a) { + let x = a.x, + y = a.y, + z = a.z, + w = a.w; + let len = x * x + y * y + z * z + w * w; + if (len > 0) { + len = 1 / Math.sqrt(len); + out.x = x * len; + out.y = y * len; + out.z = z * len; + out.w = w * len; + } + return out; + } + + /** + * Sets the specified quaternion with values corresponding to the given + * axes. Each axis is a vec3 and is expected to be unit length and + * perpendicular to all other specified axes. + * + * @param {quat} out - Quaternion to store result. + * @param {vec3} xAxis - Vector representing the local "right" direction. + * @param {vec3} yAxis - Vector representing the local "up" direction. + * @param {vec3} zAxis - Vector representing the viewing direction. + * @returns {quat} out. + */ + static fromAxes(out, xAxis, yAxis, zAxis) { + let fromAxesIIFE = (function () { + let matr = mat3.create(); + + return function (out, xAxis, yAxis, zAxis) { + mat3.set(matr, + xAxis.x, xAxis.y, xAxis.z, + yAxis.x, yAxis.y, yAxis.z, + zAxis.x, zAxis.y, zAxis.z + ); + return quat.normalize(out, quat.fromMat3(out, matr)); + }; + })(); + return fromAxesIIFE(out, xAxis, yAxis, zAxis); + } + + /** + * Calculates a quaternion from view direction and up direction + * + * @param {quat} out - Quaternion to store result. + * @param {vec3} view - View direction (must be normalized). + * @param {vec3} [up] - Up direction, default is (0,1,0) (must be normalized). + * + * @returns {quat} out. + */ + static fromViewUp(out, view, up) { + let fromViewUpIIFE = (function () { + let matr = mat3.create(); + + return function (out, view, up) { + mat3.fromViewUp(matr, view, up); + if (!matr) { + return null; + } + + return quat.normalize(out, quat.fromMat3(out, matr)); + }; + })(); + return fromViewUpIIFE(out, view, up); + } + + /** + * Sets a quaternion from the given angle and rotation axis, + * then returns it. + * + * @param {quat} out - Quaternion to store result. + * @param {vec3} axis - The axis around which to rotate. + * @param {Number} rad - The angle in radians. + * @returns {quat} out. + **/ + static fromAxisAngle(out, axis, rad) { + rad = rad * 0.5; + let s = Math.sin(rad); + out.x = s * axis.x; + out.y = s * axis.y; + out.z = s * axis.z; + out.w = Math.cos(rad); + return out; + } + + /** + * Creates a quaternion from the given 3x3 rotation matrix. + * + * NOTE: The resultant quaternion is not normalized, so you should be sure + * to re-normalize the quaternion yourself where necessary. + * + * @param {quat} out - Quaternion to store result. + * @param {mat3} m - The rotation matrix. + * @returns {quat} out. + * @function + */ + static fromMat3(out, m) { + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm + + let m00 = m.m00, m01 = m.m03, m02 = m.m06, + m10 = m.m01, m11 = m.m04, m12 = m.m07, + m20 = m.m02, m21 = m.m05, m22 = m.m08; + + let trace = m00 + m11 + m22; + + if (trace > 0) { + let s = 0.5 / Math.sqrt(trace + 1.0); + + out.w = 0.25 / s; + out.x = (m21 - m12) * s; + out.y = (m02 - m20) * s; + out.z = (m10 - m01) * s; + + } else if ((m00 > m11) && (m00 > m22)) { + let s = 2.0 * Math.sqrt(1.0 + m00 - m11 - m22); + + out.w = (m21 - m12) / s; + out.x = 0.25 * s; + out.y = (m01 + m10) / s; + out.z = (m02 + m20) / s; + + } else if (m11 > m22) { + let s = 2.0 * Math.sqrt(1.0 + m11 - m00 - m22); + + out.w = (m02 - m20) / s; + out.x = (m01 + m10) / s; + out.y = 0.25 * s; + out.z = (m12 + m21) / s; + + } else { + let s = 2.0 * Math.sqrt(1.0 + m22 - m00 - m11); + + out.w = (m10 - m01) / s; + out.x = (m02 + m20) / s; + out.y = (m12 + m21) / s; + out.z = 0.25 * s; + } + + return out; + } + + /** + * Creates a quaternion from the given euler angle x, y, z. + * + * @param {quat} out - Quaternion to store result. + * @param {number} x - Angle to rotate around X axis in degrees. + * @param {number} y - Angle to rotate around Y axis in degrees. + * @param {number} z - Angle to rotate around Z axis in degrees. + * @returns {quat} out. + * @function + */ + static fromEuler(out, x, y, z) { + x *= halfToRad; + y *= halfToRad; + z *= halfToRad; + + let sx = Math.sin(x); + let cx = Math.cos(x); + let sy = Math.sin(y); + let cy = Math.cos(y); + let sz = Math.sin(z); + let cz = Math.cos(z); + + out.x = sx * cy * cz + cx * sy * sz; + out.y = cx * sy * cz + sx * cy * sz; + out.z = cx * cy * sz - sx * sy * cz; + out.w = cx * cy * cz - sx * sy * sz; + + return out; + } + + /** + * Convert a quaternion back to euler angle (in degrees). + * + * @param {vec3} out - Euler angle stored as a vec3 + * @param {number} q - the quaternion to be converted + * @returns {vec3} out. + */ + static toEuler(out, q) { + let x = q.x, y = q.y, z = q.z, w = q.w; + let heading, attitude, bank; + let test = x * y + z * w; + if (test > 0.499) { // singularity at north pole + heading = 2 * Math.atan2(x,w); + attitude = Math.PI/2; + bank = 0; + } + if (test < -0.499) { // singularity at south pole + heading = -2 * Math.atan2(x,w); + attitude = - Math.PI/2; + bank = 0; + } + if(isNaN(heading)){ + let sqx = x*x; + let sqy = y*y; + let sqz = z*z; + heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // heading + attitude = Math.asin(2*test); // attitude + bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank + } + + out.y = toDegree(heading); + out.z = toDegree(attitude); + out.x = toDegree(bank); + + return out; + } + + /** + * Returns string representation of a quaternion. + * + * @param {quat} a - The quaternion. + * @returns {String} - String representation of this quaternion. + */ + static str(a) { + return `quat(${a.x}, ${a.y}, ${a.z}, ${a.w})`; + } + + /** + * Store components of a quaternion into array. + * + * @param {Array} out - Array to store result. + * @param {quat} q - The quaternion. + * @returns {Array} out. + */ + static array(out, q) { + out[0] = q.x; + out[1] = q.y; + out[2] = q.z; + out[3] = q.w; + + return out; + } + + /** + * Returns whether the specified quaternions are equal. (Compared using ===) + * + * @param {quat} a - The first quaternion. + * @param {quat} b - The second quaternion. + * @returns {Boolean} True if the quaternions are equal, false otherwise. + */ + static exactEquals(a, b) { + return vec4.exactEquals(a, b); + } + + /** + * Returns whether the specified quaternions are approximately equal. + * + * @param {quat} a The first quaternion. + * @param {quat} b The second quaternion. + * @returns {Boolean} True if the quaternions are approximately equal, false otherwise. + */ + static equals(a, b) { + return vec4.equals(a, b); + } +} + +export default quat; \ No newline at end of file diff --git a/cocos2d/core/vmath/utils.js b/cocos2d/core/vmath/utils.js new file mode 100644 index 00000000000..836ecc645aa --- /dev/null +++ b/cocos2d/core/vmath/utils.js @@ -0,0 +1,217 @@ +/** + * @ignore + */ +const _d2r = Math.PI / 180.0; +/** + * @ignore + */ +const _r2d = 180.0 / Math.PI; + +/** + * @property {number} EPSILON + */ +export const EPSILON = 0.000001; + +/** + * Tests whether or not the arguments have approximately the same value, within an absolute + * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less + * than or equal to 1.0, and a relative tolerance is used for larger values) + * + * @param {Number} a The first number to test. + * @param {Number} b The second number to test. + * @returns {Boolean} True if the numbers are approximately equal, false otherwise. + */ +export function equals(a, b) { + return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b)); +} + +/** + * Tests whether or not the arguments have approximately the same value by given maxDiff + * + * @param {Number} a The first number to test. + * @param {Number} b The second number to test. + * @param {Number} maxDiff Maximum difference. + * @returns {Boolean} True if the numbers are approximately equal, false otherwise. + */ +export function approx(a, b, maxDiff) { + maxDiff = maxDiff || EPSILON; + return Math.abs(a - b) <= maxDiff; +} + +/** + * Clamps a value between a minimum float and maximum float value. + * + * @method clamp + * @param {number} val + * @param {number} min + * @param {number} max + * @return {number} + */ +export function clamp(val, min, max) { + return val < min ? min : val > max ? max : val; +} + +/** + * Clamps a value between 0 and 1. + * + * @method clamp01 + * @param {number} val + * @return {number} + */ +export function clamp01(val) { + return val < 0 ? 0 : val > 1 ? 1 : val; +} + +/** + * @method lerp + * @param {number} from + * @param {number} to + * @param {number} ratio - the interpolation coefficient + * @return {number} + */ +export function lerp(from, to, ratio) { + return from + (to - from) * ratio; +} + +/** +* Convert Degree To Radian +* +* @param {Number} a Angle in Degrees +*/ +export function toRadian(a) { + return a * _d2r; +} + +/** +* Convert Radian To Degree +* +* @param {Number} a Angle in Radian +*/ +export function toDegree(a) { + return a * _r2d; +} + +/** +* @method random +*/ +export const random = Math.random; + +/** + * Returns a floating-point random number between min (inclusive) and max (exclusive). + * + * @method randomRange + * @param {number} min + * @param {number} max + * @return {number} the random number + */ +export function randomRange(min, max) { + return Math.random() * (max - min) + min; +} + +/** + * Returns a random integer between min (inclusive) and max (exclusive). + * + * @method randomRangeInt + * @param {number} min + * @param {number} max + * @return {number} the random integer + */ +export function randomRangeInt(min, max) { + return Math.floor(randomRange(min, max)); +} + +/** + * Linear congruential generator using Hull-Dobell Theorem. + * + * @method pseudoRandom + * @param {number} seed the random seed + * @return {number} the pseudo random + */ +export function pseudoRandom(seed) { + seed = (seed * 9301 + 49297) % 233280; + return seed / 233280.0; +} + +/** + * Returns a floating-point pseudo-random number between min (inclusive) and max (exclusive). + * + * @method pseudoRandomRange + * @param {number} seed + * @param {number} min + * @param {number} max + * @return {number} the random number + */ +export function pseudoRandomRange(seed, min, max) { + return pseudoRandom(seed) * (max - min) + min; +} + +/** + * Returns a pseudo-random integer between min (inclusive) and max (exclusive). + * + * @method pseudoRandomRangeInt + * @param {number} seed + * @param {number} min + * @param {number} max + * @return {number} the random integer + */ +export function pseudoRandomRangeInt(seed, min, max) { + return Math.floor(pseudoRandomRange(seed, min, max)); +} + +/** + * Returns the next power of two for the value + * + * @method nextPow2 + * @param {number} val + * @return {number} the the next power of two + */ +export function nextPow2(val) { + --val; + val = (val >> 1) | val; + val = (val >> 2) | val; + val = (val >> 4) | val; + val = (val >> 8) | val; + val = (val >> 16) | val; + ++val; + + return val; +} + +/** + * Returns float remainder for t / length + * + * @method repeat + * @param {number} t time start at 0 + * @param {number} length time of one cycle + * @return {number} the time wrapped in the first cycle + */ +export function repeat(t, length) { + return t - Math.floor(t / length) * length; +} + +/** + * Returns time wrapped in ping-pong mode + * + * @method repeat + * @param {number} t time start at 0 + * @param {number} length time of one cycle + * @return {number} the time wrapped in the first cycle + */ +export function pingPong(t, length) { + t = repeat(t, length * 2); + t = length - Math.abs(t - length); + return t; +} + +/** + * Returns ratio of a value within a given range + * + * @method repeat + * @param {number} from start value + * @param {number} to end value + * @param {number} value given value + * @return {number} the ratio between [from,to] + */ +export function inverseLerp(from, to, value) { + return (value - from) / (to - from); +} \ No newline at end of file diff --git a/cocos2d/core/vmath/vec2.js b/cocos2d/core/vmath/vec2.js new file mode 100644 index 00000000000..2cabc50f9df --- /dev/null +++ b/cocos2d/core/vmath/vec2.js @@ -0,0 +1,691 @@ +import { EPSILON, random } from './utils'; + +/** + * Mathematical 2-dimensional vector. + * + * x, y is alias of the first, second component of vector, respectively. + */ +class vec2 { + /** + * Creates a vector, with components specified separately. + * + * @param {number} x - Value assigned to x component. + * @param {number} y - Value assigned to y component. + */ + constructor(x = 0, y = 0) { + /** + * The x component. + * @type {number} + * */ + this.x = x; + + /** + * The y component. + * @type {number} + * */ + this.y = y; + } + + /** + * Creates a vector, with components specified separately. + * + * @param {number} x - Value assigned to x component. + * @param {number} y - Value assigned to y component. + * @return {vec2} The newly created vector. + */ + static create(x = 0, y = 0) { + return new vec2(x, y); + } + + /** + * Creates a zero vector. + * + * @return {vec2} The newly created vector. + */ + static zero(out) { + out.x = 0; + out.y = 0; + return out; + } + + /** + * Clone a vector. + * + * @param {vec2} a - Vector to clone. + * @returns {vec2} The newly created vector. + */ + static clone(a) { + return new vec2(a.x, a.y); + } + + /** + * Copy content of a vector into another. + * + * @param {vec2} out - The vector to modified. + * @param {vec2} a - The specified vector. + * @returns {vec2} out. + */ + static copy(out, a) { + out.x = a.x; + out.y = a.y; + return out; + } + + /** + * Sets the components of a vector to the given values. + * + * @param {vec2} out - The vector to modified. + * @param {Number} x - Value set to x component. + * @param {Number} y - Value set to y component. + * @returns {vec2} out. + */ + static set(out, x, y) { + out.x = x; + out.y = y; + return out; + } + + /** + * Add two vectors. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {vec2} out. + */ + static add(out, a, b) { + out.x = a.x + b.x; + out.y = a.y + b.y; + return out; + } + + /** + * Subtract two vectors. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {vec2} out. + */ + static subtract(out, a, b) { + out.x = a.x - b.x; + out.y = a.y - b.y; + return out; + } + + /** + *Alias of {@link vec2.subtract}. + */ + static sub(out, a, b) { + return vec2.subtract(out, a, b); + } + + /** + * Performs multiply on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {vec2} out. + */ + static multiply(out, a, b) { + out.x = a.x * b.x; + out.y = a.y * b.y; + return out; + } + + /** + *Alias of {@link vec2.multiply}. + */ + static mul(out, a, b) { + return vec2.multiply(out, a, b); + } + + /** + * Performs division on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {vec2} out. + */ + static divide(out, a, b) { + out.x = a.x / b.x; + out.y = a.y / b.y; + return out; + } + + /** + *Alias of {@link vec2.divide}. + */ + static div(out, a, b) { + return vec2.divide(out, a, b); + } + + /** + * Performs Math.ceil on each component of a vector. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to perform operation. + * @returns {vec2} out. + */ + static ceil(out, a) { + out.x = Math.ceil(a.x); + out.y = Math.ceil(a.y); + return out; + } + + /** + * Performs Math.floor on each component of a vector. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to perform operation. + * @returns {vec2} out. + */ + static floor(out, a) { + out.x = Math.floor(a.x); + out.y = Math.floor(a.y); + return out; + } + + /** + * Performs Math.min on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {vec2} out. + */ + static min(out, a, b) { + out.x = Math.min(a.x, b.x); + out.y = Math.min(a.y, b.y); + return out; + } + + /** + * Performs Math.min on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {vec2} out. + */ + static max(out, a, b) { + out.x = Math.max(a.x, b.x); + out.y = Math.max(a.y, b.y); + return out; + } + + /** + * Performs Math.round on each component of a vector. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to perform operation. + * @returns {vec2} out. + */ + static round(out, a) { + out.x = Math.round(a.x); + out.y = Math.round(a.y); + return out; + } + + /** + * Scales a vector with a number. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to scale. + * @param {number} b - The scale number. + * @returns {vec2} out. + * */ + static scale(out, a, b) { + out.x = a.x * b; + out.y = a.y * b; + return out; + } + + /** + * Add two vectors after scaling the second operand by a number. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @param {number} scale - The scale number before adding. + * @returns {vec2} out. + */ + static scaleAndAdd(out, a, b, scale) { + out.x = a.x + (b.x * scale); + out.y = a.y + (b.y * scale); + return out; + } + + /** + * Calculates the euclidian distance between two vectors. + * + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {number} Distance between a and b. + */ + static distance(a, b) { + let x = b.x - a.x, + y = b.y - a.y; + return Math.sqrt(x * x + y * y); + } + + /** + *Alias of {@link vec2.distance}. + */ + static dist(a, b) { + return vec2.distance(a, b); + } + + /** + * Calculates the squared euclidian distance between two vectors. + * + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {number} Squared distance between a and b. + */ + static squaredDistance(a, b) { + let x = b.x - a.x, + y = b.y - a.y; + return x * x + y * y; + } + + /** + *Alias of {@link vec2.squaredDistance}. + */ + static sqrDist(a, b) { + return vec2.squaredDistance(a, b); + } + + /** + * Calculates the length of a vector. + * + * @param {vec2} a - The vector. + * @returns {Number} Length of the vector. + */ + static magnitude(a) { + let x = a.x, + y = a.y; + return Math.sqrt(x * x + y * y); + } + + /** + *Alias of {@link vec2.magnitude}. + */ + static mag(a) { + return vec2.magnitude(a); + } + + /** + * Calculates the squared length of a vector. + * + * @param {vec2} a - The vector. + * @returns {Number} Squared length of the vector. + */ + static squaredMagnitude(a) { + let x = a.x, + y = a.y; + return x * x + y * y; + } + + /** + *Alias of {@link vec2.squaredMagnitude} + */ + static sqrMag(a) { + return vec2.squaredMagnitude(a); + } + + /** + * Negates each component of a vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to negate. + * @returns {vec2} out. + */ + static negate(out, a) { + out.x = -a.x; + out.y = -a.y; + return out; + } + + /** + * Invert the components of a vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to invert. + * @returns {vec2} out. + */ + static inverse(out, a) { + out.x = 1.0 / a.x; + out.y = 1.0 / a.y; + return out; + } + + /** + * Safely invert the components of a vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to invert. + * @returns {vec2} out. + */ + static inverseSafe(out, a) { + let x = a.x, + y = a.y; + + if (Math.abs(x) < EPSILON) { + out.x = 0; + } else { + out.x = 1.0 / x; + } + + if (Math.abs(y) < EPSILON) { + out.y = 0; + } else { + out.y = 1.0 / a.y; + } + + return out; + } + + /** + * Normalizes a vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to normalize. + * @returns {vec2} out. + */ + static normalize(out, a) { + let x = a.x, + y = a.y; + let len = x * x + y * y; + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len); + out.x = a.x * len; + out.y = a.y * len; + } + return out; + } + + /** + * Calculates the dot product of two vectors. + * + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {Number} Dot product of a and b. + */ + static dot(a, b) { + return a.x * b.x + a.y * b.y; + } + + /** + * Calculate the cross product of two vectors. + * Note that the cross product must by definition produce a 3D vector. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @returns {vec3} out. + */ + static cross(out, a, b) { + let z = a.x * b.y - a.y * b.x; + out.x = out.y = 0; + out.z = z; + return out; + } + + /** + * Performs a linear interpolation between two vectors. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - The first operand. + * @param {vec2} b - The second operand. + * @param {Number} t - The interpolation coefficient. + * @returns {vec2} out. + */ + static lerp(out, a, b, t) { + let ax = a.x, + ay = a.y; + out.x = ax + t * (b.x - ax); + out.y = ay + t * (b.y - ay); + return out; + } + + /** + * Generates a random vector uniformly distributed on a circle centered at the origin. + * + * @param {vec2} out - Vector to store result. + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit length vector will be returned. + * @returns {vec2} out. + */ + static random(out, scale) { + scale = scale || 1.0; + let r = random() * 2.0 * Math.PI; + out.x = Math.cos(r) * scale; + out.y = Math.sin(r) * scale; + return out; + } + + /** + * Transforms a vector with a 2x2 matrix. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to transform. + * @param {mat2} m - The matrix. + * @returns {vec2} out. + */ + static transformMat2(out, a, m) { + let x = a.x, + y = a.y; + out.x = m.m00 * x + m.m02 * y; + out.y = m.m01 * x + m.m03 * y; + return out; + } + + /** + * Transforms a vector with a 2x3 matrix. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to transform. + * @param {mat23} m - The matrix. + * @returns {vec2} out. + */ + static transformMat23(out, a, m) { + let x = a.x, + y = a.y; + out.x = m.m00 * x + m.m02 * y + m.m04; + out.y = m.m01 * x + m.m03 * y + m.m05; + return out; + } + + /** + * Transforms a vector with a 3x3 matrix. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to transform. + * @param {mat3} m - The matrix. + * @returns {vec2} out. + */ + static transformMat3(out, a, m) { + let x = a.x, + y = a.y; + out.x = m.m00 * x + m.m03 * y + m.m06; + out.y = m.m01 * x + m.m04 * y + m.m07; + return out; + } + + /** + * Transforms a vector with a 4x4 matrix. + * 3rd vector component is implicitly '0'. + * 4th vector component is implicitly '1'. + * + * @param {vec2} out - Vector to store result. + * @param {vec2} a - Vector to transform. + * @param {mat4} m - The matrix. + * @returns {vec2} out. + */ + static transformMat4(out, a, m) { + let x = a.x, + y = a.y; + out.x = m.m00 * x + m.m04 * y + m.m12; + out.y = m.m01 * x + m.m05 * y + m.m13; + return out; + } + + /** + * Perform some operation over an array of vec2s. + * + * @param {Array} a the array of vectors to iterate over. + * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed. + * @param {Number} offset Number of elements to skip at the beginning of the array. + * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array. + * @param {Function} fn Function to call for each vector in the array. + * @param {Object} [arg] additional argument to pass to fn. + * @returns {Array} a. + */ + static forEach(a, stride, offset, count, fn, arg) { + return vec2._forEach(a, stride, offset, count, fn, arg); + } + + /** + * Returns string representation of a vector. + * + * @param {vec2} a - The vector. + * @returns {String} - String representation of this vector. + */ + static str(a) { + return `vec2(${a.x}, ${a.y})`; + } + + /** + * Store components of a vector into array. + * + * @param {Array} out - Array to store result. + * @param {vec2} v - The vector. + * @returns {Array} out. + */ + static array(out, v) { + out[0] = v.x; + out[1] = v.y; + + return out; + } + + /** + * Returns whether the specified vectors are equal. (Compared using ===) + * + * @param {vec2} a - The first vector. + * @param {vec2} b - The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ + static exactEquals(a, b) { + return a.x === b.x && a.y === b.y; + } + + /** + * Returns whether the specified vectors are approximately equal. + * + * @param {vec2} a The first vector. + * @param {vec2} b The second vector. + * @returns {Boolean} True if the vectors are approximately equal, false otherwise. + */ + static equals(a, b) { + let a0 = a.x, a1 = a.y; + let b0 = b.x, b1 = b.y; + return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1))); + } + + /** + * Returns the angle between the two vectors. + * + * @param {vec2} a The first vector. + * @param {vec2} b The second vector. + * @returns {Number} The angle in radians. + */ + static angle(a, b) { + return vec2._angle(a, b); + } +} + +/** + * Perform some operation over an array of vec2s. + * + * @param {Array} a the array of vectors to iterate over. + * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed. + * @param {Number} offset Number of elements to skip at the beginning of the array. + * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array. + * @param {Function} fn Function to call for each vector in the array. + * @param {Object} [arg] additional argument to pass to fn. + * @returns {Array} a. + * @ignore + */ +vec2._forEach = (function () { + let vec = vec2.create(0, 0); + + return function (a, stride, offset, count, fn, arg) { + let i, l; + if (!stride) { + stride = 2; + } + + if (!offset) { + offset = 0; + } + + if (count) { + l = Math.min((count * stride) + offset, a.length); + } else { + l = a.length; + } + + for (i = offset; i < l; i += stride) { + vec.x = a[i]; + vec.y = a[i + 1]; + fn(vec, vec, arg); + a[i] = vec.x; + a[i + 1] = vec.y; + } + + return a; + }; +})(); + +vec2._angle = (function () { + let tempA = vec2.create(0, 0); + let tempB = vec2.create(0, 0); + + return function (a, b) { + vec2.normalize(tempA, a); + vec2.normalize(tempB, b); + let cosine = vec2.dot(tempA, tempB); + if (cosine > 1.0) { + return 0; + } + if (cosine < -1.0) { + return Math.PI; + } + return Math.acos(cosine); + }; +})(); + +export default vec2; \ No newline at end of file diff --git a/cocos2d/core/vmath/vec3.js b/cocos2d/core/vmath/vec3.js new file mode 100644 index 00000000000..09cb1e2012c --- /dev/null +++ b/cocos2d/core/vmath/vec3.js @@ -0,0 +1,927 @@ +import { EPSILON, random } from './utils'; + +/** + * Mathematical 3-dimensional vector. + * + * x, y, z is alias of the first, second, third component of vector, respectively. + */ +class vec3 { + /** + * Creates a vector, with components specified separately. + * + * @param {number} x - Value assigned to x component. + * @param {number} y - Value assigned to y component. + * @param {number} z - Value assigned to z component. + */ + constructor(x = 0, y = 0, z = 0) { + /** + * The x component. + * @type {number} + * */ + this.x = x; + + /** + * The y component. + * @type {number} + * */ + this.y = y; + + /** + * The z component. + * @type {number} + * */ + this.z = z; + } + + /** + * Creates a vector, with components specified separately. + * + * @param {number} x - Value assigned to x component. + * @param {number} y - Value assigned to y component. + * @param {number} z - Value assigned to z component. + * @return {vec3} The newly created vector. + */ + static create(x = 0, y = 0, z = 0) { + return new vec3(x, y, z); + } + + /** + * Creates a zero vector. + * + * @return {vec3} The newly created vector. + */ + static zero(out) { + out.x = 0; + out.y = 0; + out.z = 0; + return out; + } + + /** + * Clone a vector. + * + * @param {vec3} a - Vector to clone. + * @returns {vec3} The newly created vector. + */ + static clone(a) { + return new vec3(a.x, a.y, a.z); + } + + /** + * Copy content of a vector into another. + * + * @param {vec3} out - The vector to modified. + * @param {vec3} a - The specified vector. + * @returns {vec3} out. + */ + static copy(out, a) { + out.x = a.x; + out.y = a.y; + out.z = a.z; + return out; + } + + /** + * Sets the components of a vector to the given values. + * + * @param {vec3} out - The vector to modified. + * @param {Number} x - Value set to x component. + * @param {Number} y - Value set to y component. + * @param {Number} z - Value set to z component. + * @returns {vec3} out. + */ + static set(out, x, y, z) { + out.x = x; + out.y = y; + out.z = z; + return out; + } + + /** + * Add two vectors. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {vec3} out. + */ + static add(out, a, b) { + out.x = a.x + b.x; + out.y = a.y + b.y; + out.z = a.z + b.z; + return out; + } + + /** + * Subtract two vectors. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {vec3} out. + */ + static subtract(out, a, b) { + out.x = a.x - b.x; + out.y = a.y - b.y; + out.z = a.z - b.z; + return out; + } + + /** + * Alias of {@link vec3.subtract}. + */ + static sub(out, a, b) { + return vec3.subtract(out, a, b); + } + + /** + * Performs multiply on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {vec3} out. + */ + static multiply(out, a, b) { + out.x = a.x * b.x; + out.y = a.y * b.y; + out.z = a.z * b.z; + return out; + } + + /** + * Alias of {@link vec3.multiply}. + */ + static mul(out, a, b) { + return vec3.multiply(out, a, b); + } + + /** + * Performs division on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {vec3} out. + */ + static divide(out, a, b) { + out.x = a.x / b.x; + out.y = a.y / b.y; + out.z = a.z / b.z; + return out; + } + + /** + * Alias of {@link vec3.divide}. + */ + static div(out, a, b) { + return vec3.divide(out, a, b); + } + + /** + * Performs Math.ceil on each component of a vector. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to perform operation. + * @returns {vec3} out. + */ + static ceil(out, a) { + out.x = Math.ceil(a.x); + out.y = Math.ceil(a.y); + out.z = Math.ceil(a.z); + return out; + } + + /** + * Performs Math.floor on each component of a vector. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to perform operation. + * @returns {vec3} out. + */ + static floor(out, a) { + out.x = Math.floor(a.x); + out.y = Math.floor(a.y); + out.z = Math.floor(a.z); + return out; + } + + /** + * Performs Math.min on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {vec3} out. + */ + static min(out, a, b) { + out.x = Math.min(a.x, b.x); + out.y = Math.min(a.y, b.y); + out.z = Math.min(a.z, b.z); + return out; + } + + /** + * Performs Math.min on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {vec3} out. + */ + static max(out, a, b) { + out.x = Math.max(a.x, b.x); + out.y = Math.max(a.y, b.y); + out.z = Math.max(a.z, b.z); + return out; + } + + /** + * Performs Math.round on each component of a vector. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to perform operation. + * @returns {vec3} out. + */ + static round(out, a) { + out.x = Math.round(a.x); + out.y = Math.round(a.y); + out.z = Math.round(a.z); + return out; + } + + /** + * Scales a vector with a number. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to scale. + * @param {number} b - The scale number. + * @returns {vec3} out. + * */ + static scale(out, a, b) { + out.x = a.x * b; + out.y = a.y * b; + out.z = a.z * b; + return out; + } + + /** + * Add two vectors after scaling the second operand by a number. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @param {number} scale - The scale number before adding. + * @returns {vec3} out. + */ + static scaleAndAdd(out, a, b, scale) { + out.x = a.x + (b.x * scale); + out.y = a.y + (b.y * scale); + out.z = a.z + (b.z * scale); + return out; + } + + /** + * Calculates the euclidian distance between two vectors. + * + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {number} Distance between a and b. + */ + static distance(a, b) { + let x = b.x - a.x, + y = b.y - a.y, + z = b.z - a.z; + return Math.sqrt(x * x + y * y + z * z); + } + + /** + * Alias of {@link vec3.distance}. + */ + static dist(a, b) { + return vec3.distance(a, b); + } + + /** + * Calculates the squared euclidian distance between two vectors. + * + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {number} Squared distance between a and b. + */ + static squaredDistance(a, b) { + let x = b.x - a.x, + y = b.y - a.y, + z = b.z - a.z; + return x * x + y * y + z * z; + } + + /** + * Alias of {@link vec3.squaredDistance}. + */ + static sqrDist(a, b) { + return vec3.squaredDistance(a, b); + } + + /** + * Calculates the length of a vector. + * + * @param {vec3} a - The vector. + * @returns {Number} Length of the vector. + */ + static magnitude(a) { + let x = a.x, + y = a.y, + z = a.z; + return Math.sqrt(x * x + y * y + z * z); + } + + /** + *Alias of {@link vec3.magnitude}. + */ + static mag(a) { + return vec3.magnitude(a); + } + + /** + * Calculates the squared length of a vector. + * + * @param {vec3} a - The vector. + * @returns {Number} Squared length of the vector. + */ + static squaredMagnitude(a) { + let x = a.x, + y = a.y, + z = a.z; + return x * x + y * y + z * z; + } + + /** + *Alias of {@link vec3.squaredMagnitude} + */ + static sqrMag(a) { + return vec3.squaredMagnitude(a); + } + + /** + * Negates each component of a vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to negate. + * @returns {vec3} out. + */ + static negate(out, a) { + out.x = -a.x; + out.y = -a.y; + out.z = -a.z; + return out; + } + + /** + * Inverts the components of a vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to invert. + * @returns {vec3} out. + */ + static inverse(out, a) { + out.x = 1.0 / a.x; + out.y = 1.0 / a.y; + out.z = 1.0 / a.z; + return out; + } + + /** + * Safely inverts the components of a vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to invert. + * @returns {vec3} out. + */ + static inverseSafe(out, a) { + let x = a.x, + y = a.y, + z = a.z; + + if (Math.abs(x) < EPSILON) { + out.x = 0; + } else { + out.x = 1.0 / x; + } + + if (Math.abs(y) < EPSILON) { + out.y = 0; + } else { + out.y = 1.0 / y; + } + + if (Math.abs(z) < EPSILON) { + out.z = 0; + } else { + out.z = 1.0 / z; + } + + return out; + } + + /** + * Normalizes a vector. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to normalize. + * @returns {vec3} out. + */ + static normalize(out, a) { + let x = a.x, + y = a.y, + z = a.z; + + let len = x * x + y * y + z * z; + if (len > 0) { + //TODO: evaluate use of glm_invsqrt here? + len = 1 / Math.sqrt(len); + out.x = x * len; + out.y = y * len; + out.z = z * len; + } + return out; + } + + /** + * Calculates the dot product of two vectors. + * + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {Number} Dot product of a and b. + */ + static dot(a, b) { + return a.x * b.x + a.y * b.y + a.z * b.z; + } + + /** + * Calculates the cross product of two vectors. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {vec3} out. + */ + static cross(out, a, b) { + let ax = a.x, ay = a.y, az = a.z, + bx = b.x, by = b.y, bz = b.z; + + out.x = ay * bz - az * by; + out.y = az * bx - ax * bz; + out.z = ax * by - ay * bx; + return out; + } + + /** + * Performs a linear interpolation between two vectors. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @param {Number} t - The interpolation coefficient. + * @returns {vec3} out. + */ + static lerp(out, a, b, t) { + let ax = a.x, + ay = a.y, + az = a.z; + out.x = ax + t * (b.x - ax); + out.y = ay + t * (b.y - ay); + out.z = az + t * (b.z - az); + return out; + } + + /** + * Performs a hermite interpolation with two control points. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @param {vec3} c - The third operand. + * @param {vec3} d - The fourth operand. + * @param {Number} t - The interpolation coefficient. + * @returns {vec3} out. + */ + static hermite(out, a, b, c, d, t) { + let factorTimes2 = t * t, + factor1 = factorTimes2 * (2 * t - 3) + 1, + factor2 = factorTimes2 * (t - 2) + t, + factor3 = factorTimes2 * (t - 1), + factor4 = factorTimes2 * (3 - 2 * t); + + out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; + out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; + out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; + + return out; + } + + /** + * Performs a bezier interpolation with two control points. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @param {vec3} c - The third operand. + * @param {vec3} d - The fourth operand. + * @param {Number} t - The interpolation coefficient. + * @returns {vec3} out. + */ + static bezier(out, a, b, c, d, t) { + let inverseFactor = 1 - t, + inverseFactorTimesTwo = inverseFactor * inverseFactor, + factorTimes2 = t * t, + factor1 = inverseFactorTimesTwo * inverseFactor, + factor2 = 3 * t * inverseFactorTimesTwo, + factor3 = 3 * factorTimes2 * inverseFactor, + factor4 = factorTimes2 * t; + + out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; + out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; + out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; + + return out; + } + + /** + * Generates a random vector uniformly distributed on a sphere centered at the origin. + * + * @param {vec3} out - Vector to store result. + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit length vector will be returned. + * @returns {vec3} out. + */ + static random(out, scale) { + scale = scale || 1.0; + + let phi = random() * 2.0 * Math.PI; + let theta = Math.acos(random() * 2 - 1); + + out.x = Math.sin(theta) * Math.cos(phi) * scale; + out.y = Math.sin(theta) * Math.sin(phi) * scale; + out.z = Math.cos(theta) * scale; + return out; + } + + /** + * Transforms a point vector with a 4x4 matrix, + * i.e. 4th vector component is implicitly '1'. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to transform. + * @param {mat4} m - The matrix. + * @returns {vec3} out. + */ + static transformMat4(out, a, m) { + let x = a.x, y = a.y, z = a.z, + rhw = m.m03 * x + m.m07 * y + m.m11 * z + m.m15; + rhw = rhw ? 1 / rhw : 1; + out.x = (m.m00 * x + m.m04 * y + m.m08 * z + m.m12) * rhw; + out.y = (m.m01 * x + m.m05 * y + m.m09 * z + m.m13) * rhw; + out.z = (m.m02 * x + m.m06 * y + m.m10 * z + m.m14) * rhw; + return out; + } + + /** + * Transforms a normal vector with a 4x4 matrix, + * i.e. 4th vector component is implicitly '0'. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to transform. + * @param {mat4} m - The matrix. + * @returns {vec3} out. + */ + static transformMat4Normal(out, a, m) { + let x = a.x, y = a.y, z = a.z, + rhw = m.m03 * x + m.m07 * y + m.m11 * z; + rhw = rhw ? 1 / rhw : 1; + out.x = (m.m00 * x + m.m04 * y + m.m08 * z) * rhw; + out.y = (m.m01 * x + m.m05 * y + m.m09 * z) * rhw; + out.z = (m.m02 * x + m.m06 * y + m.m10 * z) * rhw; + return out; + } + + /** + * Transforms a vector with a 3x3 matrix. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to transform. + * @param {mat3} m - The matrix. + * @returns {vec3} out. + */ + static transformMat3(out, a, m) { + let x = a.x, y = a.y, z = a.z; + out.x = x * m.m00 + y * m.m03 + z * m.m06; + out.y = x * m.m01 + y * m.m04 + z * m.m07; + out.z = x * m.m02 + y * m.m05 + z * m.m08; + return out; + } + + /** + * Transforms a vector with a quaternion. + * + * @param {vec3} out - Vector to store result. + * @param {vec3} a - Vector to transform. + * @param {quat} q - The quaternion. + * @returns {vec3} out. + */ + static transformQuat(out, a, q) { + // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations + + let x = a.x, y = a.y, z = a.z; + let qx = q.x, qy = q.y, qz = q.z, qw = q.w; + + // calculate quat * vec + let ix = qw * x + qy * z - qz * y; + let iy = qw * y + qz * x - qx * z; + let iz = qw * z + qx * y - qy * x; + let iw = -qx * x - qy * y - qz * z; + + // calculate result * inverse quat + out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; + out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; + out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; + return out; + } + + /** + * Rotates a 3D vector around the x-axis. + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The point to rotate. + * @param {vec3} b - The origin of the rotation. + * @param {Number} c - The angle of rotation. + * @returns {vec3} out. + */ + static rotateX(out, a, b, c) { + // Translate point to the origin + let px = a.x - b.x; + let py = a.y - b.y; + let pz = a.z - b.z; + + //perform rotation + let rx = px; + let ry = py * Math.cos(c) - pz * Math.sin(c); + let rz = py * Math.sin(c) + pz * Math.cos(c); + + //translate to correct position + out.x = rx + b.x; + out.y = ry + b.y; + out.z = rz + b.z; + + return out; + } + + /** + * Rotates a 3D vector around the y-axis. + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The point to rotate. + * @param {vec3} b - The origin of the rotation. + * @param {Number} c - The angle of rotation. + * @returns {vec3} out. + */ + static rotateY(out, a, b, c) { + //Translate point to the origin + let px = a.x - b.x; + let py = a.y - b.y; + let pz = a.z - b.z; + + //perform rotation + let rx = pz * Math.sin(c) + px * Math.cos(c); + let ry = py; + let rz = pz * Math.cos(c) - px * Math.sin(c); + + //translate to correct position + out.x = rx + b.x; + out.y = ry + b.y; + out.z = rz + b.z; + + return out; + } + + /** + * Rotates a 3D vector around the z-axis. + * @param {vec3} out - Vector to store result. + * @param {vec3} a - The point to rotate. + * @param {vec3} b - The origin of the rotation. + * @param {Number} c - The angle of rotation. + * @returns {vec3} out. + */ + static rotateZ(out, a, b, c) { + //Translate point to the origin + let px = a.x - b.x; + let py = a.y - b.y; + let pz = a.z - b.z; + + //perform rotation + let rx = px * Math.cos(c) - py * Math.sin(c); + let ry = px * Math.sin(c) + py * Math.cos(c); + let rz = pz; + + //translate to correct position + out.x = rx + b.x; + out.y = ry + b.y; + out.z = rz + b.z; + + return out; + } + + /** + * Returns string representation of a vector. + * + * @param {vec3} a - The vector. + * @returns {String} - String representation of this vector. + */ + static str(a) { + return `vec3(${a.x}, ${a.y}, ${a.z})`; + } + + /** + * Store components of a vector into array. + * + * @param {Array} out - Array to store result. + * @param {vec3} v - The vector. + * @returns {Array} out. + */ + static array(out, v) { + out[0] = v.x; + out[1] = v.y; + out[2] = v.z; + + return out; + } + + /** + * Returns whether the specified vectors are equal. (Compared using ===) + * + * @param {vec3} a - The first vector. + * @param {vec3} b - The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ + static exactEquals(a, b) { + return a.x === b.x && a.y === b.y && a.z === b.z; + } + + /** + * Returns whether the specified vectors are approximately equal. + * + * @param {vec3} a The first vector. + * @param {vec3} b The second vector. + * @returns {Boolean} True if the vectors are approximately equal, false otherwise. + */ + static equals(a, b) { + let a0 = a.x, a1 = a.y, a2 = a.z; + let b0 = b.x, b1 = b.y, b2 = b.z; + return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); + } + + /** + * Perform some operation over an array of vec3s. + * + * @param {Array} a the array of vectors to iterate over. + * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed. + * @param {Number} offset Number of elements to skip at the beginning of the array. + * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array. + * @param {Function} fn Function to call for each vector in the array. + * @param {Object} [arg] additional argument to pass to fn. + * @returns {Array} a. + */ + static forEach(a, stride, offset, count, fn, arg) { + return vec3._forEach(a, stride, offset, count, fn, arg); + } + + /** + * Gets the angle between two vectors. + * @param {vec3} a - The first operand. + * @param {vec3} b - The second operand. + * @returns {Number} - The angle in radians. + */ + static angle(a, b) { + return vec3._angle(a, b); + } + + /** + * Projects a vector onto a plane represented by its normal. + * @param {vec3} out The result vector. + * @param {vec3} a The vector. + * @param {vec3} n The plane's normal. + */ + static projectOnPlane(out, a, n) { + return vec3.sub(out, a, vec3.project(out, a, n)); + } + + /** + * Projects a vector onto another vector. + * @param {vec3} out The result vector. + * @param {vec3} a The vector to project. + * @param {vec3} b The vector onto which the projection performs. + */ + static project(out, a, b) { + let sqrLen = vec3.squaredMagnitude(b); + if (sqrLen < 0.000001) + return vec3.set(out, 0, 0, 0); + else + return vec3.scale(out, b, vec3.dot(a, b) / sqrLen); + } +} + +/** +* Perform some operation over an array of vec3s. +* +* @param {Array} a the array of vectors to iterate over. +* @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed. +* @param {Number} offset Number of elements to skip at the beginning of the array. +* @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array. +* @param {Function} fn Function to call for each vector in the array. +* @param {Object} [arg] additional argument to pass to fn. +* @returns {Array} a. +* @ignore. +*/ +vec3._forEach = (function () { + let vec = vec3.create(0, 0, 0); + + return function (a, stride, offset, count, fn, arg) { + let i, l; + if (!stride) { + stride = 3; + } + + if (!offset) { + offset = 0; + } + + if (count) { + l = Math.min((count * stride) + offset, a.length); + } else { + l = a.length; + } + + for (i = offset; i < l; i += stride) { + vec.x = a[i]; + vec.y = a[i + 1]; + vec.z = a[i + 2]; + fn(vec, vec, arg); + a[i] = vec.x; + a[i + 1] = vec.y; + a[i + 2] = vec.z; + } + + return a; + }; +})(); + +/** + * Get the angle between two 3D vectors. + * @param {vec3} a The first operand. + * @param {vec3} b The second operand. + * @returns {Number} The angle in radians. + * @ignore + */ +vec3._angle = (function () { + let tempA = vec3.create(0, 0, 0); + let tempB = vec3.create(0, 0, 0); + + return function (a, b) { + vec3.copy(tempA, a); + vec3.copy(tempB, b); + + vec3.normalize(tempA, tempA); + vec3.normalize(tempB, tempB); + + let cosine = vec3.dot(tempA, tempB); + + if (cosine > 1.0) { + return 0; + } + + if (cosine < -1.0) { + return Math.PI; + } + + return Math.acos(cosine); + }; +})(); + +export default vec3; \ No newline at end of file diff --git a/cocos2d/core/vmath/vec4.js b/cocos2d/core/vmath/vec4.js new file mode 100644 index 00000000000..c9146083482 --- /dev/null +++ b/cocos2d/core/vmath/vec4.js @@ -0,0 +1,715 @@ +import { EPSILON, random } from './utils'; + +/** + * Mathematical 4-dimensional vector. + * + * x, y, z, w is alias of the first, second, third, fourth component of vector, respectively. + */ +class vec4 { + /** + * Creates a vector, with components specified separately. + * + * @param {number} x - Value assigned to x component. + * @param {number} y - Value assigned to y component. + * @param {number} z - Value assigned to z component. + * @param {number} w - Value assigned to w component. + */ + constructor(x = 0, y = 0, z = 0, w = 1) { + /** + * The x component. + * @type {number} + * */ + this.x = x; + + /** + * The y component. + * @type {number} + * */ + this.y = y; + + /** + * The z component. + * @type {number} + * */ + this.z = z; + + /** + * The w component. + * @type {number} + * */ + this.w = w; + } + + /** + * Create a vector, with components specified separately. + * + * @param {number} x - Value assigned to x component. + * @param {number} y - Value assigned to y component. + * @param {number} z - Value assigned to z component. + * @param {number} w - Value assigned to w component. + * @return {vec4} The newly created vector. + */ + static create(x = 0, y = 0, z = 0, w = 1) { + return new vec4(x, y, z, w); + } + + /** + * Creates a zero vector. + * + * @return {vec4} The newly created vector. + */ + static zero(out) { + out.x = 0; + out.y = 0; + out.z = 0; + out.w = 0; + return out; + } + + /** + * Clone a vector. + * + * @param {vec4} a - Vector to clone. + * @returns {vec4} The newly created vector. + */ + static clone(a) { + return new vec4(a.x, a.y, a.z, a.w); + } + + /** + * Copy content of a vector into another. + * + * @param {vec4} out - The vector to modified. + * @param {vec4} a - The specified vector. + * @returns {vec4} out. + */ + static copy(out, a) { + out.x = a.x; + out.y = a.y; + out.z = a.z; + out.w = a.w; + return out; + } + + /** + * Sets the components of a vector to the given values. + * + * @param {vec4} out - The vector to modified. + * @param {Number} x - Value set to x component. + * @param {Number} y - Value set to y component. + * @param {Number} z - Value set to z component. + * @param {Number} w - Value set to w component. + * @returns {vec4} out. + */ + static set(out, x, y, z, w) { + out.x = x; + out.y = y; + out.z = z; + out.w = w; + return out; + } + + /** + * Add two vectors. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @returns {vec4} out. + */ + static add(out, a, b) { + out.x = a.x + b.x; + out.y = a.y + b.y; + out.z = a.z + b.z; + out.w = a.w + b.w; + return out; + } + + /** + * Subtract two vectors. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @returns {vec4} out. + */ + static subtract(out, a, b) { + out.x = a.x - b.x; + out.y = a.y - b.y; + out.z = a.z - b.z; + out.w = a.w - b.w; + return out; + } + + /** + * Alias of {@link vec4.subtract}. + */ + static sub(out, a, b) { + return vec4.subtract(out, a, b); + } + + /** + * Performs multiply on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @returns {vec4} out. + */ + static multiply(out, a, b) { + out.x = a.x * b.x; + out.y = a.y * b.y; + out.z = a.z * b.z; + out.w = a.w * b.w; + return out; + } + + /** + * Alias of {@link vec4.multiply}. + */ + static mul(out, a, b) { + return vec4.multiply(out, a, b); + } + + /** + * Performs division on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @returns {vec4} out. + */ + static divide(out, a, b) { + out.x = a.x / b.x; + out.y = a.y / b.y; + out.z = a.z / b.z; + out.w = a.w / b.w; + return out; + } + + /** + * Alias of {@link vec4.divide}. + */ + static div(out, a, b) { + return vec4.divide(out, a, b); + } + + /** + * Performs Math.ceil on each component of a vector. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to perform operation. + * @returns {vec4} out. + */ + static ceil(out, a) { + out.x = Math.ceil(a.x); + out.y = Math.ceil(a.y); + out.z = Math.ceil(a.z); + out.w = Math.ceil(a.w); + return out; + } + + /** + * Performs Math.floor on each component of a vector. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to perform operation. + * @returns {vec4} out. + */ + static floor(out, a) { + out.x = Math.floor(a.x); + out.y = Math.floor(a.y); + out.z = Math.floor(a.z); + out.w = Math.floor(a.w); + return out; + } + + /** + * Performs Math.min on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @returns {vec4} out. + */ + static min(out, a, b) { + out.x = Math.min(a.x, b.x); + out.y = Math.min(a.y, b.y); + out.z = Math.min(a.z, b.z); + out.w = Math.min(a.w, b.w); + return out; + } + + /** + * Performs Math.min on each component of two vectors respectively. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @returns {vec4} out. + */ + static max(out, a, b) { + out.x = Math.max(a.x, b.x); + out.y = Math.max(a.y, b.y); + out.z = Math.max(a.z, b.z); + out.w = Math.max(a.w, b.w); + return out; + } + + /** + * Performs Math.round on each component of a vector. + * + * It doesn't matter that any amount of these parameters refer to same vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to perform operation. + * @returns {vec4} out. + */ + static round(out, a) { + out.x = Math.round(a.x); + out.y = Math.round(a.y); + out.z = Math.round(a.z); + out.w = Math.round(a.w); + return out; + } + + /** + * Scales a vector with a number. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to scale. + * @param {number} b - The scale number. + * @returns {vec4} out. + * */ + static scale(out, a, b) { + out.x = a.x * b; + out.y = a.y * b; + out.z = a.z * b; + out.w = a.w * b; + return out; + } + + /** + * Add two vectors after scaling the second operand by a number. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @param {number} scale - The scale number before adding. + * @returns {vec4} out. + */ + static scaleAndAdd(out, a, b, scale) { + out.x = a.x + (b.x * scale); + out.y = a.y + (b.y * scale); + out.z = a.z + (b.z * scale); + out.w = a.w + (b.w * scale); + return out; + } + + /** + * Calculates the euclidian distance between two vectors. + * + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @returns {number} Distance between a and b. + */ + static distance(a, b) { + let x = b.x - a.x, + y = b.y - a.y, + z = b.z - a.z, + w = b.w - a.w; + return Math.sqrt(x * x + y * y + z * z + w * w); + } + + /** + * Alias of {@link vec4.distance}. + */ + static dist(a, b) { + return vec4.distance(a, b); + } + + /** + * Calculates the squared euclidian distance between two vectors. + * + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @returns {number} Squared distance between a and b. + */ + static squaredDistance(a, b) { + let x = b.x - a.x, + y = b.y - a.y, + z = b.z - a.z, + w = b.w - a.w; + return x * x + y * y + z * z + w * w; + } + + /** + * Alias of {@link vec4.squaredDistance}. + */ + static sqrDist(a, b) { + return vec4.squaredDistance(a, b); + } + + /** + * Calculates the length of a vector. + * + * @param {vec4} a - The vector. + * @returns {Number} Length of the vector. + */ + static magnitude(a) { + let x = a.x, + y = a.y, + z = a.z, + w = a.w; + return Math.sqrt(x * x + y * y + z * z + w * w); + } + + /** + *Alias of {@link vec4.magnitude}. + */ + static mag(a) { + return vec4.magnitude(a); + } + + /** + * Calculates the squared length of a vector. + * + * @param {vec4} a - The vector. + * @returns {Number} Squared length of the vector. + */ + static squaredMagnitude(a) { + let x = a.x, + y = a.y, + z = a.z, + w = a.w; + return x * x + y * y + z * z + w * w; + } + + /** + *Alias of {@link vec4.squaredMagnitude} + */ + static sqrMag(a) { + return vec4.squaredMagnitude(a); + } + + /** + * Negates each component of a vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to negate. + * @returns {vec4} out. + */ + static negate(out, a) { + out.x = -a.x; + out.y = -a.y; + out.z = -a.z; + out.w = -a.w; + return out; + } + + /** + * Inverts the components of a vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to invert. + * @returns {vec4} out. + */ + static inverse(out, a) { + out.x = 1.0 / a.x; + out.y = 1.0 / a.y; + out.z = 1.0 / a.z; + out.w = 1.0 / a.w; + return out; + } + + /** + * Safely inverts the components of a vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to invert. + * @returns {vec4} out. + */ + static inverseSafe(out, a) { + let x = a.x, + y = a.y, + z = a.z, + w = a.w; + + if (Math.abs(x) < EPSILON) { + out.x = 0; + } else { + out.x = 1.0 / x; + } + + if (Math.abs(y) < EPSILON) { + out.y = 0; + } else { + out.y = 1.0 / y; + } + + if (Math.abs(z) < EPSILON) { + out.z = 0; + } else { + out.z = 1.0 / z; + } + + if (Math.abs(w) < EPSILON) { + out.w = 0; + } else { + out.w = 1.0 / w; + } + + return out; + } + + /** + * Normalizes a vector. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to normalize. + * @returns {vec4} out. + */ + static normalize(out, a) { + let x = a.x, + y = a.y, + z = a.z, + w = a.w; + let len = x * x + y * y + z * z + w * w; + if (len > 0) { + len = 1 / Math.sqrt(len); + out.x = x * len; + out.y = y * len; + out.z = z * len; + out.w = w * len; + } + return out; + } + + /** + * Calculates the dot product of two vectors. + * + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @returns {Number} Dot product of a and b. + */ + static dot(a, b) { + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; + } + + /** + * Performs a linear interpolation between two vectors. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - The first operand. + * @param {vec4} b - The second operand. + * @param {Number} t - The interpolation coefficient. + * @returns {vec4} out. + */ + static lerp(out, a, b, t) { + let ax = a.x, + ay = a.y, + az = a.z, + aw = a.w; + out.x = ax + t * (b.x - ax); + out.y = ay + t * (b.y - ay); + out.z = az + t * (b.z - az); + out.w = aw + t * (b.w - aw); + return out; + } + + /** + * Generates a random vector uniformly distributed on a sphere centered at the origin. + * + * @param {vec4} out - Vector to store result. + * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit length vector will be returned. + * @returns {vec4} out. + */ + static random(out, scale) { + scale = scale || 1.0; + + let phi = random() * 2.0 * Math.PI; + let theta = Math.acos(random() * 2 - 1); + + out.x = Math.sin(theta) * Math.cos(phi) * scale; + out.y = Math.sin(theta) * Math.sin(phi) * scale; + out.z = Math.cos(theta) * scale; + out.w = 0; + return out; + } + + /** + * Transforms a vector with a 4x4 matrix. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to transform. + * @param {mat4} m - The matrix. + * @returns {vec4} out. + */ + static transformMat4(out, a, m) { + let x = a.x, y = a.y, z = a.z, w = a.w; + out.x = m.m00 * x + m.m04 * y + m.m08 * z + m.m12 * w; + out.y = m.m01 * x + m.m05 * y + m.m09 * z + m.m13 * w; + out.z = m.m02 * x + m.m06 * y + m.m10 * z + m.m14 * w; + out.w = m.m03 * x + m.m07 * y + m.m11 * z + m.m15 * w; + return out; + } + + /** + * Transforms a vector with a quaternion. + * + * @param {vec4} out - Vector to store result. + * @param {vec4} a - Vector to transform. + * @param {quat} q - The quaternion. + * @returns {vec4} out. + */ + static transformQuat(out, a, q) { + let x = a.x, y = a.y, z = a.z; + let qx = q.x, qy = q.y, qz = q.z, qw = q.w; + + // calculate quat * vec + let ix = qw * x + qy * z - qz * y; + let iy = qw * y + qz * x - qx * z; + let iz = qw * z + qx * y - qy * x; + let iw = -qx * x - qy * y - qz * z; + + // calculate result * inverse quat + out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; + out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; + out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; + out.w = a.w; + return out; + } + + /** + * Returns string representation of a vector. + * + * @param {vec4} a - The vector. + * @returns {String} - String representation of this vector. + */ + static str(a) { + return `vec4(${a.x}, ${a.y}, ${a.z}, ${a.w})`; + } + + /** + * Store components of a vector into array. + * + * @param {Array} out - Array to store result. + * @param {vec4} v - The vector. + * @returns {Array} out. + */ + static array(out, v) { + out[0] = v.x; + out[1] = v.y; + out[2] = v.z; + out[3] = v.w; + + return out; + } + + /** + * Returns whether the specified vectors are equal. (Compared using ===) + * + * @param {vec4} a - The first vector. + * @param {vec4} b - The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ + static exactEquals(a, b) { + return a.x === b.x && a.y === b.y && a.z === b.z && a.w === b.w; + } + + /** + * Returns whether the specified vectors are approximately equal. + * + * @param {vec4} a The first vector. + * @param {vec4} b The second vector. + * @returns {Boolean} True if the vectors are approximately equal, false otherwise. + */ + static equals(a, b) { + let a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; + let b0 = b.x, b1 = b.y, b2 = b.z, b3 = b.w; + return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && + Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); + } + + /** + * Performs some operation over an array of vec4s. + * + * @param {Array} a the array of vectors to iterate over. + * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed. + * @param {Number} offset Number of elements to skip at the beginning of the array. + * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array. + * @param {Function} fn Function to call for each vector in the array. + * @param {Object} [arg] additional argument to pass to fn. + * @returns {Array} a. + */ + static forEach(a, stride, offset, count, fn, arg) { + return vec4._forEach(a, stride, offset, count, fn, arg); + } +} + +/** + * Perform some operation over an array of vec4s. + * + * @param {Array} a the array of vectors to iterate over. + * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed. + * @param {Number} offset Number of elements to skip at the beginning of the array. + * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array. + * @param {Function} fn Function to call for each vector in the array. + * @param {Object} [arg] additional argument to pass to fn. + * @returns {Array} a. + * @ignore + */ +vec4._forEach = (function () { + let vec = vec4.create(0, 0, 0, 0); + + return function (a, stride, offset, count, fn, arg) { + let i, l; + if (!stride) { + stride = 4; + } + + if (!offset) { + offset = 0; + } + + if (count) { + l = Math.min((count * stride) + offset, a.length); + } else { + l = a.length; + } + + for (i = offset; i < l; i += stride) { + vec.x = a[i]; + vec.y = a[i + 1]; + vec.z = a[i + 2]; + vec.w = a[i + 3]; + fn(vec, vec, arg); + a[i] = vec.x; + a[i + 1] = vec.y; + a[i + 2] = vec.z; + a[i + 3] = vec.w; + } + + return a; + }; +})(); + +export default vec4; \ No newline at end of file diff --git a/cocos2d/deprecated.js b/cocos2d/deprecated.js index 3e6beaedae9..0f6dcb35d09 100644 --- a/cocos2d/deprecated.js +++ b/cocos2d/deprecated.js @@ -623,4 +623,20 @@ if (CC_DEBUG) { if (typeof dragonBones !== 'undefined') { js.obsolete(dragonBones.CCFactory, 'dragonBones.CCFactory.getFactory', 'getInstance'); } + + // renderEngine + cc.renderer.renderEngine = { + get gfx () { + cc.warnID(1400, 'cc.renderer.renderEngine.gfx', 'cc.gfx'); + return cc.gfx; + }, + get math () { + cc.warnID(1400, 'cc.renderer.renderEngine.math', 'cc.vmath'); + return cc.vmath; + }, + get InputAssembler () { + cc.warnID(1400, 'cc.renderer.renderEngine.InputAssembler', 'cc.renderer.InputAssembler'); + return cc.renderer.InputAssembler; + } + }; } diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 5c27225e023..54959e0fa54 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -33,7 +33,7 @@ const tiffReader = require('./CCTIFFReader'); const textureUtil = require('../core/utils/texture-util'); const RenderFlow = require('../core/renderer/render-flow'); const ParticleSimulator = require('./particle-simulator'); -const Material = require('../core/assets/CCMaterial'); +const Material = require('../core/assets/material/CCMaterial'); function getImageFormatByData (imgData) { // if it is a png file buffer. @@ -1132,8 +1132,8 @@ var ParticleSystem = cc.Class({ let material = this.sharedMaterials[0]; if (!material) { material = Material.getInstantiatedBuiltinMaterial('sprite', this); - material.define('useTexture', true); - material.define('useModel', true); + material.define('USE_TEXTURE', true); + material.define('_USE_MODEL', true); } if (!this._texture || !this._texture.loaded) { diff --git a/cocos2d/particle/particle-system-assembler.js b/cocos2d/particle/particle-system-assembler.js index 6184eee4718..56069fd3bf0 100644 --- a/cocos2d/particle/particle-system-assembler.js +++ b/cocos2d/particle/particle-system-assembler.js @@ -23,15 +23,16 @@ THE SOFTWARE. ****************************************************************************/ +import IARenderData from '../renderer/render-data/ia-render-data'; + const ParticleSystem = require('./CCParticleSystem'); const renderer = require('../core/renderer/'); -const renderEngine = require('../core/renderer/render-engine'); const vfmtPosUvColor = require('../core/renderer/webgl/vertex-format').vfmtPosUvColor; const QuadBuffer = require('../core/renderer/webgl/quad-buffer'); -var particleSystemAssembler = { - useModel: true, +import InputAssembler from '../renderer/core/input-assembler'; +var particleSystemAssembler = { createIA (comp) { let device = renderer.device; // Vertex format defines vertex buffer layout: x, y, u, v color @@ -40,7 +41,7 @@ var particleSystemAssembler = { // Create quad buffer for vertex and index comp._buffer = new QuadBuffer(renderer._handle, vfmtPosUvColor); - comp._ia = new renderEngine.InputAssembler(); + comp._ia = new InputAssembler(); comp._ia._vertexBuffer = comp._buffer._vb; comp._ia._indexBuffer = comp._buffer._ib; comp._ia._start = 0; @@ -49,7 +50,7 @@ var particleSystemAssembler = { updateRenderData (comp) { if (!comp._renderData) { - comp._renderData = new renderEngine.IARenderData(); + comp._renderData = new IARenderData(); comp._renderData.ia = comp._ia; } comp._renderData.material = comp.sharedMaterials[0]; diff --git a/cocos2d/renderer/build/build-chunks.js b/cocos2d/renderer/build/build-chunks.js new file mode 100644 index 00000000000..c47cbb73740 --- /dev/null +++ b/cocos2d/renderer/build/build-chunks.js @@ -0,0 +1,20 @@ +const path_ = require('path'); +const fs = require('fs'); +const shdcLib = require('./shdc-lib'); + +let defaultChunkPath = path_.join(__dirname, './chunks'), chunksCache = {}; +let updateBuiltinChunks = function(path = defaultChunkPath) { + const fsJetpack = require('fs-jetpack'); + + let files = fsJetpack.find(path, { matching: ['**/*.inc'] }); + for (let i = 0; i < files.length; ++i) { + let name = path_.basename(files[i], '.inc'); + let content = fs.readFileSync(files[i], { encoding: 'utf8' }); + chunksCache[name] = shdcLib.glslStripComment(content); + } + + let content = 'module.exports = ' + JSON.stringify(chunksCache, null, 2); + fs.writeFileSync(path_.join(__dirname, './chunks/index.js'), content); +}; + +updateBuiltinChunks(); diff --git a/cocos2d/renderer/build/build-mapping.js b/cocos2d/renderer/build/build-mapping.js index dcd2575b4b7..21baf44b7e1 100644 --- a/cocos2d/renderer/build/build-mapping.js +++ b/cocos2d/renderer/build/build-mapping.js @@ -4,10 +4,10 @@ const Path = require('path'); const resolve = require('rollup-plugin-node-resolve'); const rollup = require('rollup'); -let src = Path.join(__dirname, '../mappings/offline-mappings.js'); -let dest = '../mappings'; +let src = Path.join(__dirname, './mappings/offline-mappings.js'); +let dest = Path.join(__dirname, './mappings'); let name = 'index'; -let sourcemap = true; +let sourcemap = false; let globals = {}; console.log('rollup mappings...'); @@ -24,7 +24,7 @@ const inputOptions = { ], }; const outputOptions = { - file: `${dest}/${name}.js`, + file: Path.join(dest, name+'.js'), format: 'cjs', name, globals, diff --git a/cocos2d/renderer/build/build-shader.js b/cocos2d/renderer/build/build-shader.js index 7b09c121dd5..b5cb577567b 100644 --- a/cocos2d/renderer/build/build-shader.js +++ b/cocos2d/renderer/build/build-shader.js @@ -3,8 +3,8 @@ const sha1 = require('js-sha1'); const shdcLib = require('./shdc-lib'); -const mappings = require('../mappings'); -const chunksCache = require('../chunks'); +const mappings = require('./mappings'); +const chunksCache = require('./chunks'); let queueRE = /(\w+)(?:([+-])(\d+))?/; let parseQueue = function (queue) { diff --git a/cocos2d/renderer/build/chunks/common.inc b/cocos2d/renderer/build/chunks/common.inc new file mode 100644 index 00000000000..d1865226c8d --- /dev/null +++ b/cocos2d/renderer/build/chunks/common.inc @@ -0,0 +1,12 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +// common module + +// constant value +#define PI 3.14159265359 +#define PI2 6.28318530718 +#define EPSILON 1e-6 +#define LOG2 1.442695 + +// common function +#define saturate(a) clamp( a, 0.0, 1.0 ) \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/gamma-correction.inc b/cocos2d/renderer/build/chunks/gamma-correction.inc new file mode 100644 index 00000000000..a824b2b1221 --- /dev/null +++ b/cocos2d/renderer/build/chunks/gamma-correction.inc @@ -0,0 +1,45 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +// sRGB-linear transform approximation +// http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html +vec3 gammaToLinearSpaceRGB(vec3 sRGB) { // TODO: use half maybe better. + return sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878); +} + +vec3 linearToGammaSpaceRGB(vec3 RGB) { // TODO: use half maybe better. + vec3 S1 = sqrt(RGB); + vec3 S2 = sqrt(S1); + vec3 S3 = sqrt(S2); + return 0.585122381 * S1 + 0.783140355 * S2 - 0.368262736 * S3; +} + +vec4 gammaToLinearSpaceRGBA(vec4 sRGBA) { + return vec4(gammaToLinearSpaceRGB(sRGBA.rgb), sRGBA.a); +} + +vec4 linearToGammaSpaceRGBA(vec4 RGBA) { + return vec4(linearToGammaSpaceRGB(RGBA.rgb), RGBA.a); +} + +// exact version +float gammaToLinearSpaceExact(float val) { + if (val <= 0.04045) { + return val / 12.92; + } else if (val < 1.0) { + return pow((val + 0.055) / 1.055, 2.4); + } else { + return pow(val, 2.2); + } +} + +float linearToGammaSpaceExact(float val) { + if (val <= 0.0) { + return 0.0; + } else if (val <= 0.0031308) { + return 12.92 * val; + } else if (val < 1.0) { + return 1.055 * pow(val, 0.4166667) - 0.055; + } else { + return pow(val, 0.45454545); + } +} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/index.js b/cocos2d/renderer/build/chunks/index.js new file mode 100644 index 00000000000..497e2b77f33 --- /dev/null +++ b/cocos2d/renderer/build/chunks/index.js @@ -0,0 +1,17 @@ +module.exports = { + "common": "\n\n\n\n\n#define PI 3.14159265359\n#define PI2 6.28318530718\n#define EPSILON 1e-6\n#define LOG2 1.442695\n\n\n#define saturate(a) clamp( a, 0.0, 1.0 )", + "gamma-correction": "\n\n\n\nvec3 gammaToLinearSpaceRGB(vec3 sRGB) { \n return sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878);\n}\n\nvec3 linearToGammaSpaceRGB(vec3 RGB) { \n vec3 S1 = sqrt(RGB);\n vec3 S2 = sqrt(S1);\n vec3 S3 = sqrt(S2);\n return 0.585122381 * S1 + 0.783140355 * S2 - 0.368262736 * S3;\n}\n\nvec4 gammaToLinearSpaceRGBA(vec4 sRGBA) {\n return vec4(gammaToLinearSpaceRGB(sRGBA.rgb), sRGBA.a);\n}\n\nvec4 linearToGammaSpaceRGBA(vec4 RGBA) {\n return vec4(linearToGammaSpaceRGB(RGBA.rgb), RGBA.a);\n}\n\n\nfloat gammaToLinearSpaceExact(float val) {\n if (val <= 0.04045) {\n return val / 12.92;\n } else if (val < 1.0) {\n return pow((val + 0.055) / 1.055, 2.4);\n } else {\n return pow(val, 2.2);\n }\n}\n\nfloat linearToGammaSpaceExact(float val) {\n if (val <= 0.0) {\n return 0.0;\n } else if (val <= 0.0031308) {\n return 12.92 * val;\n } else if (val < 1.0) {\n return 1.055 * pow(val, 0.4166667) - 0.055;\n } else {\n return pow(val, 0.45454545);\n }\n}", + "packing": "\n\nvec4 packDepthToRGBA(float depth) {\n vec4 ret = vec4(1.0, 255.0, 65025.0, 160581375.0) * depth;\n ret = fract(ret);\n ret -= ret.yzww * vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0);\n return ret;\n}\n\nfloat unpackRGBAToDepth(vec4 color) {\n return dot(color, vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 160581375.0));\n}", + "pbr-fs": "\n\n#if USE_NORMAL_TEXTURE\n#extension GL_OES_standard_derivatives : enable\n#endif\n\n#if USE_TEX_LOD\n#extension GL_EXT_shader_texture_lod: enable\n#endif\n\n#include \n#include \n\nstruct LightInfo {\n vec3 lightDir;\n vec3 radiance;\n};\n\n#if _NUM_DIR_LIGHTS > 0\n #pragma for id in range(0, _NUM_DIR_LIGHTS)\n uniform vec3 _dir_light{id}_direction;\n uniform vec3 _dir_light{id}_color;\n #pragma endFor\n#endif\n\n#if _NUM_POINT_LIGHTS > 0\n #pragma for id in range(0, _NUM_POINT_LIGHTS)\n uniform vec3 _point_light{id}_position;\n uniform vec3 _point_light{id}_color;\n uniform float _point_light{id}_range;\n #pragma endFor\n#endif\n\n#if _NUM_SPOT_LIGHTS > 0\n #pragma for id in range(0, _NUM_SPOT_LIGHTS)\n uniform vec3 _spot_light{id}_position;\n uniform vec3 _spot_light{id}_direction;\n uniform vec3 _spot_light{id}_color;\n uniform vec2 _spot_light{id}_spot;\n uniform float _spot_light{id}_range;\n #pragma endFor\n#endif\n\n\nLightInfo computeDirectionalLighting(\n vec3 lightDirection,\n vec3 lightColor\n) {\n LightInfo ret;\n ret.lightDir = -normalize(lightDirection);\n ret.radiance = lightColor;\n\n return ret;\n}\n\n\nLightInfo computePointLighting(\n vec3 lightPosition,\n vec3 positionW,\n vec3 lightColor,\n float lightRange\n) {\n LightInfo ret;\n vec3 lightDir = lightPosition - positionW;\n float attenuation = max(0.0, 1.0 - length(lightDir) / lightRange);\n ret.lightDir = normalize(lightDir);\n ret.radiance = lightColor * attenuation;\n\n return ret;\n}\n\n\nLightInfo computeSpotLighting(\n vec3 lightPosition,\n vec3 positionW,\n vec3 lightDirection,\n vec3 lightColor,\n vec2 lightSpot,\n float lightRange\n) {\n LightInfo ret;\n vec3 lightDir = lightPosition - positionW;\n float attenuation = max(0., 1.0 - length(lightDir) / lightRange);\n float cosConeAngle = max(0., dot(lightDirection, -lightDir));\n cosConeAngle = cosConeAngle < lightSpot.x ? 0.0 : cosConeAngle;\n cosConeAngle = pow(cosConeAngle,lightSpot.y);\n ret.lightDir = normalize(lightDir);\n ret.radiance = lightColor * attenuation * cosConeAngle;\n\n return ret;\n}\n\n#include \n\n#if _USE_SHADOW_MAP\n #include \n #include \n#endif\n\nuniform vec3 _eye;\n\nvarying vec3 pos_w;\nvarying vec3 normal_w;\n\n#if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_EMISSIVE_TEXTURE\n varying vec2 uv0;\n#endif\n\n#if USE_IBL\n uniform samplerCube diffuseEnvTexture;\n uniform samplerCube specularEnvTexture;\n uniform sampler2D brdfLUT;\n #if USE_TEX_LOD\n uniform float maxReflectionLod;\n #endif\n#endif\n\n\nuniform vec4 albedo;\n#if USE_ALBEDO_TEXTURE\n uniform sampler2D albedo_texture;\n#endif\n\n#if USE_MRA_TEXTURE\n uniform sampler2D mra_texture;\n#endif\n\nuniform float metallic;\n#if USE_METALLIC_TEXTURE\n uniform sampler2D metallic_texture;\n#endif\n\nuniform float roughness;\n#if USE_ROUGHNESS_TEXTURE\n uniform sampler2D roughness_texture;\n#endif\n\nuniform float ao;\n#if USE_AO_TEXTURE\n uniform sampler2D ao_texture;\n#endif\n\n#if USE_EMISSIVE\n uniform vec3 emissive;\n #if USE_EMISSIVE_TEXTURE\n uniform sampler2D emissive_texture;\n #endif\n#endif\n\n#if USE_ALPHA_TEST\n uniform float alphaTestThreshold;\n#endif\n\n#if USE_NORMAL_TEXTURE\n uniform sampler2D normal_texture;\n \n vec3 getNormalFromTexture() {\n vec3 tangentNormal = texture2D(normal_texture, uv0).rgb * 2.0 - 1.0;\n vec3 q1 = dFdx(pos_w);\n vec3 q2 = dFdy(pos_w);\n vec2 st1 = dFdx(uv0);\n vec2 st2 = dFdy(uv0);\n vec3 N = normalize(normal_w);\n vec3 T = normalize(q1*st2.t - q2*st1.t);\n vec3 B = -normalize(cross(N, T));\n mat3 TBN = mat3(T, B, N);\n\n return normalize(TBN * tangentNormal);\n }\n#endif\n\n\n\n\nfloat distributionGGX(vec3 N, vec3 H, float roughness) {\n float a = roughness * roughness;\n float a2 = a * a;\n float NdotH = max(dot(N, H), 0.0);\n float NdotH2 = NdotH * NdotH;\n float nom = a2;\n float denom = (NdotH2 * (a2 - 1.0) + 1.0);\n denom = PI * denom * denom;\n\n return nom / denom;\n}\n\n\nfloat geometrySchlickGGX(float NdotV, float roughness) {\n float r = (roughness + 1.0);\n float k = (r * r) / 8.0;\n float nom = NdotV;\n float denom = NdotV * (1.0 - k) + k;\n\n return nom / denom;\n}\nfloat geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {\n float NdotV = max(dot(N, V), 0.0);\n float NdotL = max(dot(N, L), 0.0);\n float ggx2 = geometrySchlickGGX(NdotV, roughness);\n float ggx1 = geometrySchlickGGX(NdotL, roughness);\n\n return ggx1 * ggx2;\n}\n\n\n\nvec3 fresnelSchlick(float cosTheta, vec3 F0) {\n float fresnel = exp2((-5.55473 * cosTheta - 6.98316) * cosTheta);\n return F0 + (1.0 - F0) * fresnel;\n}\nvec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) {\n float fresnel = exp2((-5.55473 * cosTheta - 6.98316) * cosTheta);\n return F0 + (max(vec3(1.0 - roughness), F0) - F0) * fresnel;\n}\n\n\nvec3 brdf(LightInfo lightInfo, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) {\n vec3 H = normalize(V + lightInfo.lightDir);\n float NDF = distributionGGX(N, H, roughness);\n float G = geometrySmith(N, V, lightInfo.lightDir, roughness);\n vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);\n vec3 nominator = NDF * G * F;\n float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, lightInfo.lightDir), 0.0) + 0.001; \n vec3 specular = nominator / denominator;\n \n vec3 kS = F;\n \n \n \n vec3 kD = vec3(1.0) - kS;\n \n \n \n kD *= 1.0 - metallic;\n float NdotL = max(dot(N, lightInfo.lightDir), 0.0);\n\n return (kD * albedo / PI + specular) * lightInfo.radiance * NdotL;\n}\n\nvec4 frag() {\n float opacity = 1.0;\n\n #if USE_ALBEDO_TEXTURE\n vec4 baseColor = albedo * gammaToLinearSpaceRGBA(texture2D(albedo_texture, uv0));\n vec3 albedo = baseColor.rgb;\n opacity = baseColor.a;\n #else\n opacity = albedo.a;\n vec3 albedo = albedo.rgb;\n #endif\n\n #if USE_ALPHA_TEST\n if(opacity < alphaTestThreshold) discard;\n #endif\n\n #if USE_MRA_TEXTURE\n vec3 metalRoughness = texture2D(mra_texture, uv0).rgb;\n float metallic = metalRoughness.r;\n float roughness = metalRoughness.g;\n float ao = metalRoughness.b;\n #else\n #if USE_METALLIC_TEXTURE\n float metallic = texture2D(metallic_texture, uv0).r;\n #endif\n #if USE_ROUGHNESS_TEXTURE\n float roughness = texture2D(roughness_texture, uv0).r;\n #endif\n #if USE_AO_TEXTURE\n float ao = texture2D(ao_texture, uv0).r;\n #endif\n #endif\n\n vec3 N = normalize(normal_w);\n #if USE_NORMAL_TEXTURE\n N = getNormalFromTexture();\n #endif\n vec3 V = normalize(_eye - pos_w);\n\n \n \n vec3 F0 = vec3(0.04);\n F0 = mix(F0, albedo, metallic);\n\n \n vec3 Lo = vec3(0.0);\n\n \n #if _NUM_POINT_LIGHTS > 0\n #pragma for id in range(0, _NUM_POINT_LIGHTS)\n LightInfo pointLight{id};\n pointLight{id} = computePointLighting(_point_light{id}_position, pos_w, _point_light{id}_color, _point_light{id}_range);\n Lo += brdf(pointLight{id}, N, V, F0, albedo, metallic, roughness);\n #pragma endFor\n #endif\n\n #if _NUM_DIR_LIGHTS > 0\n #pragma for id in range(0, _NUM_DIR_LIGHTS)\n LightInfo directionalLight{id};\n directionalLight{id} = computeDirectionalLighting(_dir_light{id}_direction, _dir_light{id}_color);\n Lo += brdf(directionalLight{id}, N, V, F0, albedo, metallic, roughness);\n #pragma endFor\n #endif\n\n #if _NUM_SPOT_LIGHTS > 0\n #pragma for id in range(0, _NUM_SPOT_LIGHTS)\n LightInfo spotLight{id};\n spotLight{id} = computeSpotLighting(_spot_light{id}_position, pos_w, _spot_light{id}_direction, _spot_light{id}_color, _spot_light{id}_spot, _spot_light{id}_range);\n Lo += brdf(spotLight{id}, N, V, F0, albedo, metallic, roughness);\n #pragma endFor\n #endif\n\n #if USE_EMISSIVE\n vec3 emissiveColor = emissive;\n #if USE_EMISSIVE_TEXTURE\n emissiveColor *= gammaToLinearSpaceRGB(texture2D(emissive_texture, uv0).rgb);\n #endif\n Lo += emissiveColor;\n #endif\n\n \n vec3 ambient = vec3(0.03) * albedo * ao;\n\n #if USE_IBL\n \n vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness);\n vec3 kS = F;\n vec3 kD = vec3(1.0) - kS;\n kD *= 1.0 - metallic;\n #if USE_RGBE_IBL_DIFFUSE\n vec3 diffuseEnv = unpackRGBE(textureCube(diffuseEnvTexture, N));\n #else\n vec3 diffuseEnv = textureCube(diffuseEnvTexture, N).rgb;\n #endif\n vec3 diffuse = diffuseEnv * albedo;\n \n vec3 R = reflect(-V, N);\n #if USE_TEX_LOD\n #if USE_RGBE_IBL_SPECULAR\n vec3 specularEnv = unpackRGBE(textureCubeLodEXT(specularEnvTexture, R, roughness * maxReflectionLod));\n #else\n vec3 specularEnv = textureCubeLodEXT(specularEnvTexture, R, roughness * maxReflectionLod).rgb;\n #endif\n #else\n #if USE_RGBE_IBL_SPECULAR\n vec3 specularEnv = unpackRGBE(textureCube(specularEnvTexture, R));\n #else\n vec3 specularEnv = textureCube(specularEnvTexture, R).rgb;\n #endif\n #endif\n vec2 brdf = texture2D(brdfLUT, vec2(max(dot(N, V), 0.0), 1.0 - roughness)).rg;\n vec3 specular = specularEnv * (F * brdf.x + brdf.y);\n ambient = (kD * diffuse + specular) * ao;\n #endif\n\n #if _USE_SHADOW_MAP\n float shadow = 1.0;\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n shadow *= computeShadowESM(_shadowMap_{id}, pos_lightspace_{id}, vDepth_{id}, _depthScale_{id}, _darkness_{id}, _frustumEdgeFalloff_{id});\n #pragma endFor\n #endif\n vec3 color = (ambient + Lo) * shadow;\n #else\n vec3 color = ambient + Lo;\n #endif\n\n \n color = color / (color + vec3(1.0));\n \n vec4 finalColor = vec4(color, opacity);\n\n return linearToGammaSpaceRGBA(finalColor);\n}\n", + "pbr-vs": "\n\nattribute vec3 a_position;\nattribute vec3 a_normal;\n\nvarying vec3 pos_w;\nvarying vec3 normal_w;\n\nuniform mat4 _model;\nuniform mat4 _viewProj;\nuniform mat3 _normalMatrix;\n\n#if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_MRA_TEXTURE || USE_EMISSIVE_TEXTURE\n attribute vec2 a_uv0;\n uniform vec2 mainTiling;\n uniform vec2 mainOffset;\n varying vec2 uv0;\n#endif\n\n#if _USE_SKINNING\n #include \n#endif\n\n#if _USE_SHADOW_MAP\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n uniform mat4 _lightViewProjMatrix_{id};\n uniform float _minDepth_{id};\n uniform float _maxDepth_{id};\n varying vec4 pos_lightspace_{id};\n varying float vDepth_{id};\n #pragma endFor\n #endif\n#endif\n\nvec4 vert () {\n vec4 pos = vec4(a_position, 1);\n\n #if _USE_SKINNING\n mat4 skinMat = skinMatrix();\n pos = skinMat * pos;\n #endif\n\n pos_w = (_model * pos).xyz;\n pos = _viewProj * _model * pos;\n\n #if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_MRA_TEXTURE || USE_EMISSIVE_TEXTURE\n uv0 = a_uv0 * mainTiling + mainOffset;\n #endif\n\n vec4 normal = vec4(a_normal, 0);\n #if _USE_SKINNING\n normal = skinMat * normal;\n #endif\n normal_w = _normalMatrix * normal.xyz;\n\n #if _USE_SHADOW_MAP\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n pos_lightspace_{id} = _lightViewProjMatrix_{id} * vec4(pos_w, 1.0);\n vDepth_{id} = (pos_lightspace_{id}.z + _minDepth_{id}) / (_minDepth_{id} + _maxDepth_{id});\n #pragma endFor\n #endif\n #endif\n\n return pos;\n}\n", + "phong-fs": "\n\n#if USE_NORMAL_TEXTURE\n#extension GL_OES_standard_derivatives : enable\n#endif\n\n#include \n#include \n\nstruct LightInfo {\n vec3 diffuse;\n vec3 specular;\n};\n\nLightInfo computeDirectionalLighting(\n vec3 lightDirection,\n vec3 lightColor,\n vec3 normal,\n vec3 viewDirection,\n float glossiness\n) {\n LightInfo lightingResult;\n float ndl = 0.0;\n float ndh = 0.0;\n vec3 lightDir = -normalize(lightDirection);\n ndl = max(0.0, dot(normal, lightDir));\n lightingResult.diffuse = lightColor * ndl;\n\n vec3 dirH = normalize(viewDirection + lightDir);\n ndh = max(0.0, dot(normal, dirH));\n ndh = (ndl == 0.0) ? 0.0: ndh;\n ndh = pow(ndh, max(1.0, glossiness * 128.0));\n lightingResult.specular = lightColor * ndh;\n\n return lightingResult;\n}\n\nLightInfo computePointLighting(\n vec3 lightPosition,\n vec3 lightColor,\n float lightRange,\n vec3 normal,\n vec3 positionW,\n vec3 viewDirection,\n float glossiness\n) {\n LightInfo lightingResult;\n float ndl = 0.0;\n float ndh = 0.0;\n vec3 lightDir = vec3(0, 0, 0);\n float attenuation = 1.0;\n lightDir = lightPosition - positionW;\n attenuation = max(0., 1.0 - length(lightDir) / lightRange);\n lightDir = normalize(lightDir);\n ndl = max(0.0, dot(normal, lightDir));\n lightingResult.diffuse = lightColor * ndl * attenuation;\n\n vec3 dirH = normalize(viewDirection + lightDir);\n ndh = max(0.0, dot(normal, dirH));\n ndh = (ndl == 0.0) ? 0.0: ndh;\n ndh = pow(ndh, max(1.0, glossiness * 128.0));\n lightingResult.specular = lightColor * ndh * attenuation;\n\n return lightingResult;\n}\n\nLightInfo computeSpotLighting(\n vec3 lightPosition,\n vec3 lightDirection,\n vec3 lightColor,\n float lightRange,\n vec2 lightSpot,\n vec3 normal,\n vec3 positionW,\n vec3 viewDirection,\n float glossiness\n) {\n LightInfo lightingResult;\n float ndl = 0.0;\n float ndh = 0.0;\n vec3 lightDir = vec3(0, 0, 0);\n float attenuation = 1.0;\n float cosConeAngle = 1.0;\n\n lightDir = lightPosition - positionW;\n attenuation = max(0., 1.0 - length(lightDir) / lightRange);\n lightDir = normalize(lightDir);\n cosConeAngle = max(0., dot(lightDirection, -lightDir));\n cosConeAngle = cosConeAngle < lightSpot.x ? 0.0 : cosConeAngle;\n cosConeAngle = pow(cosConeAngle,lightSpot.y);\n ndl = max(0.0, dot(normal, lightDir));\n lightingResult.diffuse = lightColor * ndl * attenuation * cosConeAngle;\n\n vec3 dirH = normalize(viewDirection + lightDir);\n ndh = max(0.0, dot(normal, dirH));\n ndh = (ndl == 0.0) ? 0.0: ndh;\n ndh = pow(ndh, max(1.0, glossiness * 128.0));\n lightingResult.specular = lightColor * ndh * attenuation * cosConeAngle;\n\n return lightingResult;\n}\n\n#if _NUM_DIR_LIGHTS > 0\n #pragma for id in range(0, _NUM_DIR_LIGHTS)\n uniform vec3 _dir_light{id}_direction;\n uniform vec3 _dir_light{id}_color;\n #pragma endFor\n#endif\n\n#if _NUM_POINT_LIGHTS > 0\n #pragma for id in range(0, _NUM_POINT_LIGHTS)\n uniform vec3 _point_light{id}_position;\n uniform vec3 _point_light{id}_color;\n uniform float _point_light{id}_range;\n #pragma endFor\n#endif\n\n#if _NUM_SPOT_LIGHTS > 0\n #pragma for id in range(0, _NUM_SPOT_LIGHTS)\n uniform vec3 _spot_light{id}_position;\n uniform vec3 _spot_light{id}_direction;\n uniform vec3 _spot_light{id}_color;\n uniform float _spot_light{id}_range;\n uniform vec2 _spot_light{id}_spot;\n #pragma endFor\n#endif\n\nLightInfo getPhongLighting(\n vec3 normal,\n vec3 positionW,\n vec3 viewDirection,\n float glossiness\n) {\n LightInfo result;\n result.diffuse = vec3(0, 0, 0);\n result.specular = vec3(0, 0, 0);\n LightInfo dirLighting;\n #if _NUM_DIR_LIGHTS > 0\n #pragma for id in range(0, _NUM_DIR_LIGHTS)\n dirLighting = computeDirectionalLighting(_dir_light{id}_direction,_dir_light{id}_color,normal, viewDirection, glossiness);\n result.diffuse += dirLighting.diffuse;\n result.specular += dirLighting.specular;\n #pragma endFor\n #endif\n\n LightInfo pointLighting;\n #if _NUM_POINT_LIGHTS > 0\n #pragma for id in range(0, _NUM_POINT_LIGHTS)\n pointLighting = computePointLighting(_point_light{id}_position, _point_light{id}_color, _point_light{id}_range,\n normal, positionW, viewDirection, glossiness);\n result.diffuse += pointLighting.diffuse;\n result.specular += pointLighting.specular;\n #pragma endFor\n #endif\n\n LightInfo spotLighting;\n #if _NUM_SPOT_LIGHTS > 0\n #pragma for id in range(0, _NUM_SPOT_LIGHTS)\n spotLighting = computeSpotLighting(_spot_light{id}_position, _spot_light{id}_direction, _spot_light{id}_color,\n _spot_light{id}_range, _spot_light{id}_spot,normal, positionW, viewDirection, glossiness);\n result.diffuse += spotLighting.diffuse;\n result.specular += spotLighting.specular;\n #pragma endFor\n #endif\n return result;\n}\n\n#if _USE_SHADOW_MAP\n #include \n #include \n#endif\n\nuniform vec3 _eye;\nuniform vec3 ambient;\n\nvarying vec3 normal_w;\nvarying vec3 pos_w;\n\n#if USE_NORMAL_TEXTURE || USE_DIFFUSE_TEXTURE || USE_EMISSIVE_TEXTURE\n varying vec2 uv0;\n#endif\n\nstruct phongMaterial\n{\n vec3 diffuse;\n vec3 emissive;\n vec3 specular;\n float glossiness;\n float opacity;\n};\n\nuniform vec4 diffuseColor;\n#if USE_DIFFUSE_TEXTURE\n uniform sampler2D diffuse_texture;\n#endif\n\n#if USE_EMISSIVE\n uniform vec3 emissiveColor;\n #if USE_EMISSIVE_TEXTURE\n uniform sampler2D emissive_texture;\n #endif\n#endif\n\n#if USE_SPECULAR\n uniform vec3 specularColor;\n uniform float glossiness;\n #if USE_SPECULAR_TEXTURE\n uniform sampler2D specular_texture;\n #endif\n#endif\n\n#if USE_NORMAL_TEXTURE\n uniform sampler2D normal_texture;\n uniform float normalScale; \n vec3 getNormal(vec3 pos, vec3 normal) {\n vec3 q0 = vec3( dFdx( pos.x ), dFdx( pos.y ), dFdx( pos.z ) );\n vec3 q1 = vec3( dFdy( pos.x ), dFdy( pos.y ), dFdy( pos.z ) );\n vec2 st0 = dFdx( uv0.st );\n vec2 st1 = dFdy( uv0.st );\n vec3 S = normalize( q0 * st1.t - q1 * st0.t );\n vec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n vec3 N = normal;\n vec3 mapN = texture2D(normal_texture, uv0).rgb * 2.0 - 1.0;\n mapN.xy = 1.0 * mapN.xy;\n mat3 tsn = mat3( S, T, N );\n return normalize( tsn * mapN );\n }\n#endif\n\n#if USE_ALPHA_TEST\n uniform float alphaTestThreshold;\n#endif\n\nphongMaterial getPhongMaterial() {\n phongMaterial result;\n\n #if USE_DIFFUSE_TEXTURE\n vec4 baseColor = diffuseColor * gammaToLinearSpaceRGBA(texture2D(diffuse_texture, uv0));\n result.diffuse = baseColor.rgb;\n result.opacity = baseColor.a;\n #else\n result.diffuse = diffuseColor.rgb;\n result.opacity = diffuseColor.a;\n #endif\n\n #if USE_EMISSIVE\n result.emissive = gammaToLinearSpaceRGB(emissiveColor);\n #if USE_EMISSIVE_TEXTURE\n result.emissive *= gammaToLinearSpaceRGB(texture2D(emissive_texture, uv0).rgb);\n #endif\n #endif\n\n #if USE_SPECULAR\n result.specular = gammaToLinearSpaceRGB(specularColor);\n #if USE_SPECULAR_TEXTURE\n result.specular = gammaToLinearSpaceRGB(texture2D(specular_texture, uv0).rgb);\n #endif\n\n result.glossiness = glossiness;\n #endif\n\n return result;\n}\n\nvec4 composePhongShading(LightInfo lighting, phongMaterial mtl, float shadow)\n{\n vec4 o = vec4(0.0, 0.0, 0.0, 1.0);\n\n \n o.xyz = lighting.diffuse * mtl.diffuse;\n #if USE_EMISSIVE\n o.xyz += mtl.emissive;\n #endif\n #if USE_SPECULAR\n o.xyz += lighting.specular * mtl.specular;\n #endif\n o.xyz *= shadow;\n o.w = mtl.opacity;\n\n return o;\n}\n\nvec4 frag () {\n LightInfo phongLighting;\n vec3 viewDirection = normalize(_eye - pos_w);\n\n phongMaterial mtl = getPhongMaterial();\n #if USE_ALPHA_TEST\n if(mtl.opacity < alphaTestThreshold) discard;\n #endif\n vec3 normal = normalize(normal_w);\n #if USE_NORMAL_TEXTURE\n normal = getNormal(pos_w, normal);\n #endif\n phongLighting = getPhongLighting(normal, pos_w, viewDirection, mtl.glossiness);\n phongLighting.diffuse += ambient;\n\n #if _USE_SHADOW_MAP\n float shadow = 1.0;\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n shadow *= computeShadowESM(_shadowMap_{id}, pos_lightspace_{id}, vDepth_{id}, _depthScale_{id}, _darkness_{id}, _frustumEdgeFalloff_{id});\n #pragma endFor\n #endif\n vec4 finalColor = composePhongShading(phongLighting, mtl, shadow);\n #else\n vec4 finalColor = composePhongShading(phongLighting, mtl, 1.0);\n #endif\n\n return linearToGammaSpaceRGBA(finalColor);\n}\n", + "phong-vs": "\n\nattribute vec3 a_position;\nattribute vec3 a_normal;\n\nuniform mat4 _model;\nuniform mat4 _viewProj;\nuniform mat3 _normalMatrix;\n\nvarying vec3 normal_w;\nvarying vec3 pos_w;\n\n#if USE_NORMAL_TEXTURE || USE_DIFFUSE_TEXTURE || USE_EMISSIVE_TEXTURE\n attribute vec2 a_uv0;\n uniform vec2 mainTiling;\n uniform vec2 mainOffset;\n varying vec2 uv0;\n#endif\n\n#if _USE_SKINNING\n #include \n#endif\n\n#if _USE_SHADOW_MAP\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n uniform mat4 _lightViewProjMatrix_{id};\n uniform float _minDepth_{id};\n uniform float _maxDepth_{id};\n varying vec4 pos_lightspace_{id};\n varying float vDepth_{id};\n #pragma endFor\n #endif\n#endif\n\nvec4 vert () {\n vec4 pos = vec4(a_position, 1);\n\n #if _USE_SKINNING\n mat4 skinMat = skinMatrix();\n pos = skinMat * pos;\n #endif\n\n pos_w = (_model * pos).xyz;\n pos = _viewProj * _model * pos;\n\n #if USE_NORMAL_TEXTURE || USE_DIFFUSE_TEXTURE || USE_EMISSIVE_TEXTURE\n uv0 = a_uv0 * mainTiling + mainOffset;\n #endif\n\n vec4 normal = vec4(a_normal, 0);\n #if _USE_SKINNING\n normal = skinMat * normal;\n #endif\n normal_w = _normalMatrix * normal.xyz;\n\n #if _USE_SHADOW_MAP\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n pos_lightspace_{id} = _lightViewProjMatrix_{id} * vec4(pos_w, 1.0);\n vDepth_{id} = (pos_lightspace_{id}.z + _minDepth_{id}) / (_minDepth_{id} + _maxDepth_{id});\n #pragma endFor\n #endif\n #endif\n\n return pos;\n}\n", + "rect-area-light": "\n\nmat3 transpose(mat3 v) {\n mat3 tmp;\n tmp[0] = vec3(v[0].x, v[1].x, v[2].x);\n tmp[1] = vec3(v[0].y, v[1].y, v[2].y);\n tmp[2] = vec3(v[0].z, v[1].z, v[2].z);\n\n return tmp;\n}\n\nvoid ClipQuadToHorizon(inout vec3 L[5], out int n) {\n \n int config = 0;\n if (L[0].z > 0.0) config += 1;\n if (L[1].z > 0.0) config += 2;\n if (L[2].z > 0.0) config += 4;\n if (L[3].z > 0.0) config += 8;\n config = 15;\n\n \n n = 0;\n\n if (config == 0)\n {\n \n }\n else if (config == 1) \n {\n n = 3;\n L[1] = -L[1].z * L[0] + L[0].z * L[1];\n L[2] = -L[3].z * L[0] + L[0].z * L[3];\n }\n else if (config == 2) \n {\n n = 3;\n L[0] = -L[0].z * L[1] + L[1].z * L[0];\n L[2] = -L[2].z * L[1] + L[1].z * L[2];\n }\n else if (config == 3) \n {\n n = 4;\n L[2] = -L[2].z * L[1] + L[1].z * L[2];\n L[3] = -L[3].z * L[0] + L[0].z * L[3];\n }\n else if (config == 4) \n {\n n = 3;\n L[0] = -L[3].z * L[2] + L[2].z * L[3];\n L[1] = -L[1].z * L[2] + L[2].z * L[1];\n }\n else if (config == 5) \n {\n n = 0;\n }\n else if (config == 6) \n {\n n = 4;\n L[0] = -L[0].z * L[1] + L[1].z * L[0];\n L[3] = -L[3].z * L[2] + L[2].z * L[3];\n }\n else if (config == 7) \n {\n n = 5;\n L[4] = -L[3].z * L[0] + L[0].z * L[3];\n L[3] = -L[3].z * L[2] + L[2].z * L[3];\n }\n else if (config == 8) \n {\n n = 3;\n L[0] = -L[0].z * L[3] + L[3].z * L[0];\n L[1] = -L[2].z * L[3] + L[3].z * L[2];\n L[2] = L[3];\n }\n else if (config == 9) \n {\n n = 4;\n L[1] = -L[1].z * L[0] + L[0].z * L[1];\n L[2] = -L[2].z * L[3] + L[3].z * L[2];\n }\n else if (config == 10) \n {\n n = 0;\n }\n else if (config == 11) \n {\n n = 5;\n L[4] = L[3];\n L[3] = -L[2].z * L[3] + L[3].z * L[2];\n L[2] = -L[2].z * L[1] + L[1].z * L[2];\n }\n else if (config == 12) \n {\n n = 4;\n L[1] = -L[1].z * L[2] + L[2].z * L[1];\n L[0] = -L[0].z * L[3] + L[3].z * L[0];\n }\n else if (config == 13) \n {\n n = 5;\n L[4] = L[3];\n L[3] = L[2];\n L[2] = -L[1].z * L[2] + L[2].z * L[1];\n L[1] = -L[1].z * L[0] + L[0].z * L[1];\n }\n else if (config == 14) \n {\n n = 5;\n L[4] = -L[0].z * L[3] + L[3].z * L[0];\n L[0] = -L[0].z * L[1] + L[1].z * L[0];\n }\n else if (config == 15) \n {\n n = 4;\n }\n\n if (n == 3)\n L[3] = L[0];\n if (n == 4)\n L[4] = L[0];\n}\n\n\nfloat IntegrateEdge(vec3 v1, vec3 v2) {\n float cosTheta = dot(v1, v2);\n float theta = acos(cosTheta);\n return cross(v1, v2).z * ((theta > 0.001) ? theta/sin(theta) : 4.0);\n}\n\nvec3 LTC_Evaluate(vec3 N, vec3 V, vec3 P, mat3 Minv, vec3 points[4]) {\n \n vec3 T1, T2;\n T1 = normalize(V - N*dot(V, N));\n T2 = cross(N, T1);\n\n \n Minv = Minv * transpose(mat3(T1, T2, N));\n\n \n vec3 L[5];\n L[0] = Minv * (points[0] - P);\n L[1] = Minv * (points[1] - P);\n L[2] = Minv * (points[2] - P);\n L[3] = Minv * (points[3] - P);\n\n int n;\n ClipQuadToHorizon(L, n);\n\n if (n == 0)\n return vec3(0, 0, 0);\n\n \n L[0] = normalize(L[0]);\n L[1] = normalize(L[1]);\n L[2] = normalize(L[2]);\n L[3] = normalize(L[3]);\n L[4] = normalize(L[4]);\n\n \n float sum = 0.0;\n\n sum += IntegrateEdge(L[0], L[1]);\n sum += IntegrateEdge(L[1], L[2]);\n sum += IntegrateEdge(L[2], L[3]);\n if (n >= 4)\n sum += IntegrateEdge(L[3], L[4]);\n if (n == 5)\n sum += IntegrateEdge(L[4], L[0]);\n\n sum = max(0.0, sum);\n\n vec3 Lo_i = vec3(sum, sum, sum);\n\n return Lo_i;\n}\n", + "shadow-depth-fs": "\n\nuniform float _depthScale;\nvarying float vDepth;\n\n#include \n\nvec4 frag() {\n \n \n return packDepthToRGBA(vDepth);\n \n \n}\n", + "shadow-depth-vs": "\n\nattribute vec3 a_position;\n\nuniform mat4 _model;\nuniform mat4 _lightViewProjMatrix;\nuniform float _minDepth;\nuniform float _maxDepth;\nuniform float _bias;\nvarying float vDepth;\n\n#if _USE_SKINNING\n #include \n#endif\n\nvec4 vert() {\n vec4 pos = vec4(a_position, 1);\n\n #if _USE_SKINNING\n mat4 skinMat = skinMatrix();\n pos = skinMat * pos;\n #endif\n\n \n vDepth = ((gl_Position.z + _minDepth) / (_minDepth + _maxDepth)) + _bias;\n return _lightViewProjMatrix * _model * pos;\n}\n", + "shadow-mapping": "\n\n#if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n uniform sampler2D _shadowMap_{id};\n uniform float _darkness_{id};\n uniform float _depthScale_{id};\n uniform float _frustumEdgeFalloff_{id};\n uniform float _bias_{id};\n uniform vec2 _texelSize_{id};\n varying vec4 pos_lightspace_{id};\n varying float vDepth_{id};\n #pragma endFor\n#endif\n\nfloat computeShadow(sampler2D shadowMap, vec4 pos_lightspace, float bias) {\n vec3 projCoords = pos_lightspace.xyz / pos_lightspace.w;\n projCoords = projCoords * 0.5 + 0.5;\n float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, projCoords.xy));\n float currentDepth = projCoords.z;\n float shadow = (currentDepth - bias > closestDepth) ? 0.0 : 1.0;\n return shadow;\n}\n\nfloat computeFallOff(float esm, vec2 coords, float frustumEdgeFalloff) {\n float mask = smoothstep(1.0 - frustumEdgeFalloff, 1.0, clamp(dot(coords, coords), 0.0, 1.0));\n return mix(esm, 1.0, mask);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nfloat computeShadowESM(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float depthScale, float darkness, float frustumEdgeFalloff) {\n vec2 projCoords = pos_lightspace.xy / pos_lightspace.w;\n vec2 shadowUV = projCoords * 0.5 + vec2(0.5);\n if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) {\n return 1.0;\n }\n float currentDepth = clamp(vDepth, 0.0, 1.0);\n float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, shadowUV));\n \n float esm = clamp(exp(-depthScale * (currentDepth - closestDepth)), 1.0 - darkness, 1.0);\n return computeFallOff(esm, projCoords, frustumEdgeFalloff);\n}\n\nfloat computeShadowPCF(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float darkness, vec2 texelSize, float frustumEdgeFalloff) {\n vec2 projCoords = pos_lightspace.xy / pos_lightspace.w;\n vec2 shadowUV = projCoords * 0.5 + vec2(0.5);\n if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) {\n return 1.0;\n }\n float currentDepth = clamp(vDepth, 0.0, 1.0);\n float visibility = 1.0;\n vec2 poissonDisk[4];\n poissonDisk[0] = vec2(-0.94201624, -0.39906216);\n poissonDisk[1] = vec2(0.94558609, -0.76890725);\n poissonDisk[2] = vec2(-0.094184101, -0.92938870);\n poissonDisk[3] = vec2(0.34495938, 0.29387760);\n if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[0] * texelSize)) < currentDepth) visibility -= 0.25;\n if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[1] * texelSize)) < currentDepth) visibility -= 0.25;\n if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[2] * texelSize)) < currentDepth) visibility -= 0.25;\n if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[3] * texelSize)) < currentDepth) visibility -= 0.25;\n\n return computeFallOff(min(1.0, visibility + 1.0 - darkness), projCoords, frustumEdgeFalloff);\n}", + "skinning": "\n\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n\n#if _USE_JOINTS_TEXTRUE\nuniform sampler2D _jointsTexture;\nuniform float _jointsTextureSize;\n\nmat4 getBoneMatrix(const in float i) {\n float size = _jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n\n y = dy * (y + 0.5);\n\n vec4 v1 = texture2D(_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(_jointsTexture, vec2(dx * (x + 3.5), y));\n\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 _jointMatrices[64];\n\nmat4 getBoneMatrix(const in float i) {\n return _jointMatrices[int(i)];\n}\n#endif\n\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}", + "unlit-fs": "\n\n#if USE_TEXTURE\n uniform sampler2D texture;\n#endif\n\n#if _USE_ATTRIBUTE_UV0\n varying vec2 v_uv0;\n#endif\n\n#if _USE_ATTRIBUTE_COLOR\n varying vec4 v_color;\n#endif\n\nuniform vec4 color;\n\nvec4 frag () {\n vec4 o = color;\n \n #if _USE_ATTRIBUTE_COLOR\n o *= v_color;\n #endif\n\n #if USE_TEXTURE && _USE_ATTRIBUTE_UV0\n o *= texture2D(texture, v_uv0);\n #endif\n\n return o;\n}", + "unlit-vs": "\n\nuniform mat4 _viewProj;\nuniform mat4 _model;\n\nattribute vec3 a_position;\n\n#if _USE_ATTRIBUTE_COLOR\n attribute lowp vec4 a_color;\n varying lowp vec4 v_color;\n#endif\n\n#if _USE_ATTRIBUTE_UV0\n attribute vec2 a_uv0;\n varying vec2 v_uv0;\n#endif\n\n#if _USE_SKINNING\n #include \n#endif\n\nvec4 vert () {\n mat4 mvp = _viewProj * _model;\n\n #if _USE_SKINNING\n mvp = mvp * skinMatrix();\n #endif\n\n vec4 pos = mvp * vec4(a_position, 1);\n\n #if _USE_ATTRIBUTE_UV0\n v_uv0 = a_uv0;\n #endif\n\n #if _USE_ATTRIBUTE_COLOR\n v_color = a_color;\n #endif\n\n return pos;\n}", + "unpack": "\n\nvec3 unpackNormal(vec4 nmap) {\n return nmap.xyz * 2.0 - 1.0;\n}\n\nvec3 unpackRGBE(vec4 rgbe) {\n return rgbe.rgb * pow(2.0, rgbe.a * 255.0 - 128.0);\n}" +} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/packing.inc b/cocos2d/renderer/build/chunks/packing.inc new file mode 100644 index 00000000000..5b1518d33b1 --- /dev/null +++ b/cocos2d/renderer/build/chunks/packing.inc @@ -0,0 +1,12 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +vec4 packDepthToRGBA(float depth) { + vec4 ret = vec4(1.0, 255.0, 65025.0, 160581375.0) * depth; + ret = fract(ret); + ret -= ret.yzww * vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0); + return ret; +} + +float unpackRGBAToDepth(vec4 color) { + return dot(color, vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 160581375.0)); +} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/pbr-fs.inc b/cocos2d/renderer/build/chunks/pbr-fs.inc new file mode 100644 index 00000000000..97b33cbc724 --- /dev/null +++ b/cocos2d/renderer/build/chunks/pbr-fs.inc @@ -0,0 +1,366 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#if USE_NORMAL_TEXTURE +#extension GL_OES_standard_derivatives : enable +#endif + +#if USE_TEX_LOD +#extension GL_EXT_shader_texture_lod: enable +#endif + +#include +#include + +struct LightInfo { + vec3 lightDir; + vec3 radiance; +}; + +#if _NUM_DIR_LIGHTS > 0 + #pragma for id in range(0, _NUM_DIR_LIGHTS) + uniform vec3 _dir_light{id}_direction; + uniform vec3 _dir_light{id}_color; + #pragma endFor +#endif + +#if _NUM_POINT_LIGHTS > 0 + #pragma for id in range(0, _NUM_POINT_LIGHTS) + uniform vec3 _point_light{id}_position; + uniform vec3 _point_light{id}_color; + uniform float _point_light{id}_range; + #pragma endFor +#endif + +#if _NUM_SPOT_LIGHTS > 0 + #pragma for id in range(0, _NUM_SPOT_LIGHTS) + uniform vec3 _spot_light{id}_position; + uniform vec3 _spot_light{id}_direction; + uniform vec3 _spot_light{id}_color; + uniform vec2 _spot_light{id}_spot; + uniform float _spot_light{id}_range; + #pragma endFor +#endif + +// directional light +LightInfo computeDirectionalLighting( + vec3 lightDirection, + vec3 lightColor +) { + LightInfo ret; + ret.lightDir = -normalize(lightDirection); + ret.radiance = lightColor; + + return ret; +} + +// point light +LightInfo computePointLighting( + vec3 lightPosition, + vec3 positionW, + vec3 lightColor, + float lightRange +) { + LightInfo ret; + vec3 lightDir = lightPosition - positionW; + float attenuation = max(0.0, 1.0 - length(lightDir) / lightRange); + ret.lightDir = normalize(lightDir); + ret.radiance = lightColor * attenuation; + + return ret; +} + +// spot light +LightInfo computeSpotLighting( + vec3 lightPosition, + vec3 positionW, + vec3 lightDirection, + vec3 lightColor, + vec2 lightSpot, + float lightRange +) { + LightInfo ret; + vec3 lightDir = lightPosition - positionW; + float attenuation = max(0., 1.0 - length(lightDir) / lightRange); + float cosConeAngle = max(0., dot(lightDirection, -lightDir)); + cosConeAngle = cosConeAngle < lightSpot.x ? 0.0 : cosConeAngle; + cosConeAngle = pow(cosConeAngle,lightSpot.y); + ret.lightDir = normalize(lightDir); + ret.radiance = lightColor * attenuation * cosConeAngle; + + return ret; +} + +#include + +#if _USE_SHADOW_MAP + #include + #include +#endif + +uniform vec3 _eye; + +varying vec3 pos_w; +varying vec3 normal_w; + +#if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_EMISSIVE_TEXTURE + varying vec2 uv0; +#endif + +#if USE_IBL + uniform samplerCube diffuseEnvTexture; + uniform samplerCube specularEnvTexture; + uniform sampler2D brdfLUT; + #if USE_TEX_LOD + uniform float maxReflectionLod; + #endif +#endif + +// material parameters +uniform vec4 albedo; +#if USE_ALBEDO_TEXTURE + uniform sampler2D albedo_texture; +#endif + +#if USE_MRA_TEXTURE + uniform sampler2D mra_texture; +#endif + +uniform float metallic; +#if USE_METALLIC_TEXTURE + uniform sampler2D metallic_texture; +#endif + +uniform float roughness; +#if USE_ROUGHNESS_TEXTURE + uniform sampler2D roughness_texture; +#endif + +uniform float ao; +#if USE_AO_TEXTURE + uniform sampler2D ao_texture; +#endif + +#if USE_EMISSIVE + uniform vec3 emissive; + #if USE_EMISSIVE_TEXTURE + uniform sampler2D emissive_texture; + #endif +#endif + +#if USE_ALPHA_TEST + uniform float alphaTestThreshold; +#endif + +#if USE_NORMAL_TEXTURE + uniform sampler2D normal_texture; + // get world-space normal from normal texture + vec3 getNormalFromTexture() { + vec3 tangentNormal = texture2D(normal_texture, uv0).rgb * 2.0 - 1.0; + vec3 q1 = dFdx(pos_w); + vec3 q2 = dFdy(pos_w); + vec2 st1 = dFdx(uv0); + vec2 st2 = dFdy(uv0); + vec3 N = normalize(normal_w); + vec3 T = normalize(q1*st2.t - q2*st1.t); + vec3 B = -normalize(cross(N, T)); + mat3 TBN = mat3(T, B, N); + + return normalize(TBN * tangentNormal); + } +#endif + +// Cook-Torrance BRDF _model +// D() Normal distribution function (Trowbridge-Reitz GGX) +// https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf +float distributionGGX(vec3 N, vec3 H, float roughness) { + float a = roughness * roughness; + float a2 = a * a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH * NdotH; + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// G() Geometry function (Smith's Schlick GGX) +// https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf +float geometrySchlickGGX(float NdotV, float roughness) { + float r = (roughness + 1.0); + float k = (r * r) / 8.0; + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = geometrySchlickGGX(NdotV, roughness); + float ggx1 = geometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// F() Fresnel equation (Fresnel-Schlick approximation) +// Optimized variant (presented by Epic at SIGGRAPH '13) +// https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf +vec3 fresnelSchlick(float cosTheta, vec3 F0) { + float fresnel = exp2((-5.55473 * cosTheta - 6.98316) * cosTheta); + return F0 + (1.0 - F0) * fresnel; +} +vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) { + float fresnel = exp2((-5.55473 * cosTheta - 6.98316) * cosTheta); + return F0 + (max(vec3(1.0 - roughness), F0) - F0) * fresnel; +} + +// BRDF equation +vec3 brdf(LightInfo lightInfo, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { + vec3 H = normalize(V + lightInfo.lightDir); + float NDF = distributionGGX(N, H, roughness); + float G = geometrySmith(N, V, lightInfo.lightDir, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + vec3 nominator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, lightInfo.lightDir), 0.0) + 0.001; // 0.001 to prevent divide by zero. + vec3 specular = nominator / denominator; + // kS is equal to Fresnel + vec3 kS = F; + // for energy conservation, the diffuse and specular light can't + // be above 1.0 (unless the surface emits light); to preserve this + // relationship the diffuse component (kD) should equal 1.0 - kS. + vec3 kD = vec3(1.0) - kS; + // multiply kD by the inverse metalness such that only non-metals + // have diffuse lighting, or a linear blend if partly metal (pure metals + // have no diffuse light). + kD *= 1.0 - metallic; + float NdotL = max(dot(N, lightInfo.lightDir), 0.0); + + return (kD * albedo / PI + specular) * lightInfo.radiance * NdotL; +} + +vec4 frag() { + float opacity = 1.0; + + #if USE_ALBEDO_TEXTURE + vec4 baseColor = albedo * gammaToLinearSpaceRGBA(texture2D(albedo_texture, uv0)); + vec3 albedo = baseColor.rgb; + opacity = baseColor.a; + #else + opacity = albedo.a; + vec3 albedo = albedo.rgb; + #endif + + #if USE_ALPHA_TEST + if(opacity < alphaTestThreshold) discard; + #endif + + #if USE_MRA_TEXTURE + vec3 metalRoughness = texture2D(mra_texture, uv0).rgb; + float metallic = metalRoughness.r; + float roughness = metalRoughness.g; + float ao = metalRoughness.b; + #else + #if USE_METALLIC_TEXTURE + float metallic = texture2D(metallic_texture, uv0).r; + #endif + #if USE_ROUGHNESS_TEXTURE + float roughness = texture2D(roughness_texture, uv0).r; + #endif + #if USE_AO_TEXTURE + float ao = texture2D(ao_texture, uv0).r; + #endif + #endif + + vec3 N = normalize(normal_w); + #if USE_NORMAL_TEXTURE + N = getNormalFromTexture(); + #endif + vec3 V = normalize(_eye - pos_w); + + // calculate reflectance at normal incidence; if dia-electric (like plastic) use F0 + // of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow) + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // reflection + vec3 Lo = vec3(0.0); + + // point light (a 'for' loop to accumulate all light sources) + #if _NUM_POINT_LIGHTS > 0 + #pragma for id in range(0, _NUM_POINT_LIGHTS) + LightInfo pointLight{id}; + pointLight{id} = computePointLighting(_point_light{id}_position, pos_w, _point_light{id}_color, _point_light{id}_range); + Lo += brdf(pointLight{id}, N, V, F0, albedo, metallic, roughness); + #pragma endFor + #endif + + #if _NUM_DIR_LIGHTS > 0 + #pragma for id in range(0, _NUM_DIR_LIGHTS) + LightInfo directionalLight{id}; + directionalLight{id} = computeDirectionalLighting(_dir_light{id}_direction, _dir_light{id}_color); + Lo += brdf(directionalLight{id}, N, V, F0, albedo, metallic, roughness); + #pragma endFor + #endif + + #if _NUM_SPOT_LIGHTS > 0 + #pragma for id in range(0, _NUM_SPOT_LIGHTS) + LightInfo spotLight{id}; + spotLight{id} = computeSpotLighting(_spot_light{id}_position, pos_w, _spot_light{id}_direction, _spot_light{id}_color, _spot_light{id}_spot, _spot_light{id}_range); + Lo += brdf(spotLight{id}, N, V, F0, albedo, metallic, roughness); + #pragma endFor + #endif + + #if USE_EMISSIVE + vec3 emissiveColor = emissive; + #if USE_EMISSIVE_TEXTURE + emissiveColor *= gammaToLinearSpaceRGB(texture2D(emissive_texture, uv0).rgb); + #endif + Lo += emissiveColor; + #endif + + // ambient lighting, will be replaced by IBL if IBL used. + vec3 ambient = vec3(0.03) * albedo * ao; + + #if USE_IBL + // generate ambient when using IBL. + vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness); + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + #if USE_RGBE_IBL_DIFFUSE + vec3 diffuseEnv = unpackRGBE(textureCube(diffuseEnvTexture, N)); + #else + vec3 diffuseEnv = textureCube(diffuseEnvTexture, N).rgb; + #endif + vec3 diffuse = diffuseEnv * albedo; + // sample both the specularEnvTexture and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part. + vec3 R = reflect(-V, N); + #if USE_TEX_LOD + #if USE_RGBE_IBL_SPECULAR + vec3 specularEnv = unpackRGBE(textureCubeLodEXT(specularEnvTexture, R, roughness * maxReflectionLod)); + #else + vec3 specularEnv = textureCubeLodEXT(specularEnvTexture, R, roughness * maxReflectionLod).rgb; + #endif + #else + #if USE_RGBE_IBL_SPECULAR + vec3 specularEnv = unpackRGBE(textureCube(specularEnvTexture, R)); + #else + vec3 specularEnv = textureCube(specularEnvTexture, R).rgb; + #endif + #endif + vec2 brdf = texture2D(brdfLUT, vec2(max(dot(N, V), 0.0), 1.0 - roughness)).rg; + vec3 specular = specularEnv * (F * brdf.x + brdf.y); + ambient = (kD * diffuse + specular) * ao; + #endif + + vec3 color = ambient + Lo; + #if _USE_SHADOW_MAP + color *= computeShadow(); + #endif + + // HDR tone mapping. + color = color / (color + vec3(1.0)); + // gamma correction. + vec4 finalColor = vec4(color, opacity); + + return linearToGammaSpaceRGBA(finalColor); +} diff --git a/cocos2d/renderer/build/chunks/pbr-vs.inc b/cocos2d/renderer/build/chunks/pbr-vs.inc new file mode 100644 index 00000000000..020b96eb8eb --- /dev/null +++ b/cocos2d/renderer/build/chunks/pbr-vs.inc @@ -0,0 +1,49 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +attribute vec3 a_position; +attribute vec3 a_normal; + +varying vec3 pos_w; +varying vec3 normal_w; + +uniform mat4 _model; +uniform mat4 _viewProj; +uniform mat3 _normalMatrix; + +#if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_MRA_TEXTURE || USE_EMISSIVE_TEXTURE + attribute vec2 a_uv0; + uniform vec2 mainTiling; + uniform vec2 mainOffset; + varying vec2 uv0; +#endif + +#if _USE_SKINNING + #include +#endif + +#if _USE_SHADOW_MAP + #include +#endif + +vec4 vert () { + vec4 pos = vec4(a_position, 1); + vec4 normal = vec4(a_normal, 0); + + #if _USE_SKINNING + skinVertex(pos, normal); + #endif + + pos_w = (_model * pos).xyz; + pos = _viewProj * _model * pos; + normal_w = _normalMatrix * normal.xyz; + + #if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_MRA_TEXTURE || USE_EMISSIVE_TEXTURE + uv0 = a_uv0 * mainTiling + mainOffset; + #endif + + #if _USE_SHADOW_MAP + prepareShadowData(pos_w); + #endif + + return pos; +} diff --git a/cocos2d/renderer/build/chunks/phong-fs.inc b/cocos2d/renderer/build/chunks/phong-fs.inc new file mode 100644 index 00000000000..2ad3bc88f81 --- /dev/null +++ b/cocos2d/renderer/build/chunks/phong-fs.inc @@ -0,0 +1,305 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#if USE_NORMAL_TEXTURE +#extension GL_OES_standard_derivatives : enable +#endif + +#include +#include + +struct LightInfo { + vec3 diffuse; + vec3 specular; +}; + +LightInfo computeDirectionalLighting( + vec3 lightDirection, + vec3 lightColor, + vec3 normal, + vec3 viewDirection, + float glossiness +) { + LightInfo lightingResult; + float ndl = 0.0; + float ndh = 0.0; + vec3 lightDir = -normalize(lightDirection); + ndl = max(0.0, dot(normal, lightDir)); + lightingResult.diffuse = lightColor * ndl; + + vec3 dirH = normalize(viewDirection + lightDir); + ndh = max(0.0, dot(normal, dirH)); + ndh = (ndl == 0.0) ? 0.0: ndh; + ndh = pow(ndh, max(1.0, glossiness * 128.0)); + lightingResult.specular = lightColor * ndh; + + return lightingResult; +} + +LightInfo computePointLighting( + vec3 lightPosition, + vec3 lightColor, + float lightRange, + vec3 normal, + vec3 positionW, + vec3 viewDirection, + float glossiness +) { + LightInfo lightingResult; + float ndl = 0.0; + float ndh = 0.0; + vec3 lightDir = vec3(0, 0, 0); + float attenuation = 1.0; + lightDir = lightPosition - positionW; + attenuation = max(0., 1.0 - length(lightDir) / lightRange); + lightDir = normalize(lightDir); + ndl = max(0.0, dot(normal, lightDir)); + lightingResult.diffuse = lightColor * ndl * attenuation; + + vec3 dirH = normalize(viewDirection + lightDir); + ndh = max(0.0, dot(normal, dirH)); + ndh = (ndl == 0.0) ? 0.0: ndh; + ndh = pow(ndh, max(1.0, glossiness * 128.0)); + lightingResult.specular = lightColor * ndh * attenuation; + + return lightingResult; +} + +LightInfo computeSpotLighting( + vec3 lightPosition, + vec3 lightDirection, + vec3 lightColor, + float lightRange, + vec2 lightSpot, + vec3 normal, + vec3 positionW, + vec3 viewDirection, + float glossiness +) { + LightInfo lightingResult; + float ndl = 0.0; + float ndh = 0.0; + vec3 lightDir = vec3(0, 0, 0); + float attenuation = 1.0; + float cosConeAngle = 1.0; + + lightDir = lightPosition - positionW; + attenuation = max(0., 1.0 - length(lightDir) / lightRange); + lightDir = normalize(lightDir); + cosConeAngle = max(0., dot(lightDirection, -lightDir)); + cosConeAngle = cosConeAngle < lightSpot.x ? 0.0 : cosConeAngle; + cosConeAngle = pow(cosConeAngle,lightSpot.y); + ndl = max(0.0, dot(normal, lightDir)); + lightingResult.diffuse = lightColor * ndl * attenuation * cosConeAngle; + + vec3 dirH = normalize(viewDirection + lightDir); + ndh = max(0.0, dot(normal, dirH)); + ndh = (ndl == 0.0) ? 0.0: ndh; + ndh = pow(ndh, max(1.0, glossiness * 128.0)); + lightingResult.specular = lightColor * ndh * attenuation * cosConeAngle; + + return lightingResult; +} + +#if _NUM_DIR_LIGHTS > 0 + #pragma for id in range(0, _NUM_DIR_LIGHTS) + uniform vec3 _dir_light{id}_direction; + uniform vec3 _dir_light{id}_color; + #pragma endFor +#endif + +#if _NUM_POINT_LIGHTS > 0 + #pragma for id in range(0, _NUM_POINT_LIGHTS) + uniform vec3 _point_light{id}_position; + uniform vec3 _point_light{id}_color; + uniform float _point_light{id}_range; + #pragma endFor +#endif + +#if _NUM_SPOT_LIGHTS > 0 + #pragma for id in range(0, _NUM_SPOT_LIGHTS) + uniform vec3 _spot_light{id}_position; + uniform vec3 _spot_light{id}_direction; + uniform vec3 _spot_light{id}_color; + uniform float _spot_light{id}_range; + uniform vec2 _spot_light{id}_spot; + #pragma endFor +#endif + +LightInfo getPhongLighting( + vec3 normal, + vec3 positionW, + vec3 viewDirection, + float glossiness +) { + LightInfo result; + result.diffuse = vec3(0, 0, 0); + result.specular = vec3(0, 0, 0); + LightInfo dirLighting; + #if _NUM_DIR_LIGHTS > 0 + #pragma for id in range(0, _NUM_DIR_LIGHTS) + dirLighting = computeDirectionalLighting(_dir_light{id}_direction,_dir_light{id}_color,normal, viewDirection, glossiness); + result.diffuse += dirLighting.diffuse; + result.specular += dirLighting.specular; + #pragma endFor + #endif + + LightInfo pointLighting; + #if _NUM_POINT_LIGHTS > 0 + #pragma for id in range(0, _NUM_POINT_LIGHTS) + pointLighting = computePointLighting(_point_light{id}_position, _point_light{id}_color, _point_light{id}_range, + normal, positionW, viewDirection, glossiness); + result.diffuse += pointLighting.diffuse; + result.specular += pointLighting.specular; + #pragma endFor + #endif + + LightInfo spotLighting; + #if _NUM_SPOT_LIGHTS > 0 + #pragma for id in range(0, _NUM_SPOT_LIGHTS) + spotLighting = computeSpotLighting(_spot_light{id}_position, _spot_light{id}_direction, _spot_light{id}_color, + _spot_light{id}_range, _spot_light{id}_spot,normal, positionW, viewDirection, glossiness); + result.diffuse += spotLighting.diffuse; + result.specular += spotLighting.specular; + #pragma endFor + #endif + return result; +} + +#if _USE_SHADOW_MAP + #include + #include +#endif + +uniform vec3 _eye; +uniform vec3 ambient; + +varying vec3 normal_w; +varying vec3 pos_w; + +#if USE_DIFFUSE_TEXTURE || USE_NORMAL_TEXTURE || USE_EMISSIVE_TEXTURE + varying vec2 uv0; +#endif + +struct phongMaterial +{ + vec3 diffuse; + vec3 emissive; + vec3 specular; + float glossiness; + float opacity; +}; + +uniform vec4 diffuseColor; +#if USE_DIFFUSE_TEXTURE + uniform sampler2D diffuse_texture; +#endif + +#if USE_EMISSIVE + uniform vec3 emissiveColor; + #if USE_EMISSIVE_TEXTURE + uniform sampler2D emissive_texture; + #endif +#endif + +#if USE_SPECULAR + uniform vec3 specularColor; + uniform float glossiness; + #if USE_SPECULAR_TEXTURE + uniform sampler2D specular_texture; + #endif +#endif + +#if USE_NORMAL_TEXTURE + uniform sampler2D normal_texture; + uniform float normalScale; //this is not used yet + vec3 getNormal(vec3 pos, vec3 normal) { + vec3 q0 = vec3( dFdx( pos.x ), dFdx( pos.y ), dFdx( pos.z ) ); + vec3 q1 = vec3( dFdy( pos.x ), dFdy( pos.y ), dFdy( pos.z ) ); + vec2 st0 = dFdx( uv0.st ); + vec2 st1 = dFdy( uv0.st ); + vec3 S = normalize( q0 * st1.t - q1 * st0.t ); + vec3 T = normalize( -q0 * st1.s + q1 * st0.s ); + vec3 N = normal; + vec3 mapN = texture2D(normal_texture, uv0).rgb * 2.0 - 1.0; + mapN.xy = 1.0 * mapN.xy; + mat3 tsn = mat3( S, T, N ); + return normalize( tsn * mapN ); + } +#endif + +#if USE_ALPHA_TEST + uniform float alphaTestThreshold; +#endif + +phongMaterial getPhongMaterial() { + phongMaterial result; + + #if USE_DIFFUSE_TEXTURE + vec4 baseColor = diffuseColor * gammaToLinearSpaceRGBA(texture2D(diffuse_texture, uv0)); + result.diffuse = baseColor.rgb; + result.opacity = baseColor.a; + #else + result.diffuse = diffuseColor.rgb; + result.opacity = diffuseColor.a; + #endif + + #if USE_EMISSIVE + result.emissive = gammaToLinearSpaceRGB(emissiveColor); + #if USE_EMISSIVE_TEXTURE + result.emissive *= gammaToLinearSpaceRGB(texture2D(emissive_texture, uv0).rgb); + #endif + #endif + + #if USE_SPECULAR + result.specular = gammaToLinearSpaceRGB(specularColor); + #if USE_SPECULAR_TEXTURE + result.specular = gammaToLinearSpaceRGB(texture2D(specular_texture, uv0).rgb); + #endif + + result.glossiness = glossiness; + #endif + + return result; +} + +vec4 composePhongShading(LightInfo lighting, phongMaterial mtl, float shadow) +{ + vec4 o = vec4(0.0, 0.0, 0.0, 1.0); + + //diffuse is always calculated + o.xyz = lighting.diffuse * mtl.diffuse; + #if USE_EMISSIVE + o.xyz += mtl.emissive; + #endif + #if USE_SPECULAR + o.xyz += lighting.specular * mtl.specular; + #endif + o.xyz *= shadow; + o.w = mtl.opacity; + + return o; +} + +vec4 frag () { + LightInfo phongLighting; + vec3 viewDirection = normalize(_eye - pos_w); + + phongMaterial mtl = getPhongMaterial(); + #if USE_ALPHA_TEST + if(mtl.opacity < alphaTestThreshold) discard; + #endif + vec3 normal = normalize(normal_w); + #if USE_NORMAL_TEXTURE + normal = getNormal(pos_w, normal); + #endif + phongLighting = getPhongLighting(normal, pos_w, viewDirection, mtl.glossiness); + phongLighting.diffuse += ambient; + + #if _USE_SHADOW_MAP + vec4 finalColor = composePhongShading(phongLighting, mtl, computeShadow()); + #else + vec4 finalColor = composePhongShading(phongLighting, mtl, 1.0); + #endif + + return linearToGammaSpaceRGBA(finalColor); +} diff --git a/cocos2d/renderer/build/chunks/phong-vs.inc b/cocos2d/renderer/build/chunks/phong-vs.inc new file mode 100644 index 00000000000..47ebab374a3 --- /dev/null +++ b/cocos2d/renderer/build/chunks/phong-vs.inc @@ -0,0 +1,50 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +attribute vec3 a_position; +attribute vec3 a_normal; + +uniform mat4 _model; +uniform mat4 _viewProj; +uniform mat3 _normalMatrix; + +varying vec3 normal_w; +varying vec3 pos_w; + +#if USE_DIFFUSE_TEXTURE || USE_NORMAL_TEXTURE || USE_EMISSIVE_TEXTURE + attribute vec2 a_uv0; + uniform vec2 mainTiling; + uniform vec2 mainOffset; + varying vec2 uv0; +#endif + +#if _USE_SKINNING + #include +#endif + +#if _USE_SHADOW_MAP + #include +#endif + +vec4 vert () { + vec4 pos = vec4(a_position, 1); + vec4 normal = vec4(a_normal, 0); + + #if _USE_SKINNING + skinVertex(pos, normal); + #endif + + pos_w = (_model * pos).xyz; + pos = _viewProj * _model * pos; + + normal_w = _normalMatrix * normal.xyz; + + #if _USE_SHADOW_MAP + prepareShadowData(pos_w); + #endif + + #if USE_DIFFUSE_TEXTURE || USE_NORMAL_TEXTURE || USE_EMISSIVE_TEXTURE + uv0 = a_uv0 * mainTiling + mainOffset; + #endif + + return pos; +} diff --git a/cocos2d/renderer/build/chunks/rect-area-light.inc b/cocos2d/renderer/build/chunks/rect-area-light.inc new file mode 100644 index 00000000000..85a1d00f2c5 --- /dev/null +++ b/cocos2d/renderer/build/chunks/rect-area-light.inc @@ -0,0 +1,175 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +mat3 transpose(mat3 v) { + mat3 tmp; + tmp[0] = vec3(v[0].x, v[1].x, v[2].x); + tmp[1] = vec3(v[0].y, v[1].y, v[2].y); + tmp[2] = vec3(v[0].z, v[1].z, v[2].z); + + return tmp; +} + +void ClipQuadToHorizon(inout vec3 L[5], out int n) { + // detect clipping config + int config = 0; + if (L[0].z > 0.0) config += 1; + if (L[1].z > 0.0) config += 2; + if (L[2].z > 0.0) config += 4; + if (L[3].z > 0.0) config += 8; + config = 15; + + // clip + n = 0; + + if (config == 0) + { + // clip all + } + else if (config == 1) // V1 clip V2 V3 V4 + { + n = 3; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + L[2] = -L[3].z * L[0] + L[0].z * L[3]; + } + else if (config == 2) // V2 clip V1 V3 V4 + { + n = 3; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + } + else if (config == 3) // V1 V2 clip V3 V4 + { + n = 4; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + L[3] = -L[3].z * L[0] + L[0].z * L[3]; + } + else if (config == 4) // V3 clip V1 V2 V4 + { + n = 3; + L[0] = -L[3].z * L[2] + L[2].z * L[3]; + L[1] = -L[1].z * L[2] + L[2].z * L[1]; + } + else if (config == 5) // V1 V3 clip V2 V4) impossible + { + n = 0; + } + else if (config == 6) // V2 V3 clip V1 V4 + { + n = 4; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + L[3] = -L[3].z * L[2] + L[2].z * L[3]; + } + else if (config == 7) // V1 V2 V3 clip V4 + { + n = 5; + L[4] = -L[3].z * L[0] + L[0].z * L[3]; + L[3] = -L[3].z * L[2] + L[2].z * L[3]; + } + else if (config == 8) // V4 clip V1 V2 V3 + { + n = 3; + L[0] = -L[0].z * L[3] + L[3].z * L[0]; + L[1] = -L[2].z * L[3] + L[3].z * L[2]; + L[2] = L[3]; + } + else if (config == 9) // V1 V4 clip V2 V3 + { + n = 4; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + L[2] = -L[2].z * L[3] + L[3].z * L[2]; + } + else if (config == 10) // V2 V4 clip V1 V3) impossible + { + n = 0; + } + else if (config == 11) // V1 V2 V4 clip V3 + { + n = 5; + L[4] = L[3]; + L[3] = -L[2].z * L[3] + L[3].z * L[2]; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + } + else if (config == 12) // V3 V4 clip V1 V2 + { + n = 4; + L[1] = -L[1].z * L[2] + L[2].z * L[1]; + L[0] = -L[0].z * L[3] + L[3].z * L[0]; + } + else if (config == 13) // V1 V3 V4 clip V2 + { + n = 5; + L[4] = L[3]; + L[3] = L[2]; + L[2] = -L[1].z * L[2] + L[2].z * L[1]; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + } + else if (config == 14) // V2 V3 V4 clip V1 + { + n = 5; + L[4] = -L[0].z * L[3] + L[3].z * L[0]; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + } + else if (config == 15) // V1 V2 V3 V4 + { + n = 4; + } + + if (n == 3) + L[3] = L[0]; + if (n == 4) + L[4] = L[0]; +} + +// https://eheitzresearch.wordpress.com/415-2/ +float IntegrateEdge(vec3 v1, vec3 v2) { + float cosTheta = dot(v1, v2); + float theta = acos(cosTheta); + return cross(v1, v2).z * ((theta > 0.001) ? theta/sin(theta) : 4.0); +} + +vec3 LTC_Evaluate(vec3 N, vec3 V, vec3 P, mat3 Minv, vec3 points[4]) { + // construct orthonormal basis around N + vec3 T1, T2; + T1 = normalize(V - N*dot(V, N)); + T2 = cross(N, T1); + + // rotate area light in (T1, T2, N) basis + Minv = Minv * transpose(mat3(T1, T2, N)); + + // polygon (allocate 5 vertices for clipping) + vec3 L[5]; + L[0] = Minv * (points[0] - P); + L[1] = Minv * (points[1] - P); + L[2] = Minv * (points[2] - P); + L[3] = Minv * (points[3] - P); + + int n; + ClipQuadToHorizon(L, n); + + if (n == 0) + return vec3(0, 0, 0); + + // project onto sphere + L[0] = normalize(L[0]); + L[1] = normalize(L[1]); + L[2] = normalize(L[2]); + L[3] = normalize(L[3]); + L[4] = normalize(L[4]); + + // integrate + float sum = 0.0; + + sum += IntegrateEdge(L[0], L[1]); + sum += IntegrateEdge(L[1], L[2]); + sum += IntegrateEdge(L[2], L[3]); + if (n >= 4) + sum += IntegrateEdge(L[3], L[4]); + if (n == 5) + sum += IntegrateEdge(L[4], L[0]); + + sum = max(0.0, sum); + + vec3 Lo_i = vec3(sum, sum, sum); + + return Lo_i; +} diff --git a/cocos2d/renderer/build/chunks/shadow-depth-fs.inc b/cocos2d/renderer/build/chunks/shadow-depth-fs.inc new file mode 100644 index 00000000000..432da9a9c7f --- /dev/null +++ b/cocos2d/renderer/build/chunks/shadow-depth-fs.inc @@ -0,0 +1,14 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +uniform float _depthScale; +varying float vDepth; + +#include + +vec4 frag() { + // doing exp() here will cause float precision issue. + //float depth = clamp(exp(-min(87.0, _depthScale * vDepth)), 0.0, 1.0); + return packDepthToRGBA(vDepth); + // TODO: if support float32 * 4 color buffer? + //gl_FragColor = vec4(depth, 1.0, 1.0, 1.0); +} diff --git a/cocos2d/renderer/build/chunks/shadow-depth-vs.inc b/cocos2d/renderer/build/chunks/shadow-depth-vs.inc new file mode 100644 index 00000000000..c9309beff43 --- /dev/null +++ b/cocos2d/renderer/build/chunks/shadow-depth-vs.inc @@ -0,0 +1,27 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +attribute vec3 a_position; + +uniform mat4 _model; +uniform mat4 _lightViewProjMatrix; +uniform float _minDepth; +uniform float _maxDepth; +uniform float _bias; +varying float vDepth; + +#if _USE_SKINNING + #include +#endif + +vec4 vert() { + vec4 pos = vec4(a_position, 1); + + #if _USE_SKINNING + mat4 skinMat = skinMatrix(); + pos = skinMat * pos; + #endif + + // compute vDepth according to active camera's minDepth and maxDepth. + vDepth = ((gl_Position.z + _minDepth) / (_minDepth + _maxDepth)) + _bias; + return _lightViewProjMatrix * _model * pos; +} diff --git a/cocos2d/renderer/build/chunks/shadow-mapping.inc b/cocos2d/renderer/build/chunks/shadow-mapping.inc new file mode 100644 index 00000000000..9bcafb9eba4 --- /dev/null +++ b/cocos2d/renderer/build/chunks/shadow-mapping.inc @@ -0,0 +1,85 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#if _NUM_SHADOW_LIGHTS > 0 + #pragma for id in range(0, _NUM_SHADOW_LIGHTS) + uniform sampler2D _shadowMap_{id}; + uniform float _darkness_{id}; + uniform float _depthScale_{id}; + uniform float _frustumEdgeFalloff_{id}; + uniform float _bias_{id}; + uniform vec2 _texelSize_{id}; + varying vec4 pos_lightspace_{id}; + varying float vDepth_{id}; + #pragma endFor +#endif + +// float computeShadow(sampler2D shadowMap, vec4 pos_lightspace, float bias) { +// vec3 projCoords = pos_lightspace.xyz / pos_lightspace.w; +// projCoords = projCoords * 0.5 + 0.5; +// float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, projCoords.xy)); +// float currentDepth = projCoords.z; +// float shadow = (currentDepth - bias > closestDepth) ? 0.0 : 1.0; +// return shadow; +// } + +float computeShadow() { + float shadow = 1.0; + #if _NUM_SHADOW_LIGHTS > 0 + #pragma for id in range(0, _NUM_SHADOW_LIGHTS) + shadow *= computeShadowESM(_shadowMap_{id}, pos_lightspace_{id}, vDepth_{id}, _depthScale_{id}, _darkness_{id}, _frustumEdgeFalloff_{id}); + #pragma endFor + #endif + return shadow; +} + +float computeFallOff(float esm, vec2 coords, float frustumEdgeFalloff) { + float mask = smoothstep(1.0 - frustumEdgeFalloff, 1.0, clamp(dot(coords, coords), 0.0, 1.0)); + return mix(esm, 1.0, mask); +} + +// unused for float precision issue. +// float computeShadowESM_Unused() { +// vec2 projCoords = pos_lightspace.xy / pos_lightspace.w; +// vec2 shadowUV = projCoords * 0.5 + vec2(0.5); +// if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) { +// return 1.0; +// } +// float currentDepth = clamp(vDepth, 0.0, 1.0); +// float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, shadowUV)); +// float esm = 1.0 - clamp(exp(min(87.0, depthScale * currentDepth)) * closestDepth, 0.0, darkness); +// return computeFallOff(esm, projCoords, frustumEdgeFalloff); +// } + +float computeShadowESM(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float depthScale, float darkness, float frustumEdgeFalloff) { + vec2 projCoords = pos_lightspace.xy / pos_lightspace.w; + vec2 shadowUV = projCoords * 0.5 + vec2(0.5); + if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) { + return 1.0; + } + float currentDepth = clamp(vDepth, 0.0, 1.0); + float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, shadowUV)); + //float esm = clamp(exp(min(87.0, -depthScale * (currentDepth - closestDepth))), 1.0 - darkness, 1.0); + float esm = clamp(exp(-depthScale * (currentDepth - closestDepth)), 1.0 - darkness, 1.0); + return computeFallOff(esm, projCoords, frustumEdgeFalloff); +} + +float computeShadowPCF(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float darkness, vec2 texelSize, float frustumEdgeFalloff) { + vec2 projCoords = pos_lightspace.xy / pos_lightspace.w; + vec2 shadowUV = projCoords * 0.5 + vec2(0.5); + if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) { + return 1.0; + } + float currentDepth = clamp(vDepth, 0.0, 1.0); + float visibility = 1.0; + vec2 poissonDisk[4]; + poissonDisk[0] = vec2(-0.94201624, -0.39906216); + poissonDisk[1] = vec2(0.94558609, -0.76890725); + poissonDisk[2] = vec2(-0.094184101, -0.92938870); + poissonDisk[3] = vec2(0.34495938, 0.29387760); + if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[0] * texelSize)) < currentDepth) visibility -= 0.25; + if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[1] * texelSize)) < currentDepth) visibility -= 0.25; + if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[2] * texelSize)) < currentDepth) visibility -= 0.25; + if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[3] * texelSize)) < currentDepth) visibility -= 0.25; + + return computeFallOff(min(1.0, visibility + 1.0 - darkness), projCoords, frustumEdgeFalloff); +} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/shadow-prepare.inc b/cocos2d/renderer/build/chunks/shadow-prepare.inc new file mode 100644 index 00000000000..c1d7befe86b --- /dev/null +++ b/cocos2d/renderer/build/chunks/shadow-prepare.inc @@ -0,0 +1,20 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + #if _NUM_SHADOW_LIGHTS > 0 + #pragma for id in range(0, _NUM_SHADOW_LIGHTS) + uniform mat4 _lightViewProjMatrix_{id}; + uniform float _minDepth_{id}; + uniform float _maxDepth_{id}; + varying vec4 pos_lightspace_{id}; + varying float vDepth_{id}; + #pragma endFor + #endif + + void prepareShadowData(vec3 pos_w) { + #if _NUM_SHADOW_LIGHTS > 0 + #pragma for id in range(0, _NUM_SHADOW_LIGHTS) + pos_lightspace_{id} = _lightViewProjMatrix_{id} * vec4(pos_w, 1.0); + vDepth_{id} = (pos_lightspace_{id}.z + _minDepth_{id}) / (_minDepth_{id} + _maxDepth_{id}); + #pragma endFor + #endif + } \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/skinning.inc b/cocos2d/renderer/build/chunks/skinning.inc new file mode 100644 index 00000000000..9d9defb9a04 --- /dev/null +++ b/cocos2d/renderer/build/chunks/skinning.inc @@ -0,0 +1,61 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +attribute vec4 a_weights; +attribute vec4 a_joints; + +#if _USE_JOINTS_TEXTRUE +uniform sampler2D _jointsTexture; +uniform float _jointsTextureSize; + +mat4 getBoneMatrix(const in float i) { + float size = _jointsTextureSize; + float j = i * 4.0; + float x = mod(j, size); + float y = floor(j / size); + + float dx = 1.0 / size; + float dy = 1.0 / size; + + y = dy * (y + 0.5); + + vec4 v1 = texture2D(_jointsTexture, vec2(dx * (x + 0.5), y)); + vec4 v2 = texture2D(_jointsTexture, vec2(dx * (x + 1.5), y)); + vec4 v3 = texture2D(_jointsTexture, vec2(dx * (x + 2.5), y)); + vec4 v4 = texture2D(_jointsTexture, vec2(dx * (x + 3.5), y)); + + return mat4(v1, v2, v3, v4); +} +#else +uniform mat4 _jointMatrices[64]; + +mat4 getBoneMatrix(const in float i) { + return _jointMatrices[int(i)]; +} +#endif + +mat4 skinMatrix() { + return + getBoneMatrix(a_joints.x) * a_weights.x + + getBoneMatrix(a_joints.y) * a_weights.y + + getBoneMatrix(a_joints.z) * a_weights.z + + getBoneMatrix(a_joints.w) * a_weights.w + ; +} + +void skinVertex(inout vec4 a1) { + mat4 m = skinMatrix(); + a1 = m * a1; + } + + void skinVertex(inout vec4 a1, inout vec4 a2) { + mat4 m = skinMatrix(); + a1 = m * a1; + a2 = m * a2; + } + + void skinVertex(inout vec4 a1, inout vec4 a2, inout vec4 a3) { + mat4 m = skinMatrix(); + a1 = m * a1; + a2 = m * a2; + a3 = m * a3; + } \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/unlit-fs.inc b/cocos2d/renderer/build/chunks/unlit-fs.inc new file mode 100644 index 00000000000..56be8ea6c30 --- /dev/null +++ b/cocos2d/renderer/build/chunks/unlit-fs.inc @@ -0,0 +1,29 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#if USE_TEXTURE + uniform sampler2D texture; +#endif + +#if _USE_ATTRIBUTE_UV0 + varying vec2 v_uv0; +#endif + +#if _USE_ATTRIBUTE_COLOR + varying vec4 v_color; +#endif + +uniform vec4 color; + +vec4 frag () { + vec4 o = color; + + #if _USE_ATTRIBUTE_COLOR + o *= v_color; + #endif + + #if USE_TEXTURE && _USE_ATTRIBUTE_UV0 + o *= texture2D(texture, v_uv0); + #endif + + return o; +} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/unlit-vs.inc b/cocos2d/renderer/build/chunks/unlit-vs.inc new file mode 100644 index 00000000000..621f889810c --- /dev/null +++ b/cocos2d/renderer/build/chunks/unlit-vs.inc @@ -0,0 +1,40 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +uniform mat4 _viewProj; +uniform mat4 _model; + +attribute vec3 a_position; + +#if _USE_ATTRIBUTE_COLOR + attribute lowp vec4 a_color; + varying lowp vec4 v_color; +#endif + +#if _USE_ATTRIBUTE_UV0 + attribute vec2 a_uv0; + varying vec2 v_uv0; +#endif + +#if _USE_SKINNING + #include +#endif + +vec4 vert () { + mat4 mvp = _viewProj * _model; + + #if _USE_SKINNING + mvp = mvp * skinMatrix(); + #endif + + vec4 pos = mvp * vec4(a_position, 1); + + #if _USE_ATTRIBUTE_UV0 + v_uv0 = a_uv0; + #endif + + #if _USE_ATTRIBUTE_COLOR + v_color = a_color; + #endif + + return pos; +} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/unpack.inc b/cocos2d/renderer/build/chunks/unpack.inc new file mode 100644 index 00000000000..0db1f5c5646 --- /dev/null +++ b/cocos2d/renderer/build/chunks/unpack.inc @@ -0,0 +1,9 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +vec3 unpackNormal(vec4 nmap) { + return nmap.xyz * 2.0 - 1.0; +} + +vec3 unpackRGBE(vec4 rgbe) { + return rgbe.rgb * pow(2.0, rgbe.a * 255.0 - 128.0); +} \ No newline at end of file diff --git a/cocos2d/renderer/mappings/index.js b/cocos2d/renderer/build/mappings/index.js similarity index 87% rename from cocos2d/renderer/mappings/index.js rename to cocos2d/renderer/build/mappings/index.js index 64d5f60c5a2..4a34041e0fa 100644 --- a/cocos2d/renderer/mappings/index.js +++ b/cocos2d/renderer/build/mappings/index.js @@ -156,52 +156,58 @@ const enums = { // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. var rendererEnums = { - // projection - PROJ_PERSPECTIVE: 0, - PROJ_ORTHO: 1, - - // lights - LIGHT_DIRECTIONAL: 0, - LIGHT_POINT: 1, - LIGHT_SPOT: 2, - - // shadows - SHADOW_NONE: 0, - SHADOW_HARD: 1, - SHADOW_SOFT: 2, - - // parameter type - PARAM_INT: 0, - PARAM_INT2: 1, - PARAM_INT3: 2, - PARAM_INT4: 3, - PARAM_FLOAT: 4, - PARAM_FLOAT2: 5, - PARAM_FLOAT3: 6, - PARAM_FLOAT4: 7, - PARAM_COLOR3: 8, - PARAM_COLOR4: 9, - PARAM_MAT2: 10, - PARAM_MAT3: 11, - PARAM_MAT4: 12, - PARAM_TEXTURE_2D: 13, - PARAM_TEXTURE_CUBE: 14, - - // clear flags - CLEAR_COLOR: 1, - CLEAR_DEPTH: 2, - CLEAR_STENCIL: 4, - CLEAR_SKYBOX: 8, - - // - BUFFER_VIEW_INT8: 0, - BUFFER_VIEW_UINT8: 1, - BUFFER_VIEW_INT16: 2, - BUFFER_VIEW_UINT16: 3, - BUFFER_VIEW_INT32: 4, - BUFFER_VIEW_UINT32: 5, - BUFFER_VIEW_FLOAT32: 6, - }; + // projection + PROJ_PERSPECTIVE: 0, + PROJ_ORTHO: 1, + + // lights + LIGHT_DIRECTIONAL: 0, + LIGHT_POINT: 1, + LIGHT_SPOT: 2, + + // shadows + SHADOW_NONE: 0, + SHADOW_HARD: 1, + SHADOW_SOFT: 2, + + // parameter type + PARAM_INT: 0, + PARAM_INT2: 1, + PARAM_INT3: 2, + PARAM_INT4: 3, + PARAM_FLOAT: 4, + PARAM_FLOAT2: 5, + PARAM_FLOAT3: 6, + PARAM_FLOAT4: 7, + PARAM_COLOR3: 8, + PARAM_COLOR4: 9, + PARAM_MAT2: 10, + PARAM_MAT3: 11, + PARAM_MAT4: 12, + PARAM_TEXTURE_2D: 13, + PARAM_TEXTURE_CUBE: 14, + + // clear flags + CLEAR_COLOR: 1, + CLEAR_DEPTH: 2, + CLEAR_STENCIL: 4, + CLEAR_SKYBOX: 8, + + // + BUFFER_VIEW_INT8: 0, + BUFFER_VIEW_UINT8: 1, + BUFFER_VIEW_INT16: 2, + BUFFER_VIEW_UINT16: 3, + BUFFER_VIEW_INT32: 4, + BUFFER_VIEW_UINT32: 5, + BUFFER_VIEW_FLOAT32: 6, +}; + +let RenderQueue = { + OPAQUE: 0, + TRANSPARENT: 1, + OVERLAY: 2 +}; // this file is used for offline effect building. @@ -270,6 +276,7 @@ const passParams = { let mappings = { typeParams, passParams, + RenderQueue }; module.exports = mappings; diff --git a/cocos2d/renderer/mappings/offline-mappings.js b/cocos2d/renderer/build/mappings/offline-mappings.js similarity index 93% rename from cocos2d/renderer/mappings/offline-mappings.js rename to cocos2d/renderer/build/mappings/offline-mappings.js index b3bb43bd626..858d421c00d 100644 --- a/cocos2d/renderer/mappings/offline-mappings.js +++ b/cocos2d/renderer/build/mappings/offline-mappings.js @@ -1,7 +1,8 @@ // this file is used for offline effect building. -import { enums } from './gfx/enums'; -import rendererEnums from './enums'; +import { enums } from '../../gfx/enums'; +import rendererEnums from '../../enums'; +import { RenderQueue, PassStage } from '../../core/constants'; const typeParams = { INT: rendererEnums.PARAM_INT, @@ -68,6 +69,7 @@ const passParams = { let mappings = { typeParams, passParams, + RenderQueue }; export default mappings; \ No newline at end of file diff --git a/cocos2d/renderer/build/shdc-lib.js b/cocos2d/renderer/build/shdc-lib.js index 40cc47618c6..1cf09284bca 100644 --- a/cocos2d/renderer/build/shdc-lib.js +++ b/cocos2d/renderer/build/shdc-lib.js @@ -1,7 +1,10 @@ 'use strict'; const tokenizer = require('glsl-tokenizer/string'); -const mappings = require('../mappings'); +const parser = require('glsl-parser/direct'); +const mappings = require('./mappings'); +const { sha3_224 } = require('js-sha3'); +const HJSON = require('hjson'); let includeRE = /#include +<([\w-.]+)>/gm; let defineRE = /#define\s+(\w+)\(([\w,\s]+)\)\s+(.*##.*)\n/g; @@ -14,17 +17,7 @@ let rangePragma = /range\(([\d.,\s]+)\)\s(\w+)/; let defaultPragma = /default\(([\d.,]+)\)/; let namePragma = /name\(([^)]+)\)/; let precision = /(low|medium|high)p/; - -// (HACKY) extract all builtin uniforms to the ignore list -let uniformIgnoreList = {viewProj: true, model: true}; -// let uniformIgnoreList = (function() { -// let path = 'cocos/renderer/renderers/forward-renderer.js'; -// let renderer = fs.readFileSync(path, { encoding: 'utf8' }); -// let re = /set(Uniform|Texture)\([`'"](\w+)[`'"]/g, cap = re.exec(renderer); -// let result = []; -// while (cap) { result.push(cap[2]); cap = re.exec(renderer); } -// return result; -// })(); +let builtins = /^_\w+$/; function convertType(t) { let tp = mappings.typeParams[t.toUpperCase()]; return tp === undefined ? t : tp; } @@ -53,24 +46,59 @@ function glslStripComment(code) { return result; } +/** + * say we are parsing this program: + * ``` + * // .. + * 12 #if USE_LIGHTING + * // .. + * 34 #if NUM_LIGHTS > 0 + * // .. + * 56 #endif + * // .. + * 78 #endif + * // .. + * ``` + * + * the output would be: + * ``` + * // the complete define list + * defines = [ { name: 'USE_LIGHTING', type: 'boolean' }, { name: 'NUM_LIGHTS', type: 'number' } ] + * // bookkeeping: define dependency throughout the code + * cache = { + * lines: [12, 34, 56, 78], + * 12: [ 'USE_LIGHTING' ], + * 34: [ 'USE_LIGHTING', 'NUM_LIGHTS' ], + * 56: [ 'USE_LIGHTING' ], + * 78: [] + * } + * ```` + */ function extractDefines(tokens, defines, cache) { - let curDefs = [], save = (line) => { + let loopBegIdx = 0, curDefs = [], save = (line) => { cache[line] = curDefs.reduce((acc, val) => acc.concat(val), []); cache.lines.push(line); }; - for (let i = 0; i < tokens.length; ++i) { + for (let i = 0; i < tokens.length; ) { let t = tokens[i], str = t.data, id, df; - if (t.type !== 'preprocessor') continue; + if (t.type !== 'preprocessor' || str.startsWith('#extension')) { i++; continue; } + tokens.splice(i, 1); // strip out other preprocessor tokens for parser to work str = str.split(whitespaces); - if (str[0] === '#endif') { - curDefs.pop(); save(t.line); continue; - } else if (str[0] === '#else') { + if (str[0] === '#endif') { // pop one level up + curDefs.pop(); save(t.line); continue; + } else if (str[0] === '#else') { // just clear this level curDefs[curDefs.length - 1].length = 0; save(t.line); continue; - } else if (str[0] === '#pragma') { - if (str[1] === 'for') { curDefs.push(0); save(t.line); } - else if (str[1] === 'endFor') { curDefs.pop(); save(t.line); } + } else if (str[0] === '#pragma') { // pragma treatments + // pragma loops are ignored and left to runtime + // here we jsut strip out all of them + if (str[1] === 'for') loopBegIdx = i; + else if (str[1] === 'endFor') { + tokens.splice(loopBegIdx, i - loopBegIdx); + i = loopBegIdx; + } + // record the tags for the next extraction stage else if (str[1][0] === '#') cache[t.line] = str.splice(1); - else { + else { // custom numeric define ranges let mc = rangePragma.exec(t.data); if (!mc) continue; let def = defines.find(d => d.name === mc[2]); @@ -80,40 +108,23 @@ function extractDefines(tokens, defines, cache) { } continue; } else if (!ifprocessor.test(str[0])) continue; - if (str[0] === '#elif') { curDefs.pop(); save(t.line); } + if (str[0] === '#elif') { curDefs.pop(); save(t.line); } // pop one level up let defs = []; str.splice(1).some(s => { id = s.match(ident); if (id) { // is identifier - defs.push(id[0]); + let d = curDefs.reduce((acc, val) => acc.concat(val), defs.slice()); df = defines.find(d => d.name === id[0]); - if (df) return; // first encounter - defines.push(df = { name: id[0], type: 'boolean' }); + if (df) { if (d.length < df.defines.length) df.defines = d; } + else defines.push(df = { name: id[0], type: 'boolean', defines: d }); + defs.push(id[0]); } else if (comparators.test(s)) df.type = 'number'; - else if (s === '||') return true; + else if (s === '||') return defs = []; // ignore logical OR defines all together }); curDefs.push(defs); save(t.line); } - return defines; } -/* here the `define dependency` for some param is interpreted as - * the existance of some define ids directly desides the existance of that param. - * so basically therer is no logical expression support - * (all will be treated as '&&' operator) - * for wrapping unifom, attribute and extension declarations. - * try to write them in straightforward ways like: - * #ifdef USE_COLOR - * attribute vec4 a_color; - * #endif - * or nested when needed: - * #if USE_BILLBOARD && BILLBOARD_STRETCHED - * uniform vec3 stretch_color; - * #ifdef USE_NORMAL_TEXTURE - * uniform sampler2D tex_normal; - * #endif - * #endif // no else branch - */ function extractParams(tokens, cache, uniforms, attributes, extensions) { let getDefs = line => { let idx = cache.lines.findIndex(i => i > line); @@ -126,10 +137,9 @@ function extractParams(tokens, cache, uniforms, attributes, extensions) { else if (tp === 'preprocessor' && str.startsWith('#extension')) dest = extensions; else continue; let defines = getDefs(t.line), param = {}; - if (defines.findIndex(i => !i) >= 0) continue; // inside pragmas - if (dest === uniforms && uniformIgnoreList[tokens[i+4].data]) continue; + if (dest === uniforms && builtins.test(tokens[i+4].data)) continue; if (dest === extensions) { - if (defines.length > 1) console.warn('extensions must be under controll of no more than 1 define'); + if (defines.length !== 1) console.warn('extensions must be under controll of exactly 1 define'); param.name = extensionRE.exec(str.split(whitespaces)[1])[1]; param.define = defines[0]; dest.push(param); @@ -139,7 +149,7 @@ function extractParams(tokens, cache, uniforms, attributes, extensions) { param.name = tokens[i+offset+2].data; param.type = convertType(tokens[i+offset].data); let tags = cache[t.line - 1]; - if (tags && tags[0][0] === '#') { // tags + if (tags && tags[0] && tags[0][0] === '#') { // tags let mc = defaultPragma.exec(tags.join('')); if (mc && mc[1].length > 0) { mc = JSON.parse(`[${mc[1]}]`); @@ -250,23 +260,29 @@ let expandStructMacro = (function() { }; })(); -let assemble = (function() { +let getChunkByName = (function() { let entryRE = /([\w-]+)(?::(\w+))?/; - let integrity = /void\s+main\s*\(\s*\)/g; + return function(name, cache) { + let entryCap = entryRE.exec(name), entry = entryCap[2] || 'main', content = cache[entryCap[1]]; + if (!content) { console.error(`shader ${entryCap[1]} not found!`); return [ '', entry ]; } + return [ content, entry ]; + }; +})(); + +let wrapEntry = (function() { let wrapperFactory = (vert, fn) => `\nvoid main() { ${vert ? 'gl_Position' : 'gl_FragColor'} = ${fn}(); }\n`; - return function(name, cache, vert) { - let entryCap = entryRE.exec(name), content = cache[entryCap[1]]; - if (!content) { console.error(`${entryCap[1]} not found, please check again.`); return ''; } - if (!entryCap[2]) { - if (!integrity.test(content)) console.error(`no main function found in ${name}!`); - return cache[name]; - } - return content + wrapperFactory(vert, entryCap[2]); + return function(content, name, entry, ast, isVert) { + if (!ast.scope[entry] || ast.scope[entry].parent.type !== 'function') + console.error(`entry function ${name} not found`); + return entry === 'main' ? content : content + wrapperFactory(isVert, entry); }; })(); -let build = function(vert, frag, cache) { - let defines = [], defCache = { lines: [] }, tokens; +let buildShader = function(vertName, fragName, cache) { + let [ vert, vEntry ] = getChunkByName(vertName, cache, true); + let [ frag, fEntry ] = getChunkByName(fragName, cache); + + let defines = [], defCache = { lines: [] }, tokens, ast; let uniforms = [], attributes = [], extensions = []; vert = glslStripComment(vert); @@ -275,6 +291,10 @@ let build = function(vert, frag, cache) { tokens = tokenizer(vert); extractDefines(tokens, defines, defCache); extractParams(tokens, defCache, uniforms, attributes, extensions); + try { + ast = parser(tokens); + vert = wrapEntry(vert, vertName, vEntry, ast, true); + } catch (e) { console.error(`parse ${vertName} failed: ${e}`); } defCache = { lines: [] }; frag = glslStripComment(frag); @@ -283,14 +303,127 @@ let build = function(vert, frag, cache) { tokens = tokenizer(frag); extractDefines(tokens, defines, defCache); extractParams(tokens, defCache, uniforms, attributes, extensions); + try { + ast = parser(tokens); + frag = wrapEntry(frag, fragName, fEntry, ast); + } catch (e) { console.error(`parse ${fragName} failed: ${e}`); } return { vert, frag, defines, uniforms, attributes, extensions }; }; -let assembleAndBuild = function(vertName, fragName, cache) { - let vert = assemble(vertName, cache, true); - let frag = assemble(fragName, cache); - return build(vert, frag, cache); +// ================== +// effects +// ================== + +let queueRE = /(\w+)\s*(?:([+-])\s*(\d+))?/; +let parseQueue = function (queue) { + let res = { queue: 0, priority: 0 }; + let m = queueRE.exec(queue); + if (m === null) return res; + res.queue = mappings.RenderQueue[m[1].toUpperCase()]; + if (m.length === 4) { + if (m[2] === '+') res.priority = parseInt(m[3]); + if (m[2] === '-') res.priority = -parseInt(m[3]); + } + return res; +}; + +function mapPassParam(p) { + let num; + switch (typeof p) { + case 'string': + num = parseInt(p); + return isNaN(num) ? mappings.passParams[p.toUpperCase()] : num; + case 'object': + return ((p[0] * 255) << 24 | (p[1] * 255) << 16 | (p[2] * 255) << 8 | (p[3] || 0) * 255) >>> 0; + } + return p; +} + +function buildEffectJSON(json) { + // map param's type offline. + for (let j = 0; j < json.techniques.length; ++j) { + let jsonTech = json.techniques[j]; + if (!jsonTech.stages) jsonTech.stages = ['opaque']; // Note: for creator + let { queue, priority } = parseQueue(jsonTech.queue ? jsonTech.queue : 'opaque'); + jsonTech.queue = queue; jsonTech.priority = priority; + for (let k = 0; k < jsonTech.passes.length; ++k) { + let pass = jsonTech.passes[k]; + if (pass.stage == null) { + pass.stage = 'default'; + } + for (let key in pass) { + if (key === "vert" || key === 'frag') continue; + pass[key] = mapPassParam(pass[key]); + } + } + } + for (let prop in json.properties) { + let info = json.properties[prop]; + info.type = mappings.typeParams[info.type.toUpperCase()]; + } + return json; +} + +let parseEffect = (function() { + let effectRE = /%{([^%]+)%}/; + let blockRE = /%%\s*([\w-]+)\s*{([^]+)}/; + let parenRE = /[{}]/g; + let trimToSize = content => { + let level = 1, end = content.length; + content.replace(parenRE, (p, i) => { + if (p === '{') level++; + else if (level === 1) { end = i; level = 1e9; } + else level--; + }); + return content.substring(0, end); + }; + return function (content) { + let effectCap = effectRE.exec(content); + let effect = HJSON.parse(`{${effectCap[1]}}`), templates = {}; + content = content.substring(effectCap.index + effectCap[0].length); + let blockCap = blockRE.exec(content); + while (blockCap) { + let str = templates[blockCap[1]] = trimToSize(blockCap[2]); + content = content.substring(blockCap.index + str.length); + blockCap = blockRE.exec(content); + } + return { effect, templates }; + }; +})(); + +let chunksCache = {}; +let addChunksCache = function(chunksDir) { + const path_ = require('path'); + const fsJetpack = require('fs-jetpack'); + const fs = require('fs'); + let files = fsJetpack.find(chunksDir, { matching: ['**/*.inc'] }); + for (let i = 0; i < files.length; ++i) { + let name = path_.basename(files[i], '.inc'); + let content = fs.readFileSync(files[i], { encoding: 'utf8' }); + chunksCache[name] = glslStripComment(content); + } + return chunksCache; +}; + +let buildEffect = function (name, content) { + let { effect, templates } = parseEffect(content); + effect = buildEffectJSON(effect); effect.name = name; + Object.assign(templates, chunksCache); + let shaders = effect.shaders = []; + for (let j = 0; j < effect.techniques.length; ++j) { + let jsonTech = effect.techniques[j]; + for (let k = 0; k < jsonTech.passes.length; ++k) { + let pass = jsonTech.passes[k]; + let vert = pass.vert, frag = pass.frag; + let shader = buildShader(vert, frag, templates); + let name = sha3_224(shader.vert + shader.frag); + shader.name = pass.program = name; + delete pass.vert; delete pass.frag; + shaders.push(shader); + } + } + return effect; }; // ================== @@ -298,8 +431,6 @@ let assembleAndBuild = function(vertName, fragName, cache) { // ================== module.exports = { - glslStripComment, - assemble, - build, - assembleAndBuild + addChunksCache, + buildEffect }; diff --git a/cocos2d/renderer/chunks/index.js b/cocos2d/renderer/chunks/index.js deleted file mode 100644 index 0b0ce35a0dd..00000000000 --- a/cocos2d/renderer/chunks/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - "skinning": "\n\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n\n#ifdef useJointsTexture\nuniform sampler2D jointsTexture;\nuniform float jointsTextureSize;\n\nmat4 getBoneMatrix(const in float i) {\n float size = jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n\n y = dy * (y + 0.5);\n\n vec4 v1 = texture2D(jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(jointsTexture, vec2(dx * (x + 3.5), y));\n\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 jointMatrices[64];\n\nmat4 getBoneMatrix(const in float i) {\n return jointMatrices[int(i)];\n}\n#endif\n\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}" -} \ No newline at end of file diff --git a/cocos2d/renderer/chunks/skinning.inc b/cocos2d/renderer/chunks/skinning.inc deleted file mode 100644 index ba666f460b6..00000000000 --- a/cocos2d/renderer/chunks/skinning.inc +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -attribute vec4 a_weights; -attribute vec4 a_joints; - -#ifdef useJointsTexture -uniform sampler2D jointsTexture; -uniform float jointsTextureSize; - -mat4 getBoneMatrix(const in float i) { - float size = jointsTextureSize; - float j = i * 4.0; - float x = mod(j, size); - float y = floor(j / size); - - float dx = 1.0 / size; - float dy = 1.0 / size; - - y = dy * (y + 0.5); - - vec4 v1 = texture2D(jointsTexture, vec2(dx * (x + 0.5), y)); - vec4 v2 = texture2D(jointsTexture, vec2(dx * (x + 1.5), y)); - vec4 v3 = texture2D(jointsTexture, vec2(dx * (x + 2.5), y)); - vec4 v4 = texture2D(jointsTexture, vec2(dx * (x + 3.5), y)); - - return mat4(v1, v2, v3, v4); -} -#else -uniform mat4 jointMatrices[64]; - -mat4 getBoneMatrix(const in float i) { - return jointMatrices[int(i)]; -} -#endif - -mat4 skinMatrix() { - return - getBoneMatrix(a_joints.x) * a_weights.x + - getBoneMatrix(a_joints.y) * a_weights.y + - getBoneMatrix(a_joints.z) * a_weights.z + - getBoneMatrix(a_joints.w) * a_weights.w - ; -} \ No newline at end of file diff --git a/cocos2d/renderer/config.js b/cocos2d/renderer/config.js new file mode 100644 index 00000000000..bc69c46ab08 --- /dev/null +++ b/cocos2d/renderer/config.js @@ -0,0 +1,37 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +let _stageOffset = 0; +let _name2stageID = {}; + +export default { + addStage: function (name) { + // already added + if (_name2stageID[name] !== undefined) { + return; + } + + let stageID = 1 << _stageOffset; + _name2stageID[name] = stageID; + + _stageOffset += 1; + }, + + stageID: function (name) { + let id = _name2stageID[name]; + if (id === undefined) { + return -1; + } + return id; + }, + + stageIDs: function (nameList) { + let key = 0; + for (let i = 0; i < nameList.length; ++i) { + let id = _name2stageID[nameList[i]]; + if (id !== undefined) { + key |= id; + } + } + return key; + } +}; \ No newline at end of file diff --git a/cocos2d/renderer/core/base-renderer.js b/cocos2d/renderer/core/base-renderer.js new file mode 100644 index 00000000000..4408ffd87d4 --- /dev/null +++ b/cocos2d/renderer/core/base-renderer.js @@ -0,0 +1,645 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import { RecyclePool } from '../memop'; +import enums from '../enums'; +import { vec2, vec3, vec4, mat2, mat3, mat4, color3, color4 } from '../../core/vmath'; +import ProgramLib from './program-lib'; +import View from './view'; +import Texture2D from '../gfx/texture-2d'; + +let _m3_tmp = mat3.create(); +let _m4_tmp = mat4.create(); + +let _stageInfos = new RecyclePool(() => { + return { + stage: null, + items: null, + }; +}, 8); + +let _float2_pool = new RecyclePool(() => { + return new Float32Array(2); +}, 8); + +let _float3_pool = new RecyclePool(() => { + return new Float32Array(3); +}, 8); + +let _float4_pool = new RecyclePool(() => { + return new Float32Array(4); +}, 8); + +let _float9_pool = new RecyclePool(() => { + return new Float32Array(9); +}, 8); + +let _float16_pool = new RecyclePool(() => { + return new Float32Array(16); +}, 8); + +let _float64_pool = new RecyclePool(() => { + return new Float32Array(64); +}, 8); + +let _int2_pool = new RecyclePool(() => { + return new Int32Array(2); +}, 8); + +let _int3_pool = new RecyclePool(() => { + return new Int32Array(3); +}, 8); + +let _int4_pool = new RecyclePool(() => { + return new Int32Array(4); +}, 8); + +let _int64_pool = new RecyclePool(() => { + return new Int32Array(64); +}, 8); + +let _type2uniformValue = { + [enums.PARAM_INT]: function (value) { + return value; + }, + + [enums.PARAM_INT2]: function (value) { + return vec2.array(_int2_pool.add(), value); + }, + + [enums.PARAM_INT3]: function (value) { + return vec3.array(_int3_pool.add(), value); + }, + + [enums.PARAM_INT4]: function (value) { + return vec4.array(_int4_pool.add(), value); + }, + + [enums.PARAM_FLOAT]: function (value) { + return value; + }, + + [enums.PARAM_FLOAT2]: function (value) { + return vec2.array(_float2_pool.add(), value); + }, + + [enums.PARAM_FLOAT3]: function (value) { + return vec3.array(_float3_pool.add(), value); + }, + + [enums.PARAM_FLOAT4]: function (value) { + return vec4.array(_float4_pool.add(), value); + }, + + [enums.PARAM_COLOR3]: function (value) { + return color3.array(_float3_pool.add(), value); + }, + + [enums.PARAM_COLOR4]: function (value) { + return color4.array(_float4_pool.add(), value); + }, + + [enums.PARAM_MAT2]: function (value) { + return mat2.array(_float4_pool.add(), value); + }, + + [enums.PARAM_MAT3]: function (value) { + return mat3.array(_float9_pool.add(), value); + }, + + [enums.PARAM_MAT4]: function (value) { + return mat4.array(_float16_pool.add(), value); + }, + + // [enums.PARAM_TEXTURE_2D]: function (value) { + // }, + + // [enums.PARAM_TEXTURE_CUBE]: function (value) { + // }, +}; + +let _type2uniformArrayValue = { + [enums.PARAM_INT]: { + func (values) { + let result = _int64_pool.add(); + for (let i = 0; i < values.length; ++i) { + result[i] = values[i]; + } + return result; + }, + size: 1, + }, + + [enums.PARAM_INT2]: { + func (values) { + let result = _int64_pool.add(); + for (let i = 0; i < values.length; ++i) { + result[2 * i] = values[i].x; + result[2 * i + 1] = values[i].y; + } + return result; + }, + size: 2, + }, + + [enums.PARAM_INT3]: { + func: undefined, + size: 3, + }, + + [enums.PARAM_INT4]: { + func (values) { + let result = _int64_pool.add(); + for (let i = 0; i < values.length; ++i) { + let v = values[i]; + result[4 * i] = v.x; + result[4 * i + 1] = v.y; + result[4 * i + 2] = v.z; + result[4 * i + 3] = v.w; + } + return result; + }, + size: 4, + }, + + [enums.PARAM_FLOAT]: { + func (values) { + let result = _float64_pool.add(); + for (let i = 0; i < values.length; ++i) { + result[i] = values[i]; + } + return result; + }, + size: 1 + }, + + [enums.PARAM_FLOAT2]: { + func (values) { + let result = _float64_pool.add(); + for (let i = 0; i < values.length; ++i) { + result[2 * i] = values[i].x; + result[2 * i + 1] = values[i].y; + } + return result; + }, + size: 2, + }, + + [enums.PARAM_FLOAT3]: { + func: undefined, + size: 3, + }, + + [enums.PARAM_FLOAT4]: { + func (values) { + let result = _float64_pool.add(); + for (let i = 0; i < values.length; ++i) { + let v = values[i]; + result[4 * i] = v.x; + result[4 * i + 1] = v.y; + result[4 * i + 2] = v.z; + result[4 * i + 3] = v.w; + } + return result; + }, + size: 4, + }, + + [enums.PARAM_COLOR3]: { + func: undefined, + size: 3, + }, + + [enums.PARAM_COLOR4]: { + func (values) { + let result = _float64_pool.add(); + for (let i = 0; i < values.length; ++i) { + let v = values[i]; + result[4 * i] = v.r; + result[4 * i + 1] = v.g; + result[4 * i + 2] = v.b; + result[4 * i + 3] = v.a; + } + return result; + }, + size: 4, + }, + + [enums.PARAM_MAT2]: { + func (values) { + let result = _float64_pool.add(); + for (let i = 0; i < values.length; ++i) { + let v = values[i]; + result[4 * i] = v.m00; + result[4 * i + 1] = v.m01; + result[4 * i + 2] = v.m02; + result[4 * i + 3] = v.m03; + } + return result; + }, + size: 4 + }, + + [enums.PARAM_MAT3]: { + func: undefined, + size: 9 + }, + + + [enums.PARAM_MAT4]: { + func (values) { + let result = _float64_pool.add(); + for (let i = 0; i < values.length; ++i) { + let v = values[i]; + result[16 * i] = v.m00; + result[16 * i + 1] = v.m01; + result[16 * i + 2] = v.m02; + result[16 * i + 3] = v.m03; + result[16 * i + 4] = v.m04; + result[16 * i + 5] = v.m05; + result[16 * i + 6] = v.m06; + result[16 * i + 7] = v.m07; + result[16 * i + 8] = v.m08; + result[16 * i + 9] = v.m09; + result[16 * i + 10] = v.m10; + result[16 * i + 11] = v.m11; + result[16 * i + 12] = v.m12; + result[16 * i + 13] = v.m13; + result[16 * i + 14] = v.m14; + result[16 * i + 15] = v.m15; + } + return result; + }, + size: 16 + }, + + // [enums.PARAM_TEXTURE_2D]: function (value) { + // }, + + // [enums.PARAM_TEXTURE_CUBE]: function (value) { + // }, +}; + +export default class Base { + /** + * @param {gfx.Device} device + * @param {Object} opts + * @param {gfx.Texture2D} opts.defaultTexture + * @param {gfx.TextureCube} opts.defaultTextureCube + * @param {Array} opts.programTemplates + * @param {Object} opts.programChunks + */ + constructor(device, opts) { + this._device = device; + this._programLib = new ProgramLib(device, opts.programTemplates, opts.programChunks); + this._opts = opts; + this._type2defaultValue = { + [enums.PARAM_INT]: 0, + [enums.PARAM_INT2]: vec2.create(0, 0), + [enums.PARAM_INT3]: vec3.create(0, 0, 0), + [enums.PARAM_INT4]: vec4.create(0, 0, 0, 0), + [enums.PARAM_FLOAT]: 0.0, + [enums.PARAM_FLOAT2]: vec2.create(0, 0), + [enums.PARAM_FLOAT3]: vec3.create(0, 0, 0), + [enums.PARAM_FLOAT4]: vec4.create(0, 0, 0, 0), + [enums.PARAM_COLOR3]: color3.create(0, 0, 0), + [enums.PARAM_COLOR4]: color4.create(0, 0, 0, 1), + [enums.PARAM_MAT2]: mat2.create(), + [enums.PARAM_MAT3]: mat3.create(), + [enums.PARAM_MAT4]: mat4.create(), + [enums.PARAM_TEXTURE_2D]: opts.defaultTexture, + [enums.PARAM_TEXTURE_CUBE]: opts.defaultTextureCube, + }; + this._stage2fn = {}; + this._usedTextureUnits = 0; + + this._viewPools = new RecyclePool(() => { + return new View(); + }, 8); + + this._drawItemsPools = new RecyclePool(() => { + return { + model: null, + node: null, + ia: null, + effect: null, + defines: null, + uniforms: null + }; + }, 100); + + this._stageItemsPools = new RecyclePool(() => { + return new RecyclePool(() => { + return { + model: null, + node: null, + ia: null, + effect: null, + defines: null, + technique: null, + sortKey: -1, + uniforms: null + }; + }, 100); + }, 16); + } + + _resetTextuerUnit() { + this._usedTextureUnits = 0; + } + + _allocTextureUnit() { + const device = this._device; + + let unit = this._usedTextureUnits; + if (unit >= device._caps.maxTextureUnits) { + console.warn(`Trying to use ${unit} texture units while this GPU supports only ${device._caps.maxTextureUnits}`); + } + + this._usedTextureUnits += 1; + return unit; + } + + _registerStage(name, fn) { + this._stage2fn[name] = fn; + } + + _reset() { + this._viewPools.reset(); + this._stageItemsPools.reset(); + } + + _requestView() { + return this._viewPools.add(); + } + + _render(view, scene) { + const device = this._device; + + // setup framebuffer + device.setFrameBuffer(view._framebuffer); + + // setup viewport + device.setViewport( + view._rect.x, + view._rect.y, + view._rect.w, + view._rect.h + ); + + // setup clear + let clearOpts = {}; + if (view._clearFlags & enums.CLEAR_COLOR) { + clearOpts.color = [ + view._color.r, + view._color.g, + view._color.b, + view._color.a + ]; + } + if (view._clearFlags & enums.CLEAR_DEPTH) { + clearOpts.depth = view._depth; + } + if (view._clearFlags & enums.CLEAR_STENCIL) { + clearOpts.stencil = view._stencil; + } + device.clear(clearOpts); + + // get all draw items + this._drawItemsPools.reset(); + + for (let i = 0; i < scene._models.length; ++i) { + let model = scene._models.data[i]; + + // filter model by view + if ((model._cullingMask & view._cullingMask) === 0) { + continue; + } + + let drawItem = this._drawItemsPools.add(); + model.extractDrawItem(drawItem); + } + + // TODO: update frustum + // TODO: visbility test + // frustum.update(view._viewProj); + + // dispatch draw items to different stage + _stageInfos.reset(); + + for (let i = 0; i < view._stages.length; ++i) { + let stage = view._stages[i]; + let stageItems = this._stageItemsPools.add(); + stageItems.reset(); + + for (let j = 0; j < this._drawItemsPools.length; ++j) { + let drawItem = this._drawItemsPools.data[j]; + let tech = drawItem.effect.getTechnique(stage); + + if (tech) { + let stageItem = stageItems.add(); + stageItem.model = drawItem.model; + stageItem.node = drawItem.node; + stageItem.ia = drawItem.ia; + stageItem.effect = drawItem.effect; + stageItem.defines = drawItem.defines; + stageItem.technique = tech; + stageItem.sortKey = -1; + stageItem.uniforms = drawItem.uniforms; + } + } + + let stageInfo = _stageInfos.add(); + stageInfo.stage = stage; + stageInfo.items = stageItems; + } + + // render stages + for (let i = 0; i < _stageInfos.length; ++i) { + let info = _stageInfos.data[i]; + let fn = this._stage2fn[info.stage]; + + fn(view, info.items); + } + } + + _setProperty (prop) { + const device = this._device; + let param = prop.value; + + if (param === undefined) { + param = prop.val; + } + + if (param === undefined) { + param = this._type2defaultValue[prop.type]; + } + + if (param === undefined) { + console.warn(`Failed to set technique property ${prop.name}, value not found.`); + return; + } + + if ( + prop.type === enums.PARAM_TEXTURE_2D || + prop.type === enums.PARAM_TEXTURE_CUBE + ) { + if (prop.size !== undefined) { + if (prop.size !== param.length) { + console.error(`The length of texture array (${param.length}) is not corrent(expect ${prop.size}).`); + return; + } + let slots = _int64_pool.add(); + for (let index = 0; index < param.length; ++index) { + slots[index] = this._allocTextureUnit(); + } + device.setTextureArray(prop.name, param, slots); + } else { + device.setTexture(prop.name, param, this._allocTextureUnit()); + } + } else { + let convertedValue; + if (param instanceof Float32Array || param instanceof Int32Array) { + convertedValue = param; + } + else if (prop.size !== undefined) { + let convertArray = _type2uniformArrayValue[prop.type]; + if (convertArray.func === undefined) { + console.error('Uniform array of color3/int3/float3/mat3 can not be supportted!'); + return; + } + if (prop.size * convertArray.size > 64) { + console.error('Uniform array is too long!'); + return; + } + convertedValue = convertArray.func(param); + } else { + let convertFn = _type2uniformValue[prop.type]; + convertedValue = convertFn(param); + } + device.setUniform(prop.name, convertedValue); + } + } + + _draw(item) { + const device = this._device; + const programLib = this._programLib; + const { node, ia, uniforms, technique, defines } = item; + + // reset the pool + // NOTE: we can use drawCounter optimize this + // TODO: should be configurable + _float2_pool.reset(); + _float3_pool.reset(); + _float4_pool.reset(); + _float9_pool.reset(); + _float16_pool.reset(); + _float64_pool.reset(); + _int2_pool.reset(); + _int3_pool.reset(); + _int4_pool.reset(); + _int64_pool.reset(); + + // set common uniforms + // TODO: try commit this depends on effect + // { + node.getWorldMatrix(_m4_tmp); + device.setUniform('_model', mat4.array(_float16_pool.add(), _m4_tmp)); + + let inverse = mat3.invert(_m3_tmp, mat3.fromMat4(_m3_tmp, _m4_tmp)); + if (inverse) { + mat3.transpose(_m3_tmp, inverse); + device.setUniform('_normalMatrix', mat3.array(_float9_pool.add(), _m3_tmp)); + } + // } + + for (let name in uniforms) { + let uniform = uniforms[name]; + this._setProperty(uniform); + } + + // for each pass + for (let i = 0; i < technique._passes.length; ++i) { + let pass = technique._passes[i]; + let count = ia.count; + + // set vertex buffer + device.setVertexBuffer(0, ia._vertexBuffer); + + // set index buffer + if (ia._indexBuffer) { + device.setIndexBuffer(ia._indexBuffer); + } + + // set primitive type + device.setPrimitiveType(ia._primitiveType); + + // set program + let program = programLib.getProgram(pass._programName, defines); + device.setProgram(program); + + // cull mode + device.setCullMode(pass._cullMode); + + // blend + if (pass._blend) { + device.enableBlend(); + device.setBlendFuncSep( + pass._blendSrc, + pass._blendDst, + pass._blendSrcAlpha, + pass._blendDstAlpha + ); + device.setBlendEqSep( + pass._blendEq, + pass._blendAlphaEq + ); + device.setBlendColor32(pass._blendColor); + } + + // depth test & write + if (pass._depthTest) { + device.enableDepthTest(); + device.setDepthFunc(pass._depthFunc); + } + if (pass._depthWrite) { + device.enableDepthWrite(); + } + + // stencil + if (pass._stencilTest) { + device.enableStencilTest(); + + // front + device.setStencilFuncFront( + pass._stencilFuncFront, + pass._stencilRefFront, + pass._stencilMaskFront + ); + device.setStencilOpFront( + pass._stencilFailOpFront, + pass._stencilZFailOpFront, + pass._stencilZPassOpFront, + pass._stencilWriteMaskFront + ); + + // back + device.setStencilFuncBack( + pass._stencilFuncBack, + pass._stencilRefBack, + pass._stencilMaskBack + ); + device.setStencilOpBack( + pass._stencilFailOpBack, + pass._stencilZFailOpBack, + pass._stencilZPassOpBack, + pass._stencilWriteMaskBack + ); + } + + // draw pass + device.draw(ia._start, count); + + this._resetTextuerUnit(); + } + } +} \ No newline at end of file diff --git a/cocos2d/renderer/core/constants.js b/cocos2d/renderer/core/constants.js new file mode 100644 index 00000000000..59e6ca8938d --- /dev/null +++ b/cocos2d/renderer/core/constants.js @@ -0,0 +1,13 @@ +let RenderQueue = { + OPAQUE: 0, + TRANSPARENT: 1, + OVERLAY: 2 +}; + +let PassStage = { + DEFAULT: 1, + FORWARD: 2, + SHADOWCAST: 4 +}; + +export { RenderQueue, PassStage }; diff --git a/cocos2d/renderer/effect.js b/cocos2d/renderer/core/effect.js similarity index 68% rename from cocos2d/renderer/effect.js rename to cocos2d/renderer/core/effect.js index 377962b41f2..5583b5136b1 100644 --- a/cocos2d/renderer/effect.js +++ b/cocos2d/renderer/core/effect.js @@ -1,32 +1,11 @@ // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -import { Vec2, Vec3, Vec4, Color, Mat4 } from '../core/value-types'; -import { config, renderer, gfx } from '../core/renderer/render-engine'; -const { Technique, Pass } = renderer; -const enums = renderer; +import config from '../config'; +import Pass from '../core/pass'; +import Technique from '../core/technique'; +import { ctor2default, enums2ctor } from '../types'; -const { Texture2D, TextureCube } = gfx; -const CCObject = cc.Object; - -let _typeMap = { - [enums.PARAM_INT]: Number, - [enums.PARAM_INT2]: Vec2, - [enums.PARAM_INT3]: Vec3, - [enums.PARAM_INT4]: Vec4, - [enums.PARAM_FLOAT]: Number, - [enums.PARAM_FLOAT2]: Vec2, - [enums.PARAM_FLOAT3]: Vec3, - [enums.PARAM_FLOAT4]: Vec4, - [enums.PARAM_COLOR3]: Color, - [enums.PARAM_COLOR4]: Color, - [enums.PARAM_MAT4]: Mat4, - [enums.PARAM_TEXTURE_2D]: Texture2D, - [enums.PARAM_TEXTURE_CUBE]: TextureCube, - number: Number, - boolean: Boolean, - default: CCObject -}; -let getInstanceType = function(t) { return _typeMap[t] || _typeMap.default; }; +let getInstanceType = function(t) { return enums2ctor[t] || enums2ctor.default; }; let typeCheck = function(value, type) { let instanceType = getInstanceType(type); switch (typeof value) { @@ -40,7 +19,7 @@ class Effect { /** * @param {Array} techniques */ - constructor(techniques, properties = {}, defines = [], dependencies = []) { + constructor(techniques, properties = {}, defines = {}, dependencies = []) { this._techniques = techniques; this._properties = properties; this._defines = defines; @@ -51,8 +30,12 @@ class Effect { clear() { this._techniques.length = 0; - this._properties = null; - this._defines.length = 0; + this._properties = {}; + this._defines = {}; + } + + getDefaultTechnique() { + return this._techniques[0]; } getTechnique(stage) { @@ -93,35 +76,37 @@ class Effect { } getDefine(name) { - for (let i = 0; i < this._defines.length; ++i) { - let def = this._defines[i]; - if (def.name === name) { - return def.value; - } + let def = this._defines[name]; + if (def === undefined) { + console.warn(`Failed to get define ${name}, define not found.`); } - console.warn(`Failed to get define ${name}, define not found.`); - return null; + return def; } define(name, value) { - for (let i = 0; i < this._defines.length; ++i) { - let def = this._defines[i]; - if (def.name === name) { - def.value = value; - return; - } + let def = this._defines[name]; + if (def === undefined) { + console.warn(`Failed to set define ${name}, define not found.`); + return; } - console.warn(`Failed to set define ${name}, define not found.`); + this._defines[name] = value; } - extractDefines(out = {}) { - for (let i = 0; i < this._defines.length; ++i) { - let def = this._defines[i]; - out[def.name] = def.value; + extractProperties(out = {}) { + Object.assign(out, this._properties); + if (this._dynamicConfig) { + Object.assign(out, this._dynamicConfig._uniforms); } + return out; + } + extractDefines(out = {}) { + Object.assign(out, this._defines); + if (this._dynamicConfig) { + Object.assign(out, this._dynamicConfig._defines); + } return out; } @@ -137,25 +122,7 @@ class Effect { let cloneObjArray = function(val) { return val.map(obj => Object.assign({}, obj)); }; -let _ctorMap = { - [Number]: v => v || 0, - [Boolean]: v => v || false, - [Vec2]: v => v ? cc.v2(v[0], v[1]) : cc.v2(), - [Vec3]: v => v ? cc.v3(v[0], v[1], v[2]) : cc.v3(), - [Vec4]: v => v ? cc.v4(v[0], v[1], v[2], v[3]) : cc.v4(), - [Color]: v => v ? cc.color(v[0] * 255, v[1] * 255, v[2] * 255, - (v[3] || 1) * 255) : cc.color(), - [Mat4]: v => v ? cc.mat4( - v[0], v[1], v[2], v[3], - v[4], v[5], v[6], v[7], - v[8], v[9], v[10], v[11], - v[12], v[13], v[14], v[15], - ) : cc.mat4(), - [Texture2D]: () => null, - [TextureCube]: () => null, - [CCObject]: () => null -}; -let getInstanceCtor = function(t) { return _ctorMap[getInstanceType(t)]; }; +let getInstanceCtor = function(t) { return ctor2default[getInstanceType(t)]; }; let getInvolvedPrograms = function(json) { let programs = [], lib = cc.renderer._forward._programLib; @@ -212,12 +179,12 @@ let parseProperties = (function() { }; })(); -Effect.parseEffect = function(json) { +Effect.parseEffect = function(effect) { // techniques - let techNum = json.techniques.length; + let techNum = effect.techniques.length; let techniques = new Array(techNum); for (let j = 0; j < techNum; ++j) { - let tech = json.techniques[j]; + let tech = effect.techniques[j]; let passNum = tech.passes.length; let passes = new Array(passNum); for (let k = 0; k < passNum; ++k) { @@ -234,10 +201,11 @@ Effect.parseEffect = function(json) { } techniques[j] = new Technique(tech.stages, passes, tech.layer); } - let programs = getInvolvedPrograms(json); - // uniforms - let props = parseProperties(json, programs), uniforms = {}; + let programs = getInvolvedPrograms(effect); + + let props = parseProperties(effect, programs), uniforms = {}, defines = {}; programs.forEach(p => { + // uniforms p.uniforms.forEach(u => { let name = u.name, uniform = uniforms[name] = Object.assign({}, u); uniform.value = getInstanceCtor(u.type)(u.value); @@ -246,11 +214,11 @@ Effect.parseEffect = function(json) { uniform.value = props[name].value; } }); + + p.defines.forEach(d => { + defines[d.name] = getInstanceCtor(d.type)(); + }) }); - // defines - let defines = programs.reduce((acc, cur) => acc = acc.concat(cur.defines), []); - defines = cloneObjArray(defines); - defines.forEach(d => d.value = getInstanceCtor(d.type)()); // extensions let extensions = programs.reduce((acc, cur) => acc = acc.concat(cur.extensions), []); extensions = cloneObjArray(extensions); @@ -262,14 +230,20 @@ if (CC_EDITOR) { Effect.parseForInspector = function(json) { let programs = getInvolvedPrograms(json); let props = parseProperties(json, programs), defines = {}; - programs.forEach(program => { - program.defines.forEach(define => { + for (let pn in programs) { + programs[pn].uniforms.forEach(u => { + let prop = props[u.name]; + if (!prop) return; + prop.defines = u.defines; + }); + programs[pn].defines.forEach(define => { defines[define.name] = { instanceType: getInstanceType(define.type), - value: getInstanceCtor(define.type)() + value: getInstanceCtor(define.type)(), + defines: define.defines }; }); - }); + } return { props, defines }; }; } diff --git a/cocos2d/renderer/core/input-assembler.js b/cocos2d/renderer/core/input-assembler.js new file mode 100644 index 00000000000..ebe23ca6fbb --- /dev/null +++ b/cocos2d/renderer/core/input-assembler.js @@ -0,0 +1,31 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import gfx from '../gfx'; + +export default class InputAssembler { + constructor(vb, ib, pt = gfx.PT_TRIANGLES) { + this._vertexBuffer = vb; + this._indexBuffer = ib; + this._primitiveType = pt; + this._start = 0; + this._count = -1; + + // TODO: instancing data + // this._stream = 0; + } + + /** + * @property {Number} count The number of indices or vertices to dispatch in the draw call. + */ + get count() { + if (this._count !== -1) { + return this._count; + } + + if (this._indexBuffer) { + return this._indexBuffer.count; + } + + return this._vertexBuffer.count; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/core/pass.js b/cocos2d/renderer/core/pass.js new file mode 100644 index 00000000000..acd4ec6b0a4 --- /dev/null +++ b/cocos2d/renderer/core/pass.js @@ -0,0 +1,120 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import gfx from '../gfx'; + +export default class Pass { + constructor(name) { + this._programName = name; + + // cullmode + this._cullMode = gfx.CULL_BACK; + + // blending + this._blend = false; + this._blendEq = gfx.BLEND_FUNC_ADD; + this._blendAlphaEq = gfx.BLEND_FUNC_ADD; + this._blendSrc = gfx.BLEND_SRC_ALPHA; + this._blendDst = gfx.BLEND_ONE_MINUS_SRC_ALPHA; + this._blendSrcAlpha = gfx.BLEND_SRC_ALPHA; + this._blendDstAlpha = gfx.BLEND_ONE_MINUS_SRC_ALPHA; + this._blendColor = 0xffffffff; + + // depth + this._depthTest = false; + this._depthWrite = false; + this._depthFunc = gfx.DS_FUNC_LESS, + + // stencil + this._stencilTest = false; + // front + this._stencilFuncFront = gfx.DS_FUNC_ALWAYS; + this._stencilRefFront = 0; + this._stencilMaskFront = 0xff; + this._stencilFailOpFront = gfx.STENCIL_OP_KEEP; + this._stencilZFailOpFront = gfx.STENCIL_OP_KEEP; + this._stencilZPassOpFront = gfx.STENCIL_OP_KEEP; + this._stencilWriteMaskFront = 0xff; + // back + this._stencilFuncBack = gfx.DS_FUNC_ALWAYS; + this._stencilRefBack = 0; + this._stencilMaskBack = 0xff; + this._stencilFailOpBack = gfx.STENCIL_OP_KEEP; + this._stencilZFailOpBack = gfx.STENCIL_OP_KEEP; + this._stencilZPassOpBack = gfx.STENCIL_OP_KEEP; + this._stencilWriteMaskBack = 0xff; + } + + setCullMode(cullMode = gfx.CULL_BACK) { + this._cullMode = cullMode; + } + + setBlend( + enabled = false, + blendEq = gfx.BLEND_FUNC_ADD, + blendSrc = gfx.BLEND_SRC_ALPHA, + blendDst = gfx.BLEND_ONE_MINUS_SRC_ALPHA, + blendAlphaEq = gfx.BLEND_FUNC_ADD, + blendSrcAlpha = gfx.BLEND_SRC_ALPHA, + blendDstAlpha = gfx.BLEND_ONE_MINUS_SRC_ALPHA, + blendColor = 0xffffffff + ) { + this._blend = enabled; + this._blendEq = blendEq; + this._blendSrc = blendSrc; + this._blendDst = blendDst; + this._blendAlphaEq = blendAlphaEq; + this._blendSrcAlpha = blendSrcAlpha; + this._blendDstAlpha = blendDstAlpha; + this._blendColor = blendColor; + } + + setDepth( + depthTest = false, + depthWrite = false, + depthFunc = gfx.DS_FUNC_LESS + ) { + this._depthTest = depthTest; + this._depthWrite = depthWrite; + this._depthFunc = depthFunc; + } + + setStencilFront( + enabled = false, + stencilFunc = gfx.DS_FUNC_ALWAYS, + stencilRef = 0, + stencilMask = 0xff, + stencilFailOp = gfx.STENCIL_OP_KEEP, + stencilZFailOp = gfx.STENCIL_OP_KEEP, + stencilZPassOp = gfx.STENCIL_OP_KEEP, + stencilWriteMask = 0xff + ) { + this._stencilTest = enabled; + this._stencilFuncFront = stencilFunc; + this._stencilRefFront = stencilRef; + this._stencilMaskFront = stencilMask; + this._stencilFailOpFront = stencilFailOp; + this._stencilZFailOpFront = stencilZFailOp; + this._stencilZPassOpFront = stencilZPassOp; + this._stencilWriteMaskFront = stencilWriteMask; + } + + setStencilBack( + enabled = false, + stencilFunc = gfx.DS_FUNC_ALWAYS, + stencilRef = 0, + stencilMask = 0xff, + stencilFailOp = gfx.STENCIL_OP_KEEP, + stencilZFailOp = gfx.STENCIL_OP_KEEP, + stencilZPassOp = gfx.STENCIL_OP_KEEP, + stencilWriteMask = 0xff + ) { + this._stencilTest = enabled; + this._stencilFuncBack = stencilFunc; + this._stencilRefBack = stencilRef; + this._stencilMaskBack = stencilMask; + this._stencilFailOpBack = stencilFailOp; + this._stencilZFailOpBack = stencilZFailOp; + this._stencilZPassOpBack = stencilZPassOp; + this._stencilWriteMaskBack = stencilWriteMask; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/core/program-lib.js b/cocos2d/renderer/core/program-lib.js new file mode 100644 index 00000000000..6d4543f9e21 --- /dev/null +++ b/cocos2d/renderer/core/program-lib.js @@ -0,0 +1,210 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import gfx from '../gfx'; + +let _shdID = 0; + +function _generateDefines(device, defs, deps) { + let defines = []; + for (let def in defs) { + let result = defs[def] ? 1 : 0; + // fallback if extension dependency not supported + if (deps && deps[def] && !device.ext(deps[def])) result = 0; + defines.push(`#define ${def} ${result}`); + } + return defines.join('\n'); +} + +function _replaceMacroNums(string, defs) { + let cache = {}; + let tmp = string; + for (let def in defs) { + if (Number.isInteger(defs[def])) { + cache[def] = defs[def]; + } + } + for (let def in cache) { + let reg = new RegExp(def, 'g'); + tmp = tmp.replace(reg, cache[def]); + } + return tmp; +} + +function _unrollLoops(string) { + let pattern = /#pragma for (\w+) in range\(\s*(\d+)\s*,\s*(\d+)\s*\)([\s\S]+?)#pragma endFor/g; + function replace(match, index, begin, end, snippet) { + let unroll = ''; + let parsedBegin = parseInt(begin); + let parsedEnd = parseInt(end); + if (parsedBegin.isNaN || parsedEnd.isNaN) { + console.error('Unroll For Loops Error: begin and end of range must be an int num.'); + } + for (let i = parsedBegin; i < parsedEnd; ++i) { + unroll += snippet.replace(new RegExp(`{${index}}`, 'g'), i); + } + return unroll; + } + return string.replace(pattern, replace); +} + +export default class ProgramLib { + /** + * @param {gfx.Device} device + * @param {Array} templates + * @param {Object} chunks + */ + constructor(device, templates = [], chunks = {}) { + this._device = device; + this._precision = `precision highp float;\n`; + + // register templates + this._templates = {}; + for (let i = 0; i < templates.length; ++i) { + this.define(templates[i]); + } + + // register chunks + this._chunks = {}; + Object.assign(this._chunks, chunks); + + this._cache = {}; + } + + /** + * @param {string} name + * @param {string} vert + * @param {string} frag + * @param {Object[]} defines + * + * @example: + * // this object is auto-generated from your actual shaders + * let program = { + * name: 'foobar', + * vert: vertTmpl, + * frag: fragTmpl, + * defines: [ + * { name: 'shadow', type: 'boolean' }, + * { name: 'lightCount', type: 'number', min: 1, max: 4 } + * ], + * attributes: [{ name: 'a_position', type: 'vec3' }], + * uniforms: [{ name: 'color', type: 'vec4' }], + * extensions: [{ name: 'GL_OES_standard_derivatives', defines: ['USE_NORMAL_TEXTURE'] }], + * }; + * programLib.define(program); + */ + define(prog) { + let name = prog.name, vert = prog.vert, frag = prog.frag, defines = prog.defines; + if (this._templates[name]) { + console.warn(`Failed to define shader ${name}: already exists.`); + return; + } + + let id = ++_shdID; + + // calculate option mask offset + let offset = 0; + for (let i = 0; i < defines.length; ++i) { + let def = defines[i]; + let cnt = 1; + + if (def.type === 'number') { + let range = def.range || []; + def.min = range[0] || 0; + def.max = range[1] || 4; + cnt = Math.ceil(Math.log2(def.max - def.min)); + + def._map = function (value) { + return (value - this.min) << this._offset; + }.bind(def); + } else { // boolean + def._map = function (value) { + if (value) { + return 1 << this._offset; + } + return 0; + }.bind(def); + } + + offset += cnt; + def._offset = offset; + } + + vert = this._precision + vert; + frag = this._precision + frag; + + // store it + this._templates[name] = { + id, + name, + vert, + frag, + defines, + attributes: prog.attributes, + uniforms: prog.uniforms, + extensions: prog.extensions + }; + } + + getTemplate(name) { + return this._templates[name]; + } + + /** + * Does this library has the specified program? + * @param {string} name + * @returns {boolean} + */ + hasProgram(name) { + return this._templates[name] !== undefined; + } + + /** + * @param {string} name + * @param {Object} defines + */ + getKey(name, defines) { + let tmpl = this._templates[name]; + let key = 0; + for (let i = 0; i < tmpl.defines.length; ++i) { + let tmplDefs = tmpl.defines[i]; + let value = defines[tmplDefs.name]; + if (value === undefined) { + continue; + } + + key |= tmplDefs._map(value); + } + + return key << 8 | tmpl.id; + } + + /** + * @param {string} name + * @param {Object} defines + * @param {Object} extensions + */ + getProgram(name, defines, extensions) { + let key = this.getKey(name, defines); + let program = this._cache[key]; + if (program) { + return program; + } + + // get template + let tmpl = this._templates[name]; + let customDef = _generateDefines(this._device, defines, extensions) + '\n'; + let vert = _replaceMacroNums(tmpl.vert, defines); + vert = customDef + _unrollLoops(vert); + let frag = _replaceMacroNums(tmpl.frag, defines); + frag = customDef + _unrollLoops(frag); + + program = new gfx.Program(this._device, { + vert, + frag + }); + program.link(); + this._cache[key] = program; + + return program; + } +} diff --git a/cocos2d/renderer/core/technique.js b/cocos2d/renderer/core/technique.js new file mode 100644 index 00000000000..a248bf035fc --- /dev/null +++ b/cocos2d/renderer/core/technique.js @@ -0,0 +1,32 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import config from '../config'; + +let _genID = 0; + +export default class Technique { + /** + * @param {Array} stages + * @param {Array} passes + * @param {Number} layer + */ + constructor(stages, passes, layer = 0) { + this._id = _genID++; + this._stageIDs = config.stageIDs(stages); + this._passes = passes; + this._layer = layer; + // TODO: this._version = 'webgl' or 'webgl2' // ???? + } + + setStages(stages) { + this._stageIDs = config.stageIDs(stages); + } + + get passes() { + return this._passes; + } + + get stageIDs() { + return this._stageIDs; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/core/view.js b/cocos2d/renderer/core/view.js new file mode 100644 index 00000000000..f4bbe43a072 --- /dev/null +++ b/cocos2d/renderer/core/view.js @@ -0,0 +1,78 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import { vec3, color4, mat4 } from '../../core/vmath'; +import enums from '../enums'; + +let _m4_tmp = mat4.create(); +let _genID = 0; + +/** + * A representation of a single camera view + */ +export default class View { + /** + * Setup a default view + */ + constructor() { + this._id = _genID++; + + // priority. the smaller one will be rendered first + this._priority = 0; + + // viewport + this._rect = { + x: 0, y: 0, w: 1, h: 1 + }; + + // TODO: + // this._scissor = { + // x: 0, y: 0, w: 1, h: 1 + // }; + + // clear options + this._color = color4.create(0.3, 0.3, 0.3, 1); + this._depth = 1; + this._stencil = 0; + this._clearFlags = enums.CLEAR_COLOR | enums.CLEAR_DEPTH; + this._clearModel = null; + + // matrix + this._matView = mat4.create(); + this._matProj = mat4.create(); + this._matViewProj = mat4.create(); + this._matInvViewProj = mat4.create(); + + // stages & framebuffer + this._stages = []; + this._cullingByID = false; + this._framebuffer = null; + + this._shadowLight = null; // TODO: should not refer light in view. + + this._cullingMask = 0xffffffff; + } + + /** + * Get the view's forward direction + * @param {vec3} out the receiving vector + * @returns {vec3} the receiving vector + */ + getForward(out) { + return vec3.set( + out, + -this._matView.m02, + -this._matView.m06, + -this._matView.m10 + ); + } + + /** + * Get the view's observing location + * @param {vec3} out the receiving vector + * @returns {vec3} the receiving vector + */ + getPosition(out) { + mat4.invert(_m4_tmp, this._matView); + return mat4.getTranslation(out, _m4_tmp); + } +} diff --git a/cocos2d/renderer/enums.js b/cocos2d/renderer/enums.js new file mode 100644 index 00000000000..4dd45af3019 --- /dev/null +++ b/cocos2d/renderer/enums.js @@ -0,0 +1,49 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +export default { + // projection + PROJ_PERSPECTIVE: 0, + PROJ_ORTHO: 1, + + // lights + LIGHT_DIRECTIONAL: 0, + LIGHT_POINT: 1, + LIGHT_SPOT: 2, + + // shadows + SHADOW_NONE: 0, + SHADOW_HARD: 1, + SHADOW_SOFT: 2, + + // parameter type + PARAM_INT: 0, + PARAM_INT2: 1, + PARAM_INT3: 2, + PARAM_INT4: 3, + PARAM_FLOAT: 4, + PARAM_FLOAT2: 5, + PARAM_FLOAT3: 6, + PARAM_FLOAT4: 7, + PARAM_COLOR3: 8, + PARAM_COLOR4: 9, + PARAM_MAT2: 10, + PARAM_MAT3: 11, + PARAM_MAT4: 12, + PARAM_TEXTURE_2D: 13, + PARAM_TEXTURE_CUBE: 14, + + // clear flags + CLEAR_COLOR: 1, + CLEAR_DEPTH: 2, + CLEAR_STENCIL: 4, + CLEAR_SKYBOX: 8, + + // + BUFFER_VIEW_INT8: 0, + BUFFER_VIEW_UINT8: 1, + BUFFER_VIEW_INT16: 2, + BUFFER_VIEW_UINT16: 3, + BUFFER_VIEW_INT32: 4, + BUFFER_VIEW_UINT32: 5, + BUFFER_VIEW_FLOAT32: 6, +}; diff --git a/cocos2d/renderer/gfx/device.js b/cocos2d/renderer/gfx/device.js new file mode 100644 index 00000000000..62c9df8c338 --- /dev/null +++ b/cocos2d/renderer/gfx/device.js @@ -0,0 +1,1318 @@ +import State from './state'; +import { enums } from './enums'; + +import Texture2D from './texture-2d'; +import TextureCube from './texture-cube'; + +const GL_INT = 5124; +const GL_FLOAT = 5126; +const GL_FLOAT_VEC2 = 35664; +const GL_FLOAT_VEC3 = 35665; +const GL_FLOAT_VEC4 = 35666; +const GL_INT_VEC2 = 35667; +const GL_INT_VEC3 = 35668; +const GL_INT_VEC4 = 35669; +const GL_BOOL = 35670; +const GL_BOOL_VEC2 = 35671; +const GL_BOOL_VEC3 = 35672; +const GL_BOOL_VEC4 = 35673; +const GL_FLOAT_MAT2 = 35674; +const GL_FLOAT_MAT3 = 35675; +const GL_FLOAT_MAT4 = 35676; +const GL_SAMPLER_2D = 35678; +const GL_SAMPLER_CUBE = 35680; + +/** + * _type2uniformCommit + */ +let _type2uniformCommit = { + [GL_INT]: function (gl, id, value) { + gl.uniform1i(id, value); + }, + + [GL_FLOAT]: function (gl, id, value) { + gl.uniform1f(id, value); + }, + + [GL_FLOAT_VEC2]: function (gl, id, value) { + gl.uniform2fv(id, value); + }, + + [GL_FLOAT_VEC3]: function (gl, id, value) { + gl.uniform3fv(id, value); + }, + + [GL_FLOAT_VEC4]: function (gl, id, value) { + gl.uniform4fv(id, value); + }, + + [GL_INT_VEC2]: function (gl, id, value) { + gl.uniform2iv(id, value); + }, + + [GL_INT_VEC3]: function (gl, id, value) { + gl.uniform3iv(id, value); + }, + + [GL_INT_VEC4]: function (gl, id, value) { + gl.uniform4iv(id, value); + }, + + [GL_BOOL]: function (gl, id, value) { + gl.uniform1i(id, value); + }, + + [GL_BOOL_VEC2]: function (gl, id, value) { + gl.uniform2iv(id, value); + }, + + [GL_BOOL_VEC3]: function (gl, id, value) { + gl.uniform3iv(id, value); + }, + + [GL_BOOL_VEC4]: function (gl, id, value) { + gl.uniform4iv(id, value); + }, + + [GL_FLOAT_MAT2]: function (gl, id, value) { + gl.uniformMatrix2fv(id, false, value); + }, + + [GL_FLOAT_MAT3]: function (gl, id, value) { + gl.uniformMatrix3fv(id, false, value); + }, + + [GL_FLOAT_MAT4]: function (gl, id, value) { + gl.uniformMatrix4fv(id, false, value); + }, + + [GL_SAMPLER_2D]: function (gl, id, value) { + gl.uniform1i(id, value); + }, + + [GL_SAMPLER_CUBE]: function (gl, id, value) { + gl.uniform1i(id, value); + }, +}; + +/** + * _type2uniformArrayCommit + */ +let _type2uniformArrayCommit = { + [GL_INT]: function (gl, id, value) { + gl.uniform1iv(id, value); + }, + + [GL_FLOAT]: function (gl, id, value) { + gl.uniform1fv(id, value); + }, + + [GL_FLOAT_VEC2]: function (gl, id, value) { + gl.uniform2fv(id, value); + }, + + [GL_FLOAT_VEC3]: function (gl, id, value) { + gl.uniform3fv(id, value); + }, + + [GL_FLOAT_VEC4]: function (gl, id, value) { + gl.uniform4fv(id, value); + }, + + [GL_INT_VEC2]: function (gl, id, value) { + gl.uniform2iv(id, value); + }, + + [GL_INT_VEC3]: function (gl, id, value) { + gl.uniform3iv(id, value); + }, + + [GL_INT_VEC4]: function (gl, id, value) { + gl.uniform4iv(id, value); + }, + + [GL_BOOL]: function (gl, id, value) { + gl.uniform1iv(id, value); + }, + + [GL_BOOL_VEC2]: function (gl, id, value) { + gl.uniform2iv(id, value); + }, + + [GL_BOOL_VEC3]: function (gl, id, value) { + gl.uniform3iv(id, value); + }, + + [GL_BOOL_VEC4]: function (gl, id, value) { + gl.uniform4iv(id, value); + }, + + [GL_FLOAT_MAT2]: function (gl, id, value) { + gl.uniformMatrix2fv(id, false, value); + }, + + [GL_FLOAT_MAT3]: function (gl, id, value) { + gl.uniformMatrix3fv(id, false, value); + }, + + [GL_FLOAT_MAT4]: function (gl, id, value) { + gl.uniformMatrix4fv(id, false, value); + }, + + [GL_SAMPLER_2D]: function (gl, id, value) { + gl.uniform1iv(id, value); + }, + + [GL_SAMPLER_CUBE]: function (gl, id, value) { + gl.uniform1iv(id, value); + }, +}; + +/** + * _commitBlendStates + */ +function _commitBlendStates(gl, cur, next) { + // enable/disable blend + if (cur.blend !== next.blend) { + if (!next.blend) { + gl.disable(gl.BLEND); + return; + } + + gl.enable(gl.BLEND); + + if ( + next.blendSrc === enums.BLEND_CONSTANT_COLOR || + next.blendSrc === enums.BLEND_ONE_MINUS_CONSTANT_COLOR || + next.blendDst === enums.BLEND_CONSTANT_COLOR || + next.blendDst === enums.BLEND_ONE_MINUS_CONSTANT_COLOR + ) { + gl.blendColor( + (next.blendColor >> 24) / 255, + (next.blendColor >> 16 & 0xff) / 255, + (next.blendColor >> 8 & 0xff) / 255, + (next.blendColor & 0xff) / 255 + ); + } + + if (next.blendSep) { + gl.blendFuncSeparate(next.blendSrc, next.blendDst, next.blendSrcAlpha, next.blendDstAlpha); + gl.blendEquationSeparate(next.blendEq, next.blendAlphaEq); + } else { + gl.blendFunc(next.blendSrc, next.blendDst); + gl.blendEquation(next.blendEq); + } + + return; + } + + // nothing to update + if (next.blend === false) { + return; + } + + // blend-color + if (cur.blendColor !== next.blendColor) { + gl.blendColor( + (next.blendColor >> 24) / 255, + (next.blendColor >> 16 & 0xff) / 255, + (next.blendColor >> 8 & 0xff) / 255, + (next.blendColor & 0xff) / 255 + ); + } + + // separate diff, reset all + if (cur.blendSep !== next.blendSep) { + if (next.blendSep) { + gl.blendFuncSeparate(next.blendSrc, next.blendDst, next.blendSrcAlpha, next.blendDstAlpha); + gl.blendEquationSeparate(next.blendEq, next.blendAlphaEq); + } else { + gl.blendFunc(next.blendSrc, next.blendDst); + gl.blendEquation(next.blendEq); + } + + return; + } + + if (next.blendSep) { + // blend-func-separate + if ( + cur.blendSrc !== next.blendSrc || + cur.blendDst !== next.blendDst || + cur.blendSrcAlpha !== next.blendSrcAlpha || + cur.blendDstAlpha !== next.blendDstAlpha + ) { + gl.blendFuncSeparate(next.blendSrc, next.blendDst, next.blendSrcAlpha, next.blendDstAlpha); + } + + // blend-equation-separate + if ( + cur.blendEq !== next.blendEq || + cur.blendAlphaEq !== next.blendAlphaEq + ) { + gl.blendEquationSeparate(next.blendEq, next.blendAlphaEq); + } + } else { + // blend-func + if ( + cur.blendSrc !== next.blendSrc || + cur.blendDst !== next.blendDst + ) { + gl.blendFunc(next.blendSrc, next.blendDst); + } + + // blend-equation + if (cur.blendEq !== next.blendEq) { + gl.blendEquation(next.blendEq); + } + } +} + +/** + * _commitDepthStates + */ +function _commitDepthStates(gl, cur, next) { + // enable/disable depth-test + if (cur.depthTest !== next.depthTest) { + if (!next.depthTest) { + gl.disable(gl.DEPTH_TEST); + return; + } + + gl.enable(gl.DEPTH_TEST); + gl.depthFunc(next.depthFunc); + gl.depthMask(next.depthWrite); + + return; + } + + // commit depth-write + if (cur.depthWrite !== next.depthWrite) { + gl.depthMask(next.depthWrite); + } + + // check if depth-write enabled + if (next.depthTest === false) { + if (next.depthWrite) { + next.depthTest = true; + next.depthFunc = enums.DS_FUNC_ALWAYS; + + gl.enable(gl.DEPTH_TEST); + gl.depthFunc(next.depthFunc); + } + + return; + } + + // depth-func + if (cur.depthFunc !== next.depthFunc) { + gl.depthFunc(next.depthFunc); + } +} + +/** + * _commitStencilStates + */ +function _commitStencilStates(gl, cur, next) { + if (next.stencilTest !== cur.stencilTest) { + if (!next.stencilTest) { + gl.disable(gl.STENCIL_TEST); + return; + } + + gl.enable(gl.STENCIL_TEST); + + if (next.stencilSep) { + gl.stencilFuncSeparate(gl.FRONT, next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); + gl.stencilMaskSeparate(gl.FRONT, next.stencilWriteMaskFront); + gl.stencilOpSeparate(gl.FRONT, next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); + gl.stencilFuncSeparate(gl.BACK, next.stencilFuncBack, next.stencilRefBack, next.stencilMaskBack); + gl.stencilMaskSeparate(gl.BACK, next.stencilWriteMaskBack); + gl.stencilOpSeparate(gl.BACK, next.stencilFailOpBack, next.stencilZFailOpBack, next.stencilZPassOpBack); + } else { + gl.stencilFunc(next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); + gl.stencilMask(next.stencilWriteMaskFront); + gl.stencilOp(next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); + } + + return; + } + + // fast return + if (!next.stencilTest) { + return; + } + + if (cur.stencilSep !== next.stencilSep) { + if (next.stencilSep) { + gl.stencilFuncSeparate(gl.FRONT, next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); + gl.stencilMaskSeparate(gl.FRONT, next.stencilWriteMaskFront); + gl.stencilOpSeparate(gl.FRONT, next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); + gl.stencilFuncSeparate(gl.BACK, next.stencilFuncBack, next.stencilRefBack, next.stencilMaskBack); + gl.stencilMaskSeparate(gl.BACK, next.stencilWriteMaskBack); + gl.stencilOpSeparate(gl.BACK, next.stencilFailOpBack, next.stencilZFailOpBack, next.stencilZPassOpBack); + } else { + gl.stencilFunc(next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); + gl.stencilMask(next.stencilWriteMaskFront); + gl.stencilOp(next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); + } + return; + } + + if (next.stencilSep) { + // front + if ( + cur.stencilFuncFront !== next.stencilFuncFront || + cur.stencilRefFront !== next.stencilRefFront || + cur.stencilMaskFront !== next.stencilMaskFront + ) { + gl.stencilFuncSeparate(gl.FRONT, next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); + } + if (cur.stencilWriteMaskFront !== next.stencilWriteMaskFront) { + gl.stencilMaskSeparate(gl.FRONT, next.stencilWriteMaskFront); + } + if ( + cur.stencilFailOpFront !== next.stencilFailOpFront || + cur.stencilZFailOpFront !== next.stencilZFailOpFront || + cur.stencilZPassOpFront !== next.stencilZPassOpFront + ) { + gl.stencilOpSeparate(gl.FRONT, next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); + } + + // back + if ( + cur.stencilFuncBack !== next.stencilFuncBack || + cur.stencilRefBack !== next.stencilRefBack || + cur.stencilMaskBack !== next.stencilMaskBack + ) { + gl.stencilFuncSeparate(gl.BACK, next.stencilFuncBack, next.stencilRefBack, next.stencilMaskBack); + } + if (cur.stencilWriteMaskBack !== next.stencilWriteMaskBack) { + gl.stencilMaskSeparate(gl.BACK, next.stencilWriteMaskBack); + } + if ( + cur.stencilFailOpBack !== next.stencilFailOpBack || + cur.stencilZFailOpBack !== next.stencilZFailOpBack || + cur.stencilZPassOpBack !== next.stencilZPassOpBack + ) { + gl.stencilOpSeparate(gl.BACK, next.stencilFailOpBack, next.stencilZFailOpBack, next.stencilZPassOpBack); + } + } else { + if ( + cur.stencilFuncFront !== next.stencilFuncFront || + cur.stencilRefFront !== next.stencilRefFront || + cur.stencilMaskFront !== next.stencilMaskFront + ) { + gl.stencilFunc(next.stencilFuncFront, next.stencilRefFront, next.stencilMaskFront); + } + if (cur.stencilWriteMaskFront !== next.stencilWriteMaskFront) { + gl.stencilMask(next.stencilWriteMaskFront); + } + if ( + cur.stencilFailOpFront !== next.stencilFailOpFront || + cur.stencilZFailOpFront !== next.stencilZFailOpFront || + cur.stencilZPassOpFront !== next.stencilZPassOpFront + ) { + gl.stencilOp(next.stencilFailOpFront, next.stencilZFailOpFront, next.stencilZPassOpFront); + } + } + +} + +/** + * _commitCullMode + */ +function _commitCullMode(gl, cur, next) { + if (cur.cullMode === next.cullMode) { + return; + } + + if (next.cullMode === enums.CULL_NONE) { + gl.disable(gl.CULL_FACE); + return; + } + + gl.enable(gl.CULL_FACE); + gl.cullFace(next.cullMode); +} + +/** + * _commitVertexBuffers + */ +function _commitVertexBuffers(device, gl, cur, next) { + let attrsDirty = false; + + // nothing changed for vertex buffer + if (next.maxStream === -1) { + console.warn('VertexBuffer not assigned, please call setVertexBuffer before every draw.'); + return; + } + + if (cur.maxStream !== next.maxStream) { + attrsDirty = true; + } else if (cur.program !== next.program) { + attrsDirty = true; + } else { + for (let i = 0; i < next.maxStream + 1; ++i) { + if ( + cur.vertexBuffers[i] !== next.vertexBuffers[i] || + cur.vertexBufferOffsets[i] !== next.vertexBufferOffsets[i] + ) { + attrsDirty = true; + break; + } + } + } + + if (attrsDirty) { + for (let i = 0; i < device._caps.maxVertexAttribs; ++i) { + device._newAttributes[i] = 0; + } + + for (let i = 0; i < next.maxStream + 1; ++i) { + let vb = next.vertexBuffers[i]; + let vbOffset = next.vertexBufferOffsets[i]; + if (!vb) { + continue; + } + + gl.bindBuffer(gl.ARRAY_BUFFER, vb._glID); + + for (let j = 0; j < next.program._attributes.length; ++j) { + let attr = next.program._attributes[j]; + + let el = vb._format.element(attr.name); + if (!el) { + console.warn(`Can not find vertex attribute: ${attr.name}`); + continue; + } + + if (device._enabledAttributes[attr.location] === 0) { + gl.enableVertexAttribArray(attr.location); + device._enabledAttributes[attr.location] = 1; + } + device._newAttributes[attr.location] = 1; + + gl.vertexAttribPointer( + attr.location, + el.num, + el.type, + el.normalize, + el.stride, + el.offset + vbOffset * el.stride + ); + } + } + + // disable unused attributes + for (let i = 0; i < device._caps.maxVertexAttribs; ++i) { + if (device._enabledAttributes[i] !== device._newAttributes[i]) { + gl.disableVertexAttribArray(i); + device._enabledAttributes[i] = 0; + } + } + } +} + +/** + * _commitTextures + */ +function _commitTextures(gl, cur, next) { + for (let i = 0; i < next.maxTextureSlot + 1; ++i) { + if (cur.textureUnits[i] !== next.textureUnits[i]) { + let texture = next.textureUnits[i]; + if (texture && texture._glID !== -1) { + gl.activeTexture(gl.TEXTURE0 + i); + gl.bindTexture(texture._target, texture._glID); + } + } + } +} + +/** + * _attach + */ +function _attach(gl, location, attachment, face = 0) { + if (attachment instanceof Texture2D) { + gl.framebufferTexture2D( + gl.FRAMEBUFFER, + location, + gl.TEXTURE_2D, + attachment._glID, + 0 + ); + } else if (attachment instanceof TextureCube) { + gl.framebufferTexture2D( + gl.FRAMEBUFFER, + location, + gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, + attachment._glID, + 0 + ); + } else { + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, + location, + gl.RENDERBUFFER, + attachment._glID + ); + } +} + +export default class Device { + /** + * @param {HTMLElement} canvasEL + * @param {object} opts + */ + constructor(canvasEL, opts) { + let gl; + + // default options + opts = opts || {}; + if (opts.alpha === undefined) { + opts.alpha = false; + } + if (opts.stencil === undefined) { + opts.stencil = true; + } + if (opts.depth === undefined) { + opts.depth = true; + } + if (opts.antialias === undefined) { + opts.antialias = false; + } + // NOTE: it is said the performance improved in mobile device with this flag off. + if (opts.preserveDrawingBuffer === undefined) { + opts.preserveDrawingBuffer = false; + } + + try { + gl = canvasEL.getContext('webgl', opts); + } catch (err) { + console.error(err); + return; + } + + // No errors are thrown using try catch + // Tested through ios baidu browser 4.14.1 + if (!gl) { + console.error('This device does not support webgl'); + } + + // statics + /** + * @type {WebGLRenderingContext} + */ + this._gl = gl; + this._extensions = {}; + this._caps = {}; // capability + this._stats = { + texture: 0, + vb: 0, + ib: 0, + drawcalls: 0, + }; + + this._initExtensions([ + 'EXT_texture_filter_anisotropic', + 'EXT_shader_texture_lod', + 'OES_standard_derivatives', + 'OES_texture_float', + 'OES_texture_float_linear', + 'OES_texture_half_float', + 'OES_texture_half_float_linear', + 'OES_vertex_array_object', + 'WEBGL_compressed_texture_atc', + 'WEBGL_compressed_texture_etc1', + 'WEBGL_compressed_texture_pvrtc', + 'WEBGL_compressed_texture_s3tc', + 'WEBGL_depth_texture', + 'WEBGL_draw_buffers', + ]); + this._initCaps(); + this._initStates(); + + // runtime + State.initDefault(this); + this._current = new State(this); + this._next = new State(this); + this._uniforms = {}; // name: { value, num, dirty } + this._vx = this._vy = this._vw = this._vh = 0; + this._sx = this._sy = this._sw = this._sh = 0; + this._framebuffer = null; + + // + this._enabledAttributes = new Array(this._caps.maxVertexAttribs); + this._newAttributes = new Array(this._caps.maxVertexAttribs); + + for (let i = 0; i < this._caps.maxVertexAttribs; ++i) { + this._enabledAttributes[i] = 0; + this._newAttributes[i] = 0; + } + } + + _initExtensions(extensions) { + const gl = this._gl; + + for (let i = 0; i < extensions.length; ++i) { + let name = extensions[i]; + + try { + let ext = gl.getExtension(name); + if (ext) { + this._extensions[name] = ext; + } + } catch (e) { + console.error(e); + } + } + } + + _initCaps() { + const gl = this._gl; + const extDrawBuffers = this.ext('WEBGL_draw_buffers'); + + this._caps.maxVertexStreams = 4; + this._caps.maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS); + this._caps.maxFragUniforms = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS); + this._caps.maxTextureUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + this._caps.maxVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + + this._caps.maxDrawBuffers = extDrawBuffers ? gl.getParameter(extDrawBuffers.MAX_DRAW_BUFFERS_WEBGL) : 1; + this._caps.maxColorAttachments = extDrawBuffers ? gl.getParameter(extDrawBuffers.MAX_COLOR_ATTACHMENTS_WEBGL) : 1; + } + + _initStates() { + const gl = this._gl; + + // gl.frontFace(gl.CCW); + gl.disable(gl.BLEND); + gl.blendFunc(gl.ONE, gl.ZERO); + gl.blendEquation(gl.FUNC_ADD); + gl.blendColor(1,1,1,1); + + gl.colorMask(true, true, true, true); + + gl.enable(gl.CULL_FACE); + gl.cullFace(gl.BACK); + + gl.disable(gl.DEPTH_TEST); + gl.depthFunc(gl.LESS); + gl.depthMask(false); + gl.disable(gl.POLYGON_OFFSET_FILL); + gl.depthRange(0,1); + + gl.disable(gl.STENCIL_TEST); + gl.stencilFunc(gl.ALWAYS, 0, 0xFF); + gl.stencilMask(0xFF); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + + // TODO: + // this.setAlphaToCoverage(false); + // this.setTransformFeedbackBuffer(null); + // this.setRaster(true); + // this.setDepthBias(false); + + gl.clearDepth(1); + gl.clearColor(0, 0, 0, 0); + gl.clearStencil(0); + + gl.disable(gl.SCISSOR_TEST); + } + + _restoreTexture(unit) { + const gl = this._gl; + + let texture = this._current.textureUnits[unit]; + if (texture && texture._glID !== -1) { + gl.bindTexture(texture._target, texture._glID); + } else { + gl.bindTexture(gl.TEXTURE_2D, null); + } + } + + _restoreIndexBuffer () { + const gl = this._gl; + + let ib = this._current.indexBuffer; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ib ? ib._glID : null); + } + + /** + * @method ext + * @param {string} name + */ + ext(name) { + return this._extensions[name]; + } + + allowFloatTexture() { + return this.ext("OES_texture_float") != null; + } + + // =============================== + // Immediate Settings + // =============================== + + /** + * @method setFrameBuffer + * @param {FrameBuffer} fb - null means use the backbuffer + */ + setFrameBuffer(fb) { + if (this._framebuffer === fb) { + return; + } + + this._framebuffer = fb; + const gl = this._gl; + + if (fb === null) { + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + return; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb._glID); + + let numColors = fb._colors.length; + for (let i = 0; i < numColors; ++i) { + let colorBuffer = fb._colors[i]; + _attach(gl, gl.COLOR_ATTACHMENT0 + i, colorBuffer); + + // TODO: what about cubemap face??? should be the target parameter for colorBuffer + } + for (let i = numColors; i < this._caps.maxColorAttachments; ++i) { + gl.framebufferTexture2D( + gl.FRAMEBUFFER, + gl.COLOR_ATTACHMENT0 + i, + gl.TEXTURE_2D, + null, + 0 + ); + } + + if (fb._depth) { + _attach(gl, gl.DEPTH_ATTACHMENT, fb._depth); + } + + if (fb._stencil) { + _attach(gl, gl.STENCIL_ATTACHMENT, fb._stencil); + } + + if (fb._depthStencil) { + _attach(gl, gl.DEPTH_STENCIL_ATTACHMENT, fb._depthStencil); + } + } + + /** + * @method setViewport + * @param {Number} x + * @param {Number} y + * @param {Number} w + * @param {Number} h + */ + setViewport(x, y, w, h) { + if ( + this._vx !== x || + this._vy !== y || + this._vw !== w || + this._vh !== h + ) { + this._gl.viewport(x, y, w, h); + this._vx = x; + this._vy = y; + this._vw = w; + this._vh = h; + } + } + + /** + * @method setScissor + * @param {Number} x + * @param {Number} y + * @param {Number} w + * @param {Number} h + */ + setScissor(x, y, w, h) { + if ( + this._sx !== x || + this._sy !== y || + this._sw !== w || + this._sh !== h + ) { + this._gl.scissor(x, y, w, h); + this._sx = x; + this._sy = y; + this._sw = w; + this._sh = h; + } + } + + /** + * @method clear + * @param {Object} opts + * @param {Array} opts.color + * @param {Number} opts.depth + * @param {Number} opts.stencil + */ + clear(opts) { + const gl = this._gl; + let flags = 0; + + if (opts.color !== undefined) { + flags |= gl.COLOR_BUFFER_BIT; + gl.clearColor(opts.color[0], opts.color[1], opts.color[2], opts.color[3]); + } + + if (opts.depth !== undefined) { + flags |= gl.DEPTH_BUFFER_BIT; + gl.clearDepth(opts.depth); + + gl.enable(gl.DEPTH_TEST); + gl.depthMask(true); + gl.depthFunc(gl.ALWAYS); + } + + if (opts.stencil !== undefined) { + flags |= gl.STENCIL_BUFFER_BIT; + gl.clearStencil(opts.stencil); + } + + gl.clear(flags); + + // restore depth-write + if (opts.depth !== undefined) { + if (this._current.depthTest === false) { + gl.disable(gl.DEPTH_TEST); + } else { + if (this._current.depthWrite === false) { + gl.depthMask(false); + } + if (this._current.depthFunc !== enums.DS_FUNC_ALWAYS) { + gl.depthFunc(this._current.depthFunc); + } + } + } + } + + // =============================== + // Deferred States + // =============================== + + /** + * @method enableBlend + */ + enableBlend() { + this._next.blend = true; + } + + /** + * @method enableDepthTest + */ + enableDepthTest() { + this._next.depthTest = true; + } + + /** + * @method enableDepthWrite + */ + enableDepthWrite() { + this._next.depthWrite = true; + } + + /** + * @method enableStencilTest + */ + enableStencilTest() { + this._next.stencilTest = true; + } + + /** + * @method setStencilFunc + * @param {DS_FUNC_*} func + * @param {Number} ref + * @param {Number} mask + */ + setStencilFunc(func, ref, mask) { + this._next.stencilSep = false; + this._next.stencilFuncFront = this._next.stencilFuncBack = func; + this._next.stencilRefFront = this._next.stencilRefBack = ref; + this._next.stencilMaskFront = this._next.stencilMaskBack = mask; + } + + /** + * @method setStencilFuncFront + * @param {DS_FUNC_*} func + * @param {Number} ref + * @param {Number} mask + */ + setStencilFuncFront(func, ref, mask) { + this._next.stencilSep = true; + this._next.stencilFuncFront = func; + this._next.stencilRefFront = ref; + this._next.stencilMaskFront = mask; + } + + /** + * @method setStencilFuncBack + * @param {DS_FUNC_*} func + * @param {Number} ref + * @param {Number} mask + */ + setStencilFuncBack(func, ref, mask) { + this._next.stencilSep = true; + this._next.stencilFuncBack = func; + this._next.stencilRefBack = ref; + this._next.stencilMaskBack = mask; + } + + /** + * @method setStencilOp + * @param {STENCIL_OP_*} failOp + * @param {STENCIL_OP_*} zFailOp + * @param {STENCIL_OP_*} zPassOp + * @param {Number} writeMask + */ + setStencilOp(failOp, zFailOp, zPassOp, writeMask) { + this._next.stencilFailOpFront = this._next.stencilFailOpBack = failOp; + this._next.stencilZFailOpFront = this._next.stencilZFailOpBack = zFailOp; + this._next.stencilZPassOpFront = this._next.stencilZPassOpBack = zPassOp; + this._next.stencilWriteMaskFront = this._next.stencilWriteMaskBack = writeMask; + } + + /** + * @method setStencilOpFront + * @param {STENCIL_OP_*} failOp + * @param {STENCIL_OP_*} zFailOp + * @param {STENCIL_OP_*} zPassOp + * @param {Number} writeMask + */ + setStencilOpFront(failOp, zFailOp, zPassOp, writeMask) { + this._next.stencilSep = true; + this._next.stencilFailOpFront = failOp; + this._next.stencilZFailOpFront = zFailOp; + this._next.stencilZPassOpFront = zPassOp; + this._next.stencilWriteMaskFront = writeMask; + } + + /** + * @method setStencilOpBack + * @param {STENCIL_OP_*} failOp + * @param {STENCIL_OP_*} zFailOp + * @param {STENCIL_OP_*} zPassOp + * @param {Number} writeMask + */ + setStencilOpBack(failOp, zFailOp, zPassOp, writeMask) { + this._next.stencilSep = true; + this._next.stencilFailOpBack = failOp; + this._next.stencilZFailOpBack = zFailOp; + this._next.stencilZPassOpBack = zPassOp; + this._next.stencilWriteMaskBack = writeMask; + } + + /** + * @method setDepthFunc + * @param {DS_FUNC_*} depthFunc + */ + setDepthFunc(depthFunc) { + this._next.depthFunc = depthFunc; + } + + /** + * @method setBlendColor32 + * @param {Number} rgba + */ + setBlendColor32(rgba) { + this._next.blendColor = rgba; + } + + /** + * @method setBlendColor + * @param {Number} r + * @param {Number} g + * @param {Number} b + * @param {Number} a + */ + setBlendColor(r, g, b, a) { + this._next.blendColor = ((r * 255) << 24 | (g * 255) << 16 | (b * 255) << 8 | a * 255) >>> 0; + } + + /** + * @method setBlendFunc + * @param {BELND_*} src + * @param {BELND_*} dst + */ + setBlendFunc(src, dst) { + this._next.blendSep = false; + this._next.blendSrc = src; + this._next.blendDst = dst; + } + + /** + * @method setBlendFuncSep + * @param {BELND_*} src + * @param {BELND_*} dst + * @param {BELND_*} srcAlpha + * @param {BELND_*} dstAlpha + */ + setBlendFuncSep(src, dst, srcAlpha, dstAlpha) { + this._next.blendSep = true; + this._next.blendSrc = src; + this._next.blendDst = dst; + this._next.blendSrcAlpha = srcAlpha; + this._next.blendDstAlpha = dstAlpha; + } + + /** + * @method setBlendEq + * @param {BELND_FUNC_*} eq + */ + setBlendEq(eq) { + this._next.blendSep = false; + this._next.blendEq = eq; + } + + /** + * @method setBlendEqSep + * @param {BELND_FUNC_*} eq + * @param {BELND_FUNC_*} alphaEq + */ + setBlendEqSep(eq, alphaEq) { + this._next.blendSep = true; + this._next.blendEq = eq; + this._next.blendAlphaEq = alphaEq; + } + + /** + * @method setCullMode + * @param {CULL_*} mode + */ + setCullMode(mode) { + this._next.cullMode = mode; + } + + /** + * @method setVertexBuffer + * @param {Number} stream + * @param {VertexBuffer} buffer + * @param {Number} start - start vertex + */ + setVertexBuffer(stream, buffer, start = 0) { + this._next.vertexBuffers[stream] = buffer; + this._next.vertexBufferOffsets[stream] = start; + if (this._next.maxStream < stream) { + this._next.maxStream = stream; + } + } + + /** + * @method setIndexBuffer + * @param {IndexBuffer} buffer + */ + setIndexBuffer(buffer) { + this._next.indexBuffer = buffer; + } + + /** + * @method setProgram + * @param {Program} program + */ + setProgram(program) { + this._next.program = program; + } + + /** + * @method setTexture + * @param {String} name + * @param {Texture} texture + * @param {Number} slot + */ + setTexture(name, texture, slot) { + if (slot >= this._caps.maxTextureUnits) { + console.warn(`Can not set texture ${name} at stage ${slot}, max texture exceed: ${this._caps.maxTextureUnits}`); + return; + } + + this._next.textureUnits[slot] = texture; + this.setUniform(name, slot); + + if (this._next.maxTextureSlot < slot) { + this._next.maxTextureSlot = slot; + } + } + + /** + * @method setTextureArray + * @param {String} name + * @param {Array} textures + * @param {Int32Array} slots + */ + setTextureArray(name, textures, slots) { + let len = textures.length; + if (len >= this._caps.maxTextureUnits) { + console.warn(`Can not set ${len} textures for ${name}, max texture exceed: ${this._caps.maxTextureUnits}`); + return; + } + for (let i = 0; i < len; ++i) { + let slot = slots[i]; + this._next.textureUnits[slot] = textures[i]; + } + this.setUniform(name, slots); + } + + /** + * @method setUniform + * @param {String} name + * @param {*} value + */ + setUniform(name, value) { + let uniform = this._uniforms[name]; + if (!uniform || (uniform.isArray && uniform.value.length < value.length)) { + let newValue = value; + let isArray = false; + if (value instanceof Float32Array || Array.isArray(value)) { + newValue = new Float32Array(value); + isArray = true; + } + else if (value instanceof Int32Array) { + newValue = new Int32Array(value); + isArray = true; + } + + uniform = { + dirty: true, + value: newValue, + isArray: isArray + }; + } else { + let oldValue = uniform.value; + let dirty = false; + if (uniform.isArray) { + for (let i = 0, l = oldValue.length; i < l; i++) { + if (oldValue[i] !== value[i]) { + dirty = true; + oldValue[i] = value[i]; + } + } + } + else { + if (oldValue !== value) { + dirty = true; + uniform.value = value; + } + } + + if (dirty) { + uniform.dirty = true; + } + } + this._uniforms[name] = uniform; + } + + /** + * @method setPrimitiveType + * @param {PT_*} type + */ + setPrimitiveType(type) { + this._next.primitiveType = type; + } + + /** + * @method draw + * @param {Number} base + * @param {Number} count + */ + draw(base, count) { + const gl = this._gl; + let cur = this._current; + let next = this._next; + + // commit blend + _commitBlendStates(gl, cur, next); + + // commit depth + _commitDepthStates(gl, cur, next); + + // commit stencil + _commitStencilStates(gl, cur, next); + + // commit cull + _commitCullMode(gl, cur, next); + + // commit vertex-buffer + _commitVertexBuffers(this, gl, cur, next); + + // commit index-buffer + if (cur.indexBuffer !== next.indexBuffer) { + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, next.indexBuffer ? next.indexBuffer._glID : null); + } + + // commit program + let programDirty = false; + if (cur.program !== next.program) { + if (next.program._linked) { + gl.useProgram(next.program._glID); + } else { + console.warn('Failed to use program: has not linked yet.'); + } + programDirty = true; + } + + // commit texture/sampler + _commitTextures(gl, cur, next); + + // commit uniforms + for (let i = 0; i < next.program._uniforms.length; ++i) { + let uniformInfo = next.program._uniforms[i]; + let uniform = this._uniforms[uniformInfo.name]; + if (!uniform) { + // console.warn(`Can not find uniform ${uniformInfo.name}`); + continue; + } + + if (!programDirty && !uniform.dirty) { + continue; + } + + uniform.dirty = false; + + // TODO: please consider array uniform: uniformInfo.size > 0 + + let commitFunc = (uniformInfo.size === undefined) ? _type2uniformCommit[uniformInfo.type] : _type2uniformArrayCommit[uniformInfo.type]; + if (!commitFunc) { + console.warn(`Can not find commit function for uniform ${uniformInfo.name}`); + continue; + } + + commitFunc(gl, uniformInfo.location, uniform.value); + } + + // drawPrimitives + if (next.indexBuffer) { + gl.drawElements( + this._next.primitiveType, + count, + next.indexBuffer._format, + base * next.indexBuffer._bytesPerIndex + ); + } else { + gl.drawArrays( + this._next.primitiveType, + base, + count + ); + } + + // TODO: autogen mipmap for color buffer + // if (this._framebuffer && this._framebuffer.colors[0].mipmap) { + // gl.bindTexture(this._framebuffer.colors[i]._target, colors[i]._glID); + // gl.generateMipmap(this._framebuffer.colors[i]._target); + // } + + // update stats + this._stats.drawcalls += 1; + + // reset states + cur.set(next); + next.reset(); + } +} \ No newline at end of file diff --git a/cocos2d/renderer/mappings/gfx/enums.js b/cocos2d/renderer/gfx/enums.js similarity index 100% rename from cocos2d/renderer/mappings/gfx/enums.js rename to cocos2d/renderer/gfx/enums.js diff --git a/cocos2d/renderer/gfx/frame-buffer.js b/cocos2d/renderer/gfx/frame-buffer.js new file mode 100644 index 00000000000..bd439548183 --- /dev/null +++ b/cocos2d/renderer/gfx/frame-buffer.js @@ -0,0 +1,41 @@ +export default class FrameBuffer { + /** + * @constructor + * @param {Device} device + * @param {Number} width + * @param {Number} height + * @param {Object} options + * @param {Array} options.colors + * @param {RenderBuffer|Texture2D|TextureCube} options.depth + * @param {RenderBuffer|Texture2D|TextureCube} options.stencil + * @param {RenderBuffer|Texture2D|TextureCube} options.depthStencil + */ + constructor(device, width, height, options) { + this._device = device; + this._width = width; + this._height = height; + + this._colors = options.colors || []; + this._depth = options.depth || null; + this._stencil = options.stencil || null; + this._depthStencil = options.depthStencil || null; + + this._glID = device._gl.createFramebuffer(); + } + + /** + * @method destroy + */ + destroy() { + if (this._glID === null) { + console.error('The frame-buffer already destroyed'); + return; + } + + const gl = this._device._gl; + + gl.deleteFramebuffer(this._glID); + + this._glID = null; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/gfx/index-buffer.js b/cocos2d/renderer/gfx/index-buffer.js new file mode 100644 index 00000000000..145b1931279 --- /dev/null +++ b/cocos2d/renderer/gfx/index-buffer.js @@ -0,0 +1,95 @@ +import { enums } from './enums'; + +class IndexBuffer { + /** + * @constructor + * @param {Device} device + * @param {INDEX_FMT_*} format + * @param {USAGE_*} usage + * @param {ArrayBuffer | Uint8Array} data + * @param {Number} numIndices + */ + constructor(device, format, usage, data, numIndices) { + this._device = device; + this._format = format; + this._usage = usage; + this._numIndices = numIndices; + this._bytesPerIndex = 0; + + // calculate bytes + if (format === enums.INDEX_FMT_UINT8) { + this._bytesPerIndex = 1; + } else if (format === enums.INDEX_FMT_UINT16) { + this._bytesPerIndex = 2; + } else if (format === enums.INDEX_FMT_UINT32) { + this._bytesPerIndex = 4; + } + this._bytes = this._bytesPerIndex * numIndices; + + // update + this._glID = device._gl.createBuffer(); + this.update(0, data); + + // stats + device._stats.ib += this._bytes; + } + + /** + * @method destroy + */ + destroy() { + if (this._glID === -1) { + console.error('The buffer already destroyed'); + return; + } + + let gl = this._device._gl; + gl.deleteBuffer(this._glID); + this._device._stats.ib -= this.bytes; + + this._glID = -1; + } + + /** + * @method update + * @param {Number} offset + * @param {ArrayBuffer} data + */ + update(offset, data) { + if (this._glID === -1) { + console.error('The buffer is destroyed'); + return; + } + + if (data && data.byteLength + offset > this._bytes) { + console.error('Failed to update data, bytes exceed.'); + return; + } + + /** @type{WebGLRenderingContext} */ + let gl = this._device._gl; + let glUsage = this._usage; + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._glID); + if (!data) { + if (this._bytes) { + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._bytes, glUsage); + } else { + console.warn('bufferData should not submit 0 bytes data'); + } + } else { + if (offset) { + gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, offset, data); + } else { + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, glUsage); + } + } + this._device._restoreIndexBuffer(); + } + + get count () { + return this._numIndices; + } +} + +export default IndexBuffer; diff --git a/cocos2d/renderer/gfx/index.js b/cocos2d/renderer/gfx/index.js new file mode 100644 index 00000000000..7687de67740 --- /dev/null +++ b/cocos2d/renderer/gfx/index.js @@ -0,0 +1,40 @@ +import { + enums, + attrTypeBytes, + glFilter, + glTextureFmt, +} from './enums'; + +import VertexFormat from './vertex-format'; +import IndexBuffer from './index-buffer'; +import VertexBuffer from './vertex-buffer'; +import Program from './program'; +import Texture from './texture'; +import Texture2D from './texture-2d'; +import TextureCube from './texture-cube'; +import RenderBuffer from './render-buffer'; +import FrameBuffer from './frame-buffer'; +import Device from './device'; + +let gfx = { + // classes + VertexFormat, + IndexBuffer, + VertexBuffer, + Program, + Texture, + Texture2D, + TextureCube, + RenderBuffer, + FrameBuffer, + Device, + + // functions + attrTypeBytes, + glFilter, + glTextureFmt, +}; +Object.assign(gfx, enums); + +export default gfx; +cc.gfx = gfx; diff --git a/cocos2d/renderer/gfx/misc.js b/cocos2d/renderer/gfx/misc.js new file mode 100644 index 00000000000..9825541ea85 --- /dev/null +++ b/cocos2d/renderer/gfx/misc.js @@ -0,0 +1,3 @@ +export function isPow2(v) { + return !(v & (v - 1)) && (!!v); +} \ No newline at end of file diff --git a/cocos2d/renderer/gfx/program.js b/cocos2d/renderer/gfx/program.js new file mode 100644 index 00000000000..6961b73372f --- /dev/null +++ b/cocos2d/renderer/gfx/program.js @@ -0,0 +1,176 @@ +let _genID = 0; + +function _parseError(out, type, errorLog) { + errorLog.split('\n').forEach(msg => { + if (msg.length < 5) { + return; + } + + let parts = /^ERROR:\s+(\d+):(\d+):\s*(.*)$/.exec(msg); + if (parts) { + out.push({ + type: type, + fileID: parts[1] | 0, + line: parts[2] | 0, + message: parts[3].trim() + }); + } else if (msg.length > 0) { + out.push({ + type: type, + fileID: -1, + line: 0, + message: msg + }); + } + }); +} + +export default class Program { + /** + * @param {ef.GraphicsDevice} device - graphic device + * @param {object} options - shader definition + * @param {string} options.vert - vertex shader source code + * @param {string} options.frag - fragment shader shader source code + * @example + * let prog = new Program(device, { + * vert: ` + * attribute vec3 a_position; + * void main() { + * gl_Position = vec4( a_position, 1.0 ); + * } + * `, + * frag: ` + * precision mediump float; + * void main() { + * gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 ); + * } + * ` + * }); + */ + constructor(device, options) { + this._device = device; + + // stores gl information: { location, type } + this._attributes = []; + this._uniforms = []; + this._samplers = []; + this._errors = []; + this._linked = false; + this._vertSource = options.vert; + this._fragSource = options.frag; + this._glID = null; + this._id = _genID++; + } + + get id() { + return this._id; + } + + link() { + if (this._linked) { + return; + } + + let gl = this._device._gl; + + let vertShader = _createShader(gl, gl.VERTEX_SHADER, this._vertSource); + let fragShader = _createShader(gl, gl.FRAGMENT_SHADER, this._fragSource); + + let program = gl.createProgram(); + gl.attachShader(program, vertShader); + gl.attachShader(program, fragShader); + gl.linkProgram(program); + + let failed = false; + let errors = this._errors; + + if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) { + _parseError(errors, 'vs', gl.getShaderInfoLog(vertShader)); + failed = true; + } + + if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)) { + _parseError(errors, 'fs', gl.getShaderInfoLog(fragShader)); + failed = true; + } + + gl.deleteShader(vertShader); + gl.deleteShader(fragShader); + + if (failed) { + errors.forEach(err => { + console.error(`Failed to compile ${err.type} ${err.fileID} (ln ${err.line}): ${err.message}`); + }); + return; + } + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + console.error(`Failed to link shader program: ${gl.getProgramInfoLog(program)}`); + failed = true; + } + + if (failed) { + return; + } + + this._glID = program; + + // parse attribute + let numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); + for (let i = 0; i < numAttributes; ++i) { + let info = gl.getActiveAttrib(program, i); + let location = gl.getAttribLocation(program, info.name); + + this._attributes.push({ + name: info.name, + location: location, + type: info.type, + }); + } + + // parse uniform + let numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); + for (let i = 0; i < numUniforms; ++i) { + let info = gl.getActiveUniform(program, i); + let name = info.name; + let location = gl.getUniformLocation(program, name); + let isArray = name.substr(name.length - 3) === '[0]'; + if (isArray) { + name = name.substr(0, name.length - 3); + } + + let uniform = { + name: name, + location: location, + type: info.type, + size: isArray ? info.size : undefined, // used when uniform is an array + }; + this._uniforms.push(uniform); + } + + this._linked = true; + } + + destroy() { + let gl = this._device._gl; + gl.deleteProgram(this._glID); + + this._linked = false; + this._glID = null; + this._attributes = []; + this._uniforms = []; + this._samplers = []; + } +} + +// ==================== +// internal +// ==================== + +function _createShader(gl, type, src) { + let shader = gl.createShader(type); + gl.shaderSource(shader, src); + gl.compileShader(shader); + + return shader; +} \ No newline at end of file diff --git a/cocos2d/renderer/gfx/render-buffer.js b/cocos2d/renderer/gfx/render-buffer.js new file mode 100644 index 00000000000..1e30ceb55ba --- /dev/null +++ b/cocos2d/renderer/gfx/render-buffer.js @@ -0,0 +1,43 @@ +export default class RenderBuffer { + /** + * @constructor + * @param {Device} device + * @param {RB_FMT_*} format + * @param {Number} width + * @param {Number} height + */ + constructor(device, format, width, height) { + this._device = device; + this._format = format; + + this._glID = device._gl.createRenderbuffer(); + this.update(width, height); + } + + update (width, height) { + this._width = width; + this._height = height; + + const gl = this._device._gl; + gl.bindRenderbuffer(gl.RENDERBUFFER, this._glID); + gl.renderbufferStorage(gl.RENDERBUFFER, this._format, width, height); + gl.bindRenderbuffer(gl.RENDERBUFFER, null); + } + + /** + * @method destroy + */ + destroy() { + if (this._glID === null) { + console.error('The render-buffer already destroyed'); + return; + } + + const gl = this._device._gl; + + gl.bindRenderbuffer(gl.RENDERBUFFER, null); + gl.deleteRenderbuffer(this._glID); + + this._glID = null; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/gfx/state.js b/cocos2d/renderer/gfx/state.js new file mode 100644 index 00000000000..747ed4a7b9b --- /dev/null +++ b/cocos2d/renderer/gfx/state.js @@ -0,0 +1,133 @@ +import { enums } from './enums'; + +const _default = { + // blend + blend: false, + blendSep: false, + blendColor: 0xffffffff, + blendEq: enums.BLEND_FUNC_ADD, + blendAlphaEq: enums.BLEND_FUNC_ADD, + blendSrc: enums.BLEND_ONE, + blendDst: enums.BLEND_ZERO, + blendSrcAlpha: enums.BLEND_ONE, + blendDstAlpha: enums.BLEND_ZERO, + + // depth + depthTest: false, + depthWrite: false, + depthFunc: enums.DS_FUNC_LESS, + + // stencil + stencilTest: false, + stencilSep: false, + stencilFuncFront: enums.DS_FUNC_ALWAYS, + stencilRefFront: 0, + stencilMaskFront: 0xff, + stencilFailOpFront: enums.STENCIL_OP_KEEP, + stencilZFailOpFront: enums.STENCIL_OP_KEEP, + stencilZPassOpFront: enums.STENCIL_OP_KEEP, + stencilWriteMaskFront: 0xff, + stencilFuncBack: enums.DS_FUNC_ALWAYS, + stencilRefBack: 0, + stencilMaskBack: 0xff, + stencilFailOpBack: enums.STENCIL_OP_KEEP, + stencilZFailOpBack: enums.STENCIL_OP_KEEP, + stencilZPassOpBack: enums.STENCIL_OP_KEEP, + stencilWriteMaskBack: 0xff, + + // cull-mode + cullMode: enums.CULL_BACK, + + // primitive-type + primitiveType: enums.PT_TRIANGLES, + + // bindings + maxStream: -1, + vertexBuffers: [], + vertexBufferOffsets: [], + indexBuffer: null, + maxTextureSlot: -1, + textureUnits: [], + program: null, +}; + +export default class State { + constructor(device) { + // bindings + this.vertexBuffers = new Array(device._caps.maxVertexStreams); + this.vertexBufferOffsets = new Array(device._caps.maxVertexStreams); + this.textureUnits = new Array(device._caps.maxTextureUnits); + + this.set(_default); + } + + static initDefault(device) { + _default.vertexBuffers = new Array(device._caps.maxVertexStreams); + _default.vertexBufferOffsets = new Array(device._caps.maxVertexStreams); + _default.textureUnits = new Array(device._caps.maxTextureUnits); + } + + reset () { + this.set(_default); + } + + set (cpy) { + // blending + this.blend = cpy.blend; + this.blendSep = cpy.blendSep; + this.blendColor = cpy.blendColor; + this.blendEq = cpy.blendEq; + this.blendAlphaEq = cpy.blendAlphaEq; + this.blendSrc = cpy.blendSrc; + this.blendDst = cpy.blendDst; + this.blendSrcAlpha = cpy.blendSrcAlpha; + this.blendDstAlpha = cpy.blendDstAlpha; + + // depth + this.depthTest = cpy.depthTest; + this.depthWrite = cpy.depthWrite; + this.depthFunc = cpy.depthFunc; + + // stencil + this.stencilTest = cpy.stencilTest; + this.stencilSep = cpy.stencilSep; + this.stencilFuncFront = cpy.stencilFuncFront; + this.stencilRefFront = cpy.stencilRefFront; + this.stencilMaskFront = cpy.stencilMaskFront; + this.stencilFailOpFront = cpy.stencilFailOpFront; + this.stencilZFailOpFront = cpy.stencilZFailOpFront; + this.stencilZPassOpFront = cpy.stencilZPassOpFront; + this.stencilWriteMaskFront = cpy.stencilWriteMaskFront; + this.stencilFuncBack = cpy.stencilFuncBack; + this.stencilRefBack = cpy.stencilRefBack; + this.stencilMaskBack = cpy.stencilMaskBack; + this.stencilFailOpBack = cpy.stencilFailOpBack; + this.stencilZFailOpBack = cpy.stencilZFailOpBack; + this.stencilZPassOpBack = cpy.stencilZPassOpBack; + this.stencilWriteMaskBack = cpy.stencilWriteMaskBack; + + // cull-mode + this.cullMode = cpy.cullMode; + + // primitive-type + this.primitiveType = cpy.primitiveType; + + // buffer bindings + this.maxStream = cpy.maxStream; + for (let i = 0; i < cpy.vertexBuffers.length; ++i) { + this.vertexBuffers[i] = cpy.vertexBuffers[i]; + } + for (let i = 0; i < cpy.vertexBufferOffsets.length; ++i) { + this.vertexBufferOffsets[i] = cpy.vertexBufferOffsets[i]; + } + this.indexBuffer = cpy.indexBuffer; + + // texture bindings + this.maxTextureSlot = cpy.maxTextureSlot; + for (let i = 0; i < cpy.textureUnits.length; ++i) { + this.textureUnits[i] = cpy.textureUnits[i]; + } + + this.program = cpy.program; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/gfx/texture-2d.js b/cocos2d/renderer/gfx/texture-2d.js new file mode 100644 index 00000000000..c2bad215f09 --- /dev/null +++ b/cocos2d/renderer/gfx/texture-2d.js @@ -0,0 +1,327 @@ +// @ts-check +import Texture from './texture'; +import { enums, glFilter, glTextureFmt } from './enums'; +import { isPow2 } from './misc'; + +const ArrayBufferView = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array)).constructor + +/** + * @typedef {HTMLImageElement | HTMLCanvasElement} HTMLImageSource + * @typedef {HTMLImageSource | ArrayBufferView} ImageSource + * @typedef {{width?: number, height?: number, minFilter?: number, magFilter?: number, mipFilter?: number, wrapS?: number, wrapT?: number, format?: number, mipmap?: boolean, images?: ImageSource[], image?: ImageSource, flipY?: boolean, premultiplyAlpha?: boolean, anisotropy?: number}} TextureUpdateOpts + * @typedef {import("../gfx/device").default} Device + */ + +export default class Texture2D extends Texture { + /** + * @constructor + * @param {Device} device + * @param {TextureUpdateOpts} options + */ + constructor(device, options) { + super(device); + + let gl = this._device._gl; + this._target = gl.TEXTURE_2D; + this._glID = gl.createTexture(); + + // always alloc texture in GPU when we create it. + options.images = options.images || [null]; + this.update(options); + } + + /** + * @method update + * @param {TextureUpdateOpts} options + */ + update(options) { + let gl = this._device._gl; + let genMipmap = this._hasMipmap; + + if (options) { + if (options.width !== undefined) { + this._width = options.width; + } + if (options.height !== undefined) { + this._height = options.height; + } + if (options.anisotropy !== undefined) { + this._anisotropy = options.anisotropy; + } + if (options.minFilter !== undefined) { + this._minFilter = options.minFilter; + } + if (options.magFilter !== undefined) { + this._magFilter = options.magFilter; + } + if (options.mipFilter !== undefined) { + this._mipFilter = options.mipFilter; + } + if (options.wrapS !== undefined) { + this._wrapS = options.wrapS; + } + if (options.wrapT !== undefined) { + this._wrapT = options.wrapT; + } + if (options.format !== undefined) { + this._format = options.format; + this._compressed = ( + this._format >= enums.TEXTURE_FMT_RGB_DXT1 && + this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1 + ); + } + + // check if generate mipmap + if (options.mipmap !== undefined) { + this._hasMipmap = options.mipmap; + genMipmap = options.mipmap; + } + + if (options.images !== undefined) { + if (options.images.length > 1) { + genMipmap = false; + let maxLength = options.width > options.height ? options.width : options.height; + if (maxLength >> (options.images.length - 1) !== 1) { + console.error('texture-2d mipmap is invalid, should have a 1x1 mipmap.'); + } + } + } + } + + // NOTE: get pot after this._width, this._height has been assigned. + let pot = isPow2(this._width) && isPow2(this._height); + if (!pot) { + genMipmap = false; + } + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this._glID); + if (options.images !== undefined && options.images.length > 0) { + this._setMipmap(options.images, options.flipY, options.premultiplyAlpha); + if (options.images.length > 1) this._hasMipmap = true; + } + if (genMipmap) { + gl.hint(gl.GENERATE_MIPMAP_HINT, gl.NICEST); + gl.generateMipmap(gl.TEXTURE_2D); + this._hasMipmap = true; + } + + this._setTexInfo(); + this._device._restoreTexture(0); + } + + /** + * @method updateSubImage + * @param {Object} options + * @param {Number} options.x + * @param {Number} options.y + * @param {Number} options.width + * @param {Number} options.height + * @param {Number} options.level + * @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image + * @param {Boolean} options.flipY + * @param {Boolean} options.premultiplyAlpha + */ + updateSubImage(options) { + let gl = this._device._gl; + let glFmt = glTextureFmt(this._format); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this._glID); + this._setSubImage(glFmt, options); + this._device._restoreTexture(0); + } + + /** + * @method updateImage + * @param {Object} options + * @param {Number} options.width + * @param {Number} options.height + * @param {Number} options.level + * @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image + * @param {Boolean} options.flipY + * @param {Boolean} options.premultiplyAlpha + */ + updateImage(options) { + let gl = this._device._gl; + let glFmt = glTextureFmt(this._format); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this._glID); + this._setImage(glFmt, options); + this._device._restoreTexture(0); + } + + _setSubImage(glFmt, options) { + let gl = this._device._gl; + let flipY = options.flipY; + let premultiplyAlpha = options.premultiplyAlpha; + let img = options.image; + + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (flipY === undefined) { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + } else { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + } + + if (premultiplyAlpha === undefined) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); + } + + gl.texSubImage2D(gl.TEXTURE_2D, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); + } else { + if (flipY === undefined) { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + } + + if (premultiplyAlpha === undefined) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); + } + + if (this._compressed) { + gl.compressedTexSubImage2D(gl.TEXTURE_2D, + options.level, + options.x, + options.y, + options.width, + options.height, + glFmt.format, + img + ); + } else { + gl.texSubImage2D( + gl.TEXTURE_2D, + options.level, + options.x, + options.y, + options.width, + options.height, + glFmt.format, + glFmt.pixelType, + img + ); + } + } + } + + _setImage(glFmt, options) { + let gl = this._device._gl; + let flipY = options.flipY; + let premultiplyAlpha = options.premultiplyAlpha; + let img = options.image; + + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + if (flipY === undefined) { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + } else { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + } + + if (premultiplyAlpha === undefined) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); + } + + gl.texImage2D( + gl.TEXTURE_2D, + options.level, + glFmt.internalFormat, + glFmt.format, + glFmt.pixelType, + img + ); + } else { + if (flipY === undefined) { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + } + + if (premultiplyAlpha === undefined) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); + } + + if (this._compressed) { + gl.compressedTexImage2D( + gl.TEXTURE_2D, + options.level, + glFmt.internalFormat, + options.width, + options.height, + 0, + img + ); + } else { + gl.texImage2D( + gl.TEXTURE_2D, + options.level, + glFmt.internalFormat, + options.width, + options.height, + 0, + glFmt.format, + glFmt.pixelType, + img + ); + } + } + } + + _setMipmap(images, flipY, premultiplyAlpha) { + let glFmt = glTextureFmt(this._format); + let options = { + width: this._width, + height: this._height, + flipY: flipY, + premultiplyAlpha: premultiplyAlpha, + level: 0, + image: null + }; + + for (let i = 0; i < images.length; ++i) { + options.level = i; + options.width = this._width >> i; + options.height = this._height >> i; + options.image = images[i]; + this._setImage(glFmt, options); + } + } + + _setTexInfo() { + let gl = this._device._gl; + let pot = isPow2(this._width) && isPow2(this._height); + + // WebGL1 doesn't support all wrap modes with NPOT textures + if (!pot && (this._wrapS !== enums.WRAP_CLAMP || this._wrapT !== enums.WRAP_CLAMP)) { + console.warn('WebGL1 doesn\'t support all wrap modes with NPOT textures'); + this._wrapS = enums.WRAP_CLAMP; + this._wrapT = enums.WRAP_CLAMP; + } + + let mipFilter = this._hasMipmap ? this._mipFilter : -1; + if (!pot && mipFilter !== -1) { + console.warn('NPOT textures do not support mipmap filter'); + mipFilter = -1; + } + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, glFilter(gl, this._minFilter, mipFilter)); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, glFilter(gl, this._magFilter, -1)); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._wrapS); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._wrapT); + + let ext = this._device.ext('EXT_texture_filter_anisotropic'); + if (ext) { + gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy); + } + } +} \ No newline at end of file diff --git a/cocos2d/renderer/gfx/texture-cube.js b/cocos2d/renderer/gfx/texture-cube.js new file mode 100644 index 00000000000..0c019236d08 --- /dev/null +++ b/cocos2d/renderer/gfx/texture-cube.js @@ -0,0 +1,338 @@ +import Texture from './texture'; +import { enums, glFilter, glTextureFmt } from './enums'; +import { isPow2 } from './misc'; + +export default class TextureCube extends Texture { + /** + * @constructor + * @param {Device} device + * @param {Object} options + * @param {Array} options.images + * @param {Boolean} options.mipmap + * @param {Number} options.width + * @param {Number} options.height + * @param {TEXTURE_FMT_*} options.format + * @param {Number} options.anisotropy + * @param {FILTER_*} options.minFilter + * @param {FILTER_*} options.magFilter + * @param {FILTER_*} options.mipFilter + * @param {WRAP_*} options.wrapS + * @param {WRAP_*} options.wrapT + * @param {WRAP_*} options.wrapR + * @param {Boolean} options.flipY + * @param {Boolean} options.premultiplyAlpha + */ + constructor(device, options) { + super(device); + let gl = this._device._gl; + this._target = gl.TEXTURE_CUBE_MAP; + this._glID = gl.createTexture(); + this.update(options); + } + + /** + * @method update + * @param {Object} options + * @param {Array} options.images + * @param {Boolean} options.mipmap + * @param {Number} options.width + * @param {Number} options.height + * @param {TEXTURE_FMT_*} options.format + * @param {Number} options.anisotropy + * @param {FILTER_*} options.minFilter + * @param {FILTER_*} options.magFilter + * @param {FILTER_*} options.mipFilter + * @param {WRAP_*} options.wrapS + * @param {WRAP_*} options.wrapT + * @param {WRAP_*} options.wrapR + * @param {Boolean} options.flipY + * @param {Boolean} options.premultiplyAlpha + */ + update(options) { + let gl = this._device._gl; + let genMipmap = this._hasMipmap; + + if (options) { + if (options.width !== undefined) { + this._width = options.width; + } + if (options.height !== undefined) { + this._height = options.height; + } + if (options.anisotropy !== undefined) { + this._anisotropy = options.anisotropy; + } + if (options.minFilter !== undefined) { + this._minFilter = options.minFilter; + } + if (options.magFilter !== undefined) { + this._magFilter = options.magFilter; + } + if (options.mipFilter !== undefined) { + this._mipFilter = options.mipFilter; + } + if (options.wrapS !== undefined) { + this._wrapS = options.wrapS; + } + if (options.wrapT !== undefined) { + this._wrapT = options.wrapT; + } + // wrapR available in webgl2 + // if (options.wrapR !== undefined) { + // this._wrapR = options.wrapR; + // } + if (options.format !== undefined) { + this._format = options.format; + this._compressed = ( + this._format >= enums.TEXTURE_FMT_RGB_DXT1 && + this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1 + ); + } + + // check if generate mipmap + if (options.mipmap !== undefined) { + this._hasMipmap = options.mipmap; + genMipmap = options.mipmap; + } + + if (options.images !== undefined) { + if (options.images.length > 1) { + genMipmap = false; + if (options.width !== options.height) { + console.warn('texture-cube width and height should be identical.'); + } + if (options.width >> (options.images.length - 1) !== 1) { + console.error('texture-cube mipmap is invalid. please set mipmap as 1x1, 2x2, 4x4 ... nxn'); + } + } + } + } + + // NOTE: get pot after this._width, this._height has been assigned. + let pot = isPow2(this._width) && isPow2(this._height); + if (!pot) { + genMipmap = false; + } + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID); + if (options.images !== undefined && options.images.length > 0) { + this._setMipmap(options.images, options.flipY, options.premultiplyAlpha); + if (options.images.length > 1) this._hasMipmap = true; + } + if (genMipmap) { + gl.hint(gl.GENERATE_MIPMAP_HINT, gl.NICEST); + gl.generateMipmap(gl.TEXTURE_CUBE_MAP); + this._hasMipmap = true; + } + + this._setTexInfo(); + + this._device._restoreTexture(0); + } + + /** + * @method updateSubImage + * @param {Object} options + * @param {Number} options.x + * @param {Number} options.y + * @param {Number} options.width + * @param {Number} options.height + * @param {Number} options.level + * @param {Number} options.faceIndex + * @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image + * @param {Boolean} options.flipY + * @param {Boolean} options.premultiplyAlpha + */ + updateSubImage(options) { + let gl = this._device._gl; + let glFmt = glTextureFmt(this._format); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID); + this._setSubImage(glFmt, options); + + this._device._restoreTexture(0); + } + + /** + * @method updateImage + * @param {Object} options + * @param {Number} options.width + * @param {Number} options.height + * @param {Number} options.level + * @param {Number} options.faceIndex + * @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image + * @param {Boolean} options.flipY + * @param {Boolean} options.premultiplyAlpha + */ + updateImage(options) { + let gl = this._device._gl; + let glFmt = glTextureFmt(this._format); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID); + this._setImage(glFmt, options); + this._device._restoreTexture(0); + } + + _setSubImage(glFmt, options) { + let gl = this._device._gl; + let flipY = options.flipY; + let premultiplyAlpha = options.premultiplyAlpha; + let faceIndex = options.faceIndex; + let img = options.image; + + if (flipY === undefined) { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + } + + if (premultiplyAlpha === undefined) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); + } + + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img); + } else { + if (this._compressed) { + gl.compressedTexSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, + options.level, + options.x, + options.y, + options.width, + options.height, + glFmt.format, + img + ); + } else { + gl.texSubImage2D( + gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, + options.level, + options.x, + options.y, + options.width, + options.height, + glFmt.format, + glFmt.pixelType, + img + ); + } + } + } + + _setImage(glFmt, options) { + let gl = this._device._gl; + let flipY = options.flipY; + let premultiplyAlpha = options.premultiplyAlpha; + let faceIndex = options.faceIndex; + let img = options.image; + + if (flipY === undefined) { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + } + + if (premultiplyAlpha === undefined) { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + } else { + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); + } + if (img && !ArrayBuffer.isView(img) && !(img instanceof ArrayBuffer)) { + gl.texImage2D( + gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, + options.level, + glFmt.internalFormat, + glFmt.format, + glFmt.pixelType, + img + ); + } else { + if (this._compressed) { + gl.compressedTexImage2D( + gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, + options.level, + glFmt.internalFormat, + options.width, + options.height, + 0, + img + ); + } else { + gl.texImage2D( + gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, + options.level, + glFmt.internalFormat, + options.width, + options.height, + 0, + glFmt.format, + glFmt.pixelType, + img + ); + } + } + } + + // levelImages = [imagePosX, imageNegX, imagePosY, imageNegY, imagePosZ, imageNegz] + // images = [levelImages0, levelImages1, ...] + _setMipmap(images, flipY, premultiplyAlpha) { + let glFmt = glTextureFmt(this._format); + let options = { + width: this._width, + height: this._height, + faceIndex: 0, + flipY: flipY, + premultiplyAlpha: premultiplyAlpha, + level: 0, + image: null + }; + + for (let i = 0; i < images.length; ++i) { + let levelImages = images[i]; + options.level = i; + options.width = this._width >> i; + options.height = this._height >> i; + + for (let face = 0; face < 6; ++face) { + options.faceIndex = face; + options.image = levelImages[face]; + this._setImage(glFmt, options); + } + } + } + + _setTexInfo() { + let gl = this._device._gl; + let pot = isPow2(this._width) && isPow2(this._height); + + // WebGL1 doesn't support all wrap modes with NPOT textures + if (!pot && (this._wrapS !== enums.WRAP_CLAMP || this._wrapT !== enums.WRAP_CLAMP)) { + console.warn('WebGL1 doesn\'t support all wrap modes with NPOT textures'); + this._wrapS = enums.WRAP_CLAMP; + this._wrapT = enums.WRAP_CLAMP; + } + + let mipFilter = this._hasMipmap ? this._mipFilter : -1; + if (!pot && mipFilter !== -1) { + console.warn('NPOT textures do not support mipmap filter'); + mipFilter = -1; + } + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, glFilter(gl, this._minFilter, mipFilter)); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, glFilter(gl, this._magFilter, -1)); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, this._wrapS); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, this._wrapT); + // wrapR available in webgl2 + // gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, this._wrapR); + + let ext = this._device.ext('EXT_texture_filter_anisotropic'); + if (ext) { + gl.texParameteri(gl.TEXTURE_CUBE_MAP, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy); + } + } +} diff --git a/cocos2d/renderer/gfx/texture.js b/cocos2d/renderer/gfx/texture.js new file mode 100644 index 00000000000..428f1193db4 --- /dev/null +++ b/cocos2d/renderer/gfx/texture.js @@ -0,0 +1,56 @@ +import { enums } from './enums'; + +/** + * @type {WebGLTexture} + */ +const _nullWebGLTexture = null; + +let _textureID = 0; + +/** + * @typedef {import("../gfx/device").default} Device + */ + +export default class Texture { + /** + * @param {Device} device + */ + constructor(device) { + this._device = device; + + this._width = 4; + this._height = 4; + this._hasMipmap = false; + this._compressed = false; + + this._anisotropy = 1; + this._minFilter = enums.FILTER_LINEAR; + this._magFilter = enums.FILTER_LINEAR; + this._mipFilter = enums.FILTER_LINEAR; + this._wrapS = enums.WRAP_REPEAT; + this._wrapT = enums.WRAP_REPEAT; + // wrapR available in webgl2 + // this._wrapR = enums.WRAP_REPEAT; + this._format = enums.TEXTURE_FMT_RGBA8; + + this._target = -1; + + this._id = _textureID++; + } + + /** + * @method destroy + */ + destroy() { + if (this._glID === _nullWebGLTexture) { + console.error('The texture already destroyed'); + return; + } + + let gl = this._device._gl; + gl.deleteTexture(this._glID); + + this._device._stats.tex -= this.bytes; + this._glID = _nullWebGLTexture; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/gfx/vertex-buffer.js b/cocos2d/renderer/gfx/vertex-buffer.js new file mode 100644 index 00000000000..5b50e87cbe6 --- /dev/null +++ b/cocos2d/renderer/gfx/vertex-buffer.js @@ -0,0 +1,86 @@ +import { enums } from './enums'; + +class VertexBuffer { + /** + * @constructor + * @param {Device} device + * @param {VertexFormat} format + * @param {USAGE_*} usage + * @param {ArrayBuffer | Uint8Array} data + * @param {Number} numVertices + */ + constructor(device, format, usage, data, numVertices) { + this._device = device; + this._format = format; + this._usage = usage; + this._numVertices = numVertices; + + // calculate bytes + this._bytes = this._format._bytes * numVertices; + + // update + this._glID = device._gl.createBuffer(); + this.update(0, data); + + // stats + device._stats.vb += this._bytes; + } + + /** + * @method destroy + */ + destroy() { + if (this._glID === -1) { + console.error('The buffer already destroyed'); + return; + } + + let gl = this._device._gl; + gl.deleteBuffer(this._glID); + this._device._stats.vb -= this.bytes; + + this._glID = -1; + } + + /** + * @method update + * @param {Number} offset + * @param {ArrayBuffer} data + */ + update(offset, data) { + if (this._glID === -1) { + console.error('The buffer is destroyed'); + return; + } + + if (data && data.byteLength + offset > this._bytes) { + console.error('Failed to update data, bytes exceed.'); + return; + } + + let gl = this._device._gl; + let glUsage = this._usage; + + gl.bindBuffer(gl.ARRAY_BUFFER, this._glID); + if (!data) { + if (this._bytes) { + gl.bufferData(gl.ARRAY_BUFFER, this._bytes, glUsage); + } else { + console.warn('bufferData should not submit 0 bytes data'); + } + } else { + if (offset) { + gl.bufferSubData(gl.ARRAY_BUFFER, offset, data); + } else { + gl.bufferData(gl.ARRAY_BUFFER, data, glUsage); + } + } + gl.bindBuffer(gl.ARRAY_BUFFER, null); + } + + get count () { + return this._numVertices; + } +} + +export default VertexBuffer; diff --git a/cocos2d/renderer/gfx/vertex-format.js b/cocos2d/renderer/gfx/vertex-format.js new file mode 100644 index 00000000000..8f3fc4981a8 --- /dev/null +++ b/cocos2d/renderer/gfx/vertex-format.js @@ -0,0 +1,56 @@ +import { attrTypeBytes } from './enums'; + +// ==================== +// exports +// ==================== + +export default class VertexFormat { + /** + * @constructor + * @param {Array} infos + * + * @example + * let vertexFmt = new VertexFormat([ + * { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 3 }, + * { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, + * { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_FLOAT32, num: 4, normalize: true }, + * ]) + */ + constructor(infos) { + this._attr2el = {}; + this._elements = []; + this._bytes = 0; + + for (let i = 0, len = infos.length; i < len; ++i) { + let info = infos[i]; + let el = { + name: info.name, + offset: this._bytes, + stride: 0, + stream: -1, + type: info.type, + num: info.num, + normalize: (info.normalize === undefined) ? false : info.normalize, + bytes: info.num * attrTypeBytes(info.type), + }; + + this._attr2el[el.name] = el; + this._elements.push(el); + + this._bytes += el.bytes; + } + + for (let i = 0, len = this._elements.length; i < len; ++i) { + let el = this._elements[i]; + el.stride = this._bytes; + } + } + + /** + * @method element + * @param {string} attrName + */ + element(attrName) { + return this._attr2el[attrName]; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/mappings/enums.js b/cocos2d/renderer/mappings/enums.js deleted file mode 100644 index 62f638b02a6..00000000000 --- a/cocos2d/renderer/mappings/enums.js +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -export default { - // projection - PROJ_PERSPECTIVE: 0, - PROJ_ORTHO: 1, - - // lights - LIGHT_DIRECTIONAL: 0, - LIGHT_POINT: 1, - LIGHT_SPOT: 2, - - // shadows - SHADOW_NONE: 0, - SHADOW_HARD: 1, - SHADOW_SOFT: 2, - - // parameter type - PARAM_INT: 0, - PARAM_INT2: 1, - PARAM_INT3: 2, - PARAM_INT4: 3, - PARAM_FLOAT: 4, - PARAM_FLOAT2: 5, - PARAM_FLOAT3: 6, - PARAM_FLOAT4: 7, - PARAM_COLOR3: 8, - PARAM_COLOR4: 9, - PARAM_MAT2: 10, - PARAM_MAT3: 11, - PARAM_MAT4: 12, - PARAM_TEXTURE_2D: 13, - PARAM_TEXTURE_CUBE: 14, - - // clear flags - CLEAR_COLOR: 1, - CLEAR_DEPTH: 2, - CLEAR_STENCIL: 4, - CLEAR_SKYBOX: 8, - - // - BUFFER_VIEW_INT8: 0, - BUFFER_VIEW_UINT8: 1, - BUFFER_VIEW_INT16: 2, - BUFFER_VIEW_UINT16: 3, - BUFFER_VIEW_INT32: 4, - BUFFER_VIEW_UINT32: 5, - BUFFER_VIEW_FLOAT32: 6, - }; - \ No newline at end of file diff --git a/cocos2d/renderer/mappings/index.js.map b/cocos2d/renderer/mappings/index.js.map deleted file mode 100644 index 14ed6d899e3..00000000000 --- a/cocos2d/renderer/mappings/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sources":["gfx/enums.js","enums.js","offline-mappings.js"],"sourcesContent":["const GL_NEAREST = 9728; // gl.NEAREST\nconst GL_LINEAR = 9729; // gl.LINEAR\nconst GL_NEAREST_MIPMAP_NEAREST = 9984; // gl.NEAREST_MIPMAP_NEAREST\nconst GL_LINEAR_MIPMAP_NEAREST = 9985; // gl.LINEAR_MIPMAP_NEAREST\nconst GL_NEAREST_MIPMAP_LINEAR = 9986; // gl.NEAREST_MIPMAP_LINEAR\nconst GL_LINEAR_MIPMAP_LINEAR = 9987; // gl.LINEAR_MIPMAP_LINEAR\n\n// const GL_BYTE = 5120; // gl.BYTE\nconst GL_UNSIGNED_BYTE = 5121; // gl.UNSIGNED_BYTE\n// const GL_SHORT = 5122; // gl.SHORT\nconst GL_UNSIGNED_SHORT = 5123; // gl.UNSIGNED_SHORT\nconst GL_UNSIGNED_INT = 5125; // gl.UNSIGNED_INT\nconst GL_FLOAT = 5126; // gl.FLOAT\nconst GL_UNSIGNED_SHORT_5_6_5 = 33635; // gl.UNSIGNED_SHORT_5_6_5\nconst GL_UNSIGNED_SHORT_4_4_4_4 = 32819; // gl.UNSIGNED_SHORT_4_4_4_4\nconst GL_UNSIGNED_SHORT_5_5_5_1 = 32820; // gl.UNSIGNED_SHORT_5_5_5_1\nconst GL_HALF_FLOAT_OES = 36193; // gl.HALF_FLOAT_OES\n\nconst GL_DEPTH_COMPONENT = 6402; // gl.DEPTH_COMPONENT\n\nconst GL_ALPHA = 6406; // gl.ALPHA\nconst GL_RGB = 6407; // gl.RGB\nconst GL_RGBA = 6408; // gl.RGBA\nconst GL_LUMINANCE = 6409; // gl.LUMINANCE\nconst GL_LUMINANCE_ALPHA = 6410; // gl.LUMINANCE_ALPHA\n\nconst GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; // ext.COMPRESSED_RGB_S3TC_DXT1_EXT\nconst GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; // ext.COMPRESSED_RGBA_S3TC_DXT1_EXT\nconst GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; // ext.COMPRESSED_RGBA_S3TC_DXT3_EXT\nconst GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; // ext.COMPRESSED_RGBA_S3TC_DXT5_EXT\n\nconst GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; // ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG\nconst GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; // ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG\nconst GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; // ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG\nconst GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; // ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG\n\nconst GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; // ext.COMPRESSED_RGB_ETC1_WEBGL\n\nconst _filterGL = [\n [ GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR ],\n [ GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR ],\n];\n\nconst _textureFmtGL = [\n // TEXTURE_FMT_RGB_DXT1: 0\n { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixelType: null },\n\n // TEXTURE_FMT_RGBA_DXT1: 1\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixelType: null },\n\n // TEXTURE_FMT_RGBA_DXT3: 2\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, pixelType: null },\n\n // TEXTURE_FMT_RGBA_DXT5: 3\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, pixelType: null },\n\n // TEXTURE_FMT_RGB_ETC1: 4\n { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_ETC1_WEBGL, pixelType: null },\n\n // TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5\n { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, pixelType: null },\n\n // TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, pixelType: null },\n\n // TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7\n { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, pixelType: null },\n\n // TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8\n { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, pixelType: null },\n\n // TEXTURE_FMT_A8: 9\n { format: GL_ALPHA, internalFormat: GL_ALPHA, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_L8: 10\n { format: GL_LUMINANCE, internalFormat: GL_LUMINANCE, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_L8_A8: 11\n { format: GL_LUMINANCE_ALPHA, internalFormat: GL_LUMINANCE_ALPHA, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_R5_G6_B5: 12\n { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_SHORT_5_6_5 },\n\n // TEXTURE_FMT_R5_G5_B5_A1: 13\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_5_5_5_1 },\n\n // TEXTURE_FMT_R4_G4_B4_A4: 14\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_4_4_4_4 },\n\n // TEXTURE_FMT_RGB8: 15\n { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_RGBA8: 16\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_BYTE },\n\n // TEXTURE_FMT_RGB16F: 17\n { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_HALF_FLOAT_OES },\n\n // TEXTURE_FMT_RGBA16F: 18\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_HALF_FLOAT_OES },\n\n // TEXTURE_FMT_RGB32F: 19\n { format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_FLOAT },\n\n // TEXTURE_FMT_RGBA32F: 20\n { format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_FLOAT },\n\n // TEXTURE_FMT_R32F: 21\n { format: null, internalFormat: null, pixelType: null },\n\n // TEXTURE_FMT_111110F: 22\n { format: null, internalFormat: null, pixelType: null },\n\n // TEXTURE_FMT_SRGB: 23\n { format: null, internalFormat: null, pixelType: null },\n\n // TEXTURE_FMT_SRGBA: 24\n { format: null, internalFormat: null, pixelType: null },\n\n // TEXTURE_FMT_D16: 25\n { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_SHORT },\n\n // TEXTURE_FMT_D32: 26\n { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_INT },\n\n // TEXTURE_FMT_D24S8: 27\n { format: null, internalFormat: null, pixelType: null },\n];\n\n/**\n * enums\n */\nexport const enums = {\n // buffer usage\n USAGE_STATIC: 35044, // gl.STATIC_DRAW\n USAGE_DYNAMIC: 35048, // gl.DYNAMIC_DRAW\n USAGE_STREAM: 35040, // gl.STREAM_DRAW\n\n // index buffer format\n INDEX_FMT_UINT8: 5121, // gl.UNSIGNED_BYTE\n INDEX_FMT_UINT16: 5123, // gl.UNSIGNED_SHORT\n INDEX_FMT_UINT32: 5125, // gl.UNSIGNED_INT (OES_element_index_uint)\n\n // vertex attribute semantic\n ATTR_POSITION: 'a_position',\n ATTR_NORMAL: 'a_normal',\n ATTR_TANGENT: 'a_tangent',\n ATTR_BITANGENT: 'a_bitangent',\n ATTR_WEIGHTS: 'a_weights',\n ATTR_JOINTS: 'a_joints',\n ATTR_COLOR: 'a_color',\n ATTR_COLOR0: 'a_color0',\n ATTR_COLOR1: 'a_color1',\n ATTR_UV: 'a_uv',\n ATTR_UV0: 'a_uv0',\n ATTR_UV1: 'a_uv1',\n ATTR_UV2: 'a_uv2',\n ATTR_UV3: 'a_uv3',\n ATTR_UV4: 'a_uv4',\n ATTR_UV5: 'a_uv5',\n ATTR_UV6: 'a_uv6',\n ATTR_UV7: 'a_uv7',\n\n // vertex attribute type\n ATTR_TYPE_INT8: 5120, // gl.BYTE\n ATTR_TYPE_UINT8: 5121, // gl.UNSIGNED_BYTE\n ATTR_TYPE_INT16: 5122, // gl.SHORT\n ATTR_TYPE_UINT16: 5123, // gl.UNSIGNED_SHORT\n ATTR_TYPE_INT32: 5124, // gl.INT\n ATTR_TYPE_UINT32: 5125, // gl.UNSIGNED_INT\n ATTR_TYPE_FLOAT32: 5126, // gl.FLOAT\n\n // texture filter\n FILTER_NEAREST: 0,\n FILTER_LINEAR: 1,\n\n // texture wrap mode\n WRAP_REPEAT: 10497, // gl.REPEAT\n WRAP_CLAMP: 33071, // gl.CLAMP_TO_EDGE\n WRAP_MIRROR: 33648, // gl.MIRRORED_REPEAT\n\n // texture format\n // compress formats\n TEXTURE_FMT_RGB_DXT1: 0,\n TEXTURE_FMT_RGBA_DXT1: 1,\n TEXTURE_FMT_RGBA_DXT3: 2,\n TEXTURE_FMT_RGBA_DXT5: 3,\n TEXTURE_FMT_RGB_ETC1: 4,\n TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5,\n TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6,\n TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7,\n TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8,\n\n // normal formats\n TEXTURE_FMT_A8: 9,\n TEXTURE_FMT_L8: 10,\n TEXTURE_FMT_L8_A8: 11,\n TEXTURE_FMT_R5_G6_B5: 12,\n TEXTURE_FMT_R5_G5_B5_A1: 13,\n TEXTURE_FMT_R4_G4_B4_A4: 14,\n TEXTURE_FMT_RGB8: 15,\n TEXTURE_FMT_RGBA8: 16,\n TEXTURE_FMT_RGB16F: 17,\n TEXTURE_FMT_RGBA16F: 18,\n TEXTURE_FMT_RGB32F: 19,\n TEXTURE_FMT_RGBA32F: 20,\n TEXTURE_FMT_R32F: 21,\n TEXTURE_FMT_111110F: 22,\n TEXTURE_FMT_SRGB: 23,\n TEXTURE_FMT_SRGBA: 24,\n\n // depth formats\n TEXTURE_FMT_D16: 25,\n TEXTURE_FMT_D32: 26,\n TEXTURE_FMT_D24S8: 27,\n\n // depth and stencil function\n DS_FUNC_NEVER: 512, // gl.NEVER\n DS_FUNC_LESS: 513, // gl.LESS\n DS_FUNC_EQUAL: 514, // gl.EQUAL\n DS_FUNC_LEQUAL: 515, // gl.LEQUAL\n DS_FUNC_GREATER: 516, // gl.GREATER\n DS_FUNC_NOTEQUAL: 517, // gl.NOTEQUAL\n DS_FUNC_GEQUAL: 518, // gl.GEQUAL\n DS_FUNC_ALWAYS: 519, // gl.ALWAYS\n\n // render-buffer format\n RB_FMT_RGBA4: 32854, // gl.RGBA4\n RB_FMT_RGB5_A1: 32855, // gl.RGB5_A1\n RB_FMT_RGB565: 36194, // gl.RGB565\n RB_FMT_D16: 33189, // gl.DEPTH_COMPONENT16\n RB_FMT_S8: 36168, // gl.STENCIL_INDEX8\n RB_FMT_D24S8: 34041, // gl.DEPTH_STENCIL\n\n // blend-equation\n BLEND_FUNC_ADD: 32774, // gl.FUNC_ADD\n BLEND_FUNC_SUBTRACT: 32778, // gl.FUNC_SUBTRACT\n BLEND_FUNC_REVERSE_SUBTRACT: 32779, // gl.FUNC_REVERSE_SUBTRACT\n\n // blend\n BLEND_ZERO: 0, // gl.ZERO\n BLEND_ONE: 1, // gl.ONE\n BLEND_SRC_COLOR: 768, // gl.SRC_COLOR\n BLEND_ONE_MINUS_SRC_COLOR: 769, // gl.ONE_MINUS_SRC_COLOR\n BLEND_DST_COLOR: 774, // gl.DST_COLOR\n BLEND_ONE_MINUS_DST_COLOR: 775, // gl.ONE_MINUS_DST_COLOR\n BLEND_SRC_ALPHA: 770, // gl.SRC_ALPHA\n BLEND_ONE_MINUS_SRC_ALPHA: 771, // gl.ONE_MINUS_SRC_ALPHA\n BLEND_DST_ALPHA: 772, // gl.DST_ALPHA\n BLEND_ONE_MINUS_DST_ALPHA: 773, // gl.ONE_MINUS_DST_ALPHA\n BLEND_CONSTANT_COLOR: 32769, // gl.CONSTANT_COLOR\n BLEND_ONE_MINUS_CONSTANT_COLOR: 32770, // gl.ONE_MINUS_CONSTANT_COLOR\n BLEND_CONSTANT_ALPHA: 32771, // gl.CONSTANT_ALPHA\n BLEND_ONE_MINUS_CONSTANT_ALPHA: 32772, // gl.ONE_MINUS_CONSTANT_ALPHA\n BLEND_SRC_ALPHA_SATURATE: 776, // gl.SRC_ALPHA_SATURATE\n\n // stencil operation\n STENCIL_OP_KEEP: 7680, // gl.KEEP\n STENCIL_OP_ZERO: 0, // gl.ZERO\n STENCIL_OP_REPLACE: 7681, // gl.REPLACE\n STENCIL_OP_INCR: 7682, // gl.INCR\n STENCIL_OP_INCR_WRAP: 34055, // gl.INCR_WRAP\n STENCIL_OP_DECR: 7683, // gl.DECR\n STENCIL_OP_DECR_WRAP: 34056, // gl.DECR_WRAP\n STENCIL_OP_INVERT: 5386, // gl.INVERT\n\n // cull\n CULL_NONE: 0,\n CULL_FRONT: 1028,\n CULL_BACK: 1029,\n CULL_FRONT_AND_BACK: 1032,\n\n // primitive type\n PT_POINTS: 0, // gl.POINTS\n PT_LINES: 1, // gl.LINES\n PT_LINE_LOOP: 2, // gl.LINE_LOOP\n PT_LINE_STRIP: 3, // gl.LINE_STRIP\n PT_TRIANGLES: 4, // gl.TRIANGLES\n PT_TRIANGLE_STRIP: 5, // gl.TRIANGLE_STRIP\n PT_TRIANGLE_FAN: 6, // gl.TRIANGLE_FAN\n};\n\n/**\n * @method attrTypeBytes\n * @param {ATTR_TYPE_*} attrType\n */\nexport function attrTypeBytes(attrType) {\n if (attrType === enums.ATTR_TYPE_INT8) {\n return 1;\n } else if (attrType === enums.ATTR_TYPE_UINT8) {\n return 1;\n } else if (attrType === enums.ATTR_TYPE_INT16) {\n return 2;\n } else if (attrType === enums.ATTR_TYPE_UINT16) {\n return 2;\n } else if (attrType === enums.ATTR_TYPE_INT32) {\n return 4;\n } else if (attrType === enums.ATTR_TYPE_UINT32) {\n return 4;\n } else if (attrType === enums.ATTR_TYPE_FLOAT32) {\n return 4;\n }\n\n console.warn(`Unknown ATTR_TYPE: ${attrType}`);\n return 0;\n}\n\n/**\n * @method glFilter\n * @param {WebGLContext} gl\n * @param {FILTER_*} filter\n * @param {FILTER_*} mipFilter\n */\nexport function glFilter(gl, filter, mipFilter = -1) {\n let result = _filterGL[filter][mipFilter+1];\n if (result === undefined) {\n console.warn(`Unknown FILTER: ${filter}`);\n return mipFilter === -1 ? gl.LINEAR : gl.LINEAR_MIPMAP_LINEAR;\n }\n\n return result;\n}\n\n/**\n * @method glTextureFmt\n * @param {TEXTURE_FMT_*} fmt\n */\nexport function glTextureFmt(fmt) {\n let result = _textureFmtGL[fmt];\n if (result === undefined) {\n console.warn(`Unknown TEXTURE_FMT: ${fmt}`);\n return _textureFmtGL[enums.TEXTURE_FMT_RGBA8];\n }\n\n return result;\n}","// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.\n\nexport default {\n // projection\n PROJ_PERSPECTIVE: 0,\n PROJ_ORTHO: 1,\n \n // lights\n LIGHT_DIRECTIONAL: 0,\n LIGHT_POINT: 1,\n LIGHT_SPOT: 2,\n \n // shadows\n SHADOW_NONE: 0,\n SHADOW_HARD: 1,\n SHADOW_SOFT: 2,\n \n // parameter type\n PARAM_INT: 0,\n PARAM_INT2: 1,\n PARAM_INT3: 2,\n PARAM_INT4: 3,\n PARAM_FLOAT: 4,\n PARAM_FLOAT2: 5,\n PARAM_FLOAT3: 6,\n PARAM_FLOAT4: 7,\n PARAM_COLOR3: 8,\n PARAM_COLOR4: 9,\n PARAM_MAT2: 10,\n PARAM_MAT3: 11,\n PARAM_MAT4: 12,\n PARAM_TEXTURE_2D: 13,\n PARAM_TEXTURE_CUBE: 14,\n \n // clear flags\n CLEAR_COLOR: 1,\n CLEAR_DEPTH: 2,\n CLEAR_STENCIL: 4,\n CLEAR_SKYBOX: 8,\n \n //\n BUFFER_VIEW_INT8: 0,\n BUFFER_VIEW_UINT8: 1,\n BUFFER_VIEW_INT16: 2,\n BUFFER_VIEW_UINT16: 3,\n BUFFER_VIEW_INT32: 4,\n BUFFER_VIEW_UINT32: 5,\n BUFFER_VIEW_FLOAT32: 6,\n };\n ","// this file is used for offline effect building.\n\nimport { enums } from './gfx/enums';\nimport rendererEnums from './enums';\n\nconst typeParams = {\n INT: rendererEnums.PARAM_INT,\n IVEC2: rendererEnums.PARAM_INT2,\n IVEC3: rendererEnums.PARAM_INT3,\n IVEC4: rendererEnums.PARAM_INT4,\n FLOAT: rendererEnums.PARAM_FLOAT,\n VEC2: rendererEnums.PARAM_FLOAT2,\n VEC3: rendererEnums.PARAM_FLOAT3,\n VEC4: rendererEnums.PARAM_FLOAT4,\n COLOR3: rendererEnums.PARAM_COLOR3,\n COLOR4: rendererEnums.PARAM_COLOR4,\n MAT2: rendererEnums.PARAM_MAT2,\n MAT3: rendererEnums.PARAM_MAT3,\n MAT4: rendererEnums.PARAM_MAT4,\n SAMPLER2D: rendererEnums.PARAM_TEXTURE_2D,\n SAMPLERCUBE: rendererEnums.PARAM_TEXTURE_CUBE,\n [rendererEnums.PARAM_FLOAT3]: rendererEnums.PARAM_COLOR3,\n [rendererEnums.PARAM_FLOAT4]: rendererEnums.PARAM_COLOR4\n};\n\nconst passParams = {\n BACK: enums.CULL_BACK,\n FRONT: enums.CULL_FRONT,\n NONE: enums.CULL_NONE,\n\n ADD: enums.BLEND_FUNC_ADD,\n SUBTRACT: enums.BLEND_FUNC_SUBTRACT,\n REVERSESUBTRACT: enums.BLEND_FUNC_REVERSE_SUBTRACT,\n ZERO: enums.BLEND_ZERO,\n ONE: enums.BLEND_ONE,\n SRCCOLOR: enums.BLEND_SRC_COLOR,\n ONEMINUSSRCCOLOR: enums.BLEND_ONE_MINUS_SRC_COLOR,\n DSTCOLOR: enums.BLEND_DST_COLOR,\n ONEMINUSDSTCOLOR: enums.BLEND_ONE_MINUS_DST_COLOR,\n SRCALPHA: enums.BLEND_SRC_ALPHA,\n ONEMINUSSRCALPHA: enums.BLEND_ONE_MINUS_SRC_ALPHA,\n DSTALPHA: enums.BLEND_DST_ALPHA,\n ONEMINUSDSTALPHA: enums.BLEND_ONE_MINUS_DST_ALPHA,\n CONSTCOLOR: enums.BLEND_CONSTANT_COLOR,\n ONEMINUSCONSTCOLOR: enums.BLEND_ONE_MINUS_CONSTANT_COLOR,\n CONSTALPHA: enums.BLEND_CONSTANT_ALPHA,\n ONEMINUSCONSTALPHA: enums.BLEND_ONE_MINUS_CONSTANT_ALPHA,\n SRCALPHASATURATE: enums.BLEND_SRC_ALPHA_SATURATE,\n\n NEVER: enums.DS_FUNC_NEVER,\n LESS: enums.DS_FUNC_LESS,\n EQUAL: enums.DS_FUNC_EQUAL,\n LEQUAL: enums.DS_FUNC_LEQUAL,\n GREATER: enums.DS_FUNC_GREATER,\n NOTEQUAL: enums.DS_FUNC_NOTEQUAL,\n GEQUAL: enums.DS_FUNC_GEQUAL,\n ALWAYS: enums.DS_FUNC_ALWAYS,\n\n KEEP: enums.STENCIL_OP_KEEP,\n REPLACE: enums.STENCIL_OP_REPLACE,\n INCR: enums.STENCIL_OP_INCR,\n INCR_WRAP: enums.STENCIL_OP_INCR_WRAP,\n DECR: enums.STENCIL_OP_DECR,\n DECR_WRAP: enums.STENCIL_OP_DECR_WRAP,\n INVERT: enums.STENCIL_OP_INVERT\n};\n\nlet mappings = {\n typeParams,\n passParams,\n};\n\nexport default mappings;"],"names":[],"mappings":";;AAiIA;;;AAGA,AAAO,MAAM,KAAK,GAAG;;EAEnB,YAAY,EAAE,KAAK;EACnB,aAAa,EAAE,KAAK;EACpB,YAAY,EAAE,KAAK;;;EAGnB,eAAe,EAAE,IAAI;EACrB,gBAAgB,EAAE,IAAI;EACtB,gBAAgB,EAAE,IAAI;;;EAGtB,aAAa,EAAE,YAAY;EAC3B,WAAW,EAAE,UAAU;EACvB,YAAY,EAAE,WAAW;EACzB,cAAc,EAAE,aAAa;EAC7B,YAAY,EAAE,WAAW;EACzB,WAAW,EAAE,UAAU;EACvB,UAAU,EAAE,SAAS;EACrB,WAAW,EAAE,UAAU;EACvB,WAAW,EAAE,UAAU;EACvB,OAAO,EAAE,MAAM;EACf,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;EACjB,QAAQ,EAAE,OAAO;;;EAGjB,cAAc,EAAE,IAAI;EACpB,eAAe,EAAE,IAAI;EACrB,eAAe,EAAE,IAAI;EACrB,gBAAgB,EAAE,IAAI;EACtB,eAAe,EAAE,IAAI;EACrB,gBAAgB,EAAE,IAAI;EACtB,iBAAiB,EAAE,IAAI;;;EAGvB,cAAc,EAAE,CAAC;EACjB,aAAa,EAAE,CAAC;;;EAGhB,WAAW,EAAE,KAAK;EAClB,UAAU,EAAE,KAAK;EACjB,WAAW,EAAE,KAAK;;;;EAIlB,oBAAoB,EAAE,CAAC;EACvB,qBAAqB,EAAE,CAAC;EACxB,qBAAqB,EAAE,CAAC;EACxB,qBAAqB,EAAE,CAAC;EACxB,oBAAoB,EAAE,CAAC;EACvB,4BAA4B,EAAE,CAAC;EAC/B,6BAA6B,EAAE,CAAC;EAChC,4BAA4B,EAAE,CAAC;EAC/B,6BAA6B,EAAE,CAAC;;;EAGhC,cAAc,EAAE,CAAC;EACjB,cAAc,EAAE,EAAE;EAClB,iBAAiB,EAAE,EAAE;EACrB,oBAAoB,EAAE,EAAE;EACxB,uBAAuB,EAAE,EAAE;EAC3B,uBAAuB,EAAE,EAAE;EAC3B,gBAAgB,EAAE,EAAE;EACpB,iBAAiB,EAAE,EAAE;EACrB,kBAAkB,EAAE,EAAE;EACtB,mBAAmB,EAAE,EAAE;EACvB,kBAAkB,EAAE,EAAE;EACtB,mBAAmB,EAAE,EAAE;EACvB,gBAAgB,EAAE,EAAE;EACpB,mBAAmB,EAAE,EAAE;EACvB,gBAAgB,EAAE,EAAE;EACpB,iBAAiB,EAAE,EAAE;;;EAGrB,eAAe,EAAE,EAAE;EACnB,eAAe,EAAE,EAAE;EACnB,iBAAiB,EAAE,EAAE;;;EAGrB,aAAa,EAAE,GAAG;EAClB,YAAY,EAAE,GAAG;EACjB,aAAa,EAAE,GAAG;EAClB,cAAc,EAAE,GAAG;EACnB,eAAe,EAAE,GAAG;EACpB,gBAAgB,EAAE,GAAG;EACrB,cAAc,EAAE,GAAG;EACnB,cAAc,EAAE,GAAG;;;EAGnB,YAAY,EAAE,KAAK;EACnB,cAAc,EAAE,KAAK;EACrB,aAAa,EAAE,KAAK;EACpB,UAAU,EAAE,KAAK;EACjB,SAAS,EAAE,KAAK;EAChB,YAAY,EAAE,KAAK;;;EAGnB,cAAc,EAAE,KAAK;EACrB,mBAAmB,EAAE,KAAK;EAC1B,2BAA2B,EAAE,KAAK;;;EAGlC,UAAU,EAAE,CAAC;EACb,SAAS,EAAE,CAAC;EACZ,eAAe,EAAE,GAAG;EACpB,yBAAyB,EAAE,GAAG;EAC9B,eAAe,EAAE,GAAG;EACpB,yBAAyB,EAAE,GAAG;EAC9B,eAAe,EAAE,GAAG;EACpB,yBAAyB,EAAE,GAAG;EAC9B,eAAe,EAAE,GAAG;EACpB,yBAAyB,EAAE,GAAG;EAC9B,oBAAoB,EAAE,KAAK;EAC3B,8BAA8B,EAAE,KAAK;EACrC,oBAAoB,EAAE,KAAK;EAC3B,8BAA8B,EAAE,KAAK;EACrC,wBAAwB,EAAE,GAAG;;;EAG7B,eAAe,EAAE,IAAI;EACrB,eAAe,EAAE,CAAC;EAClB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,oBAAoB,EAAE,KAAK;EAC3B,eAAe,EAAE,IAAI;EACrB,oBAAoB,EAAE,KAAK;EAC3B,iBAAiB,EAAE,IAAI;;;EAGvB,SAAS,EAAE,CAAC;EACZ,UAAU,EAAE,IAAI;EAChB,SAAS,EAAE,IAAI;EACf,mBAAmB,EAAE,IAAI;;;EAGzB,SAAS,EAAE,CAAC;EACZ,QAAQ,EAAE,CAAC;EACX,YAAY,EAAE,CAAC;EACf,aAAa,EAAE,CAAC;EAChB,YAAY,EAAE,CAAC;EACf,iBAAiB,EAAE,CAAC;EACpB,eAAe,EAAE,CAAC;CACnB,CAAC;;ACxRF;;AAEA,oBAAe;;IAEX,gBAAgB,EAAE,CAAC;IACnB,UAAU,EAAE,CAAC;;;IAGb,iBAAiB,EAAE,CAAC;IACpB,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,CAAC;;;IAGb,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,CAAC;;;IAGd,SAAS,cAAc,CAAC;IACxB,UAAU,aAAa,CAAC;IACxB,UAAU,aAAa,CAAC;IACxB,UAAU,aAAa,CAAC;IACxB,WAAW,YAAY,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,YAAY,WAAW,CAAC;IACxB,UAAU,YAAY,EAAE;IACxB,UAAU,YAAY,EAAE;IACxB,UAAU,YAAY,EAAE;IACxB,gBAAgB,MAAM,EAAE;IACxB,kBAAkB,IAAI,EAAE;;;IAGxB,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,CAAC;IACd,aAAa,EAAE,CAAC;IAChB,YAAY,EAAE,CAAC;;;IAGf,gBAAgB,EAAE,CAAC;IACnB,iBAAiB,EAAE,CAAC;IACpB,iBAAiB,EAAE,CAAC;IACpB,kBAAkB,EAAE,CAAC;IACrB,iBAAiB,EAAE,CAAC;IACpB,kBAAkB,EAAE,CAAC;IACrB,mBAAmB,EAAE,CAAC;GACvB,CAAC;;AChDJ;AACA,AAGA;AACA,MAAM,UAAU,GAAG;EACjB,GAAG,EAAE,aAAa,CAAC,SAAS;EAC5B,KAAK,EAAE,aAAa,CAAC,UAAU;EAC/B,KAAK,EAAE,aAAa,CAAC,UAAU;EAC/B,KAAK,EAAE,aAAa,CAAC,UAAU;EAC/B,KAAK,EAAE,aAAa,CAAC,WAAW;EAChC,IAAI,EAAE,aAAa,CAAC,YAAY;EAChC,IAAI,EAAE,aAAa,CAAC,YAAY;EAChC,IAAI,EAAE,aAAa,CAAC,YAAY;EAChC,MAAM,EAAE,aAAa,CAAC,YAAY;EAClC,MAAM,EAAE,aAAa,CAAC,YAAY;EAClC,IAAI,EAAE,aAAa,CAAC,UAAU;EAC9B,IAAI,EAAE,aAAa,CAAC,UAAU;EAC9B,IAAI,EAAE,aAAa,CAAC,UAAU;EAC9B,SAAS,EAAE,aAAa,CAAC,gBAAgB;EACzC,WAAW,EAAE,aAAa,CAAC,kBAAkB;EAC7C,CAAC,aAAa,CAAC,YAAY,GAAG,aAAa,CAAC,YAAY;EACxD,CAAC,aAAa,CAAC,YAAY,GAAG,aAAa,CAAC,YAAY;CACzD,CAAC;;AAEF,MAAM,UAAU,GAAG;EACjB,IAAI,EAAE,KAAK,CAAC,SAAS;EACrB,KAAK,EAAE,KAAK,CAAC,UAAU;EACvB,IAAI,EAAE,KAAK,CAAC,SAAS;;EAErB,GAAG,EAAE,KAAK,CAAC,cAAc;EACzB,QAAQ,EAAE,KAAK,CAAC,mBAAmB;EACnC,eAAe,EAAE,KAAK,CAAC,2BAA2B;EAClD,IAAI,EAAE,KAAK,CAAC,UAAU;EACtB,GAAG,EAAE,KAAK,CAAC,SAAS;EACpB,QAAQ,EAAE,KAAK,CAAC,eAAe;EAC/B,gBAAgB,EAAE,KAAK,CAAC,yBAAyB;EACjD,QAAQ,EAAE,KAAK,CAAC,eAAe;EAC/B,gBAAgB,EAAE,KAAK,CAAC,yBAAyB;EACjD,QAAQ,EAAE,KAAK,CAAC,eAAe;EAC/B,gBAAgB,EAAE,KAAK,CAAC,yBAAyB;EACjD,QAAQ,EAAE,KAAK,CAAC,eAAe;EAC/B,gBAAgB,EAAE,KAAK,CAAC,yBAAyB;EACjD,UAAU,EAAE,KAAK,CAAC,oBAAoB;EACtC,kBAAkB,EAAE,KAAK,CAAC,8BAA8B;EACxD,UAAU,EAAE,KAAK,CAAC,oBAAoB;EACtC,kBAAkB,EAAE,KAAK,CAAC,8BAA8B;EACxD,gBAAgB,EAAE,KAAK,CAAC,wBAAwB;;EAEhD,KAAK,EAAE,KAAK,CAAC,aAAa;EAC1B,IAAI,EAAE,KAAK,CAAC,YAAY;EACxB,KAAK,EAAE,KAAK,CAAC,aAAa;EAC1B,MAAM,EAAE,KAAK,CAAC,cAAc;EAC5B,OAAO,EAAE,KAAK,CAAC,eAAe;EAC9B,QAAQ,EAAE,KAAK,CAAC,gBAAgB;EAChC,MAAM,EAAE,KAAK,CAAC,cAAc;EAC5B,MAAM,EAAE,KAAK,CAAC,cAAc;;EAE5B,IAAI,EAAE,KAAK,CAAC,eAAe;EAC3B,OAAO,EAAE,KAAK,CAAC,kBAAkB;EACjC,IAAI,EAAE,KAAK,CAAC,eAAe;EAC3B,SAAS,EAAE,KAAK,CAAC,oBAAoB;EACrC,IAAI,EAAE,KAAK,CAAC,eAAe;EAC3B,SAAS,EAAE,KAAK,CAAC,oBAAoB;EACrC,MAAM,EAAE,KAAK,CAAC,iBAAiB;CAChC,CAAC;;AAEF,IAAI,QAAQ,GAAG;EACb,UAAU;EACV,UAAU;CACX,CAAC;;;;"} \ No newline at end of file diff --git a/cocos2d/renderer/memop/circular-pool.js b/cocos2d/renderer/memop/circular-pool.js new file mode 100644 index 00000000000..3dfafd5628f --- /dev/null +++ b/cocos2d/renderer/memop/circular-pool.js @@ -0,0 +1,17 @@ +export default class CircularPool { + constructor(fn, size) { + this._cursor = 0; + this._data = new Array(size); + + for (let i = 0; i < size; ++i) { + this._data[i] = fn(); + } + } + + request() { + let item = this._data[this._cursor]; + this._cursor = (this._cursor + 1) % this._data.length; + + return item; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/memop/fixed-array.js b/cocos2d/renderer/memop/fixed-array.js new file mode 100644 index 00000000000..5ba91344632 --- /dev/null +++ b/cocos2d/renderer/memop/fixed-array.js @@ -0,0 +1,73 @@ +import sort from './timsort'; + +export default class FixedArray { + constructor(size) { + this._count = 0; + this._data = new Array(size); + } + + _resize(size) { + if (size > this._data.length) { + for (let i = this._data.length; i < size; ++i) { + this._data[i] = undefined; + } + } + } + + get length() { + return this._count; + } + + get data() { + return this._data; + } + + reset() { + for (let i = 0; i < this._count; ++i) { + this._data[i] = undefined; + } + + this._count = 0; + } + + push(val) { + if (this._count >= this._data.length) { + this._resize(this._data.length * 2); + } + + this._data[this._count] = val; + ++this._count; + } + + pop() { + --this._count; + + if (this._count < 0) { + this._count = 0; + } + + let ret = this._data[this._count]; + this._data[this._count] = undefined; + + return ret; + } + + fastRemove(idx) { + if (idx >= this._count || idx < 0) { + return; + } + + let last = this._count - 1; + this._data[idx] = this._data[last]; + this._data[last] = undefined; + this._count -= 1; + } + + indexOf(val) { + return this._data.indexOf(val); + } + + sort(cmp) { + return sort(this._data, 0, this._count, cmp); + } +} \ No newline at end of file diff --git a/cocos2d/renderer/memop/index.js b/cocos2d/renderer/memop/index.js new file mode 100644 index 00000000000..092d7d82ad7 --- /dev/null +++ b/cocos2d/renderer/memop/index.js @@ -0,0 +1,6 @@ +export { default as CircularPool } from './circular-pool'; +export { default as FixedArray } from './fixed-array'; +export { default as LinkedArray } from './linked-array'; +export { default as Pool } from './pool'; +export { default as RecyclePool } from './recycle-pool'; +export { default as TypedArrayPool } from './typed-array-pool'; \ No newline at end of file diff --git a/cocos2d/renderer/memop/linked-array.js b/cocos2d/renderer/memop/linked-array.js new file mode 100644 index 00000000000..2b217c2ab97 --- /dev/null +++ b/cocos2d/renderer/memop/linked-array.js @@ -0,0 +1,82 @@ +import Pool from './pool'; + +// NOTE: you must have `_prev` and `_next` field in the object returns by `fn` + +export default class LinkedArray { + constructor(fn, size) { + this._fn = fn; + this._count = 0; + this._head = null; + this._tail = null; + + this._pool = new Pool(fn, size); + } + + get head() { + return this._head; + } + + get tail() { + return this._tail; + } + + get length() { + return this._count; + } + + add() { + let node = this._pool.alloc(); + + if (!this._tail) { + this._head = node; + } else { + this._tail._next = node; + node._prev = this._tail; + } + this._tail = node; + this._count += 1; + + return node; + } + + remove(node) { + if (node._prev) { + node._prev._next = node._next; + } else { + this._head = node._next; + } + + if (node._next) { + node._next._prev = node._prev; + } else { + this._tail = node._prev; + } + + node._next = null; + node._prev = null; + this._pool.free(node); + this._count -= 1; + } + + forEach(fn, binder) { + let cursor = this._head; + if (!cursor) { + return; + } + + if (binder) { + fn = fn.bind(binder); + } + + let idx = 0; + let next = cursor; + + while (cursor) { + next = cursor._next; + fn(cursor, idx, this); + + cursor = next; + ++idx; + } + } +} \ No newline at end of file diff --git a/cocos2d/renderer/memop/optimized-array.js b/cocos2d/renderer/memop/optimized-array.js new file mode 100644 index 00000000000..3f013e06b2c --- /dev/null +++ b/cocos2d/renderer/memop/optimized-array.js @@ -0,0 +1,187 @@ +export class OptimizedArray { + /** + * Initialize this array with specified capacity. + * @param {Number} [size] The size. + */ + constructor(size = 0) { + this._size = size; + this._data = new Array(size); + } + + /** + * Size of this array. + * @return {Number} + */ + get size() { + return this._size; + } + + /** + * The underlying Array of this array. + * @return {Array} + */ + get data() { + return this._data; + } + + /** + * Capacity of this array. + */ + get capacity() { + return this._data.length; + } + + /** + * Push a value to back of this array. + * @param {any} value + */ + push(value) { + if (this._size > this._data.length) + this._extends(this._data.length); + this._data[this._size] = value; + ++this._size; + } + + /** + * Remove the last element and return it, if exists. + */ + pop() { + if (this._size == 0) + return; + --this._size; + let ret = this._data[this._size]; + this._data[this._size] = undefined; + return ret; + } + + /** + * Remove all elements. + */ + clear() { + for (let i = 0; i < this._data.length; ++i) + this._data[i] = undefined; + this._size = 0; + } + + /** + * @ignore + * @param {Number} size + */ + _extends(size) { + let finalSize = this._data.length + size; + for (let i = this._data.length; i < finalSize; ++i) + this._data[i] = undefined; + } +} + +export class OptimizedValueArray { + /** + * Initialize this array with specified capacity. + * @param {any} ctor The constructor to create the value. + * @param {Number} [size] The size. + */ + constructor(ctor, dtor, size = 0) { + this._size = size; + this._data = new Array(); + this._ctor = ctor; + this._dtor = dtor; + this._extends(size); + } + + /** + * Size of this array. + * @return {Number} + */ + get size() { + return this._size; + } + + /** + * The underlying Array of this array. + * @return {Array} + */ + get data() { + return this._data; + } + + /** + * Capacity of this array. + */ + get capacity() { + return this._data.length; + } + + /** + * Push a value to back of this array. + */ + push() { + if (this._size >= this._data.length) + this._extends(this._data.length + 1); + let retval = this._data[this._size]; + ++this._size; + return retval; + } + + /** + * Remove the last element, if exists. + * Since that element is not erased, so we cannot return it. + */ + pop() { + if (this._size == 0) + return; + --this._size; + this._dtor(this._data[this._size]); + } + + /** + * Remove all elements. + */ + clear() { + this._size = 0; + for (let i = 0; i < this._data.length; ++i) + this._dtor(this._data[i]); + } + + splice(from, number) { + if (number == 0) + return; + + if (from >= this.size) + return; // throw + + number = Math.min(this.size - from, number); + + let originalSize = this._size; + this._size -= number; + + for (let i = 0, moveStart = from + number, moveNumber = originalSize - moveStart; i < moveNumber; ++i) { + let temp = this._data[from + i]; + this._data[from + i] = this._data[moveStart + i]; + this._data[moveStart + i] = temp; + } + for (let i = this._size; i != originalSize; ++i) + this._dtor(this._data[i]); + } + + forEach(fx) { + for (let i = 0; i < this.size; ++i) + fx(this.data[i], i, this); + } + + map(fx) { + let result = new Array(); + for (let i = 0; i < this.size; ++i) + result.push(fx(this.data[i], i, this)); + return result; + } + + /** + * @ignore + * @param {Number} size + */ + _extends(size) { + let finalSize = this._data.length + size; + for (let i = this._data.length; i < finalSize; ++i) + this._data[i] = this._ctor(); + } +} \ No newline at end of file diff --git a/cocos2d/renderer/memop/pool.js b/cocos2d/renderer/memop/pool.js new file mode 100644 index 00000000000..4db7e02a64a --- /dev/null +++ b/cocos2d/renderer/memop/pool.js @@ -0,0 +1,45 @@ +export default class Pool { + constructor(fn, size) { + this._fn = fn; + this._idx = size - 1; + this._frees = new Array(size); + + for (let i = 0; i < size; ++i) { + this._frees[i] = fn(); + } + } + + _expand(size) { + let old = this._frees; + this._frees = new Array(size); + + let len = size - old.length; + for (let i = 0; i < len; ++i) { + this._frees[i] = this._fn(); + } + + for (let i = len, j = 0; i < size; ++i, ++j) { + this._frees[i] = old[j]; + } + + this._idx += len; + } + + alloc() { + // create some more space (expand by 20%, minimum 1) + if (this._idx < 0) { + this._expand(Math.round(this._frees.length * 1.2) + 1); + } + + let ret = this._frees[this._idx]; + this._frees[this._idx] = null; + --this._idx; + + return ret; + } + + free(obj) { + ++this._idx; + this._frees[this._idx] = obj; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/memop/recycle-pool.js b/cocos2d/renderer/memop/recycle-pool.js new file mode 100644 index 00000000000..98f80973120 --- /dev/null +++ b/cocos2d/renderer/memop/recycle-pool.js @@ -0,0 +1,57 @@ +import sort from './timsort'; + +export default class RecyclePool { + constructor(fn, size) { + this._fn = fn; + this._count = 0; + this._data = new Array(size); + + for (let i = 0; i < size; ++i) { + this._data[i] = fn(); + } + } + + get length() { + return this._count; + } + + get data() { + return this._data; + } + + reset() { + this._count = 0; + } + + resize(size) { + if (size > this._data.length) { + for (let i = this._data.length; i < size; ++i) { + this._data[i] = this._fn(); + } + } + } + + add() { + if (this._count >= this._data.length) { + this.resize(this._data.length * 2); + } + + return this._data[this._count++]; + } + + remove(idx) { + if (idx >= this._count) { + return; + } + + let last = this._count - 1; + let tmp = this._data[idx]; + this._data[idx] = this._data[last]; + this._data[last] = tmp; + this._count -= 1; + } + + sort(cmp) { + return sort(this._data, 0, this._count, cmp); + } +} \ No newline at end of file diff --git a/cocos2d/renderer/memop/sort.js b/cocos2d/renderer/memop/sort.js new file mode 100644 index 00000000000..34e0e295125 --- /dev/null +++ b/cocos2d/renderer/memop/sort.js @@ -0,0 +1,166 @@ +// reference: https://github.com/v8/v8/blob/master/src/js/array.js + +function _compare(a, b) { + return a - b; +} + +function _sort(array, from, to, comparefn) { + + function _insertionSort(a, from, to) { + for (let i = from + 1; i < to; i++) { + let element = a[i]; + let j; + + for (j = i - 1; j >= from; j--) { + let tmp = a[j]; + let order = comparefn(tmp, element); + if (order > 0) { + a[j + 1] = tmp; + } else { + break; + } + } + a[j + 1] = element; + } + } + + // function _getThirdIndex(a, from, to) { + // let t_array = new Array(); + // // Use both 'from' and 'to' to determine the pivot candidates. + // let increment = 200 + ((to - from) & 15); + // let j = 0; + // from += 1; + // to -= 1; + // for (let i = from; i < to; i += increment) { + // t_array[j] = [i, a[i]]; + // j++; + // } + // t_array.sort(function (a, b) { + // return comparefn(a[1], b[1]); + // }); + // let third_index = t_array[t_array.length >> 1][0]; + // return third_index; + // } + + function _quickSort(a, from, to) { + let third_index = 0; + + while (true) { + // Insertion sort is faster for short arrays. + if (to - from <= 10) { + _insertionSort(a, from, to); + return; + } + // if (to - from > 1000) { + // third_index = _getThirdIndex(a, from, to); + // } else { + third_index = from + ((to - from) >> 1); + // } + // Find a pivot as the median of first, last and middle element. + let v0 = a[from]; + let v1 = a[to - 1]; + let v2 = a[third_index]; + let c01 = comparefn(v0, v1); + if (c01 > 0) { + // v1 < v0, so swap them. + let tmp = v0; + v0 = v1; + v1 = tmp; + } // v0 <= v1. + let c02 = comparefn(v0, v2); + if (c02 >= 0) { + // v2 <= v0 <= v1. + let tmp = v0; + v0 = v2; + v2 = v1; + v1 = tmp; + } else { + // v0 <= v1 && v0 < v2 + let c12 = comparefn(v1, v2); + if (c12 > 0) { + // v0 <= v2 < v1 + let tmp = v1; + v1 = v2; + v2 = tmp; + } + } + // v0 <= v1 <= v2 + a[from] = v0; + a[to - 1] = v2; + let pivot = v1; + let low_end = from + 1; // Upper bound of elements lower than pivot. + let high_start = to - 1; // Lower bound of elements greater than pivot. + a[third_index] = a[low_end]; + a[low_end] = pivot; + + // From low_end to i are elements equal to pivot. + // From i to high_start are elements that haven't been compared yet. + partition: for (let i = low_end + 1; i < high_start; i++) { + let element = a[i]; + let order = comparefn(element, pivot); + if (order < 0) { + a[i] = a[low_end]; + a[low_end] = element; + low_end++; + } else if (order > 0) { + do { + high_start--; + if (high_start == i) break partition; + let top_elem = a[high_start]; + order = comparefn(top_elem, pivot); + } while (order > 0); + a[i] = a[high_start]; + a[high_start] = element; + if (order < 0) { + element = a[i]; + a[i] = a[low_end]; + a[low_end] = element; + low_end++; + } + } + } + if (to - high_start < low_end - from) { + _quickSort(a, high_start, to); + to = low_end; + } else { + _quickSort(a, from, low_end); + from = high_start; + } + } + } + + if (to - from < 2) { + return array; + } + + _quickSort(array, from, to); + + return array; +} + + +/** + * Calls the _quickSort function with it's initial values. + * + * @public + * @param {array} array The input array which should be sorted + * @param {Number} from + * @param {Number} to + * @param {Function} cmp + * @returns {array} array Sorted array + */ +export default function (array, from, to, cmp) { + if (from === undefined) { + from = 0; + } + + if (to === undefined) { + to = array.length; + } + + if (cmp === undefined) { + cmp = _compare; + } + + return _sort(array, from, to, cmp); +} \ No newline at end of file diff --git a/cocos2d/renderer/memop/timsort.js b/cocos2d/renderer/memop/timsort.js new file mode 100644 index 00000000000..737a47af933 --- /dev/null +++ b/cocos2d/renderer/memop/timsort.js @@ -0,0 +1,967 @@ +// reference: https://github.com/mziccard/node-timsort + +/** + * Default minimum size of a run. + */ +const DEFAULT_MIN_MERGE = 32; + +/** + * Minimum ordered subsequece required to do galloping. + */ +const DEFAULT_MIN_GALLOPING = 7; + +/** + * Default tmp storage length. Can increase depending on the size of the + * smallest run to merge. + */ +const DEFAULT_TMP_STORAGE_LENGTH = 256; + +/** + * Pre-computed powers of 10 for efficient lexicographic comparison of + * small integers. + */ +const POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9] + +/** + * Estimate the logarithm base 10 of a small integer. + * + * @param {number} x - The integer to estimate the logarithm of. + * @return {number} - The estimated logarithm of the integer. + */ +function log10(x) { + if (x < 1e5) { + if (x < 1e2) { + return x < 1e1 ? 0 : 1; + } + + if (x < 1e4) { + return x < 1e3 ? 2 : 3; + } + + return 4; + } + + if (x < 1e7) { + return x < 1e6 ? 5 : 6; + } + + if (x < 1e9) { + return x < 1e8 ? 7 : 8; + } + + return 9; +} + +/** + * Default alphabetical comparison of items. + * + * @param {string|object|number} a - First element to compare. + * @param {string|object|number} b - Second element to compare. + * @return {number} - A positive number if a.toString() > b.toString(), a + * negative number if .toString() < b.toString(), 0 otherwise. + */ +function alphabeticalCompare(a, b) { + if (a === b) { + return 0; + } + + if (~~a === a && ~~b === b) { + if (a === 0 || b === 0) { + return a < b ? -1 : 1; + } + + if (a < 0 || b < 0) { + if (b >= 0) { + return -1; + } + + if (a >= 0) { + return 1; + } + + a = -a; + b = -b; + } + + const al = log10(a); + const bl = log10(b); + + let t = 0; + + if (al < bl) { + a *= POWERS_OF_TEN[bl - al - 1]; + b /= 10; + t = -1; + } else if (al > bl) { + b *= POWERS_OF_TEN[al - bl - 1]; + a /= 10; + t = 1; + } + + if (a === b) { + return t; + } + + return a < b ? -1 : 1; + } + + let aStr = String(a); + let bStr = String(b); + + if (aStr === bStr) { + return 0; + } + + return aStr < bStr ? -1 : 1; +} + +/** + * Compute minimum run length for TimSort + * + * @param {number} n - The size of the array to sort. + */ +function minRunLength(n) { + let r = 0; + + while (n >= DEFAULT_MIN_MERGE) { + r |= (n & 1); + n >>= 1; + } + + return n + r; +} + +/** + * Counts the length of a monotonically ascending or strictly monotonically + * descending sequence (run) starting at array[lo] in the range [lo, hi). If + * the run is descending it is made ascending. + * + * @param {array} array - The array to reverse. + * @param {number} lo - First element in the range (inclusive). + * @param {number} hi - Last element in the range. + * @param {function} compare - Item comparison function. + * @return {number} - The length of the run. + */ +function makeAscendingRun(array, lo, hi, compare) { + let runHi = lo + 1; + + if (runHi === hi) { + return 1; + } + + // Descending + if (compare(array[runHi++], array[lo]) < 0) { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { + runHi++; + } + + reverseRun(array, lo, runHi); + // Ascending + } else { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { + runHi++; + } + } + + return runHi - lo; +} + +/** + * Reverse an array in the range [lo, hi). + * + * @param {array} array - The array to reverse. + * @param {number} lo - First element in the range (inclusive). + * @param {number} hi - Last element in the range. + */ +function reverseRun(array, lo, hi) { + hi--; + + while (lo < hi) { + let t = array[lo]; + array[lo++] = array[hi]; + array[hi--] = t; + } +} + +/** + * Perform the binary sort of the array in the range [lo, hi) where start is + * the first element possibly out of order. + * + * @param {array} array - The array to sort. + * @param {number} lo - First element in the range (inclusive). + * @param {number} hi - Last element in the range. + * @param {number} start - First element possibly out of order. + * @param {function} compare - Item comparison function. + */ +function binaryInsertionSort(array, lo, hi, start, compare) { + if (start === lo) { + start++; + } + + for (; start < hi; start++) { + let pivot = array[start]; + + // Ranges of the array where pivot belongs + let left = lo; + let right = start; + + /* + * pivot >= array[i] for i in [lo, left) + * pivot < array[i] for i in in [right, start) + */ + while (left < right) { + let mid = (left + right) >>> 1; + + if (compare(pivot, array[mid]) < 0) { + right = mid; + } else { + left = mid + 1; + } + } + + /* + * Move elements right to make room for the pivot. If there are elements + * equal to pivot, left points to the first slot after them: this is also + * a reason for which TimSort is stable + */ + let n = start - left; + // Switch is just an optimization for small arrays + switch (n) { + case 3: + array[left + 3] = array[left + 2]; + /* falls through */ + case 2: + array[left + 2] = array[left + 1]; + /* falls through */ + case 1: + array[left + 1] = array[left]; + break; + default: + while (n > 0) { + array[left + n] = array[left + n - 1]; + n--; + } + } + + array[left] = pivot; + } +} + +/** + * Find the position at which to insert a value in a sorted range. If the range + * contains elements equal to the value the leftmost element index is returned + * (for stability). + * + * @param {number} value - Value to insert. + * @param {array} array - The array in which to insert value. + * @param {number} start - First element in the range. + * @param {number} length - Length of the range. + * @param {number} hint - The index at which to begin the search. + * @param {function} compare - Item comparison function. + * @return {number} - The index where to insert value. + */ +function gallopLeft(value, array, start, length, hint, compare) { + let lastOffset = 0; + let maxOffset = 0; + let offset = 1; + + if (compare(value, array[start + hint]) > 0) { + maxOffset = length - hint; + + while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + + if (offset > maxOffset) { + offset = maxOffset; + } + + // Make offsets relative to start + lastOffset += hint; + offset += hint; + + // value <= array[start + hint] + } else { + maxOffset = hint + 1; + while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + + // Make offsets relative to start + let tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + } + + /* + * Now array[start+lastOffset] < value <= array[start+offset], so value + * belongs somewhere in the range (start + lastOffset, start + offset]. Do a + * binary search, with invariant array[start + lastOffset - 1] < value <= + * array[start + offset]. + */ + lastOffset++; + while (lastOffset < offset) { + let m = lastOffset + ((offset - lastOffset) >>> 1); + + if (compare(value, array[start + m]) > 0) { + lastOffset = m + 1; + + } else { + offset = m; + } + } + return offset; +} + +/** + * Find the position at which to insert a value in a sorted range. If the range + * contains elements equal to the value the rightmost element index is returned + * (for stability). + * + * @param {number} value - Value to insert. + * @param {array} array - The array in which to insert value. + * @param {number} start - First element in the range. + * @param {number} length - Length of the range. + * @param {number} hint - The index at which to begin the search. + * @param {function} compare - Item comparison function. + * @return {number} - The index where to insert value. + */ +function gallopRight(value, array, start, length, hint, compare) { + let lastOffset = 0; + let maxOffset = 0; + let offset = 1; + + if (compare(value, array[start + hint]) < 0) { + maxOffset = hint + 1; + + while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + + if (offset > maxOffset) { + offset = maxOffset; + } + + // Make offsets relative to start + let tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + + // value >= array[start + hint] + } else { + maxOffset = length - hint; + + while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + + if (offset <= 0) { + offset = maxOffset; + } + } + + if (offset > maxOffset) { + offset = maxOffset; + } + + // Make offsets relative to start + lastOffset += hint; + offset += hint; + } + + /* + * Now array[start+lastOffset] < value <= array[start+offset], so value + * belongs somewhere in the range (start + lastOffset, start + offset]. Do a + * binary search, with invariant array[start + lastOffset - 1] < value <= + * array[start + offset]. + */ + lastOffset++; + + while (lastOffset < offset) { + let m = lastOffset + ((offset - lastOffset) >>> 1); + + if (compare(value, array[start + m]) < 0) { + offset = m; + + } else { + lastOffset = m + 1; + } + } + + return offset; +} + +class TimSort { + + constructor(array, compare) { + this.array = array; + this.compare = compare; + this.minGallop = DEFAULT_MIN_GALLOPING; + this.length = array.length; + + this.tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH; + if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) { + this.tmpStorageLength = this.length >>> 1; + } + + this.tmp = new Array(this.tmpStorageLength); + + this.stackLength = + (this.length < 120 ? 5 : + this.length < 1542 ? 10 : + this.length < 119151 ? 19 : 40); + + this.runStart = new Array(this.stackLength); + this.runLength = new Array(this.stackLength); + this.stackSize = 0; + } + + /** + * Push a new run on TimSort's stack. + * + * @param {number} runStart - Start index of the run in the original array. + * @param {number} runLength - Length of the run; + */ + pushRun(runStart, runLength) { + this.runStart[this.stackSize] = runStart; + this.runLength[this.stackSize] = runLength; + this.stackSize += 1; + } + + /** + * Merge runs on TimSort's stack so that the following holds for all i: + * 1) runLength[i - 3] > runLength[i - 2] + runLength[i - 1] + * 2) runLength[i - 2] > runLength[i - 1] + */ + mergeRuns() { + while (this.stackSize > 1) { + let n = this.stackSize - 2; + + if ((n >= 1 && + this.runLength[n - 1] <= this.runLength[n] + this.runLength[n + 1]) || + (n >= 2 && + this.runLength[n - 2] <= this.runLength[n] + this.runLength[n - 1])) { + + if (this.runLength[n - 1] < this.runLength[n + 1]) { + n--; + } + + } else if (this.runLength[n] > this.runLength[n + 1]) { + break; + } + this.mergeAt(n); + } + } + + /** + * Merge all runs on TimSort's stack until only one remains. + */ + forceMergeRuns() { + while (this.stackSize > 1) { + let n = this.stackSize - 2; + + if (n > 0 && this.runLength[n - 1] < this.runLength[n + 1]) { + n--; + } + + this.mergeAt(n); + } + } + + /** + * Merge the runs on the stack at positions i and i+1. Must be always be called + * with i=stackSize-2 or i=stackSize-3 (that is, we merge on top of the stack). + * + * @param {number} i - Index of the run to merge in TimSort's stack. + */ + mergeAt(i) { + let compare = this.compare; + let array = this.array; + + let start1 = this.runStart[i]; + let length1 = this.runLength[i]; + let start2 = this.runStart[i + 1]; + let length2 = this.runLength[i + 1]; + + this.runLength[i] = length1 + length2; + + if (i === this.stackSize - 3) { + this.runStart[i + 1] = this.runStart[i + 2]; + this.runLength[i + 1] = this.runLength[i + 2]; + } + + this.stackSize--; + + /* + * Find where the first element in the second run goes in run1. Previous + * elements in run1 are already in place + */ + let k = gallopRight(array[start2], array, start1, length1, 0, compare); + start1 += k; + length1 -= k; + + if (length1 === 0) { + return; + } + + /* + * Find where the last element in the first run goes in run2. Next elements + * in run2 are already in place + */ + length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); + + if (length2 === 0) { + return; + } + + /* + * Merge remaining runs. A tmp array with length = min(length1, length2) is + * used + */ + if (length1 <= length2) { + this.mergeLow(start1, length1, start2, length2); + + } else { + this.mergeHigh(start1, length1, start2, length2); + } + } + + /** + * Merge two adjacent runs in a stable way. The runs must be such that the + * first element of run1 is bigger than the first element in run2 and the + * last element of run1 is greater than all the elements in run2. + * The method should be called when run1.length <= run2.length as it uses + * TimSort temporary array to store run1. Use mergeHigh if run1.length > + * run2.length. + * + * @param {number} start1 - First element in run1. + * @param {number} length1 - Length of run1. + * @param {number} start2 - First element in run2. + * @param {number} length2 - Length of run2. + */ + mergeLow(start1, length1, start2, length2) { + + let compare = this.compare; + let array = this.array; + let tmp = this.tmp; + let i = 0; + + for (i = 0; i < length1; i++) { + tmp[i] = array[start1 + i]; + } + + let cursor1 = 0; + let cursor2 = start2; + let dest = start1; + + array[dest++] = array[cursor2++]; + + if (--length2 === 0) { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + return; + } + + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + return; + } + + let minGallop = this.minGallop; + + while (true) { + let count1 = 0; + let count2 = 0; + let exit = false; + + do { + if (compare(array[cursor2], tmp[cursor1]) < 0) { + array[dest++] = array[cursor2++]; + count2++; + count1 = 0; + + if (--length2 === 0) { + exit = true; + break; + } + + } else { + array[dest++] = tmp[cursor1++]; + count1++; + count2 = 0; + if (--length1 === 1) { + exit = true; + break; + } + } + } while ((count1 | count2) < minGallop); + + if (exit) { + break; + } + + do { + count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); + + if (count1 !== 0) { + for (i = 0; i < count1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + + dest += count1; + cursor1 += count1; + length1 -= count1; + if (length1 <= 1) { + exit = true; + break; + } + } + + array[dest++] = array[cursor2++]; + + if (--length2 === 0) { + exit = true; + break; + } + + count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); + + if (count2 !== 0) { + for (i = 0; i < count2; i++) { + array[dest + i] = array[cursor2 + i]; + } + + dest += count2; + cursor2 += count2; + length2 -= count2; + + if (length2 === 0) { + exit = true; + break; + } + } + array[dest++] = tmp[cursor1++]; + + if (--length1 === 1) { + exit = true; + break; + } + + minGallop--; + + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + + if (exit) { + break; + } + + if (minGallop < 0) { + minGallop = 0; + } + + minGallop += 2; + } + + this.minGallop = minGallop; + + if (minGallop < 1) { + this.minGallop = 1; + } + + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + + } else if (length1 === 0) { + throw new Error('mergeLow preconditions were not respected'); + + } else { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + } + } + + /** + * Merge two adjacent runs in a stable way. The runs must be such that the + * first element of run1 is bigger than the first element in run2 and the + * last element of run1 is greater than all the elements in run2. + * The method should be called when run1.length > run2.length as it uses + * TimSort temporary array to store run2. Use mergeLow if run1.length <= + * run2.length. + * + * @param {number} start1 - First element in run1. + * @param {number} length1 - Length of run1. + * @param {number} start2 - First element in run2. + * @param {number} length2 - Length of run2. + */ + mergeHigh(start1, length1, start2, length2) { + let compare = this.compare; + let array = this.array; + let tmp = this.tmp; + let i = 0; + + for (i = 0; i < length2; i++) { + tmp[i] = array[start2 + i]; + } + + let cursor1 = start1 + length1 - 1; + let cursor2 = length2 - 1; + let dest = start2 + length2 - 1; + let customCursor = 0; + let customDest = 0; + + array[dest--] = array[cursor1--]; + + if (--length1 === 0) { + customCursor = dest - (length2 - 1); + + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + + return; + } + + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + + array[dest] = tmp[cursor2]; + return; + } + + let minGallop = this.minGallop; + + while (true) { + let count1 = 0; + let count2 = 0; + let exit = false; + + do { + if (compare(tmp[cursor2], array[cursor1]) < 0) { + array[dest--] = array[cursor1--]; + count1++; + count2 = 0; + if (--length1 === 0) { + exit = true; + break; + } + + } else { + array[dest--] = tmp[cursor2--]; + count2++; + count1 = 0; + if (--length2 === 1) { + exit = true; + break; + } + } + + } while ((count1 | count2) < minGallop); + + if (exit) { + break; + } + + do { + count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); + + if (count1 !== 0) { + dest -= count1; + cursor1 -= count1; + length1 -= count1; + customDest = dest + 1; + customCursor = cursor1 + 1; + + for (i = count1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + + if (length1 === 0) { + exit = true; + break; + } + } + + array[dest--] = tmp[cursor2--]; + + if (--length2 === 1) { + exit = true; + break; + } + + count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); + + if (count2 !== 0) { + dest -= count2; + cursor2 -= count2; + length2 -= count2; + customDest = dest + 1; + customCursor = cursor2 + 1; + + for (i = 0; i < count2; i++) { + array[customDest + i] = tmp[customCursor + i]; + } + + if (length2 <= 1) { + exit = true; + break; + } + } + + array[dest--] = array[cursor1--]; + + if (--length1 === 0) { + exit = true; + break; + } + + minGallop--; + + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + + if (exit) { + break; + } + + if (minGallop < 0) { + minGallop = 0; + } + + minGallop += 2; + } + + this.minGallop = minGallop; + + if (minGallop < 1) { + this.minGallop = 1; + } + + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + + array[dest] = tmp[cursor2]; + + } else if (length2 === 0) { + throw new Error('mergeHigh preconditions were not respected'); + + } else { + customCursor = dest - (length2 - 1); + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + } + } +} + +/** + * Sort an array in the range [lo, hi) using TimSort. + * + * @param {array} array - The array to sort. + * @param {number} lo - First element in the range (inclusive). + * @param {number} hi - Last element in the range. + * @param {function=} compare - Item comparison function. Default is alphabetical. + */ +export default function (array, lo, hi, compare) { + if (!Array.isArray(array)) { + throw new TypeError('Can only sort arrays'); + } + + /* + * Handle the case where a comparison function is not provided. We do + * lexicographic sorting + */ + + if (lo === undefined) { + lo = 0; + } + + if (hi === undefined) { + hi = array.length; + } + + if (compare === undefined) { + compare = alphabeticalCompare; + } + + let remaining = hi - lo; + + // The array is already sorted + if (remaining < 2) { + return; + } + + let runLength = 0; + // On small arrays binary sort can be used directly + if (remaining < DEFAULT_MIN_MERGE) { + runLength = makeAscendingRun(array, lo, hi, compare); + binaryInsertionSort(array, lo, hi, lo + runLength, compare); + return; + } + + let ts = new TimSort(array, compare); + + let minRun = minRunLength(remaining); + + do { + runLength = makeAscendingRun(array, lo, hi, compare); + if (runLength < minRun) { + let force = remaining; + if (force > minRun) { + force = minRun; + } + + binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); + runLength = force; + } + // Push new run and merge if necessary + ts.pushRun(lo, runLength); + ts.mergeRuns(); + + // Go find next run + remaining -= runLength; + lo += runLength; + + } while (remaining !== 0); + + // Force merging of remaining runs + ts.forceMergeRuns(); +} \ No newline at end of file diff --git a/cocos2d/renderer/memop/typed-array-pool.js b/cocos2d/renderer/memop/typed-array-pool.js new file mode 100644 index 00000000000..9711e8fdb49 --- /dev/null +++ b/cocos2d/renderer/memop/typed-array-pool.js @@ -0,0 +1,129 @@ +let _bufferPools = Array(8); +for (let i = 0; i < 8; ++i) { + _bufferPools[i] = []; +} + +function _nextPow16(v) { + for (let i = 16; i <= (1 << 28); i *= 16) { + if (v <= i) { + return i; + } + } + return 0; +} + +function _log2(v) { + let r, shift; + r = (v > 0xFFFF) << 4; v >>>= r; + shift = (v > 0xFF) << 3; v >>>= shift; r |= shift; + shift = (v > 0xF) << 2; v >>>= shift; r |= shift; + shift = (v > 0x3) << 1; v >>>= shift; r |= shift; + return r | (v >> 1); +} + +function _alloc(n) { + let sz = _nextPow16(n); + let bin = _bufferPools[_log2(sz) >> 2]; + if (bin.length > 0) { + return bin.pop(); + } + return new ArrayBuffer(sz); +} + +function _free(buf) { + _bufferPools[_log2(buf.byteLength) >> 2].push(buf); +} + +export default { + alloc_int8(n) { + let result = new Int8Array(_alloc(n), 0, n); + if (result.length !== n) { + return result.subarray(0, n); + } + + return result; + }, + + alloc_uint8(n) { + let result = new Uint8Array(_alloc(n), 0, n); + if (result.length !== n) { + return result.subarray(0, n); + } + + return result; + }, + + alloc_int16(n) { + let result = new Int16Array(_alloc(2 * n), 0, n); + if (result.length !== n) { + return result.subarray(0, n); + } + + return result; + }, + + alloc_uint16(n) { + let result = new Uint16Array(_alloc(2 * n), 0, n); + if (result.length !== n) { + return result.subarray(0, n); + } + + return result; + }, + + alloc_int32(n) { + let result = new Int32Array(_alloc(4 * n), 0, n); + if (result.length !== n) { + return result.subarray(0, n); + } + + return result; + }, + + alloc_uint32(n) { + let result = new Uint32Array(_alloc(4 * n), 0, n); + if (result.length !== n) { + return result.subarray(0, n); + } + + return result; + }, + + alloc_float32(n) { + let result = new Float32Array(_alloc(4 * n), 0, n); + if (result.length !== n) { + return result.subarray(0, n); + } + + return result; + }, + + alloc_float64(n) { + let result = new Float64Array(_alloc(8 * n), 0, n); + if (result.length !== n) { + return result.subarray(0, n); + } + + return result; + }, + + alloc_dataview(n) { + let result = new DataView(_alloc(n), 0, n); + if (result.length !== n) { + return result.subarray(0, n); + } + + return result; + }, + + free(array) { + _free(array.buffer); + }, + + reset() { + let _bufferPools = Array(8); + for (let i = 0; i < 8; ++i) { + _bufferPools[i] = []; + } + }, +}; \ No newline at end of file diff --git a/cocos2d/renderer/render-data/base-render-data.js b/cocos2d/renderer/render-data/base-render-data.js new file mode 100644 index 00000000000..7f74c81e81e --- /dev/null +++ b/cocos2d/renderer/render-data/base-render-data.js @@ -0,0 +1,14 @@ +// Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. + +/** + * BaseRenderData is a core data abstraction for renderer, this is a abstract class. + * An inherited render data type should define raw vertex datas. + * User should also define the effect, vertex count and index count. + */ +export default class BaseRenderData { + constructor () { + this.material = null; + this.vertexCount = 0; + this.indiceCount = 0; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/render-data/ia-render-data.js b/cocos2d/renderer/render-data/ia-render-data.js new file mode 100644 index 00000000000..265f3f16bdc --- /dev/null +++ b/cocos2d/renderer/render-data/ia-render-data.js @@ -0,0 +1,21 @@ +// Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. + +import BaseRenderData from './base-render-data'; + +/** + * IARenderData is user customized render data type, user should provide the entier input assembler. + * IARenderData just defines a property `ia` for accessing the input assembler. + * It doesn't manage memory so users should manage the memory of input assembler by themselves. + */ +export default class IARenderData extends BaseRenderData { + constructor () { + super(); + this.ia = null; + } + + get type () { + return IARenderData.type; + } +} + +IARenderData.type = 'IARenderData'; \ No newline at end of file diff --git a/cocos2d/renderer/render-data/render-data.js b/cocos2d/renderer/render-data/render-data.js new file mode 100644 index 00000000000..8f161c81bbe --- /dev/null +++ b/cocos2d/renderer/render-data/render-data.js @@ -0,0 +1,102 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import { Pool } from '../memop'; +import BaseRenderData from './base-render-data'; + +var _pool; +var _dataPool = new Pool(() => { + return { + x: 0.0, + y: 0.0, + z: 0.0, + u: 0.0, + v: 0.0, + color: 0 + }; +}, 128); + +/** + * RenderData is most widely used render data type. + * It describes raw vertex data with a fixed data layout. + * Each vertex is described by five property: x, y, u, v, color. The data layout might be extended in the future. + * Vertex data objects are managed automatically by RenderData, user only need to set the dataLength property. + * User can also define rendering index orders for the vertex list. + */ +export default class RenderData extends BaseRenderData { + constructor () { + super(); + this._data = []; + this._indices = []; + + this._pivotX = 0; + this._pivotY = 0; + this._width = 0; + this._height = 0; + + this.uvDirty = true; + this.vertDirty = true; + } + + get type () { + return RenderData.type; + } + + get dataLength () { + return this._data.length; + } + + set dataLength (length) { + let data = this._data; + if (data.length !== length) { + // Free extra data + for (let i = length; i < data.length; i++) { + _dataPool.free(data[i]); + } + // Alloc needed data + for (let i = data.length; i < length; i++) { + data[i] = _dataPool.alloc(); + } + data.length = length; + } + } + + updateSizeNPivot (width, height, pivotX, pivotY) { + if (width !== this._width || + height !== this._height || + pivotX !== this._pivotX || + pivotY !== this._pivotY) + { + this._width = width; + this._height = height; + this._pivotX = pivotX; + this._pivotY = pivotY; + this.vertDirty = true; + } + } + + static alloc () { + return _pool.alloc(); + } + + static free (data) { + if (data instanceof RenderData) { + for (let i = data.length-1; i > 0; i--) { + _dataPool.free(data._data[i]); + } + data._data.length = 0; + data._indices.length = 0; + data.material = null; + data.uvDirty = true; + data.vertDirty = true; + data.vertexCount = 0; + data.indiceCount = 0; + _pool.free(data); + } + } +} + +RenderData.type = 'RenderData'; + +_pool = new Pool(() => { + return new RenderData(); +}, 32); \ No newline at end of file diff --git a/cocos2d/renderer/renderers/forward-renderer.js b/cocos2d/renderer/renderers/forward-renderer.js new file mode 100644 index 00000000000..0ca65738fe5 --- /dev/null +++ b/cocos2d/renderer/renderers/forward-renderer.js @@ -0,0 +1,255 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import { vec3, mat4 } from '../../core/vmath'; +import BaseRenderer from '../core/base-renderer'; +import enums from '../enums'; + +let _a16_view = new Float32Array(16); +let _a16_proj = new Float32Array(16); +let _a16_viewProj = new Float32Array(16); +let _a3_camPos = new Float32Array(3); +let _a16_lightViewProj = new Float32Array(16); + +let _camPos = vec3.create(0, 0, 0); +let _camFwd = vec3.create(0, 0, 0); +let _v3_tmp1 = vec3.create(0, 0, 0); + +export default class ForwardRenderer extends BaseRenderer { + constructor(device, builtin) { + super(device, builtin); + + this._directionalLights = []; + this._pointLights = []; + this._spotLights = []; + this._shadowLights = []; + + this._numLights = 0; + + this._registerStage('shadowcast', this._shadowStage.bind(this)); + this._registerStage('opaque', this._opaqueStage.bind(this)); + this._registerStage('transparent', this._transparentStage.bind(this)); + } + + reset () { + this._reset(); + } + + render (scene) { + this._reset(); + + this._updateLights(scene); + + const canvas = this._device._gl.canvas; + for (let i = 0; i < scene._cameras.length; ++i) { + let view = this._requestView(); + let width = canvas.width; + let height = canvas.height; + let camera = scene._cameras.data[i]; + camera.extractView(view, width, height); + } + + // render by cameras + this._viewPools.sort((a, b) => { + return (a._priority - b._priority); + }); + + for (let i = 0; i < this._viewPools.length; ++i) { + let view = this._viewPools.data[i]; + this._render(view, scene); + } + } + + _updateLights (scene) { + this._directionalLights.length = 0; + this._pointLights.length = 0; + this._spotLights.length = 0; + this._shadowLights.length = 0; + + let lights = scene._lights; + for (let i = 0; i < lights.length; ++i) { + let light = lights.data[i]; + light.update(this._device); + if (light.shadowType !== enums.SHADOW_NONE) { + this._shadowLights.push(light); + let view = this._requestView(); + light.extractView(view, ['shadowcast']); + } + if (light._type === enums.LIGHT_DIRECTIONAL) { + this._directionalLights.push(light); + } else if (light._type === enums.LIGHT_POINT) { + this._pointLights.push(light); + } else { + this._spotLights.push(light); + } + } + + this._numLights = lights._count; + } + + _submitLightsUniforms () { + let device = this._device; + + if (this._directionalLights.length > 0) { + for (let index = 0; index < this._directionalLights.length; ++index) { + let light = this._directionalLights[index]; + device.setUniform(`_dir_light${index}_direction`, light._directionUniform); + device.setUniform(`_dir_light${index}_color`, light._colorUniform); + } + } + + if (this._pointLights.length > 0) { + for (let index = 0; index < this._pointLights.length; ++index) { + let light = this._pointLights[index]; + device.setUniform(`_point_light${index}_position`, light._positionUniform); + device.setUniform(`_point_light${index}_color`, light._colorUniform); + device.setUniform(`_point_light${index}_range`, light._range); + } + } + + if (this._spotLights.length > 0) { + for (let index = 0; index < this._spotLights.length; ++index) { + let light = this._spotLights[index]; + device.setUniform(`_spot_light${index}_position`, light._positionUniform); + device.setUniform(`_spot_light${index}_direction`, light._directionUniform); + device.setUniform(`_spot_light${index}_color`, light._colorUniform); + device.setUniform(`_spot_light${index}_range`, light._range); + device.setUniform(`_spot_light${index}_spot`, light._spotUniform); + } + } + } + + _submitShadowStageUniforms(view) { + let light = view._shadowLight; + this._device.setUniform('_minDepth', light.shadowMinDepth); + this._device.setUniform('_maxDepth', light.shadowMaxDepth); + this._device.setUniform('_bias', light.shadowBias); + this._device.setUniform('_depthScale', light.shadowDepthScale); + } + + _submitOtherStagesUniforms() { + for (let index = 0; index < this._shadowLights.length; ++index) { + let light = this._shadowLights[index]; + this._device.setUniform(`_lightViewProjMatrix_${index}`, mat4.array(_a16_lightViewProj, light.viewProjMatrix)); + this._device.setUniform(`_minDepth_${index}`, light.shadowMinDepth); + this._device.setUniform(`_maxDepth_${index}`, light.shadowMaxDepth); + this._device.setUniform(`_bias_${index}`, light.shadowBias); + this._device.setUniform(`_depthScale_${index}`, light.shadowDepthScale); + this._device.setUniform(`_darkness_${index}`, light.shadowDarkness); + this._device.setUniform(`_frustumEdgeFalloff_${index}`, light.frustumEdgeFalloff); + this._device.setUniform(`_texelSize_${index}`, new Float32Array([1.0 / light.shadowResolution, 1.0 / light.shadowResolution])); + } + } + + _updateShaderDefines (item) { + let defines = item.defines; + + defines._NUM_DIR_LIGHTS = Math.min(4, this._directionalLights.length); + defines._NUM_POINT_LIGHTS = Math.min(4, this._pointLights.length); + defines._NUM_SPOT_LIGHTS = Math.min(4, this._spotLights.length); + + defines._NUM_SHADOW_LIGHTS = Math.min(4, this._shadowLights.length); + } + + _sortItems (items) { + // sort items + items.sort((a, b) => { + let techA = a.technique; + let techB = b.technique; + + if (techA._layer !== techB._layer) { + return techA._layer - techB._layer; + } + + if (techA._passes.length !== techB._passes.length) { + return techA._passes.length - techB._passes.length; + } + + return a.sortKey - b.sortKey; + }); + } + + _shadowStage (view, items) { + this._device.setUniform('_lightViewProjMatrix', mat4.array(_a16_viewProj, view._matViewProj)); + + // update rendering + this._submitShadowStageUniforms(view); + + // this._sortItems(items); + + // draw it + for (let i = 0; i < items.length; ++i) { + let item = items.data[i]; + if (item.defines._SHADOW_CASTING) { + this._updateShaderDefines(item); + this._draw(item); + } + } + } + + _drawItems (view, items) { + let shadowLights = this._shadowLights; + if (shadowLights.length === 0 && this._numLights === 0) { + for (let i = 0; i < items.length; ++i) { + let item = items.data[i]; + this._draw(item); + } + } + else { + for (let i = 0; i < items.length; ++i) { + let item = items.data[i]; + + for (let index = 0; index < shadowLights.length; ++index) { + let light = shadowLights[index]; + this._device.setTexture(`_shadowMap_${index}`, light.shadowMap, this._allocTextureUnit()); + } + + this._updateShaderDefines(item); + this._draw(item); + } + } + } + + _opaqueStage (view, items) { + view.getPosition(_camPos); + + // update uniforms + this._device.setUniform('_view', mat4.array(_a16_view, view._matView)); + this._device.setUniform('_proj', mat4.array(_a16_proj, view._matProj)); + this._device.setUniform('_viewProj', mat4.array(_a16_viewProj, view._matViewProj)); + this._device.setUniform('_eye', vec3.array(_a3_camPos, _camPos)); + + // update rendering + this._submitLightsUniforms(); + this._submitOtherStagesUniforms(); + + this._drawItems(view, items); + } + + _transparentStage (view, items) { + view.getPosition(_camPos); + view.getForward(_camFwd); + + // update uniforms + this._device.setUniform('_view', mat4.array(_a16_view, view._matView)); + this._device.setUniform('_proj', mat4.array(_a16_proj, view._matProj)); + this._device.setUniform('_viewProj', mat4.array(_a16_viewProj, view._matViewProj)); + this._device.setUniform('_eye', vec3.array(_a3_camPos, _camPos)); + + this._submitLightsUniforms(); + this._submitOtherStagesUniforms(); + + // calculate zdist + for (let i = 0; i < items.length; ++i) { + let item = items.data[i]; + + // TODO: we should use mesh center instead! + item.node.getWorldPosition(_v3_tmp1); + + vec3.sub(_v3_tmp1, _v3_tmp1, _camPos); + item.sortKey = -vec3.dot(_v3_tmp1, _camFwd); + } + + this._sortItems(items); + this._drawItems(view, items); + } +} \ No newline at end of file diff --git a/cocos2d/renderer/scene/camera.js b/cocos2d/renderer/scene/camera.js new file mode 100644 index 00000000000..67660f54503 --- /dev/null +++ b/cocos2d/renderer/scene/camera.js @@ -0,0 +1,466 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import { color4, vec3, mat4, lerp } from '../../core/vmath'; +import { ray } from '../../core/3d/geom-utils'; +import enums from '../enums'; + +let _matView = mat4.create(); +let _matProj = mat4.create(); +let _matViewProj = mat4.create(); +let _matInvViewProj = mat4.create(); +let _tmp_v3 = vec3.create(); +let _tmp2_v3 = vec3.create(); + +/** + * A representation of a camera instance + */ +export default class Camera { + /** + * Setup a default perspective camera + */ + constructor() { + this._poolID = -1; + this._node = null; + + // + this._projection = enums.PROJ_PERSPECTIVE; + + // priority. the smaller one will be rendered first + this._priority = 0; + + // clear options + this._color = color4.create(0.2, 0.3, 0.47, 1); + this._depth = 1; + this._stencil = 0; + this._clearFlags = enums.CLEAR_COLOR | enums.CLEAR_DEPTH; + this._clearModel = null; + + // stages & framebuffer + this._stages = []; + this._framebuffer = null; + + // projection properties + this._near = 0.01; + this._far = 1000.0; + this._fov = Math.PI/4.0; // vertical fov + this._rect = { + x: 0, y: 0, w: 1, h: 1 + }; + + // ortho properties + this._orthoHeight = 10; + + this._cullingMask = 0xffffffff; + } + + /** + * Get the hosting node of this camera + * @returns {Node} the hosting node + */ + getNode() { + return this._node; + } + + /** + * Set the hosting node of this camera + * @param {Node} node the hosting node + */ + setNode(node) { + this._node = node; + } + + /** + * Get the projection type of the camera + * @returns {number} camera projection type + */ + getType() { + return this._projection; + } + + /** + * Set the projection type of the camera + * @param {number} type camera projection type + */ + setType(type) { + this._projection = type; + } + + /** + * Get the priority of the camera + * @returns {number} camera priority + */ + getPriority() { + return this._priority; + } + + /** + * Set the priority of the camera + * @param {number} priority camera priority + */ + setPriority(priority) { + this._priority = priority; + } + + /** + * Get the orthogonal height of the camera + * @returns {number} camera height + */ + getOrthoHeight() { + return this._orthoHeight; + } + + /** + * Set the orthogonal height of the camera + * @param {number} val camera height + */ + setOrthoHeight(val) { + this._orthoHeight = val; + } + + /** + * Get the field of view of the camera + * @returns {number} camera field of view + */ + getFov() { + return this._fov; + } + + /** + * Set the field of view of the camera + * @param {number} fov camera field of view + */ + setFov(fov) { + this._fov = fov; + } + + /** + * Get the near clipping distance of the camera + * @returns {number} camera near clipping distance + */ + getNear() { + return this._near; + } + + /** + * Set the near clipping distance of the camera + * @param {number} near camera near clipping distance + */ + setNear(near) { + this._near = near; + } + + /** + * Get the far clipping distance of the camera + * @returns {number} camera far clipping distance + */ + getFar() { + return this._far; + } + + /** + * Set the far clipping distance of the camera + * @param {number} far camera far clipping distance + */ + setFar(far) { + this._far = far; + } + + /** + * Get the clear color of the camera + * @returns {color4} out the receiving color vector + */ + getColor(out) { + return color4.copy(out, this._color); + } + + /** + * Set the clear color of the camera + * @param {number} r red channel of camera clear color + * @param {number} g green channel of camera clear color + * @param {number} b blue channel of camera clear color + * @param {number} a alpha channel of camera clear color + */ + setColor(r, g, b, a) { + color4.set(this._color, r, g, b, a); + } + + /** + * Get the clear depth of the camera + * @returns {number} camera clear depth + */ + getDepth() { + return this._depth; + } + + /** + * Set the clear depth of the camera + * @param {number} depth camera clear depth + */ + setDepth(depth) { + this._depth = depth; + } + + /** + * Get the clearing stencil value of the camera + * @returns {number} camera clearing stencil value + */ + getStencil() { + return this._stencil; + } + + /** + * Set the clearing stencil value of the camera + * @param {number} stencil camera clearing stencil value + */ + setStencil(stencil) { + this._stencil = stencil; + } + + /** + * Get the clearing flags of the camera + * @returns {number} camera clearing flags + */ + getClearFlags() { + return this._clearFlags; + } + + /** + * Set the clearing flags of the camera + * @param {number} flags camera clearing flags + */ + setClearFlags(flags) { + this._clearFlags = flags; + } + + /** + * Get the rect of the camera + * @param {Object} out the receiving object + * @returns {Object} camera rect + */ + getRect(out) { + out.x = this._rect.x; + out.y = this._rect.y; + out.w = this._rect.w; + out.h = this._rect.h; + + return out; + } + + /** + * Set the rect of the camera + * @param {Number} x - [0,1] + * @param {Number} y - [0,1] + * @param {Number} w - [0,1] + * @param {Number} h - [0,1] + */ + setRect(x, y, w, h) { + this._rect.x = x; + this._rect.y = y; + this._rect.w = w; + this._rect.h = h; + } + + /** + * Get the stages of the camera + * @returns {string[]} camera stages + */ + getStages() { + return this._stages; + } + + /** + * Set the stages of the camera + * @param {string[]} stages camera stages + */ + setStages(stages) { + this._stages = stages; + } + + /** + * Get the framebuffer of the camera + * @returns {FrameBuffer} camera framebuffer + */ + getFramebuffer() { + return this._framebuffer; + } + + /** + * Set the framebuffer of the camera + * @param {FrameBuffer} framebuffer camera framebuffer + */ + setFramebuffer(framebuffer) { + this._framebuffer = framebuffer; + } + + _calcMatrices(width, height) { + // view matrix + this._node.getWorldRT(_matView); + mat4.invert(_matView, _matView); + + // projection matrix + let aspect = width / height; + if (this._projection === enums.PROJ_PERSPECTIVE) { + mat4.perspective(_matProj, + this._fov, + aspect, + this._near, + this._far + ); + } else { + let x = this._orthoHeight * aspect; + let y = this._orthoHeight; + mat4.ortho(_matProj, + -x, x, -y, y, this._near, this._far + ); + } + + // view-projection + mat4.mul(_matViewProj, _matProj, _matView); + // inv view-projection + mat4.invert(_matInvViewProj, _matViewProj); + } + + /** + * extract a view of this camera + * @param {View} out the receiving view + * @param {number} width framebuffer width + * @param {number} height framebuffer height + */ + extractView(out, width, height) { + if (this._framebuffer) { + width = this._framebuffer._width; + height = this._framebuffer._height; + } + + // priority + out._priority = this._priority; + + // rect + out._rect.x = this._rect.x * width; + out._rect.y = this._rect.y * height; + out._rect.w = this._rect.w * width; + out._rect.h = this._rect.h * height; + + // clear opts + this.getColor(out._color); + out._depth = this._depth; + out._stencil = this._stencil; + out._clearFlags = this._clearFlags; + out._clearModel = this._clearModel; + + // stages & framebuffer + out._stages = this._stages; + out._framebuffer = this._framebuffer; + + this._calcMatrices(width, height); + mat4.copy(out._matView, _matView); + mat4.copy(out._matProj, _matProj); + mat4.copy(out._matViewProj, _matViewProj); + mat4.copy(out._matInvViewProj, _matInvViewProj); + + out._cullingMask = this._cullingMask; + } + + /** + * transform a screen position to a world space ray + * @param {number} x the screen x position to be transformed + * @param {number} y the screen y position to be transformed + * @param {number} width framebuffer width + * @param {number} height framebuffer height + * @param {ray} out the resulting ray + * @returns {Ray} the resulting ray + */ + screenPointToRay(x, y, width, height, out) { + out = out || ray.create(); + this._calcMatrices(width, height); + + let cx = this._rect.x * width; + let cy = this._rect.y * height; + let cw = this._rect.w * width; + let ch = this._rect.h * height; + + // far plane intersection + vec3.set(_tmp2_v3, (x - cx) / cw * 2 - 1, (y - cy) / ch * 2 - 1, 1); + vec3.transformMat4(_tmp2_v3, _tmp2_v3, _matInvViewProj); + + if (this._projection === enums.PROJ_PERSPECTIVE) { + // camera origin + this._node.getWorldPosition(_tmp_v3); + } else { + // near plane intersection + vec3.set(_tmp_v3, (x - cx) / cw * 2 - 1, (y - cy) / ch * 2 - 1, -1); + vec3.transformMat4(_tmp_v3, _tmp_v3, _matInvViewProj); + } + + return ray.fromPoints(out, _tmp_v3, _tmp2_v3); + } + + /** + * transform a screen position to world space + * @param {vec3} out the resulting vector + * @param {vec3} screenPos the screen position to be transformed + * @param {number} width framebuffer width + * @param {number} height framebuffer height + * @returns {vec3} the resulting vector + */ + screenToWorld(out, screenPos, width, height) { + this._calcMatrices(width, height); + + let cx = this._rect.x * width; + let cy = this._rect.y * height; + let cw = this._rect.w * width; + let ch = this._rect.h * height; + + if (this._projection === enums.PROJ_PERSPECTIVE) { + // calculate screen pos in far clip plane + vec3.set(out, + (screenPos.x - cx) / cw * 2 - 1, + (screenPos.y - cy) / ch * 2 - 1, + 1.0 + ); + + // transform to world + vec3.transformMat4(out, out, _matInvViewProj); + + // lerp to depth z + this._node.getWorldPosition(_tmp_v3); + + vec3.lerp(out, _tmp_v3, out, lerp(this._near / this._far, 1, screenPos.z)); + } else { + vec3.set(out, + (screenPos.x - cx) / cw * 2 - 1, + (screenPos.y - cy) / ch * 2 - 1, + screenPos.z * 2 - 1 + ); + + // transform to world + vec3.transformMat4(out, out, _matInvViewProj); + } + + return out; + } + + /** + * transform a world space position to screen space + * @param {vec3} out the resulting vector + * @param {vec3} worldPos the world space position to be transformed + * @param {number} width framebuffer width + * @param {number} height framebuffer height + * @returns {vec3} the resulting vector + */ + worldToScreen(out, worldPos, width, height) { + this._calcMatrices(width, height); + + let cx = this._rect.x * width; + let cy = this._rect.y * height; + let cw = this._rect.w * width; + let ch = this._rect.h * height; + + vec3.transformMat4(out, worldPos, _matViewProj); + out.x = cx + (out.x + 1) * 0.5 * cw; + out.y = cy + (out.y + 1) * 0.5 * ch; + out.z = out.z * 0.5 + 0.5; + + return out; + } +} diff --git a/cocos2d/renderer/scene/light.js b/cocos2d/renderer/scene/light.js new file mode 100644 index 00000000000..672efe6125f --- /dev/null +++ b/cocos2d/renderer/scene/light.js @@ -0,0 +1,492 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import { color3, color4, mat4, mat3, vec3, toRadian } from '../../core/vmath'; +import gfx from '../gfx'; + +import enums from '../enums'; + +const _forward = vec3.create(0, 0, -1); + +let _m4_tmp = mat4.create(); +let _m3_tmp = mat3.create(); +let _transformedLightDirection = vec3.create(0, 0, 0); + +// compute light viewProjMat for shadow. +function _computeSpotLightViewProjMatrix(light, outView, outProj) { + // view matrix + light._node.getWorldRT(outView); + mat4.invert(outView, outView); + + // proj matrix + mat4.perspective(outProj, light._spotAngle * light._spotAngleScale, 1, light._shadowMinDepth, light._shadowMaxDepth); +} + +function _computeDirectionalLightViewProjMatrix(light, outView, outProj) { + // view matrix + light._node.getWorldRT(outView); + mat4.invert(outView, outView); + + // TODO: should compute directional light frustum based on rendered meshes in scene. + // proj matrix + let halfSize = light._shadowFrustumSize / 2; + mat4.ortho(outProj, -halfSize, halfSize, -halfSize, halfSize, light._shadowMinDepth, light._shadowMaxDepth); +} + +function _computePointLightViewProjMatrix(light, outView, outProj) { + // view matrix + light._node.getWorldRT(outView); + mat4.invert(outView, outView); + + // The transformation from Cartesian to polar coordinates is not a linear function, + // so it cannot be achieved by means of a fixed matrix multiplication. + // Here we just use a nearly 180 degree perspective matrix instead. + mat4.perspective(outProj, toRadian(179), 1, light._shadowMinDepth, light._shadowMaxDepth); +} + +/** + * A representation of a light source. + * Could be a point light, a spot light or a directional light. + */ +export default class Light { + /** + * Setup a default directional light with no shadows + */ + constructor() { + this._poolID = -1; + this._node = null; + + this._type = enums.LIGHT_DIRECTIONAL; + + this._color = color3.create(1, 1, 1); + this._intensity = 1; + + // used for spot and point light + this._range = 1; + // used for spot light, default to 60 degrees + this._spotAngle = toRadian(60); + this._spotExp = 1; + // cached for uniform + this._directionUniform = new Float32Array(3); + this._positionUniform = new Float32Array(3); + this._colorUniform = new Float32Array([this._color.r * this._intensity, this._color.g * this._intensity, this._color.b * this._intensity]); + this._spotUniform = new Float32Array([Math.cos(this._spotAngle * 0.5), this._spotExp]); + + // shadow params + this._shadowType = enums.SHADOW_NONE; + this._shadowFrameBuffer = null; + this._shadowMap = null; + this._shadowMapDirty = false; + this._shadowDepthBuffer = null; + this._shadowResolution = 1024; + this._shadowBias = 0.0005; + this._shadowDarkness = 1; + this._shadowMinDepth = 1; + this._shadowMaxDepth = 1000; + this._shadowDepthScale = 50; // maybe need to change it if the distance between shadowMaxDepth and shadowMinDepth is small. + this._frustumEdgeFalloff = 0; // used by directional and spot light. + this._viewProjMatrix = mat4.create(); + this._spotAngleScale = 1; // used for spot light. + this._shadowFrustumSize = 50; // used for directional light. + } + + /** + * set the hosting node of this light + * @param {Node} node the hosting node + */ + setNode(node) { + this._node = node; + } + + /** + * set the color of the light source + * @param {number} r red channel of the light color + * @param {number} g green channel of the light color + * @param {number} b blue channel of the light color + */ + setColor(r, g, b) { + color3.set(this._color, r, g, b); + this._colorUniform[0] = r * this._intensity; + this._colorUniform[1] = g * this._intensity; + this._colorUniform[2] = b * this._intensity; + } + + /** + * get the color of the light source + * @returns {color3} the light color + */ + get color() { + return this._color; + } + + /** + * set the intensity of the light source + * @param {number} val the light intensity + */ + setIntensity(val) { + this._intensity = val; + this._colorUniform[0] = val * this._color.r; + this._colorUniform[1] = val * this._color.g; + this._colorUniform[2] = val * this._color.b; + } + + /** + * get the intensity of the light source + * @returns {number} the light intensity + */ + get intensity() { + return this._intensity; + } + + /** + * set the type of the light source + * @param {number} type light source type + */ + setType(type) { + this._type = type; + } + + /** + * get the type of the light source + * @returns {number} light source type + */ + get type() { + return this._type; + } + + /** + * set the spot light angle + * @param {number} val spot light angle + */ + setSpotAngle(val) { + this._spotAngle = val; + this._spotUniform[0] = Math.cos(this._spotAngle * 0.5); + } + + /** + * get the spot light angle + * @returns {number} spot light angle + */ + get spotAngle() { + return this._spotAngle; + } + + /** + * set the spot light exponential + * @param {number} val spot light exponential + */ + setSpotExp(val) { + this._spotExp = val; + this._spotUniform[1] = val; + } + + /** + * get the spot light exponential + * @returns {number} spot light exponential + */ + get spotExp() { + return this._spotExp; + } + + /** + * set the range of the light source + * @param {number} val light source range + */ + setRange(val) { + this._range = val; + } + + /** + * get the range of the light source + * @returns {number} range of the light source + */ + get range() { + return this._range; + } + + /** + * set the shadow type of the light source + * @param {number} type light source shadow type + */ + setShadowType(type) { + if (this._shadowType === enums.SHADOW_NONE && type !== enums.SHADOW_NONE) { + this._shadowMapDirty = true; + } + this._shadowType = type; + } + + /** + * get the shadow type of the light source + * @returns {number} light source shadow type + */ + get shadowType() { + return this._shadowType; + } + + /** + * get the shadowmap of the light source + * @returns {Texture2D} light source shadowmap + */ + get shadowMap() { + return this._shadowMap; + } + + /** + * get the view-projection matrix of the light source + * @returns {mat4} light source view-projection matrix + */ + get viewProjMatrix() { + return this._viewProjMatrix; + } + + /** + * set the shadow resolution of the light source + * @param {number} val light source shadow resolution + */ + setShadowResolution(val) { + if (this._shadowResolution !== val) { + this._shadowMapDirty = true; + } + this._shadowResolution = val; + } + + /** + * get the shadow resolution of the light source + * @returns {number} light source shadow resolution + */ + get shadowResolution() { + return this._shadowResolution; + } + + /** + * set the shadow bias of the light source + * @param {number} val light source shadow bias + */ + setShadowBias(val) { + this._shadowBias = val; + } + + /** + * get the shadow bias of the light source + * @returns {number} light source shadow bias + */ + get shadowBias() { + return this._shadowBias; + } + + /** + * set the shadow darkness of the light source + * @param {number} val light source shadow darkness + */ + setShadowDarkness(val) { + this._shadowDarkness = val; + } + + /** + * get the shadow darkness of the light source + * @returns {number} light source shadow darkness + */ + get shadowDarkness() { + return this._shadowDarkness; + } + + /** + * set the shadow min depth of the light source + * @param {number} val light source shadow min depth + */ + setShadowMinDepth(val) { + this._shadowMinDepth = val; + } + + /** + * get the shadow min depth of the light source + * @returns {number} light source shadow min depth + */ + get shadowMinDepth() { + if (this._type === enums.LIGHT_DIRECTIONAL) { + return 1.0; + } + return this._shadowMinDepth; + } + + /** + * set the shadow max depth of the light source + * @param {number} val light source shadow max depth + */ + setShadowMaxDepth(val) { + this._shadowMaxDepth = val; + } + + /** + * get the shadow max depth of the light source + * @returns {number} light source shadow max depth + */ + get shadowMaxDepth() { + if (this._type === enums.LIGHT_DIRECTIONAL) { + return 1.0; + } + return this._shadowMaxDepth; + } + + /** + * set the shadow depth scale of the light source + * @param {number} val light source shadow depth scale + */ + setShadowDepthScale(val) { + this._shadowDepthScale = val; + } + + /** + * get the shadow depth scale of the light source + * @returns {number} light source shadow depth scale + */ + get shadowDepthScale() { + return this._shadowDepthScale; + } + + /** + * set the frustum edge falloff of the light source + * @param {number} val light source frustum edge falloff + */ + setFrustumEdgeFalloff(val) { + this._frustumEdgeFalloff = val; + } + + /** + * get the frustum edge falloff of the light source + * @returns {number} light source frustum edge falloff + */ + get frustumEdgeFalloff() { + return this._frustumEdgeFalloff; + } + + /** + * set the shadow frustum size of the light source + * @param {number} val light source shadow frustum size + */ + setShadowFrustumSize(val) { + this._shadowFrustumSize = val; + } + + /** + * get the shadow frustum size of the light source + * @returns {number} light source shadow frustum size + */ + get shadowFrustumSize() { + return this._shadowFrustumSize; + } + + /** + * extract a view of this light source + * @param {View} out the receiving view + * @param {string[]} stages the stages using the view + */ + extractView(out, stages) { + // TODO: view should not handle light. + out._shadowLight = this; + + // priority. TODO: use varying value for shadow view? + out._priority = -1; + + // rect + out._rect.x = 0; + out._rect.y = 0; + out._rect.w = this._shadowResolution; + out._rect.h = this._shadowResolution; + + // clear opts + color4.set(out._color, 1, 1, 1, 1); + out._depth = 1; + out._stencil = 1; + out._clearFlags = enums.CLEAR_COLOR | enums.CLEAR_DEPTH; + + // stages & framebuffer + out._stages = stages; + out._framebuffer = this._shadowFrameBuffer; + + // view projection matrix + switch(this._type) { + case enums.LIGHT_SPOT: + _computeSpotLightViewProjMatrix(this, out._matView, out._matProj); + break; + + case enums.LIGHT_DIRECTIONAL: + _computeDirectionalLightViewProjMatrix(this, out._matView, out._matProj); + break; + + case enums.LIGHT_POINT: + _computePointLightViewProjMatrix(this, out._matView, out._matProj); + break; + + default: + console.warn('shadow of this light type is not supported'); + } + + // view-projection + mat4.mul(out._matViewProj, out._matProj, out._matView); + this._viewProjMatrix = out._matViewProj; + mat4.invert(out._matInvViewProj, out._matViewProj); + + // update view's frustum + // out._frustum.update(out._matViewProj, out._matInvViewProj); + + out._cullingMask = 0xffffffff; + } + + _updateLightPositionAndDirection() { + this._node.getWorldMatrix(_m4_tmp); + mat3.fromMat4(_m3_tmp, _m4_tmp); + vec3.transformMat3(_transformedLightDirection, _forward, _m3_tmp); + vec3.array(this._directionUniform, _transformedLightDirection); + let pos = this._positionUniform; + pos[0] = _m4_tmp.m12; + pos[1] = _m4_tmp.m13; + pos[2] = _m4_tmp.m14; + } + + _generateShadowMap(device) { + this._shadowMap = new gfx.Texture2D(device, { + width: this._shadowResolution, + height: this._shadowResolution, + format: gfx.TEXTURE_FMT_RGBA8, + wrapS: gfx.WRAP_CLAMP, + wrapT: gfx.WRAP_CLAMP, + }); + this._shadowDepthBuffer = new gfx.RenderBuffer(device, + gfx.RB_FMT_D16, + this._shadowResolution, + this._shadowResolution + ); + this._shadowFrameBuffer = new gfx.FrameBuffer(device, this._shadowResolution, this._shadowResolution, { + colors: [this._shadowMap], + depth: this._shadowDepthBuffer, + }); + } + + _destroyShadowMap() { + if (this._shadowMap) { + this._shadowMap.destroy(); + this._shadowDepthBuffer.destroy(); + this._shadowFrameBuffer.destroy(); + this._shadowMap = null; + this._shadowDepthBuffer = null; + this._shadowFrameBuffer = null; + } + } + + /** + * update the light source + * @param {Device} device the rendering device + */ + update(device) { + this._updateLightPositionAndDirection(); + + if (this._shadowType === enums.SHADOW_NONE) { + this._destroyShadowMap(); + } else if (this._shadowMapDirty) { + this._destroyShadowMap(); + this._generateShadowMap(device); + this._shadowMapDirty = false; + } + + } +} \ No newline at end of file diff --git a/cocos2d/renderer/scene/model.js b/cocos2d/renderer/scene/model.js new file mode 100644 index 00000000000..6e0291bacf9 --- /dev/null +++ b/cocos2d/renderer/scene/model.js @@ -0,0 +1,104 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +import { aabb } from '../../core/3d/geom-utils'; + +/** + * A representation of a model + */ +export default class Model { + /** + * Setup a default empty model + */ + constructor() { + this._type = 'default'; + this._poolID = -1; + this._node = null; + this._inputAssembler = null; + this._effect = null; + this._defines = {}; + this._dependencies = {}; + this._viewID = -1; + this._cameraID = -1; + this._userKey = -1; + this._castShadow = false; + this._boundingShape = null; + this._uniforms = null; + } + + _updateTransform() { + if (!this._node._hasChanged || !this._boundingShape) return; + this._node.updateWorldTransformFull(); + this._bsModelSpace.transform(this._node._mat, this._node._pos, + this._node._rot, this._node._scale, this._boundingShape); + } + + /** + * Create the bounding shape of this model + * @param {vec3} minPos the min position of the model + * @param {vec3} maxPos the max position of the model + */ + createBoundingShape(minPos, maxPos) { + if (!minPos || !maxPos) return; + this._bsModelSpace = aabb.fromPoints(aabb.create(), minPos, maxPos); + this._boundingShape = aabb.clone(this._bsModelSpace); + } + + /** + * Set the hosting node of this model + * @param {Node} node the hosting node + */ + setNode(node) { + this._node = node; + } + + /** + * Set the input assembler + * @param {InputAssembler} ia + */ + setInputAssembler(ia) { + this._inputAssembler = ia; + } + + /** + * Set the model effect + * @param {?Effect} effect the effect to use + */ + setEffect(effect, customProperties) { + this._defines = Object.create(null); + this._dependencies = Object.create(null); + this._uniforms = Object.create(null); + this._effect = effect; + + if (effect) { + effect.extractDefines(this._defines); + effect.extractProperties(this._uniforms); + effect.extractDependencies(this._dependencies); + } + + if (customProperties) { + customProperties.extractDefines(this._defines); + customProperties.extractProperties(this._uniforms); + } + } + + /** + * Set the user key + * @param {number} key + */ + setUserKey(key) { + this._userKey = key; + } + + /** + * Extract a drawing item + * @param {Object} out the receiving item + */ + extractDrawItem(out) { + out.model = this; + out.node = this._node; + out.ia = this._inputAssembler; + out.effect = this._effect; + out.defines = this._defines; + out.dependencies = this._dependencies; + out.uniforms = this._uniforms; + } +} \ No newline at end of file diff --git a/cocos2d/renderer/scene/scene.js b/cocos2d/renderer/scene/scene.js new file mode 100644 index 00000000000..0f338ba1969 --- /dev/null +++ b/cocos2d/renderer/scene/scene.js @@ -0,0 +1,192 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +import { FixedArray } from '../memop'; + +/** + * A representation of the scene + */ +class Scene { + /** + * Setup a default empty scene + */ + constructor(app) { + this._lights = new FixedArray(16); + this._models = new FixedArray(16); + this._cameras = new FixedArray(16); + this._debugCamera = null; + this._app = app; + + // NOTE: we don't use pool for views (because it's less changed and it doesn't have poolID) + this._views = []; + } + + _add(pool, item) { + if (item._poolID !== -1) { + return; + } + + pool.push(item); + item._poolID = pool.length - 1; + } + + _remove(pool, item) { + if (item._poolID === -1) { + return; + } + + pool.data[pool.length-1]._poolID = item._poolID; + pool.fastRemove(item._poolID); + item._poolID = -1; + } + + /** + * update built-in bounding shapes if needed, + * used in the frustum culling process + */ + tick() { + for (let i = 0; i < this._models.length; ++i) { + let model = this._models.data[i]; + model._updateTransform(); + } + } + + /** + * reset the model viewIDs + */ + reset() { + for (let i = 0; i < this._models.length; ++i) { + let model = this._models.data[i]; + model._viewID = -1; + } + } + + /** + * Set the debug camera + * @param {Camera} cam the debug camera + */ + setDebugCamera(cam) { + this._debugCamera = cam; + } + + /** + * Get the count of registered cameras + * @returns {number} camera count + */ + getCameraCount() { + return this._cameras.length; + } + + /** + * Get the specified camera + * @param {number} idx camera index + * @returns {Camera} the specified camera + */ + getCamera(idx) { + return this._cameras.data[idx]; + } + + /** + * register a camera + * @param {Camera} camera the new camera + */ + addCamera(camera) { + this._add(this._cameras, camera); + } + + /** + * remove a camera + * @param {Camera} camera the camera to be removed + */ + removeCamera(camera) { + this._remove(this._cameras, camera); + } + + /** + * Get the count of registered model + * @returns {number} model count + */ + getModelCount() { + return this._models.length; + } + + /** + * Get the specified model + * @param {number} idx model index + * @returns {Model} the specified model + */ + getModel(idx) { + return this._models.data[idx]; + } + + /** + * register a model + * @param {Model} model the new model + */ + addModel(model) { + this._add(this._models, model); + } + + /** + * remove a model + * @param {Model} model the model to be removed + */ + removeModel(model) { + this._remove(this._models, model); + } + + /** + * Get the count of registered light + * @returns {number} light count + */ + getLightCount() { + return this._lights.length; + } + + /** + * Get the specified light + * @param {number} idx light index + * @returns {Light} the specified light + */ + getLight(idx) { + return this._lights.data[idx]; + } + + /** + * register a light + * @param {Light} light the new light + */ + addLight(light) { + this._add(this._lights, light); + } + + /** + * remove a light + * @param {Light} light the light to be removed + */ + removeLight(light) { + this._remove(this._lights, light); + } + + /** + * register a view + * @param {View} view the new view + */ + addView(view) { + if (this._views.indexOf(view) === -1) { + this._views.push(view); + } + } + + /** + * remove a view + * @param {View} view the view to be removed + */ + removeView(view) { + let idx = this._views.indexOf(view); + if (idx !== -1) { + this._views.splice(idx, 1); + } + } +} + +export default Scene; diff --git a/cocos2d/renderer/types.js b/cocos2d/renderer/types.js new file mode 100644 index 00000000000..5f5edf11644 --- /dev/null +++ b/cocos2d/renderer/types.js @@ -0,0 +1,60 @@ +import enums from './enums'; +import { Vec2, Vec3, Vec4, Color, Mat4 } from '../core/value-types'; +import Texture2D from '../core/assets/CCTexture2D'; +import gfxTexture2D from './gfx/texture-2d'; +import gfxTextureCube from './gfx/texture-cube'; + +const CCObject = cc.Object; + +export let ctor2default = { + [Number]: v => v || 0, + [Boolean]: v => v || false, + [Vec2]: v => v ? cc.v2(v[0], v[1]) : cc.v2(), + [Vec3]: v => v ? cc.v3(v[0], v[1], v[2]) : cc.v3(), + [Vec4]: v => v ? cc.v4(v[0], v[1], v[2], v[3]) : cc.v4(), + [Color]: v => v ? cc.color(v[0] * 255, v[1] * 255, v[2] * 255, + (v[3] || 1) * 255) : cc.color(), + [Mat4]: v => v ? cc.mat4( + v[0], v[1], v[2], v[3], + v[4], v[5], v[6], v[7], + v[8], v[9], v[10], v[11], + v[12], v[13], v[14], v[15], + ) : cc.mat4(), + [Texture2D]: () => null, + // [TextureCube]: () => null, + [CCObject]: () => null +}; + + +export let enums2ctor = { + [enums.PARAM_INT]: Number, + [enums.PARAM_INT2]: Vec2, + [enums.PARAM_INT3]: Vec3, + [enums.PARAM_INT4]: Vec4, + [enums.PARAM_FLOAT]: Number, + [enums.PARAM_FLOAT2]: Vec2, + [enums.PARAM_FLOAT3]: Vec3, + [enums.PARAM_FLOAT4]: Vec4, + [enums.PARAM_COLOR3]: Color, + [enums.PARAM_COLOR4]: Color, + [enums.PARAM_MAT4]: Mat4, + [enums.PARAM_TEXTURE_2D]: Texture2D, + // [enums.PARAM_TEXTURE_CUBE]: TextureCube, + number: Number, + boolean: Boolean, + default: CCObject +}; + +export let ctor2enums = { + [Number]: enums.PARAM_FLOAT, + [Vec2]: enums.PARAM_FLOAT2, + [Vec3]: enums.PARAM_FLOAT3, + [Vec4]: enums.PARAM_FLOAT4, + [Color]: enums.PARAM_COLOR3, + [Color]: enums.PARAM_COLOR4, + [Mat4]: enums.PARAM_MAT4, + [Texture2D]: enums.PARAM_TEXTURE_2D, + [gfxTexture2D]: enums.PARAM_TEXTURE_2D, + // [TextureCube]: enums.PARAM_TEXTURE_CUBE, + // [gfxTextureCube]: enums.PARAM_TEXTURE_CUBE, +}; diff --git a/cocos2d/tilemap/CCTiledLayer.js b/cocos2d/tilemap/CCTiledLayer.js index a8525ae91e5..fc9fedd30d5 100644 --- a/cocos2d/tilemap/CCTiledLayer.js +++ b/cocos2d/tilemap/CCTiledLayer.js @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ const RenderComponent = require('../core/components/CCRenderComponent'); -const Material = require('../core/assets/CCMaterial'); +const Material = require('../core/assets/material/CCMaterial'); /** * !#en Render the TMX layer. @@ -633,7 +633,7 @@ let TiledLayer = cc.Class({ let material = this.sharedMaterials[0]; if (!material) { material = Material.getInstantiatedBuiltinMaterial('sprite', this); - material.define('useTexture', true); + material.define('USE_TEXTURE', true); } if (this._texture) { @@ -646,8 +646,6 @@ let TiledLayer = cc.Class({ else { this.disableRender(); } - - this.setMaterial(0, material); }, }); diff --git a/cocos2d/tilemap/tmx-layer-assembler.js b/cocos2d/tilemap/tmx-layer-assembler.js index b0cf893776a..309f4eea485 100644 --- a/cocos2d/tilemap/tmx-layer-assembler.js +++ b/cocos2d/tilemap/tmx-layer-assembler.js @@ -26,7 +26,6 @@ const TiledLayer = require('./CCTiledLayer'); const TiledMap = require('./CCTiledMap'); -const renderEngine = require('../core/renderer/render-engine'); const RenderFlow = require('../core/renderer/render-flow'); const Orientation = TiledMap.Orientation; @@ -35,9 +34,7 @@ const FLIPPED_MASK = TileFlag.FLIPPED_MASK; const StaggerAxis = TiledMap.StaggerAxis; const StaggerIndex = TiledMap.StaggerIndex; -const math = renderEngine.math; -const mat4 = math.mat4; -const vec3 = math.vec3; +import { mat4, vec3 } from '../core/vmath'; let _mat4_temp = mat4.create(); let _mat4_temp2 = mat4.create(); @@ -149,7 +146,7 @@ let tmxAssembler = { let cullingA = a, cullingD = d, cullingMapx = tx, cullingMapy = ty, cullingW = w, cullingH = h; - let enabledCulling = cc.macro.ENABLE_TILEDMAP_CULLING; + let enabledCulling = !CC_EDITOR && cc.macro.ENABLE_TILEDMAP_CULLING; if (enabledCulling) { let camera = cc.Camera.findCamera(comp.node); diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 83f9ef1e4fd..e664db053bb 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -23,10 +23,10 @@ THE SOFTWARE. ****************************************************************************/ +import { mat4 } from '../core/vmath'; + const utils = require('../core/platform/utils'); const sys = require('../core/platform/CCSys'); -const renderEngine = require('../core/renderer/render-engine'); -const math = renderEngine.math; const READY_STATE = { HAVE_NOTHING: 0, @@ -36,7 +36,7 @@ const READY_STATE = { HAVE_ENOUGH_DATA: 4 } -let _mat4_temp = math.mat4.create(); +let _mat4_temp = mat4.create(); let VideoPlayerImpl = cc.Class({ name: 'VideoPlayerImpl', diff --git a/cocos2d/webview/webview-impl.js b/cocos2d/webview/webview-impl.js index 9df5c8ccae8..35f5534bd5a 100644 --- a/cocos2d/webview/webview-impl.js +++ b/cocos2d/webview/webview-impl.js @@ -23,12 +23,12 @@ THE SOFTWARE. ****************************************************************************/ +import { mat4 } from '../core/vmath'; + const utils = require('../core/platform/utils'); const sys = require('../core/platform/CCSys'); -const renderEngine = require('../core/renderer/render-engine'); -const math = renderEngine.math; -let _mat4_temp = math.mat4.create(); +let _mat4_temp = mat4.create(); let WebViewImpl = cc.Class({ name: "WebViewImpl", diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 0b04fd080f7..f50925f7f3b 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -25,7 +25,7 @@ ****************************************************************************/ const RenderComponent = require('../../cocos2d/core/components/CCRenderComponent'); -const Material = require('../../cocos2d/core/assets/CCMaterial'); +const Material = require('../../cocos2d/core/assets/material/CCMaterial'); let EventTarget = require('../../cocos2d/core/event/event-target'); @@ -359,8 +359,7 @@ let ArmatureDisplay = cc.Class({ let material = this.sharedMaterials[0]; if (!material) { material = Material.getInstantiatedBuiltinMaterial('sprite', this); - material.define('useTexture', true); - material.define('useColor', true); + material.define('USE_TEXTURE', true); } if (texture) { diff --git a/extensions/dragonbones/CCSlot.js b/extensions/dragonbones/CCSlot.js index ce59f5116be..8aba4d963cf 100644 --- a/extensions/dragonbones/CCSlot.js +++ b/extensions/dragonbones/CCSlot.js @@ -23,7 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -const math = require('../../cocos2d/core/renderer/render-engine').math; +import { mat4 } from '../../cocos2d/core/vmath'; + const BlendFactor = require('../../cocos2d/core/platform/CCMacro'); const BinaryOffset = dragonBones.BinaryOffset; const BoneType = dragonBones.BoneType; @@ -36,7 +37,7 @@ dragonBones.CCSlot = cc.Class({ this._vertices = []; this._localVertices = []; this._indices = []; - this._matrix = math.mat4.create(); + this._matrix = mat4.create(); this._visible = false; this._color = cc.color(); }, @@ -45,7 +46,7 @@ dragonBones.CCSlot = cc.Class({ this._vertices.length = 0; this._localVertices.length = 0; this._indices.length = 0; - math.mat4.identity(this._matrix); + mat4.identity(this._matrix); this._visible = false; }, @@ -351,7 +352,7 @@ dragonBones.CCSlot = cc.Class({ if (this._display instanceof dragonBones.ArmatureDisplay) { let node = this._display.node; - math.mat4.copy(node._matrix, t); + mat4.copy(node._matrix, t); node._localMatDirty = false; node.setWorldDirty(); } diff --git a/extensions/dragonbones/canvas-assembler.js b/extensions/dragonbones/canvas-assembler.js index e73c1d71aec..7a4c45d9056 100644 --- a/extensions/dragonbones/canvas-assembler.js +++ b/extensions/dragonbones/canvas-assembler.js @@ -1,13 +1,12 @@ -const Armature = require('./ArmatureDisplay'); -const renderEngine = require('../../cocos2d/core/renderer/render-engine'); -const math = renderEngine.math; +import { mat4 } from '../../cocos2d/core/vmath'; +const Armature = require('./ArmatureDisplay'); const utils = require('../../cocos2d/core/renderer/canvas/renderers/utils'); let _color = cc.color(); -let _matrix = math.mat4.create(); -let _matrix2 = math.mat4.create(); +let _matrix = mat4.create(); +let _matrix2 = mat4.create(); let armatureAssembler = { draw (ctx, comp) { diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 2946723517e..4122ce54680 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -23,24 +23,18 @@ THE SOFTWARE. ****************************************************************************/ -const Armature = require('./ArmatureDisplay'); - -const renderEngine = require('../../cocos2d/core/renderer/render-engine'); -const math = renderEngine.math; - -const js = require('../../cocos2d/core/platform/js'); +import { mat4 } from '../../cocos2d/core/vmath'; +const Armature = require('./ArmatureDisplay'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); -let _matrix = math.mat4.create(); -let _v3 = cc.v3(); +let _matrix = mat4.create(); let _vbuf, _uintbuf, _vertexId, _ibuf, _vertexOffset, _indiceOffset, _a, _b, _c, _d, _tx, _ty, _nodeR, _nodeG, _nodeB, _nodeA, - _renderData, _worldMatrix; let armatureAssembler = { @@ -126,7 +120,7 @@ let armatureAssembler = { if (!slot._visible || !slot._displayData) continue; if (slot.childArmature) { - math.mat4.mul(_matrix, _worldMatrix, slot._matrix); + mat4.mul(_matrix, _worldMatrix, slot._matrix); _a = _matrix.m00; _b = _matrix.m01; _c = _matrix.m04; _d = _matrix.m05; _tx = _matrix.m12; _ty = _matrix.m13; this.fillVertexBufferWithArmature(slot.childArmature); diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 31afdab5c55..04609a1c426 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -27,7 +27,7 @@ const TrackEntryListeners = require('./track-entry-listeners'); const RenderComponent = require('../../cocos2d/core/components/CCRenderComponent'); const spine = require('./lib/spine'); -const Material = require('../../cocos2d/core/assets/CCMaterial'); +const Material = require('../../cocos2d/core/assets/material/CCMaterial'); const Graphics = require('../../cocos2d/core/graphics/graphics'); /** diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 7436b116fd1..b3f53e310bd 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -26,11 +26,9 @@ const StencilManager = require('../../cocos2d/core/renderer/webgl/stencil-manager').sharedManager; const Skeleton = require('./Skeleton'); const spine = require('./lib/spine'); -const renderer = require('../../cocos2d/core/renderer'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); -const Material = require('../../cocos2d/core/assets/CCMaterial'); -const renderEngine = renderer.renderEngine; -const gfx = renderEngine.gfx; +const Material = require('../../cocos2d/core/assets/material/CCMaterial'); +import gfx from '../../cocos2d/renderer/gfx'; const STENCIL_SEP = '@'; @@ -70,7 +68,7 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { let materials = comp._materials; let material = materials[key]; if (!material) { - var baseKey = baseMaterial._hash; + var baseKey = baseMaterial.getHash(); if (!materials[baseKey]) { material = baseMaterial; } else { @@ -78,14 +76,15 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { material.copy(baseMaterial); } - material.define('useModel', true); - material.define('useTexture', true); + material.define('_USE_MODEL', true); + material.define('USE_TEXTURE', true); // update texture material.setProperty('texture', tex); // update blend function - let pass = material._effect.getTechnique('transparent').passes[0]; + let pass = material.effect.getDefaultTechnique().passes[0]; pass.setBlend( + true, gfx.BLEND_FUNC_ADD, src, dst, gfx.BLEND_FUNC_ADD, @@ -102,9 +101,6 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { } var spineAssembler = { - // Use model to avoid per vertex transform - useModel: true, - _readAttachmentData (comp, attachment, slot, premultipliedAlpha, renderData, dataOffset) { // the vertices in format: // X1, Y1, C1R, C1G, C1B, C1A, U1, V1 @@ -310,7 +306,7 @@ var spineAssembler = { // For generate new material for skeleton render data nested in mask, // otherwise skeleton inside/outside mask with same material will interfere each other - let key = data.material._hash; + let key = data.material.getHash(); let newKey = _updateKeyWithStencilRef(key, StencilManager.getStencilRef()); if (key !== newKey) { data.material = materials[newKey] || data.material.clone(); diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index d7449919ceb..6bea4d49324 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -43,13 +43,13 @@ var jsbSkipModules = [ ]; var jsbAliasify = { replacements: { - '(.*)render-engine(.js)?': require.resolve('../../cocos2d/core/renderer/render-engine.jsb') + // '(.*)render-engine(.js)?': require.resolve('../../cocos2d/core/renderer/render-engine.jsb') }, verbose: false }; var canvasAliasify = { replacements: { - '(.*)render-engine(.js)?': require.resolve('../../cocos2d/core/renderer/render-engine.canvas') + // '(.*)render-engine(.js)?': require.resolve('../../cocos2d/core/renderer/render-engine.canvas') }, verbose: false }; diff --git a/gulp/util/create-bundler.js b/gulp/util/create-bundler.js index 4a4e4a097a1..f8b57eeae52 100644 --- a/gulp/util/create-bundler.js +++ b/gulp/util/create-bundler.js @@ -75,7 +75,7 @@ module.exports = function createBundler(entryFiles, options) { 'env' ]; - // var plugins = [ + var plugins = [ // // https://babeljs.io/docs/plugins/transform-es2015-shorthand-properties/ // 'babel-plugin-transform-es2015-shorthand-properties', // // https://babeljs.io/docs/plugins/transform-es2015-template-literals/ @@ -85,7 +85,11 @@ module.exports = function createBundler(entryFiles, options) { // // < 6.16.0 // [ 'babel-plugin-parser-opts', { allowReturnOutsideFunction: true } ] - // ]; + 'transform-decorators-legacy', + 'transform-class-properties', + + 'add-module-exports', + ]; var Babelify; try { @@ -121,7 +125,7 @@ module.exports = function createBundler(entryFiles, options) { .exclude(Path.join(__dirname, '../../package.json')) .transform(Babelify, (options && options.babelifyOpt) || { presets: presets, - // plugins: plugins, + plugins: plugins, // >= 6.16.0 // parserOpts: { diff --git a/package.json b/package.json index 509d12a21ef..af6881508ac 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,13 @@ ], "license": "MIT", "scripts": { - "test": "gulp test-in-ci" + "test": "gulp test-in-ci", + "build-chunks": "node ./cocos2d/renderer/build/build-chunks", + "build-mapping": "node ./cocos2d/renderer/build/build-mapping" }, "devDependencies": { "async": "1.5.2", + "babel-plugin-add-module-exports": "^0.2.1", "babel-plugin-parser-opts": "1.0.1", "babel-plugin-transform-class-properties": "6.22.0", "babel-plugin-transform-decorators-legacy": "^1.3.4", From c132247d400e0d1a1cc850e86d282a5650b18c36 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Wed, 2 Jan 2019 18:39:47 +0800 Subject: [PATCH 0366/1631] Merge fix of modify bar-filled to use mesh-buffer for batch rendering in v2.1. (#3701) --- .../renderer/webgl/assemblers/sprite/bar-filled.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index 1a5eb5ec954..cd8d945ff99 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -220,8 +220,10 @@ module.exports = { a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - let buffer = renderer._quadBuffer, - vertexOffset = buffer.byteOffset >> 2; + let buffer = renderer._meshBuffer, + vertexOffset = buffer.byteOffset >> 2, + indiceOffset = buffer.indiceOffset, + vertexId = buffer.vertexOffset; buffer.request(4, 6); @@ -238,5 +240,13 @@ module.exports = { vbuf[vertexOffset++] = vert.v; uintbuf[vertexOffset++] = color; } + + let ibuf = buffer._iData; + ibuf[indiceOffset++] = vertexId; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 2; + ibuf[indiceOffset++] = vertexId + 1; + ibuf[indiceOffset++] = vertexId + 3; + ibuf[indiceOffset++] = vertexId + 2; } }; From ec140424af70e8bd23583a03bb53da64c192fd12 Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 2 Jan 2019 22:42:41 +0800 Subject: [PATCH 0367/1631] fix android system version (#3704) --- cocos2d/core/platform/CCSys.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 152e87964dc..51b6f97bed6 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -829,7 +829,7 @@ function initSys () { // Get the os of system var isAndroid = false, iOS = false, osVersion = '', osMainVersion = 0; - var uaResult = /android (\d+(?:\.\d+)+)/i.exec(ua) || /android (\d+(?:\.\d+)+)/i.exec(nav.platform); + var uaResult = /android (\d+(?:\.\d+)*)/i.exec(ua) || /android (\d+(?:\.\d+)*)/i.exec(nav.platform); if (uaResult) { isAndroid = true; osVersion = uaResult[1] || ''; From 172bb54b5d14fff6e9773d4dc5d56c35468105ff Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 3 Jan 2019 11:48:14 +0800 Subject: [PATCH 0368/1631] add forced update size to cc.view._resizeEvent (#3694) * add forced update size to cc.view._resizeEvent * refine code --- cocos2d/core/platform/CCView.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 86fe571b176..5808f8c7f09 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -198,7 +198,7 @@ cc.js.mixin(View.prototype, { }, // Resize helper functions - _resizeEvent: function () { + _resizeEvent: function (forceOrEvent) { var view; if (this.setDesignResolutionSize) { view = this; @@ -220,7 +220,7 @@ cc.js.mixin(View.prototype, { else { view._initFrameSize(); } - if (view._isRotated === prevRotated && view._frameSize.width === prevFrameW && view._frameSize.height === prevFrameH) + if (forceOrEvent !== true && view._isRotated === prevRotated && view._frameSize.width === prevFrameW && view._frameSize.height === prevFrameH) return; // Frame size changed, do resize works @@ -612,7 +612,7 @@ cc.js.mixin(View.prototype, { this._frameSize.height = height; cc.game.frame.style.width = width + "px"; cc.game.frame.style.height = height + "px"; - this._resizeEvent(); + this._resizeEvent(true); }, /** From 0e634c023294ff8556a971ba70174836cc819e59 Mon Sep 17 00:00:00 2001 From: id-ilych Date: Thu, 3 Jan 2019 07:51:30 +0200 Subject: [PATCH 0369/1631] Port label vertical alignment fix (#3692) https://github.com/cocos-creator/engine/pull/3664/files --- .../core/label/CCSGLabelCanvasRenderCmd.js | 99 ++++++++----------- 1 file changed, 40 insertions(+), 59 deletions(-) diff --git a/cocos2d/core/label/CCSGLabelCanvasRenderCmd.js b/cocos2d/core/label/CCSGLabelCanvasRenderCmd.js index da059f14737..9190dba2ddc 100644 --- a/cocos2d/core/label/CCSGLabelCanvasRenderCmd.js +++ b/cocos2d/core/label/CCSGLabelCanvasRenderCmd.js @@ -25,6 +25,10 @@ THE SOFTWARE. ****************************************************************************/ + +var BASELINE_RATIO = 0.25; +var MIDDLE_RATIO = (BASELINE_RATIO + 1) / 2 - BASELINE_RATIO; + (function () { _ccsg.Label.TTFLabelBaker = function () {}; @@ -278,9 +282,10 @@ var paragraphedStrings = node._string.split('\n'); var i; var ctx = this._labelContext; + var margin = this._getMargin(); if (_ccsg.Label.Overflow.RESIZE_HEIGHT === node._overFlow) { - this._canvasSize.height = this._splitedStrings.length * this._getLineHeight(); + this._canvasSize.height = (this._splitedStrings.length + BASELINE_RATIO) * this._getLineHeight() + 2 * margin; _ccsg.Node.prototype.setContentSize.call(node, this._canvasSize); } else if(_ccsg.Label.Overflow.NONE === node._overFlow) { @@ -291,10 +296,10 @@ var paraLength = this._safeMeasureText(ctx, paragraphedStrings[i]); canvasSizeX = canvasSizeX > paraLength ? canvasSizeX : paraLength; } - canvasSizeY = this._splitedStrings.length * this._getLineHeight(); + canvasSizeY = (this._splitedStrings.length + BASELINE_RATIO) * this._getLineHeight(); - this._canvasSize.width = Math.round(canvasSizeX.toFixed(2)) + 2 * this._getMargin(); - this._canvasSize.height = Math.round(canvasSizeY.toFixed(2)); + this._canvasSize.width = Math.round(canvasSizeX.toFixed(2)) + 2 * margin; + this._canvasSize.height = Math.round(canvasSizeY.toFixed(2)) + 2 * margin; if(node._isItalic) { //0.0174532925 = 3.141592653 / 180 this._canvasSize.width += node._drawFontsize * Math.tan(12 * 0.0174532925); @@ -309,29 +314,30 @@ proto._calculateFillTextStartPosition = function() { var node = this._node; - var lineHeight = this._getLineHeight(); - var lineCount = this._splitedStrings.length; - var labelX; - var firstLinelabelY; + var labelX = 0; + var margin = this._getMargin(); if (cc.TextAlignment.RIGHT === node._hAlign) { - labelX = this._canvasSize.width - this._getMargin(); + labelX = this._canvasSize.width - margin; } else if (cc.TextAlignment.CENTER === node._hAlign) { labelX = this._canvasSize.width / 2; } else { - labelX = 0 + this._getMargin(); + labelX = 0 + margin; } + var firstLinelabelY = 0; + var lineHeight = this._getLineHeight(); + var drawStartY = lineHeight * (this._splitedStrings.length - 1); if (cc.VerticalTextAlignment.TOP === node._vAlign) { - firstLinelabelY = 0; + firstLinelabelY = lineHeight + margin; } else if (cc.VerticalTextAlignment.CENTER === node._vAlign) { - firstLinelabelY = this._canvasSize.height / 2 - lineHeight * (lineCount - 1) / 2; + firstLinelabelY = (this._canvasSize.height - drawStartY) * 0.5 + node._drawFontsize * MIDDLE_RATIO; } else { - firstLinelabelY = this._canvasSize.height - lineHeight * (lineCount - 1); + firstLinelabelY = this._canvasSize.height - drawStartY - node._drawFontsize * BASELINE_RATIO - margin; } return cc.p(labelX, firstLinelabelY); @@ -353,16 +359,7 @@ } this._labelContext.textAlign = hAlign; - if (cc.VerticalTextAlignment.TOP === node._vAlign) { - vAlign = 'top'; - } - else if (cc.VerticalTextAlignment.CENTER === node._vAlign) { - vAlign = 'middle'; - } - else { - vAlign = 'bottom'; - } - this._labelContext.textBaseline = vAlign; + this._labelContext.textBaseline = 'alphabetic'; }; proto._bakeLabel = function () { @@ -381,28 +378,6 @@ }; - proto._calculateUnderlineStartPosition = function () { - var node = this._node; - var lineHeight = this._getLineHeight(); - var lineCount = this._splitedStrings.length; - var labelX; - var firstLinelabelY; - - labelX = 0 + this._getMargin(); - - if (cc.VerticalTextAlignment.TOP === node._vAlign) { - firstLinelabelY = node._fontSize; - } - else if (cc.VerticalTextAlignment.CENTER === node._vAlign) { - firstLinelabelY = this._canvasSize.height / 2 - lineHeight * (lineCount - 1) / 2 + node._fontSize / 2; - } - else { - firstLinelabelY = this._canvasSize.height - lineHeight * (lineCount - 1); - } - - return cc.p(labelX, firstLinelabelY); - }; - proto._updateTexture = function() { this._labelContext.clearRect(0, 0, this._canvasSize.width, this._canvasSize.height); @@ -417,15 +392,32 @@ var underlineStartPosition; //do real rendering + var margin = this._getMargin(); for (var i = 0; i < this._splitedStrings.length; ++i) { + var drawTextPosX = startPosition.x; + var drawTextPosY = startPosition.y + i * lineHeight; + + if(this._node._isUnderline) { + var underlineThickness = this._node._fontSize / 8; + var drawUnderlinePosX = 0 + margin; + var drawUnderlinePosY = drawTextPosY + underlineThickness; + this._labelContext.save(); + this._labelContext.beginPath(); + this._labelContext.lineWidth = underlineThickness; + this._labelContext.strokeStyle = 'rgb(' + color.r + ',' + color.g + ',' + color.b + ')'; + this._labelContext.moveTo(drawUnderlinePosX, drawUnderlinePosY); + this._labelContext.lineTo(drawUnderlinePosX + this._labelCanvas.width, drawUnderlinePosY); + this._labelContext.stroke(); + this._labelContext.restore(); + } + if(this._node.isOutlined()) { var strokeColor = this._node.getOutlineColor() || cc.color(255,255,255,255); this._labelContext.globalCompositeOperation = 'source-over'; this._labelContext.strokeStyle = 'rgb(' + strokeColor.r + ',' + strokeColor.g + ',' + strokeColor.b + ')'; this._labelContext.lineWidth = this._node.getOutlineWidth() * 2; - this._labelContext.strokeText(this._splitedStrings[i], - startPosition.x, startPosition.y + i * lineHeight); + this._labelContext.strokeText(this._splitedStrings[i], drawTextPosX, drawTextPosY); } if(this._node.getFillColorGradientEnabled()) { var gradientStartColor = this._node.getGradientStartColor() || cc.color(255, 255, 255, 255); @@ -436,18 +428,7 @@ gradient.addColorStop(1, cc.colorToHex(gradientEndColor)); this._labelContext.fillStyle = gradient; } - this._labelContext.fillText(this._splitedStrings[i], startPosition.x, startPosition.y + i * lineHeight); - if(this._node._isUnderline) { - underlineStartPosition = this._calculateUnderlineStartPosition(); - this._labelContext.save(); - this._labelContext.beginPath(); - this._labelContext.lineWidth = this._node._fontSize / 8; - this._labelContext.strokeStyle = 'rgb(' + color.r + ',' + color.g + ',' + color.b + ')'; - this._labelContext.moveTo(underlineStartPosition.x, underlineStartPosition.y + i * lineHeight - 1); - this._labelContext.lineTo(underlineStartPosition.x + this._labelCanvas.width, underlineStartPosition.y + i * lineHeight - 1); - this._labelContext.stroke(); - this._labelContext.restore(); - } + this._labelContext.fillText(this._splitedStrings[i], drawTextPosX, drawTextPosY); } this._texture.loaded = false; From bd609b8412ed0687cf3e8e73c20e8c2fe7633568 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Thu, 3 Jan 2019 13:57:31 +0800 Subject: [PATCH 0370/1631] Fix the error of ttf in the WeChat subdomain. (#3703) * Fix the error of ttf in the WeChat subdomain. * fix ttf texture error in canvas --- cocos2d/core/renderer/canvas/renderers/label/ttf.js | 5 +++-- cocos2d/core/renderer/utils/label/ttf.js | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/canvas/renderers/label/ttf.js b/cocos2d/core/renderer/canvas/renderers/label/ttf.js index 74067e53cb2..c9b52afbed6 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/ttf.js +++ b/cocos2d/core/renderer/canvas/renderers/label/ttf.js @@ -53,7 +53,8 @@ module.exports = js.addon({ _updateTexture (comp) { ttfUtils._updateTexture(comp); - utils.dropColorizedImage(comp._texture, comp.node.color); + let texture = comp._frame._texture; + utils.dropColorizedImage(texture, comp.node.color); }, draw (ctx, comp) { @@ -70,7 +71,7 @@ module.exports = js.addon({ // opacity ctx.globalAlpha = node.opacity / 255; - let tex = comp._texture, + let tex = comp._frame._texture, data = comp._renderData._data; let image = tex.getHtmlElementObj(); diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 27ff10f2173..c431ec5f5e0 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -124,7 +124,7 @@ module.exports = { this._calculateSplitedStrings(); this._updateLabelDimensions(); this._calculateTextBaseline(); - this._updateTexture(); + this._updateTexture(comp); this._calDynamicAtlas(comp); comp._actualFontSize = _fontSize; @@ -242,7 +242,7 @@ module.exports = { return cc.v2(labelX, firstLinelabelY); }, - _updateTexture () { + _updateTexture (comp) { _context.clearRect(0, 0, _canvas.width, _canvas.height); _context.font = _fontDesc; From 9e2d8579254b1bcfa43720779a469ec05f143c88 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Thu, 3 Jan 2019 18:22:13 +0800 Subject: [PATCH 0371/1631] refer to webfontloader, use fontfaceset to detect if font has loaded (#3708) --- cocos2d/core/load-pipeline/font-loader.js | 103 +++++++++++++++++++--- 1 file changed, 91 insertions(+), 12 deletions(-) diff --git a/cocos2d/core/load-pipeline/font-loader.js b/cocos2d/core/load-pipeline/font-loader.js index c892019acbf..d8ae4e49c32 100644 --- a/cocos2d/core/load-pipeline/font-loader.js +++ b/cocos2d/core/load-pipeline/font-loader.js @@ -26,7 +26,8 @@ const textUtils = require('../utils/text-utils'); let _canvasContext = null; -let _testString = "BES bswy:->@"; +// letter symbol number CJK +let _testString = "BES bswy:->@123\u4E01\u3041\u1101"; let _fontFaces = {}; let _intervalId = -1; @@ -34,6 +35,35 @@ let _loadingFonts = []; // 60 seconds timeout let _timeout = 60000; +// 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(); @@ -68,6 +98,50 @@ function _checkFontLoaded () { } } +// 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 (item, callback) { let url = item.url; @@ -112,19 +186,24 @@ var fontLoader = { divStyle.top = "-100px"; document.body.appendChild(preloadDiv); - // Save loading font - let fontLoadHandle = { - fontFamilyName, - refWidth, - callback, - startTime: Date.now() + if (useNativeCheck()) { + nativeCheckFontLoaded(Date.now(), fontFamilyName, callback); } - _loadingFonts.push(fontLoadHandle); - _fontFaces[fontFamilyName] = fontStyle; - - if (_intervalId === -1) { - _intervalId = setInterval(_checkFontLoaded, 100); + else { + // Save loading font + let fontLoadHandle = { + fontFamilyName, + refWidth, + callback, + startTime: Date.now() + } + _loadingFonts.push(fontLoadHandle); + if (_intervalId === -1) { + _intervalId = setInterval(_checkFontLoaded, 100); + } } + _fontFaces[fontFamilyName] = fontStyle; + }, _getFontFamily: function (fontHandle) { From 9815c0cae70a981a32475cf97d3e1e71cdb08b77 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 3 Jan 2019 18:48:36 +0800 Subject: [PATCH 0372/1631] update Dynamic Atlas modules.json add "WebGL Renderer" to dependencies --- modules.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules.json b/modules.json index 985824f30ae..03744c81c23 100644 --- a/modules.json +++ b/modules.json @@ -51,7 +51,7 @@ "entries": [ "./cocos2d/core/renderer/utils/dynamic-atlas/manager.js" ], - "dependencies": ["Renderer Texture"] + "dependencies": ["WebGL Renderer", "Renderer Texture"] }, { "name": "LabelOutline", From eff43cc656979bee32e745f898d33cb330778428 Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 3 Jan 2019 20:54:49 +0800 Subject: [PATCH 0373/1631] fix load mp3 as audioClip (#3712) --- cocos2d/core/assets/CCAudioClip.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/assets/CCAudioClip.js b/cocos2d/core/assets/CCAudioClip.js index fa7f40a081c..a3570fd3f3b 100644 --- a/cocos2d/core/assets/CCAudioClip.js +++ b/cocos2d/core/assets/CCAudioClip.js @@ -61,8 +61,15 @@ var AudioClip = cc.Class({ return this._audio; }, set (value) { - this._audio = value; - if (value) { + // HACK: fix load mp3 as audioClip, _nativeAsset is set as audioClip. + // Should load mp3 as audioBuffer indeed. + if (value instanceof cc.AudioClip) { + this._audio = value._nativeAsset; + } + else { + this._audio = value; + } + if (this._audio) { this.loaded = true; this.emit('load'); } From 793337f1cf7d60e68a6d0ebb068256da1635ec45 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 8 Jan 2019 10:17:12 +0800 Subject: [PATCH 0374/1631] fix open data context resolution views display incorrectly (#3718) * fix open data context resolution views display incorrectly for 2d-tasks/issues/859 * refine code * refine api --- cocos2d/core/components/WXSubContextView.js | 24 ++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/components/WXSubContextView.js b/cocos2d/core/components/WXSubContextView.js index 43c31377ea1..62b46080b03 100644 --- a/cocos2d/core/components/WXSubContextView.js +++ b/cocos2d/core/components/WXSubContextView.js @@ -77,11 +77,9 @@ else { // Setup subcontext canvas size if (wx.getOpenDataContext) { this._context = wx.getOpenDataContext(); - let sharedCanvas = this._context.canvas; - if (sharedCanvas) { - sharedCanvas.width = this.node.width; - sharedCanvas.height = this.node.height; - } + // reset sharedCanvas width and height + this.reset(); + this._tex.setPremultiplyAlpha(true); this._tex.initWithElement(sharedCanvas); @@ -97,6 +95,22 @@ else { } }, + /** + * !#en Reset open data context size and viewport + * !#zh 重置开放数据域的尺寸和视窗 + * @method reset + */ + reset () { + if (this._context) { + this.updateSubContextViewport(); + let sharedCanvas = this._context.canvas; + if (sharedCanvas) { + sharedCanvas.width = this.node.width; + sharedCanvas.height = this.node.height; + } + } + }, + onEnable () { this.updateSubContextViewport(); }, From f4d7225b8f410a52cf5abfc9eb4d12fb2909f212 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 8 Jan 2019 10:36:01 +0800 Subject: [PATCH 0375/1631] small fixed (#3724) * fixed indent * hide blend from inspector default * fixed init tiled object group * add tiled-layer inspector --- cocos2d/core/components/CCRenderComponent.js | 6 ++-- cocos2d/renderer/build/chunks/skinning.inc | 30 ++++++++++---------- cocos2d/tilemap/CCTiledLayer.js | 4 +++ cocos2d/tilemap/CCTiledObjectGroup.js | 15 ++++++++-- 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index b229d070d16..c3f1b7654e3 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -72,7 +72,8 @@ let RenderComponent = cc.Class({ }, animatable: false, type:BlendFactor, - tooltip: CC_DEV && 'i18n:COMPONENT.sprite.src_blend_factor' + tooltip: CC_DEV && 'i18n:COMPONENT.sprite.src_blend_factor', + visible: false }, /** @@ -94,7 +95,8 @@ let RenderComponent = cc.Class({ }, animatable: false, type: BlendFactor, - tooltip: CC_DEV && 'i18n:COMPONENT.sprite.dst_blend_factor' + tooltip: CC_DEV && 'i18n:COMPONENT.sprite.dst_blend_factor', + visible: false }, _materials: { diff --git a/cocos2d/renderer/build/chunks/skinning.inc b/cocos2d/renderer/build/chunks/skinning.inc index 9d9defb9a04..554fd3cc4ca 100644 --- a/cocos2d/renderer/build/chunks/skinning.inc +++ b/cocos2d/renderer/build/chunks/skinning.inc @@ -43,19 +43,19 @@ mat4 skinMatrix() { } void skinVertex(inout vec4 a1) { - mat4 m = skinMatrix(); - a1 = m * a1; - } - - void skinVertex(inout vec4 a1, inout vec4 a2) { - mat4 m = skinMatrix(); - a1 = m * a1; - a2 = m * a2; - } + mat4 m = skinMatrix(); + a1 = m * a1; +} - void skinVertex(inout vec4 a1, inout vec4 a2, inout vec4 a3) { - mat4 m = skinMatrix(); - a1 = m * a1; - a2 = m * a2; - a3 = m * a3; - } \ No newline at end of file +void skinVertex(inout vec4 a1, inout vec4 a2) { + mat4 m = skinMatrix(); + a1 = m * a1; + a2 = m * a2; +} + +void skinVertex(inout vec4 a1, inout vec4 a2, inout vec4 a3) { + mat4 m = skinMatrix(); + a1 = m * a1; + a2 = m * a2; + a3 = m * a3; +} \ No newline at end of file diff --git a/cocos2d/tilemap/CCTiledLayer.js b/cocos2d/tilemap/CCTiledLayer.js index fc9fedd30d5..2c2887e0768 100644 --- a/cocos2d/tilemap/CCTiledLayer.js +++ b/cocos2d/tilemap/CCTiledLayer.js @@ -39,6 +39,10 @@ let TiledLayer = cc.Class({ // because TiledLayer not create or maintains the sgNode by itself. extends: RenderComponent, + editor: { + inspector: 'packages://inspector/inspectors/comps/tiled-layer.js', + }, + ctor () { this._tiles = []; this._texGrids = []; diff --git a/cocos2d/tilemap/CCTiledObjectGroup.js b/cocos2d/tilemap/CCTiledObjectGroup.js index cf88f783452..d6b8d9e5ec7 100644 --- a/cocos2d/tilemap/CCTiledObjectGroup.js +++ b/cocos2d/tilemap/CCTiledObjectGroup.js @@ -143,14 +143,23 @@ let TiledObjectGroup = cc.Class({ for (let i = 0, l = objects.length; i < l; i++) { let object = objects[i]; object.offset = cc.v2(object.x, object.y); - if (cc.TiledMap.Orientation.ISO !== this._mapOrientation) { + + let points = object.points || object.polylinePoints; + if (points) { + for (let pi = 0; pi < points.length; pi++) { + points[pi].y *= -1; + } + } + + if (cc.TiledMap.Orientation.ISO !== mapInfo.orientation) { object.y = height - object.y; } else { - let posIdxX = object.offset.x / tileSize.width * 2; - let posIdxY = object.offset.y / tileSize.height; + let posIdxX = object.x / tileSize.width * 2; + let posIdxY = object.y / tileSize.height; object.x = tileSize.width / 2 * (mapSize.width + posIdxX - posIdxY); object.y = tileSize.height / 2 * (mapSize.height * 2 - posIdxX - posIdxY); } + } this._objects = objects; } From 7897096cc0854531a121b33ddc1f313a0dc73914 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 8 Jan 2019 11:52:16 +0800 Subject: [PATCH 0376/1631] fix RichText use font and on event param invalid (#3723) * fix RichText use font invalid * fix richt on event param invalid --- cocos2d/core/components/CCRichText.js | 4 ++-- cocos2d/core/utils/html-text-parser.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index 7ed506d6a1a..7203e30d49d 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -91,9 +91,9 @@ pool.get = function (string, richtext) { if (typeof string !== 'string') { string = '' + string; } - let isAsset = richtext.fontAsset instanceof cc.Font; + let isAsset = richtext.font instanceof cc.Font; if (isAsset) { - labelComponent.font = richtext.fontAsset; + labelComponent.font = richtext.font; } else { labelComponent.fontFamily = richtext.fontFamily; } diff --git a/cocos2d/core/utils/html-text-parser.js b/cocos2d/core/utils/html-text-parser.js index 479a78c14e3..1a946b32324 100644 --- a/cocos2d/core/utils/html-text-parser.js +++ b/cocos2d/core/utils/html-text-parser.js @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -var eventRegx = /^(click)(\s)*=/; +var eventRegx = /^(click)(\s)*=|(param)(\s)*=/; var imageAttrReg = /(\s)*src(\s)*=|(\s)*height(\s)*=|(\s)*width(\s)*=|(\s)*click(\s)*=|(\s)*param(\s)*=/; /** * A utils class for parsing HTML texts. The parsed results will be an object array. From 4d9ca95228c5044733dd3d15ecd4cc747b86e0a1 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 8 Jan 2019 11:54:54 +0800 Subject: [PATCH 0377/1631] fix EngineErrorMap scheduleSelector log (#3726) --- EngineErrorMap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EngineErrorMap.md b/EngineErrorMap.md index c49be798ac0..369240cbd7a 100644 --- a/EngineErrorMap.md +++ b/EngineErrorMap.md @@ -276,7 +276,7 @@ warning: you CANNOT change update priority in scheduled function ### 1507 -CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f +CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %s to %s" ### 1508 From 003d5cd3804e9dae54bfa95d53c0be1098a7601f Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 8 Jan 2019 18:56:41 +0800 Subject: [PATCH 0378/1631] remove x5 adaption for videoplayer (#3722) --- cocos2d/videoplayer/video-player-impl.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 437c5820559..57bbacb873f 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -170,13 +170,6 @@ let VideoPlayerImpl = cc.Class({ video.setAttribute('webkit-playsinline', ''); video.setAttribute('playsinline', ''); - // Stupid tencent x5 adaptation - video.setAttribute("x5-playsinline", ""); - video.setAttribute("x5-video-player-type", "h5"); - video.setAttribute("x5-video-player-fullscreen", this._fullScreenEnabled ? "true" : "false"); - let orientation = cc.winSize.width > cc.winSize.height ? "landscape" : "portrait"; - video.setAttribute("x5-video-orientation", orientation); - this._video = video; cc.game.container.appendChild(video); }, From 8f6eaf9196b844ce2a39c704f1b51457f25eef02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=BA=E6=98=8E?= Date: Tue, 8 Jan 2019 19:01:04 +0800 Subject: [PATCH 0379/1631] change network modules name (#3729) --- modules.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules.json b/modules.json index 03744c81c23..9b598fb8c38 100644 --- a/modules.json +++ b/modules.json @@ -261,6 +261,6 @@ ] }, { - "name": "Native NetWork" + "name": "Native Socket" } ] From 3d5e9323cda720d2f054ff31f4991ef87e83fc77 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Tue, 8 Jan 2019 19:26:13 +0800 Subject: [PATCH 0380/1631] fixed overflow of localZOrder and remove _zIndex (#3720) --- cocos2d/core/CCNode.js | 30 +++++++++++++------ .../renderer/utils/dynamic-atlas/manager.js | 2 +- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 88fc24ec00d..98daff3dc0a 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -51,7 +51,6 @@ var _vec2b = cc.v2(); var _mat4_temp = math.mat4.create(); var _vec3_temp = math.vec3.create(); var _quat_temp = math.quat.create(); -var _globalOrderOfArrival = 1; var _cachedArray = new Array(16); _cachedArray.length = 0; @@ -567,11 +566,15 @@ var Node = cc.Class({ _quat: cc.Quat, _skewX: 0.0, _skewY: 0.0, + _zIndex: { + default: undefined, + type: cc.Integer + }, _localZOrder: { default: 0, serializable: false }, - _zIndex: 0, + _childArrivalOrder: 1, // internal properties @@ -1104,7 +1107,7 @@ var Node = cc.Class({ */ zIndex: { get () { - return this._zIndex; + return this._localZOrder >> 16; }, set (value) { if (value > macro.MAX_ZINDEX) { @@ -1116,8 +1119,7 @@ var Node = cc.Class({ value = macro.MIN_ZINDEX; } - if (this._zIndex !== value) { - this._zIndex = value; + if (this.zIndex !== value) { this._localZOrder = (this._localZOrder & 0x0000ffff) | (value << 16); if (this._parent) { @@ -1284,9 +1286,9 @@ var Node = cc.Class({ this._scale.y = this._scaleY; this._scaleY = undefined; } - - if (this._localZOrder !== 0) { - this._zIndex = (this._localZOrder & 0xffff0000) >> 16; + if (this._zIndex !== undefined) { + this._localZOrder = this._zIndex << 16; + this._zIndex = undefined; } // TODO: remove _rotationX & _rotationY in future version, 3.0 ? @@ -2933,8 +2935,18 @@ var Node = cc.Class({ }, _updateOrderOfArrival () { - var arrivalOrder = ++_globalOrderOfArrival; + var arrivalOrder = this._parent ? ++this._parent._childArrivalOrder : 0; this._localZOrder = (this._localZOrder & 0xffff0000) | arrivalOrder; + // redistribute + if (arrivalOrder === 0x0000ffff) { + var siblings = this._parent._children; + + siblings.forEach(function (node, index) { + node._localZOrder = (node._localZOrder & 0xffff0000) | (index + 1); + }); + + this._parent._childArrivalOrder = siblings.length; + } }, /** diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js index 2d8e90b9b0d..4a4bbdfc3bd 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js @@ -159,7 +159,7 @@ let dynamicAtlasManager = { _debugNode.height = height; _debugNode.x = width/2; _debugNode.y = height/2; - _debugNode._zIndex = cc.macro.MAX_ZINDEX; + _debugNode.zIndex = cc.macro.MAX_ZINDEX; _debugNode.parent = cc.director.getScene(); _debugNode.groupIndex = cc.Node.BuiltinGroupIndex.DEBUG; From 92930f50fd2646683ad09ec062fef63292017bc7 Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 9 Jan 2019 10:27:11 +0800 Subject: [PATCH 0381/1631] setResizeCallback does not support use in the editor (#3730) --- cocos2d/core/platform/CCView.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 5808f8c7f09..fe2766c452a 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -307,6 +307,7 @@ cc.js.mixin(View.prototype, { * @param {Function|Null} callback - The callback function */ setResizeCallback: function (callback) { + if (CC_EDITOR) return; if (typeof callback === 'function' || callback == null) { this._resizeCallback = callback; } From 05ddefc1d67f904d927d3266536f5ec38ca2342c Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Wed, 9 Jan 2019 10:36:33 +0800 Subject: [PATCH 0382/1631] To adapt the adjust of the webview impl in the jsb (#3697) --- cocos2d/webview/CCWebView.js | 6 +++--- cocos2d/webview/webview-impl.js | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cocos2d/webview/CCWebView.js b/cocos2d/webview/CCWebView.js index a740a2e044a..d9091b079f4 100644 --- a/cocos2d/webview/CCWebView.js +++ b/cocos2d/webview/CCWebView.js @@ -107,17 +107,17 @@ let WebView = cc.Class({ statics: { EventType: EventType, + // Impl will be overrided in the different platform. Impl: WebViewImpl }, - ctor () { - this._impl = new WebViewImpl(); + this._impl = new WebView.Impl(); }, onRestore () { if (!this._impl) { - this._impl = new WebViewImpl(); + this._impl = new WebView.Impl(); } }, diff --git a/cocos2d/webview/webview-impl.js b/cocos2d/webview/webview-impl.js index 9df5c8ccae8..f9ef1e89352 100644 --- a/cocos2d/webview/webview-impl.js +++ b/cocos2d/webview/webview-impl.js @@ -182,6 +182,7 @@ let WebViewImpl = cc.Class({ setOnJSCallback (callback) {}, setJavascriptInterfaceScheme (scheme) {}, + // private method loadData (data, MIMEType, encoding, baseURL) {}, loadHTMLString (string, baseURL) {}, From 76cafcabfc4016bb08b395b872c79d7fdd6e02ba Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 9 Jan 2019 17:44:36 +0800 Subject: [PATCH 0383/1631] Fix tiled assembler variable def issue --- cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js index 61b0031cb57..a9d8f1d1df5 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js @@ -33,8 +33,6 @@ module.exports = { }, updateRenderData (sprite) { - let frame = sprite.spriteFrame; - // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here sprite._calDynamicAtlas(); From 51617f8f74c5b00ffaa9c7a46c9fac267e12843f Mon Sep 17 00:00:00 2001 From: mac <1053210246@qq.com> Date: Wed, 9 Jan 2019 20:19:03 +0800 Subject: [PATCH 0384/1631] fix skip module when not use native renderer --- extensions/spine/index.js | 4 ++-- gulp/tasks/engine.js | 6 ------ predefine.js | 1 + 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/extensions/spine/index.js b/extensions/spine/index.js index 0d7cf499b9d..d9a57ab5179 100644 --- a/extensions/spine/index.js +++ b/extensions/spine/index.js @@ -44,7 +44,7 @@ var _global = typeof window === 'undefined' ? global : window; var _isUseSpine = true; -if (CC_JSB && _global.spine === undefined) { +if (CC_NATIVERENDERER && CC_JSB && _global.spine === undefined) { _isUseSpine = false; } @@ -106,7 +106,7 @@ if (_isUseSpine) { */ if (!CC_EDITOR || !Editor.isMainProcess) { - if (CC_JSB) { + if (CC_NATIVERENDERER && CC_JSB) { sp.spine = _global.spine; } else { sp.spine = require('./lib/spine'); diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index ad72b7e7649..d7449919ceb 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -40,12 +40,6 @@ const Optimizejs = require('gulp-optimize-js'); var jsbSkipModules = [ // modules need to skip in jsb - '../../extensions/spine/lib/spine.js', - '../../extensions/dragonbones/lib/dragonBones.js', - '../../extensions/dragonbones/CCArmatureDisplay.js', - '../../extensions/dragonbones/CCFactory.js', - '../../extensions/dragonbones/CCSlot.js', - '../../extensions/dragonbones/CCTextureData.js' ]; var jsbAliasify = { replacements: { diff --git a/predefine.js b/predefine.js index aaaf3faf32a..2d5f3ce3e7f 100644 --- a/predefine.js +++ b/predefine.js @@ -156,6 +156,7 @@ else { defineMacro('CC_DEV', true); // (CC_EDITOR && !CC_BUILD) || CC_PREVIEW || CC_TEST defineMacro('CC_DEBUG', true); // CC_DEV || Debug Build defineMacro('CC_JSB', defined('jsb')); + defineMacro('CC_NATIVERENDERER', defined('CC_NATIVERENDERER')); defineMacro('CC_WECHATGAME_SUB', !!(defined('wx') && wx.getSharedCanvas)); defineMacro('CC_WECHATGAME', !!(defined('wx') && (wx.getSystemInfoSync || wx.getSharedCanvas))); defineMacro('CC_QQPLAY', defined('bk')); From 52182cd056f8348f3171814f2ffe5e48ac657307 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Wed, 9 Jan 2019 22:53:13 +0800 Subject: [PATCH 0385/1631] fix the creator.d.ts EventListener lost prop (#3727) fix the text and label note error --- cocos2d/core/components/CCLabel.js | 2 +- cocos2d/core/components/CCRichText.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index a58301cf66b..23fbab46080 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -371,7 +371,7 @@ let Label = cc.Class({ /** * !#en Whether use system font name or not. * !#zh 是否使用系统字体。 - * @property {Boolean} isSystemFontUsed + * @property {Boolean} useSystemFont */ useSystemFont: { get () { diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index 7203e30d49d..e2fa38f4fb6 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -237,7 +237,7 @@ let RichText = cc.Class({ /** * !#en Whether use system font name or not. * !#zh 是否使用系统字体。 - * @property {Boolean} isSystemFontUsed + * @property {Boolean} useSystemFont */ _isSystemFontUsed: true, useSystemFont: { From 1ca330b14a627b5e9db1aa5907ed7f7d16ac03f1 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Thu, 10 Jan 2019 10:26:47 +0800 Subject: [PATCH 0386/1631] Fix bmfont error in subdomain and setting color invalid. (#3731) --- cocos2d/core/renderer/canvas/renderers/label/bmfont.js | 4 ++-- cocos2d/core/renderer/canvas/renderers/utils.js | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js index 301a950090e..fdfae6720ca 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js +++ b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js @@ -87,10 +87,10 @@ module.exports = js.addon({ // opacity ctx.globalAlpha = node.opacity / 255; - let tex = comp._texture, + let tex = comp._frame._texture, data = comp._renderData._data; - let image = tex.getHtmlElementObj(); + let image = utils.getColorizedImage(tex, node._color); for (let i = 0, l = data.length; i < l; i+=2) { let x = data[i].x; diff --git a/cocos2d/core/renderer/canvas/renderers/utils.js b/cocos2d/core/renderer/canvas/renderers/utils.js index 202add731da..427ffae0eae 100644 --- a/cocos2d/core/renderer/canvas/renderers/utils.js +++ b/cocos2d/core/renderer/canvas/renderers/utils.js @@ -27,9 +27,6 @@ const WHITE = (255<<16) + (255<<8) + 255; const MAX_CANVAS_COUNT = 32; function colorizedFrame (canvas, texture, color, sx, sy, sw, sh) { - if (cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { - return canvas; - } let image = texture._image; let ctx = canvas.getContext("2d"); From 5969250e36d76035376c6f5fe82163c47710f728 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Thu, 10 Jan 2019 14:10:11 +0800 Subject: [PATCH 0387/1631] upgrade spine (#3721) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update spine-assembler.js spine骨骼动画一直播放导致内存不断上涨 * Update spine-assembler.js 优化释放数据逻辑;格式化代码 * Update spine-assembler.js 删掉空行 * fix spine leak * upgrade spine * upgrade spine * upgrade spine * upgrade spine * upgrade spine * upgrade spine * upgrade spine --- cocos2d/core/renderer/render-engine.js | 115 + cocos2d/core/renderer/render-engine.jsb.js | 117 +- .../renderer/webgl/render-component-walker.js | 4 + cocos2d/core/renderer/webgl/spine-buffer.js | 34 + cocos2d/core/renderer/webgl/vertex-format.js | 10 + editor/i18n/en/localization.js | 1 + editor/i18n/zh/localization.js | 1 + extensions/spine/Skeleton.js | 57 +- extensions/spine/lib/spine.js | 4987 ++++++++++------- extensions/spine/spine-assembler.js | 522 +- 10 files changed, 3724 insertions(+), 2124 deletions(-) create mode 100644 cocos2d/core/renderer/webgl/spine-buffer.js diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 7252acac440..a16d6f86d64 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -13718,6 +13718,16 @@ var templates = [ { name: 'alphaTest', }, { name: 'use2DPos', }, { name: 'useColor', } ], + }, + { + name: 'spine', + vert: '\n \nuniform mat4 viewProj;\n\n#ifdef use2DPos\n attribute vec2 a_position;\n#else\n attribute vec3 a_position;\n#endif\n\nattribute lowp vec4 a_color;\n#ifdef useTint\n attribute lowp vec4 a_color0;\n#endif\n\n#ifdef useModel\n uniform mat4 model;\n#endif\n\nattribute mediump vec2 a_uv0;\nvarying mediump vec2 uv0;\n\nvarying lowp vec4 v_light;\n#ifdef useTint\n varying lowp vec4 v_dark;\n#endif\n\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n\n v_light = a_color;\n #ifdef useTint\n v_dark = a_color0;\n #endif\n\n uv0 = a_uv0;\n\n gl_Position = pos;\n}', + frag: '\n \nuniform sampler2D texture;\nvarying mediump vec2 uv0;\n\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n\nvarying lowp vec4 v_light;\n#ifdef useTint\n varying lowp vec4 v_dark;\n#endif\n\nvoid main () {\n vec4 texColor = texture2D(texture, uv0);\n vec4 finalColor;\n\n #ifdef useTint\n finalColor.a = v_light.a * texColor.a;\n finalColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;\n #else\n finalColor = texColor * v_light;\n #endif\n\n #ifdef alphaTest\n if (finalColor.a <= alphaThreshold)\n discard;\n #endif\n\n gl_FragColor = finalColor;\n}', + defines: [ + { name: 'useModel', }, + { name: 'alphaTest', }, + { name: 'use2DPos', }, + { name: 'useTint', } ], } ]; var shaders = { @@ -14245,6 +14255,110 @@ var SpriteMaterial = (function (Material$$1) { // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +var SpineMaterial = (function (Material$$1) { +function SpineMaterial() { + Material$$1.call(this, false); + + var pass = new renderer.Pass('spine'); + pass.setDepth(false, false); + pass.setCullMode(gfx.CULL_NONE); + pass.setBlend( + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA, + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA + ); + + var mainTech = new renderer.Technique( + ['transparent'], + [ + { name: 'texture', type: renderer.PARAM_TEXTURE_2D } ], + [ + pass + ] + ); + + this._effect = new renderer.Effect( + [ + mainTech ], + { + + }, + [ + { name: 'useModel', value: true }, + { name: 'alphaTest', value: false }, + { name: 'use2DPos', value: true }, + { name: 'useTint', value: false } ] + ); + + this._mainTech = mainTech; + this._texture = null; +} + +if ( Material$$1 ) SpineMaterial.__proto__ = Material$$1; +SpineMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); +SpineMaterial.prototype.constructor = SpineMaterial; + +var prototypeAccessors = { effect: { configurable: true },useModel: { configurable: true },use2DPos: { configurable: true },useTint: { configurable: false },texture: { configurable: true } }; + +prototypeAccessors.effect.get = function () { + return this._effect; +}; + +prototypeAccessors.useModel.get = function () { + return this._effect.getDefine('useModel'); +}; + +prototypeAccessors.useModel.set = function (val) { + this._effect.define('useModel', val); +}; + +prototypeAccessors.use2DPos.get = function () { + return this._effect.getDefine('use2DPos'); +}; + +prototypeAccessors.use2DPos.set = function (val) { + this._effect.define('use2DPos', val); +}; + +prototypeAccessors.useTint.get = function () { + return this._effect.getDefine('useTint'); +}; + +prototypeAccessors.useTint.set = function (val) { + this._effect.define('useTint', val); +}; + +prototypeAccessors.texture.get = function () { + return this._texture; +}; + +prototypeAccessors.texture.set = function (val) { + if (this._texture !== val) { + this._texture = val; + this._effect.setProperty('texture', val.getImpl()); + this._texIds['texture'] = val.getId(); + } +}; + +SpineMaterial.prototype.clone = function clone () { + var copy = new SpineMaterial(); + copy._mainTech.copy(this._mainTech); + copy.texture = this.texture; + copy.useModel = this.useModel; + copy.use2DPos = this.use2DPos; + copy.useTint = this.useTint; + copy._hash = this._hash; + return copy; +}; + +Object.defineProperties( SpineMaterial.prototype, prototypeAccessors ); + +return SpineMaterial; +}(Material)); + +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + var GraySpriteMaterial = (function (Material$$1) { function GraySpriteMaterial() { Material$$1.call(this, false); @@ -14612,6 +14726,7 @@ var renderEngine = { Material: Material, // materials + SpineMaterial: SpineMaterial, SpriteMaterial: SpriteMaterial, GraySpriteMaterial: GraySpriteMaterial, StencilMaterial: StencilMaterial, diff --git a/cocos2d/core/renderer/render-engine.jsb.js b/cocos2d/core/renderer/render-engine.jsb.js index 8368e2baee8..9e0e68affda 100644 --- a/cocos2d/core/renderer/render-engine.jsb.js +++ b/cocos2d/core/renderer/render-engine.jsb.js @@ -1042,7 +1042,17 @@ var templates = [ { name: 'alphaTest', }, { name: 'use2DPos', }, { name: 'useColor', } ], - } ]; + }, + { + name: 'spine', + vert: '\n \nuniform mat4 viewProj;\n\n#ifdef use2DPos\n attribute vec2 a_position;\n#else\n attribute vec3 a_position;\n#endif\n\nattribute lowp vec4 a_color;\n#ifdef useTint\n attribute lowp vec4 a_color0;\n#endif\n\n#ifdef useModel\n uniform mat4 model;\n#endif\n\nattribute mediump vec2 a_uv0;\nvarying mediump vec2 uv0;\n\nvarying lowp vec4 v_light;\n#ifdef useTint\n varying lowp vec4 v_dark;\n#endif\n\nvoid main () {\n mat4 mvp;\n #ifdef useModel\n mvp = viewProj * model;\n #else\n mvp = viewProj;\n #endif\n\n #ifdef use2DPos\n vec4 pos = mvp * vec4(a_position, 0, 1);\n #else\n vec4 pos = mvp * vec4(a_position, 1);\n #endif\n\n v_light = a_color;\n #ifdef useTint\n v_dark = a_color0;\n #endif\n\n uv0 = a_uv0;\n\n gl_Position = pos;\n}', + frag: '\n \nuniform sampler2D texture;\nvarying mediump vec2 uv0;\n\n#ifdef alphaTest\n uniform lowp float alphaThreshold;\n#endif\n\nvarying lowp vec4 v_light;\n#ifdef useTint\n varying lowp vec4 v_dark;\n#endif\n\nvoid main () {\n vec4 texColor = texture2D(texture, uv0);\n vec4 finalColor;\n\n #ifdef useTint\n finalColor.a = v_light.a * v_dark.a;\n finalColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;\n #else\n finalColor = texColor * v_light;\n #endif\n\n #ifdef alphaTest\n if (finalColor.a <= alphaThreshold)\n discard;\n #endif\n\n gl_FragColor = finalColor;\n}', + defines: [ + { name: 'useModel', }, + { name: 'alphaTest', }, + { name: 'use2DPos', }, + { name: 'useTint', } ], + } ]; var shaders = { chunks: chunks, @@ -2824,6 +2834,110 @@ var SpriteMaterial = (function (Material$$1) { // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +var SpineMaterial = (function (Material$$1) { +function SpineMaterial() { + Material$$1.call(this, false); + + var pass = new renderer.Pass('spine'); + pass.setDepth(false, false); + pass.setCullMode(gfx.CULL_NONE); + pass.setBlend( + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA, + gfx.BLEND_FUNC_ADD, + gfx.BLEND_SRC_ALPHA, gfx.BLEND_ONE_MINUS_SRC_ALPHA + ); + + var mainTech = new renderer.Technique( + ['transparent'], + [ + { name: 'texture', type: renderer.PARAM_TEXTURE_2D } ], + [ + pass + ] + ); + + this._effect = new renderer.Effect( + [ + mainTech ], + { + + }, + [ + { name: 'useModel', value: true }, + { name: 'alphaTest', value: false }, + { name: 'use2DPos', value: true }, + { name: 'useTint', value: false } ] + ); + + this._mainTech = mainTech; + this._texture = null; +} + +if ( Material$$1 ) SpineMaterial.__proto__ = Material$$1; +SpineMaterial.prototype = Object.create( Material$$1 && Material$$1.prototype ); +SpineMaterial.prototype.constructor = SpineMaterial; + +var prototypeAccessors = { effect: { configurable: true },useModel: { configurable: true },use2DPos: { configurable: true },useTint: { configurable: false },texture: { configurable: true } }; + +prototypeAccessors.effect.get = function () { + return this._effect; +}; + +prototypeAccessors.useModel.get = function () { + return this._effect.getDefine('useModel'); +}; + +prototypeAccessors.useModel.set = function (val) { + this._effect.define('useModel', val); +}; + +prototypeAccessors.use2DPos.get = function () { + return this._effect.getDefine('use2DPos'); +}; + +prototypeAccessors.use2DPos.set = function (val) { + this._effect.define('use2DPos', val); +}; + +prototypeAccessors.useTint.get = function () { + return this._effect.getDefine('useTint'); +}; + +prototypeAccessors.useTint.set = function (val) { + this._effect.define('useTint', val); +}; + +prototypeAccessors.texture.get = function () { + return this._texture; +}; + +prototypeAccessors.texture.set = function (val) { + if (this._texture !== val) { + this._texture = val; + this._effect.setProperty('texture', val.getImpl()); + this._texIds['texture'] = val.getId(); + } +}; + +SpineMaterial.prototype.clone = function clone () { + var copy = new SpineMaterial(); + copy._mainTech.copy(this._mainTech); + copy.texture = this.texture; + copy.useModel = this.useModel; + copy.use2DPos = this.use2DPos; + copy.useTint = this.useTint; + copy._hash = this._hash; + return copy; +}; + +Object.defineProperties( SpineMaterial.prototype, prototypeAccessors ); + +return SpineMaterial; +}(Material)); + +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + var GraySpriteMaterial = (function (Material$$1) { function GraySpriteMaterial() { Material$$1.call(this, false); @@ -10458,6 +10572,7 @@ var renderEngine = { Material: Material, // materials + SpineMaterial: SpineMaterial, SpriteMaterial: SpriteMaterial, GraySpriteMaterial: GraySpriteMaterial, StencilMaterial: StencilMaterial, diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/render-component-walker.js index b4607819121..121d8707818 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/render-component-walker.js @@ -31,6 +31,7 @@ const dynamicAtlasManager = require('../utils/dynamic-atlas/manager'); const RenderFlow = require('../render-flow'); const QuadBuffer = require('./quad-buffer'); const MeshBuffer = require('./mesh-buffer'); +const SpineBuffer = require('./spine-buffer'); let idGenerater = new (require('../../platform/id-generater'))('VertextFormat'); @@ -239,6 +240,9 @@ RenderComponentWalker.prototype = { else if (type === 'quad') { buffer = new QuadBuffer(this, vertextFormat); } + else if (type === 'spine') { + buffer = new SpineBuffer(this, vertextFormat); + } else { cc.error(`Not support buffer type [${type}]`); return null; diff --git a/cocos2d/core/renderer/webgl/spine-buffer.js b/cocos2d/core/renderer/webgl/spine-buffer.js new file mode 100644 index 00000000000..15a82130750 --- /dev/null +++ b/cocos2d/core/renderer/webgl/spine-buffer.js @@ -0,0 +1,34 @@ +var SpineBuffer = cc.Class({ + name: 'cc.SpineBuffer', + extends: require('./mesh-buffer'), + + requestStatic (vertexCount, indiceCount) { + let byteOffset = this.byteOffset + vertexCount * this._vertexBytes; + let indiceOffset = this.indiceOffset + indiceCount; + + let byteLength = this._vData.byteLength; + let indiceLength = this._iData.length; + if (byteOffset > byteLength || indiceOffset > indiceLength) { + while (byteLength < byteOffset || indiceLength < indiceOffset) { + this._initVDataCount *= 2; + this._initIDataCount *= 2; + + byteLength = this._initVDataCount * 4; + indiceLength = this._initIDataCount; + } + + this._reallocBuffer(); + } + }, + + adjust (vertexCount, indiceCount) { + this.vertexOffset += vertexCount; + this.indiceOffset += indiceCount; + + this.byteOffset = this.byteOffset + vertexCount * this._vertexBytes; + + this._dirty = true; + } +}); + +cc.SpineBuffer = module.exports = SpineBuffer; \ No newline at end of file diff --git a/cocos2d/core/renderer/webgl/vertex-format.js b/cocos2d/core/renderer/webgl/vertex-format.js index 4d0169467f7..75a270f78e5 100644 --- a/cocos2d/core/renderer/webgl/vertex-format.js +++ b/cocos2d/core/renderer/webgl/vertex-format.js @@ -42,6 +42,15 @@ var vfmtPosUvColor = new gfx.VertexFormat([ vfmtPosUvColor.name = 'vfmtPosUvColor'; gfx.VertexFormat.XY_UV_Color = vfmtPosUvColor; +var vfmtPosUvTwoColor = new gfx.VertexFormat([ + { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, + { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, + { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true }, + { name: gfx.ATTR_COLOR0, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true }, +]); +vfmtPosUvTwoColor.name = 'vfmtPosUvTwoColor'; +gfx.VertexFormat.XY_UV_Two_Color = vfmtPosUvTwoColor; + var vfmtPosUv = new gfx.VertexFormat([ { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 }, { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 } @@ -59,6 +68,7 @@ gfx.VertexFormat.XY_Color = vfmtPosColor; module.exports = { vfmt3D, vfmtPosUvColor, + vfmtPosUvTwoColor, vfmtPosUv, vfmtPosColor }; \ No newline at end of file diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 5a7e8269c51..2e93ad00d10 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -258,6 +258,7 @@ module.exports = { "debug_slots": "Indicates whether show debug slots.", "debug_bones": "Indicates whether show debug bones.", "premultipliedAlpha": "Indicates whether to enable premultiplied alpha.", + "use_tint": "Indicates whether to use tint effect." }, "dragon_bones": { "dragon_bones_asset": "The json data contains the DragonBones information, drag the json file exported from DragonBones to get started.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 85f72f2beb7..c082c6914eb 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -262,6 +262,7 @@ module.exports = { "debug_slots": "是否显示 slot 的 debug 信息", "debug_bones": "是否显示 bone 的 debug 信息", "premultipliedAlpha": "是否启用贴图预乘", + "use_tint": "是否启用染色效果" }, "dragon_bones": { "dragon_bones_asset": "骨骼信息数据,拖拽 DragonBones 导出的骨骼动画信息 json 资源到这里来开始使用", diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 2a2869041f4..65a24839cc3 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -27,7 +27,7 @@ const TrackEntryListeners = require('./track-entry-listeners'); const RenderComponent = require('../../cocos2d/core/components/CCRenderComponent'); const spine = require('./lib/spine'); -const SpriteMaterial = require('../../cocos2d/core/renderer/render-engine').SpriteMaterial; +const SpineMaterial = require('../../cocos2d/core/renderer/render-engine').SpineMaterial; const Graphics = require('../../cocos2d/core/graphics/graphics'); const BlendFactor = require('../../cocos2d/core/platform/CCMacro').BlendFactor; @@ -354,6 +354,26 @@ sp.Skeleton = cc.Class({ this._initDebugDraw(); } }, + + /** + * !#en Enabled two color tint. + * !#zh 是否启用染色效果。 + * @property {Boolean} useTint + * @default false + */ + useTint: { + default: false, + tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.use_tint', + notify () { + var cache = this._materialCache + for (var mKey in cache) { + var material = cache[mKey]; + if (material) { + material.useTint = this.useTint; + } + } + } + } }, // CONSTRUCTOR @@ -362,10 +382,11 @@ sp.Skeleton = cc.Class({ this._rootBone = null; this._listener = null; this._boundingBox = cc.rect(); - this._material = new SpriteMaterial(); + this._material = new SpineMaterial(); this._materialCache = {}; - this._renderDatas = []; this._debugRenderer = null; + this._startSlotIndex = -1; + this._endSlotIndex = -1; }, // override @@ -390,10 +411,21 @@ sp.Skeleton = cc.Class({ } this._skeleton = new spine.Skeleton(skeletonData); - // this._skeleton.updateWorldTransform(); + this._clipper = new spine.SkeletonClipping(); this._rootBone = this._skeleton.getRootBone(); }, + /** + * !#en Sets slots visible range. + * !#zh 设置骨骼插槽可视范围。 + * @method setSkeletonData + * @param {sp.spine.SkeletonData} skeletonData + */ + setSlotsRange (startSlotIndex, endSlotIndex) { + this._startSlotIndex = startSlotIndex; + this._endSlotIndex = endSlotIndex; + }, + /** * !#en Sets animation state data.
* The parameter type is {{#crossLinkModule "sp.spine"}}sp.spine{{/crossLinkModule}}.AnimationStateData. @@ -444,26 +476,11 @@ sp.Skeleton = cc.Class({ // Destroyed and restored in Editor if (!this._material) { this._boundingBox = cc.rect(); - this._material = new SpriteMaterial(); + this._material = new SpineMaterial(); this._materialCache = {}; - this._renderDatas = []; } }, - onDestroy () { - this._super(); - // Render datas will be destroyed automatically by RenderComponent.onDestroy - this._renderDatas.length = 0; - }, - - // _getLocalBounds: CC_EDITOR && function (out_rect) { - // var rect = this._boundingBox; - // out_rect.x = rect.x; - // out_rect.y = rect.y; - // out_rect.width = rect.width; - // out_rect.height = rect.height; - // }, - // RENDERER /** diff --git a/extensions/spine/lib/spine.js b/extensions/spine/lib/spine.js index 2ca6537665b..e3c07760962 100644 --- a/extensions/spine/lib/spine.js +++ b/extensions/spine/lib/spine.js @@ -1,10 +1,18 @@ -// Spine runtime version 3.5.35 +// Spine runtime version 3.6 -var __extends = (this && this.__extends) || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); -}; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + } + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); var spine; (function (spine) { var Animation = (function () { @@ -17,7 +25,7 @@ var spine; this.timelines = timelines; this.duration = duration; } - Animation.prototype.apply = function (skeleton, lastTime, time, loop, events, alpha, setupPose, mixingOut) { + Animation.prototype.apply = function (skeleton, lastTime, time, loop, events, alpha, pose, direction) { if (skeleton == null) throw new Error("skeleton cannot be null."); if (loop && this.duration != 0) { @@ -27,7 +35,7 @@ var spine; } var timelines = this.timelines; for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, lastTime, time, events, alpha, setupPose, mixingOut); + timelines[i].apply(skeleton, lastTime, time, events, alpha, pose, direction); }; Animation.binarySearch = function (values, target, step) { if (step === void 0) { step = 1; } @@ -55,6 +63,18 @@ var spine; return Animation; }()); spine.Animation = Animation; + var MixPose; + (function (MixPose) { + MixPose[MixPose["setup"] = 0] = "setup"; + MixPose[MixPose["current"] = 1] = "current"; + MixPose[MixPose["currentLayered"] = 2] = "currentLayered"; + })(MixPose = spine.MixPose || (spine.MixPose = {})); + var MixDirection; + (function (MixDirection) { + MixDirection[MixDirection["in"] = 0] = "in"; + MixDirection[MixDirection["out"] = 1] = "out"; + })(MixDirection = spine.MixDirection || (spine.MixDirection = {})); + var TimelineType; (function (TimelineType) { TimelineType[TimelineType["rotate"] = 0] = "rotate"; TimelineType[TimelineType["translate"] = 1] = "translate"; @@ -70,8 +90,8 @@ var spine; TimelineType[TimelineType["pathConstraintPosition"] = 11] = "pathConstraintPosition"; TimelineType[TimelineType["pathConstraintSpacing"] = 12] = "pathConstraintSpacing"; TimelineType[TimelineType["pathConstraintMix"] = 13] = "pathConstraintMix"; - })(spine.TimelineType || (spine.TimelineType = {})); - var TimelineType = spine.TimelineType; + TimelineType[TimelineType["twoColor"] = 14] = "twoColor"; + })(TimelineType = spine.TimelineType || (spine.TimelineType = {})); var CurveTimeline = (function () { function CurveTimeline(frameCount) { if (frameCount <= 0) @@ -157,8 +177,9 @@ var spine; var RotateTimeline = (function (_super) { __extends(RotateTimeline, _super); function RotateTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount << 1); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount << 1); + return _this; } RotateTimeline.prototype.getPropertyId = function () { return (TimelineType.rotate << 24) + this.boneIndex; @@ -168,21 +189,28 @@ var spine; this.frames[frameIndex] = time; this.frames[frameIndex + RotateTimeline.ROTATION] = degrees; }; - RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var frames = this.frames; var bone = skeleton.bones[this.boneIndex]; if (time < frames[0]) { - if (setupPose) - bone.rotation = bone.data.rotation; + switch (pose) { + case MixPose.setup: + bone.rotation = bone.data.rotation; + return; + case MixPose.current: + var r_1 = bone.data.rotation - bone.rotation; + r_1 -= (16384 - ((16384.499999999996 - r_1 / 360) | 0)) * 360; + bone.rotation += r_1 * alpha; + } return; } if (time >= frames[frames.length - RotateTimeline.ENTRIES]) { - if (setupPose) + if (pose == MixPose.setup) bone.rotation = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] * alpha; else { - var r_1 = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] - bone.rotation; - r_1 -= (16384 - ((16384.499999999996 - r_1 / 360) | 0)) * 360; - bone.rotation += r_1 * alpha; + var r_2 = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] - bone.rotation; + r_2 -= (16384 - ((16384.499999999996 - r_2 / 360) | 0)) * 360; + bone.rotation += r_2 * alpha; } return; } @@ -193,7 +221,7 @@ var spine; var r = frames[frame + RotateTimeline.ROTATION] - prevRotation; r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; r = prevRotation + r * percent; - if (setupPose) { + if (pose == MixPose.setup) { r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; bone.rotation = bone.data.rotation + r * alpha; } @@ -213,8 +241,9 @@ var spine; var TranslateTimeline = (function (_super) { __extends(TranslateTimeline, _super); function TranslateTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES); + return _this; } TranslateTimeline.prototype.getPropertyId = function () { return (TimelineType.translate << 24) + this.boneIndex; @@ -225,13 +254,18 @@ var spine; this.frames[frameIndex + TranslateTimeline.X] = x; this.frames[frameIndex + TranslateTimeline.Y] = y; }; - TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var frames = this.frames; var bone = skeleton.bones[this.boneIndex]; if (time < frames[0]) { - if (setupPose) { - bone.x = bone.data.x; - bone.y = bone.data.y; + switch (pose) { + case MixPose.setup: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case MixPose.current: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; } return; } @@ -249,7 +283,7 @@ var spine; x += (frames[frame + TranslateTimeline.X] - x) * percent; y += (frames[frame + TranslateTimeline.Y] - y) * percent; } - if (setupPose) { + if (pose == MixPose.setup) { bone.x = bone.data.x + x * alpha; bone.y = bone.data.y + y * alpha; } @@ -270,18 +304,23 @@ var spine; var ScaleTimeline = (function (_super) { __extends(ScaleTimeline, _super); function ScaleTimeline(frameCount) { - _super.call(this, frameCount); + return _super.call(this, frameCount) || this; } ScaleTimeline.prototype.getPropertyId = function () { return (TimelineType.scale << 24) + this.boneIndex; }; - ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var frames = this.frames; var bone = skeleton.bones[this.boneIndex]; if (time < frames[0]) { - if (setupPose) { - bone.scaleX = bone.data.scaleX; - bone.scaleY = bone.data.scaleY; + switch (pose) { + case MixPose.setup: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case MixPose.current: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; } return; } @@ -305,7 +344,7 @@ var spine; } else { var bx = 0, by = 0; - if (setupPose) { + if (pose == MixPose.setup) { bx = bone.data.scaleX; by = bone.data.scaleY; } @@ -313,7 +352,7 @@ var spine; bx = bone.scaleX; by = bone.scaleY; } - if (mixingOut) { + if (direction == MixDirection.out) { x = Math.abs(x) * spine.MathUtils.signum(bx); y = Math.abs(y) * spine.MathUtils.signum(by); } @@ -331,18 +370,23 @@ var spine; var ShearTimeline = (function (_super) { __extends(ShearTimeline, _super); function ShearTimeline(frameCount) { - _super.call(this, frameCount); + return _super.call(this, frameCount) || this; } ShearTimeline.prototype.getPropertyId = function () { return (TimelineType.shear << 24) + this.boneIndex; }; - ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var frames = this.frames; var bone = skeleton.bones[this.boneIndex]; if (time < frames[0]) { - if (setupPose) { - bone.shearX = bone.data.shearX; - bone.shearY = bone.data.shearY; + switch (pose) { + case MixPose.setup: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case MixPose.current: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; } return; } @@ -360,7 +404,7 @@ var spine; x = x + (frames[frame + ShearTimeline.X] - x) * percent; y = y + (frames[frame + ShearTimeline.Y] - y) * percent; } - if (setupPose) { + if (pose == MixPose.setup) { bone.shearX = bone.data.shearX + x * alpha; bone.shearY = bone.data.shearY + y * alpha; } @@ -375,8 +419,9 @@ var spine; var ColorTimeline = (function (_super) { __extends(ColorTimeline, _super); function ColorTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES); + return _this; } ColorTimeline.prototype.getPropertyId = function () { return (TimelineType.color << 24) + this.slotIndex; @@ -389,12 +434,18 @@ var spine; this.frames[frameIndex + ColorTimeline.B] = b; this.frames[frameIndex + ColorTimeline.A] = a; }; - ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var slot = skeleton.slots[this.slotIndex]; var frames = this.frames; if (time < frames[0]) { - if (setupPose) - slot.color.setFromColor(slot.data.color); + switch (pose) { + case MixPose.setup: + slot.color.setFromColor(slot.data.color); + return; + case MixPose.current: + var color = slot.color, setup = slot.data.color; + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha); + } return; } var r = 0, g = 0, b = 0, a = 0; @@ -422,7 +473,7 @@ var spine; slot.color.set(r, g, b, a); else { var color = slot.color; - if (setupPose) + if (pose == MixPose.setup) color.setFromColor(slot.data.color); color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); } @@ -440,6 +491,106 @@ var spine; return ColorTimeline; }(CurveTimeline)); spine.ColorTimeline = ColorTimeline; + var TwoColorTimeline = (function (_super) { + __extends(TwoColorTimeline, _super); + function TwoColorTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TwoColorTimeline.ENTRIES); + return _this; + } + TwoColorTimeline.prototype.getPropertyId = function () { + return (TimelineType.twoColor << 24) + this.slotIndex; + }; + TwoColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a, r2, g2, b2) { + frameIndex *= TwoColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TwoColorTimeline.R] = r; + this.frames[frameIndex + TwoColorTimeline.G] = g; + this.frames[frameIndex + TwoColorTimeline.B] = b; + this.frames[frameIndex + TwoColorTimeline.A] = a; + this.frames[frameIndex + TwoColorTimeline.R2] = r2; + this.frames[frameIndex + TwoColorTimeline.G2] = g2; + this.frames[frameIndex + TwoColorTimeline.B2] = b2; + }; + TwoColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { + var slot = skeleton.slots[this.slotIndex]; + var frames = this.frames; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + slot.color.setFromColor(slot.data.color); + slot.darkColor.setFromColor(slot.data.darkColor); + return; + case MixPose.current: + var light = slot.color, dark = slot.darkColor, setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha, (setupLight.a - light.a) * alpha); + dark.add((setupDark.r - dark.r) * alpha, (setupDark.g - dark.g) * alpha, (setupDark.b - dark.b) * alpha, 0); + } + return; + } + var r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + if (time >= frames[frames.length - TwoColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + TwoColorTimeline.PREV_R]; + g = frames[i + TwoColorTimeline.PREV_G]; + b = frames[i + TwoColorTimeline.PREV_B]; + a = frames[i + TwoColorTimeline.PREV_A]; + r2 = frames[i + TwoColorTimeline.PREV_R2]; + g2 = frames[i + TwoColorTimeline.PREV_G2]; + b2 = frames[i + TwoColorTimeline.PREV_B2]; + } + else { + var frame = Animation.binarySearch(frames, time, TwoColorTimeline.ENTRIES); + r = frames[frame + TwoColorTimeline.PREV_R]; + g = frames[frame + TwoColorTimeline.PREV_G]; + b = frames[frame + TwoColorTimeline.PREV_B]; + a = frames[frame + TwoColorTimeline.PREV_A]; + r2 = frames[frame + TwoColorTimeline.PREV_R2]; + g2 = frames[frame + TwoColorTimeline.PREV_G2]; + b2 = frames[frame + TwoColorTimeline.PREV_B2]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TwoColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TwoColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + TwoColorTimeline.R] - r) * percent; + g += (frames[frame + TwoColorTimeline.G] - g) * percent; + b += (frames[frame + TwoColorTimeline.B] - b) * percent; + a += (frames[frame + TwoColorTimeline.A] - a) * percent; + r2 += (frames[frame + TwoColorTimeline.R2] - r2) * percent; + g2 += (frames[frame + TwoColorTimeline.G2] - g2) * percent; + b2 += (frames[frame + TwoColorTimeline.B2] - b2) * percent; + } + if (alpha == 1) { + slot.color.set(r, g, b, a); + slot.darkColor.set(r2, g2, b2, 1); + } + else { + var light = slot.color, dark = slot.darkColor; + if (pose == MixPose.setup) { + light.setFromColor(slot.data.color); + dark.setFromColor(slot.data.darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0); + } + }; + TwoColorTimeline.ENTRIES = 8; + TwoColorTimeline.PREV_TIME = -8; + TwoColorTimeline.PREV_R = -7; + TwoColorTimeline.PREV_G = -6; + TwoColorTimeline.PREV_B = -5; + TwoColorTimeline.PREV_A = -4; + TwoColorTimeline.PREV_R2 = -3; + TwoColorTimeline.PREV_G2 = -2; + TwoColorTimeline.PREV_B2 = -1; + TwoColorTimeline.R = 1; + TwoColorTimeline.G = 2; + TwoColorTimeline.B = 3; + TwoColorTimeline.A = 4; + TwoColorTimeline.R2 = 5; + TwoColorTimeline.G2 = 6; + TwoColorTimeline.B2 = 7; + return TwoColorTimeline; + }(CurveTimeline)); + spine.TwoColorTimeline = TwoColorTimeline; var AttachmentTimeline = (function () { function AttachmentTimeline(frameCount) { this.frames = spine.Utils.newFloatArray(frameCount); @@ -455,16 +606,16 @@ var spine; this.frames[frameIndex] = time; this.attachmentNames[frameIndex] = attachmentName; }; - AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var slot = skeleton.slots[this.slotIndex]; - if (mixingOut && setupPose) { + if (direction == MixDirection.out && pose == MixPose.setup) { var attachmentName_1 = slot.data.attachmentName; slot.setAttachment(attachmentName_1 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_1)); return; } var frames = this.frames; if (time < frames[0]) { - if (setupPose) { + if (pose == MixPose.setup) { var attachmentName_2 = slot.data.attachmentName; slot.setAttachment(attachmentName_2 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_2)); } @@ -482,59 +633,83 @@ var spine; return AttachmentTimeline; }()); spine.AttachmentTimeline = AttachmentTimeline; + var zeros = null; var DeformTimeline = (function (_super) { __extends(DeformTimeline, _super); function DeformTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount); - this.frameVertices = new Array(frameCount); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount); + _this.frameVertices = new Array(frameCount); + if (zeros == null) + zeros = spine.Utils.newFloatArray(64); + return _this; } DeformTimeline.prototype.getPropertyId = function () { - return (TimelineType.deform << 24) + this.slotIndex; + return (TimelineType.deform << 27) + +this.attachment.id + this.slotIndex; }; DeformTimeline.prototype.setFrame = function (frameIndex, time, vertices) { this.frames[frameIndex] = time; this.frameVertices[frameIndex] = vertices; }; - DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var slot = skeleton.slots[this.slotIndex]; var slotAttachment = slot.getAttachment(); if (!(slotAttachment instanceof spine.VertexAttachment) || !slotAttachment.applyDeform(this.attachment)) return; - var frames = this.frames; var verticesArray = slot.attachmentVertices; + if (verticesArray.length == 0) + alpha = 1; + var frameVertices = this.frameVertices; + var vertexCount = frameVertices[0].length; + var frames = this.frames; if (time < frames[0]) { - if (setupPose) - spine.Utils.setArraySize(verticesArray, 0); + var vertexAttachment = slotAttachment; + switch (pose) { + case MixPose.setup: + verticesArray.length = 0; + return; + case MixPose.current: + if (alpha == 1) { + verticesArray.length = 0; + break; + } + var vertices_1 = spine.Utils.setArraySize(verticesArray, vertexCount); + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + vertices_1[i] += (setupVertices[i] - vertices_1[i]) * alpha; + } + else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + vertices_1[i] *= alpha; + } + } return; } - var frameVertices = this.frameVertices; - var vertexCount = frameVertices[0].length; - if (verticesArray.length != vertexCount) - alpha = 1; var vertices = spine.Utils.setArraySize(verticesArray, vertexCount); if (time >= frames[frames.length - 1]) { var lastVertices = frameVertices[frames.length - 1]; if (alpha == 1) { spine.Utils.arrayCopy(lastVertices, 0, vertices, 0, vertexCount); } - else if (setupPose) { + else if (pose == MixPose.setup) { var vertexAttachment = slotAttachment; if (vertexAttachment.bones == null) { - var setupVertices = vertexAttachment.vertices; - for (var i = 0; i < vertexCount; i++) { - var setup = setupVertices[i]; - vertices[i] = setup + (lastVertices[i] - setup) * alpha; + var setupVertices_1 = vertexAttachment.vertices; + for (var i_1 = 0; i_1 < vertexCount; i_1++) { + var setup = setupVertices_1[i_1]; + vertices[i_1] = setup + (lastVertices[i_1] - setup) * alpha; } } else { - for (var i = 0; i < vertexCount; i++) - vertices[i] = lastVertices[i] * alpha; + for (var i_2 = 0; i_2 < vertexCount; i_2++) + vertices[i_2] = lastVertices[i_2] * alpha; } } else { - for (var i = 0; i < vertexCount; i++) - vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + for (var i_3 = 0; i_3 < vertexCount; i_3++) + vertices[i_3] += (lastVertices[i_3] - vertices[i_3]) * alpha; } return; } @@ -544,31 +719,31 @@ var spine; var frameTime = frames[frame]; var percent = this.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); if (alpha == 1) { - for (var i = 0; i < vertexCount; i++) { - var prev = prevVertices[i]; - vertices[i] = prev + (nextVertices[i] - prev) * percent; + for (var i_4 = 0; i_4 < vertexCount; i_4++) { + var prev = prevVertices[i_4]; + vertices[i_4] = prev + (nextVertices[i_4] - prev) * percent; } } - else if (setupPose) { + else if (pose == MixPose.setup) { var vertexAttachment = slotAttachment; if (vertexAttachment.bones == null) { - var setupVertices = vertexAttachment.vertices; - for (var i = 0; i < vertexCount; i++) { - var prev = prevVertices[i], setup = setupVertices[i]; - vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + var setupVertices_2 = vertexAttachment.vertices; + for (var i_5 = 0; i_5 < vertexCount; i_5++) { + var prev = prevVertices[i_5], setup = setupVertices_2[i_5]; + vertices[i_5] = setup + (prev + (nextVertices[i_5] - prev) * percent - setup) * alpha; } } else { - for (var i = 0; i < vertexCount; i++) { - var prev = prevVertices[i]; - vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + for (var i_6 = 0; i_6 < vertexCount; i_6++) { + var prev = prevVertices[i_6]; + vertices[i_6] = (prev + (nextVertices[i_6] - prev) * percent) * alpha; } } } else { - for (var i = 0; i < vertexCount; i++) { - var prev = prevVertices[i]; - vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + for (var i_7 = 0; i_7 < vertexCount; i_7++) { + var prev = prevVertices[i_7]; + vertices[i_7] += (prev + (nextVertices[i_7] - prev) * percent - vertices[i_7]) * alpha; } } }; @@ -590,13 +765,13 @@ var spine; this.frames[frameIndex] = event.time; this.events[frameIndex] = event; }; - EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { if (firedEvents == null) return; var frames = this.frames; var frameCount = this.frames.length; if (lastTime > time) { - this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, setupPose, mixingOut); + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, pose, direction); lastTime = -1; } else if (lastTime >= frames[frameCount - 1]) @@ -636,16 +811,16 @@ var spine; this.frames[frameIndex] = time; this.drawOrders[frameIndex] = drawOrder; }; - DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var drawOrder = skeleton.drawOrder; var slots = skeleton.slots; - if (mixingOut && setupPose) { + if (direction == MixDirection.out && pose == MixPose.setup) { spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); return; } var frames = this.frames; if (time < frames[0]) { - if (setupPose) + if (pose == MixPose.setup) spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); return; } @@ -668,8 +843,9 @@ var spine; var IkConstraintTimeline = (function (_super) { __extends(IkConstraintTimeline, _super); function IkConstraintTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES); + return _this; } IkConstraintTimeline.prototype.getPropertyId = function () { return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex; @@ -680,25 +856,30 @@ var spine; this.frames[frameIndex + IkConstraintTimeline.MIX] = mix; this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection; }; - IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.ikConstraints[this.ikConstraintIndex]; if (time < frames[0]) { - if (setupPose) { - constraint.mix = constraint.data.mix; - constraint.bendDirection = constraint.data.bendDirection; + switch (pose) { + case MixPose.setup: + constraint.mix = constraint.data.mix; + constraint.bendDirection = constraint.data.bendDirection; + return; + case MixPose.current: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.bendDirection = constraint.data.bendDirection; } return; } if (time >= frames[frames.length - IkConstraintTimeline.ENTRIES]) { - if (setupPose) { + if (pose == MixPose.setup) { constraint.mix = constraint.data.mix + (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.data.mix) * alpha; - constraint.bendDirection = mixingOut ? constraint.data.bendDirection + constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection : frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; } else { constraint.mix += (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.mix) * alpha; - if (!mixingOut) + if (direction == MixDirection["in"]) constraint.bendDirection = frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; } return; @@ -707,13 +888,13 @@ var spine; var mix = frames[frame + IkConstraintTimeline.PREV_MIX]; var frameTime = frames[frame]; var percent = this.getCurvePercent(frame / IkConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + IkConstraintTimeline.PREV_TIME] - frameTime)); - if (setupPose) { + if (pose == MixPose.setup) { constraint.mix = constraint.data.mix + (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.data.mix) * alpha; - constraint.bendDirection = mixingOut ? constraint.data.bendDirection : frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection : frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; } else { constraint.mix += (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.mix) * alpha; - if (!mixingOut) + if (direction == MixDirection["in"]) constraint.bendDirection = frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; } }; @@ -729,8 +910,9 @@ var spine; var TransformConstraintTimeline = (function (_super) { __extends(TransformConstraintTimeline, _super); function TransformConstraintTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES); + return _this; } TransformConstraintTimeline.prototype.getPropertyId = function () { return (TimelineType.transformConstraint << 24) + this.transformConstraintIndex; @@ -743,16 +925,23 @@ var spine; this.frames[frameIndex + TransformConstraintTimeline.SCALE] = scaleMix; this.frames[frameIndex + TransformConstraintTimeline.SHEAR] = shearMix; }; - TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.transformConstraints[this.transformConstraintIndex]; if (time < frames[0]) { - if (setupPose) { - var data = constraint.data; - constraint.rotateMix = data.rotateMix; - constraint.translateMix = data.rotateMix; - constraint.scaleMix = data.scaleMix; - constraint.shearMix = data.shearMix; + var data = constraint.data; + switch (pose) { + case MixPose.setup: + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + return; + case MixPose.current: + constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; + constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; + constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha; } return; } @@ -777,7 +966,7 @@ var spine; scale += (frames[frame + TransformConstraintTimeline.SCALE] - scale) * percent; shear += (frames[frame + TransformConstraintTimeline.SHEAR] - shear) * percent; } - if (setupPose) { + if (pose == MixPose.setup) { var data = constraint.data; constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; @@ -807,8 +996,9 @@ var spine; var PathConstraintPositionTimeline = (function (_super) { __extends(PathConstraintPositionTimeline, _super); function PathConstraintPositionTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES); + return _this; } PathConstraintPositionTimeline.prototype.getPropertyId = function () { return (TimelineType.pathConstraintPosition << 24) + this.pathConstraintIndex; @@ -818,12 +1008,17 @@ var spine; this.frames[frameIndex] = time; this.frames[frameIndex + PathConstraintPositionTimeline.VALUE] = value; }; - PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; if (time < frames[0]) { - if (setupPose) - constraint.position = constraint.data.position; + switch (pose) { + case MixPose.setup: + constraint.position = constraint.data.position; + return; + case MixPose.current: + constraint.position += (constraint.data.position - constraint.position) * alpha; + } return; } var position = 0; @@ -836,7 +1031,7 @@ var spine; var percent = this.getCurvePercent(frame / PathConstraintPositionTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintPositionTimeline.PREV_TIME] - frameTime)); position += (frames[frame + PathConstraintPositionTimeline.VALUE] - position) * percent; } - if (setupPose) + if (pose == MixPose.setup) constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; else constraint.position += (position - constraint.position) * alpha; @@ -851,17 +1046,22 @@ var spine; var PathConstraintSpacingTimeline = (function (_super) { __extends(PathConstraintSpacingTimeline, _super); function PathConstraintSpacingTimeline(frameCount) { - _super.call(this, frameCount); + return _super.call(this, frameCount) || this; } PathConstraintSpacingTimeline.prototype.getPropertyId = function () { return (TimelineType.pathConstraintSpacing << 24) + this.pathConstraintIndex; }; - PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; if (time < frames[0]) { - if (setupPose) - constraint.spacing = constraint.data.spacing; + switch (pose) { + case MixPose.setup: + constraint.spacing = constraint.data.spacing; + return; + case MixPose.current: + constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; + } return; } var spacing = 0; @@ -874,7 +1074,7 @@ var spine; var percent = this.getCurvePercent(frame / PathConstraintSpacingTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintSpacingTimeline.PREV_TIME] - frameTime)); spacing += (frames[frame + PathConstraintSpacingTimeline.VALUE] - spacing) * percent; } - if (setupPose) + if (pose == MixPose.setup) constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; else constraint.spacing += (spacing - constraint.spacing) * alpha; @@ -885,8 +1085,9 @@ var spine; var PathConstraintMixTimeline = (function (_super) { __extends(PathConstraintMixTimeline, _super); function PathConstraintMixTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES); + return _this; } PathConstraintMixTimeline.prototype.getPropertyId = function () { return (TimelineType.pathConstraintMix << 24) + this.pathConstraintIndex; @@ -897,13 +1098,18 @@ var spine; this.frames[frameIndex + PathConstraintMixTimeline.ROTATE] = rotateMix; this.frames[frameIndex + PathConstraintMixTimeline.TRANSLATE] = translateMix; }; - PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; if (time < frames[0]) { - if (setupPose) { - constraint.rotateMix = constraint.data.rotateMix; - constraint.translateMix = constraint.data.translateMix; + switch (pose) { + case MixPose.setup: + constraint.rotateMix = constraint.data.rotateMix; + constraint.translateMix = constraint.data.translateMix; + return; + case MixPose.current: + constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; } return; } @@ -921,7 +1127,7 @@ var spine; rotate += (frames[frame + PathConstraintMixTimeline.ROTATE] - rotate) * percent; translate += (frames[frame + PathConstraintMixTimeline.TRANSLATE] - translate) * percent; } - if (setupPose) { + if (pose == MixPose.setup) { constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; } @@ -949,6 +1155,7 @@ var spine; this.listeners = new Array(); this.queue = new EventQueue(this); this.propertyIDs = new spine.IntSet(); + this.mixingTo = new Array(); this.animationsChanged = false; this.timeScale = 1; this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); }); @@ -986,33 +1193,42 @@ var spine; continue; } } - else { - if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { - tracks[i] = null; - this.queue.end(current); - this.disposeNext(current); - continue; + else if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { + tracks[i] = null; + this.queue.end(current); + this.disposeNext(current); + continue; + } + if (current.mixingFrom != null && this.updateMixingFrom(current, delta)) { + var from = current.mixingFrom; + current.mixingFrom = null; + while (from != null) { + this.queue.end(from); + from = from.mixingFrom; } } - this.updateMixingFrom(current, delta); current.trackTime += currentDelta; } this.queue.drain(); }; - AnimationState.prototype.updateMixingFrom = function (entry, delta) { - var from = entry.mixingFrom; + AnimationState.prototype.updateMixingFrom = function (to, delta) { + var from = to.mixingFrom; if (from == null) - return; - this.updateMixingFrom(from, delta); - if (entry.mixTime >= entry.mixDuration && from.mixingFrom != null && entry.mixTime > 0) { - entry.mixingFrom = null; - this.queue.end(from); - return; - } + return true; + var finished = this.updateMixingFrom(from, delta); from.animationLast = from.nextAnimationLast; from.trackLast = from.nextTrackLast; + if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; + } from.trackTime += delta * from.timeScale; - entry.mixTime += delta * from.timeScale; + to.mixTime += delta * to.timeScale; + return false; }; AnimationState.prototype.apply = function (skeleton) { if (skeleton == null) @@ -1021,35 +1237,41 @@ var spine; this._animationsChanged(); var events = this.events; var tracks = this.tracks; + var applied = false; for (var i = 0, n = tracks.length; i < n; i++) { var current = tracks[i]; if (current == null || current.delay > 0) continue; + applied = true; + var currentPose = i == 0 ? spine.MixPose.current : spine.MixPose.currentLayered; var mix = current.alpha; if (current.mixingFrom != null) - mix *= this.applyMixingFrom(current, skeleton); - else if (current.trackTime >= current.trackEnd) + mix *= this.applyMixingFrom(current, skeleton, currentPose); + else if (current.trackTime >= current.trackEnd && current.next == null) mix = 0; var animationLast = current.animationLast, animationTime = current.getAnimationTime(); var timelineCount = current.animation.timelines.length; var timelines = current.animation.timelines; if (mix == 1) { for (var ii = 0; ii < timelineCount; ii++) - timelines[ii].apply(skeleton, animationLast, animationTime, events, 1, true, false); + timelines[ii].apply(skeleton, animationLast, animationTime, events, 1, spine.MixPose.setup, spine.MixDirection["in"]); } else { + var timelineData = current.timelineData; var firstFrame = current.timelinesRotation.length == 0; if (firstFrame) spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null); var timelinesRotation = current.timelinesRotation; - var timelinesFirst = current.timelinesFirst; for (var ii = 0; ii < timelineCount; ii++) { var timeline = timelines[ii]; + var pose = timelineData[ii] >= AnimationState.FIRST ? spine.MixPose.setup : currentPose; if (timeline instanceof spine.RotateTimeline) { - this.applyRotateTimeline(timeline, skeleton, animationTime, mix, timelinesFirst[ii], timelinesRotation, ii << 1, firstFrame); + this.applyRotateTimeline(timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); + } + else { + spine.Utils.webkit602BugfixHelper(mix, pose); + timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, spine.MixDirection["in"]); } - else - timeline.apply(skeleton, animationLast, animationTime, events, mix, timelinesFirst[ii], false); } } this.queueEvents(current, animationTime); @@ -1058,16 +1280,19 @@ var spine; current.nextTrackLast = current.trackTime; } this.queue.drain(); + return applied; }; - AnimationState.prototype.applyMixingFrom = function (entry, skeleton) { - var from = entry.mixingFrom; + AnimationState.prototype.applyMixingFrom = function (to, skeleton, currentPose) { + var from = to.mixingFrom; if (from.mixingFrom != null) - this.applyMixingFrom(from, skeleton); + this.applyMixingFrom(from, skeleton, currentPose); var mix = 0; - if (entry.mixDuration == 0) + if (to.mixDuration == 0) { mix = 1; + currentPose = spine.MixPose.setup; + } else { - mix = entry.mixTime / entry.mixDuration; + mix = to.mixTime / to.mixDuration; if (mix > 1) mix = 1; } @@ -1076,46 +1301,68 @@ var spine; var animationLast = from.animationLast, animationTime = from.getAnimationTime(); var timelineCount = from.animation.timelines.length; var timelines = from.animation.timelines; - var timelinesFirst = from.timelinesFirst; - var alpha = from.alpha * entry.mixAlpha * (1 - mix); + var timelineData = from.timelineData; + var timelineDipMix = from.timelineDipMix; var firstFrame = from.timelinesRotation.length == 0; if (firstFrame) spine.Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null); var timelinesRotation = from.timelinesRotation; + var pose; + var alphaDip = from.alpha * to.interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha = 0; + from.totalAlpha = 0; for (var i = 0; i < timelineCount; i++) { var timeline = timelines[i]; - var setupPose = timelinesFirst[i]; - if (timeline instanceof spine.RotateTimeline) - this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, setupPose, timelinesRotation, i << 1, firstFrame); - else { - if (!setupPose) { + switch (timelineData[i]) { + case AnimationState.SUBSEQUENT: if (!attachments && timeline instanceof spine.AttachmentTimeline) continue; if (!drawOrder && timeline instanceof spine.DrawOrderTimeline) continue; - } - timeline.apply(skeleton, animationLast, animationTime, events, alpha, setupPose, true); + pose = currentPose; + alpha = alphaMix; + break; + case AnimationState.FIRST: + pose = spine.MixPose.setup; + alpha = alphaMix; + break; + case AnimationState.DIP: + pose = spine.MixPose.setup; + alpha = alphaDip; + break; + default: + pose = spine.MixPose.setup; + alpha = alphaDip; + var dipMix = timelineDipMix[i]; + alpha *= Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (timeline instanceof spine.RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); + else { + spine.Utils.webkit602BugfixHelper(alpha, pose); + timeline.apply(skeleton, animationLast, animationTime, events, alpha, pose, spine.MixDirection.out); } } - if (entry.mixDuration > 0) + if (to.mixDuration > 0) this.queueEvents(from, animationTime); this.events.length = 0; from.nextAnimationLast = animationTime; from.nextTrackLast = from.trackTime; return mix; }; - AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, setupPose, timelinesRotation, i, firstFrame) { + AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, pose, timelinesRotation, i, firstFrame) { if (firstFrame) timelinesRotation[i] = 0; if (alpha == 1) { - timeline.apply(skeleton, 0, time, null, 1, setupPose, false); + timeline.apply(skeleton, 0, time, null, 1, pose, spine.MixDirection["in"]); return; } var rotateTimeline = timeline; var frames = rotateTimeline.frames; var bone = skeleton.bones[rotateTimeline.boneIndex]; if (time < frames[0]) { - if (setupPose) + if (pose == spine.MixPose.setup) bone.rotation = bone.data.rotation; return; } @@ -1132,7 +1379,7 @@ var spine; r2 = prevRotation + r2 * percent + bone.data.rotation; r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; } - var r1 = setupPose ? bone.data.rotation : bone.rotation; + var r1 = pose == spine.MixPose.setup ? bone.data.rotation : bone.rotation; var total = 0, diff = r2 - r1; if (diff == 0) { total = timelinesRotation[i]; @@ -1177,10 +1424,13 @@ var spine; continue; this.queue.event(entry, event_1); } - if (entry.loop ? (trackLastWrapped > entry.trackTime % duration) - : (animationTime >= animationEnd && entry.animationLast < animationEnd)) { + var complete = false; + if (entry.loop) + complete = duration == 0 || trackLastWrapped > entry.trackTime % duration; + else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) this.queue.complete(entry); - } for (; i < n; i++) { var event_2 = events[i]; if (event_2.time < animationStart) @@ -1189,11 +1439,12 @@ var spine; } }; AnimationState.prototype.clearTracks = function () { + var oldDrainDisabled = this.queue.drainDisabled; this.queue.drainDisabled = true; for (var i = 0, n = this.tracks.length; i < n; i++) this.clearTrack(i); this.tracks.length = 0; - this.queue.drainDisabled = false; + this.queue.drainDisabled = oldDrainDisabled; this.queue.drain(); }; AnimationState.prototype.clearTrack = function (trackIndex) { @@ -1224,9 +1475,9 @@ var spine; this.queue.interrupt(from); current.mixingFrom = from; current.mixTime = 0; - from.timelinesRotation.length = 0; if (from.mixingFrom != null && from.mixDuration > 0) - current.mixAlpha *= Math.min(from.mixTime / from.mixDuration, 1); + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; } this.queue.start(current); }; @@ -1281,8 +1532,13 @@ var spine; last.next = entry; if (delay <= 0) { var duration = last.animationEnd - last.animationStart; - if (duration != 0) - delay += duration * (1 + ((last.trackTime / duration) | 0)) - this.data.getMix(last.animation, animation); + if (duration != 0) { + if (last.loop) + delay += duration * (1 + ((last.trackTime / duration) | 0)); + else + delay += duration; + delay -= this.data.getMix(last.animation, animation); + } else delay = 0; } @@ -1305,13 +1561,14 @@ var spine; return entry; }; AnimationState.prototype.setEmptyAnimations = function (mixDuration) { + var oldDrainDisabled = this.queue.drainDisabled; this.queue.drainDisabled = true; for (var i = 0, n = this.tracks.length; i < n; i++) { var current = this.tracks[i]; if (current != null) this.setEmptyAnimation(current.trackIndex, mixDuration); } - this.queue.drainDisabled = false; + this.queue.drainDisabled = oldDrainDisabled; this.queue.drain(); }; AnimationState.prototype.expandToIndex = function (index) { @@ -1340,7 +1597,7 @@ var spine; entry.trackEnd = Number.MAX_VALUE; entry.timeScale = 1; entry.alpha = 1; - entry.mixAlpha = 1; + entry.interruptAlpha = 1; entry.mixTime = 0; entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation); return entry; @@ -1356,50 +1613,14 @@ var spine; AnimationState.prototype._animationsChanged = function () { this.animationsChanged = false; var propertyIDs = this.propertyIDs; - var i = 0, n = this.tracks.length; propertyIDs.clear(); - for (; i < n; i++) { - var entry = this.tracks[i]; - if (entry == null) - continue; - this.setTimelinesFirst(entry); - i++; - break; - } - for (; i < n; i++) { + var mixingTo = this.mixingTo; + for (var i = 0, n = this.tracks.length; i < n; i++) { var entry = this.tracks[i]; if (entry != null) - this.checkTimelinesFirst(entry); - } - }; - AnimationState.prototype.setTimelinesFirst = function (entry) { - if (entry.mixingFrom != null) { - this.setTimelinesFirst(entry.mixingFrom); - this.checkTimelinesUsage(entry, entry.timelinesFirst); - return; - } - var propertyIDs = this.propertyIDs; - var timelines = entry.animation.timelines; - var n = timelines.length; - var usage = spine.Utils.setArraySize(entry.timelinesFirst, n, false); - for (var i = 0; i < n; i++) { - propertyIDs.add(timelines[i].getPropertyId()); - usage[i] = true; + entry.setTimelineData(null, mixingTo, propertyIDs); } }; - AnimationState.prototype.checkTimelinesFirst = function (entry) { - if (entry.mixingFrom != null) - this.checkTimelinesFirst(entry.mixingFrom); - this.checkTimelinesUsage(entry, entry.timelinesFirst); - }; - AnimationState.prototype.checkTimelinesUsage = function (entry, usageArray) { - var propertyIDs = this.propertyIDs; - var timelines = entry.animation.timelines; - var n = timelines.length; - var usage = spine.Utils.setArraySize(usageArray, n); - for (var i = 0; i < n; i++) - usage[i] = propertyIDs.add(timelines[i].getPropertyId()); - }; AnimationState.prototype.getCurrent = function (trackIndex) { if (trackIndex >= this.tracks.length) return null; @@ -1422,12 +1643,17 @@ var spine; this.queue.clear(); }; AnimationState.emptyAnimation = new spine.Animation("", [], 0); + AnimationState.SUBSEQUENT = 0; + AnimationState.FIRST = 1; + AnimationState.DIP = 2; + AnimationState.DIP_MIX = 3; return AnimationState; }()); spine.AnimationState = AnimationState; var TrackEntry = (function () { function TrackEntry() { - this.timelinesFirst = new Array(); + this.timelineData = new Array(); + this.timelineDipMix = new Array(); this.timelinesRotation = new Array(); } TrackEntry.prototype.reset = function () { @@ -1435,9 +1661,52 @@ var spine; this.mixingFrom = null; this.animation = null; this.listener = null; - this.timelinesFirst.length = 0; + this.timelineData.length = 0; + this.timelineDipMix.length = 0; this.timelinesRotation.length = 0; }; + TrackEntry.prototype.setTimelineData = function (to, mixingToArray, propertyIDs) { + if (to != null) + mixingToArray.push(to); + var lastEntry = this.mixingFrom != null ? this.mixingFrom.setTimelineData(this, mixingToArray, propertyIDs) : this; + if (to != null) + mixingToArray.pop(); + var mixingTo = mixingToArray; + var mixingToLast = mixingToArray.length - 1; + var timelines = this.animation.timelines; + var timelinesCount = this.animation.timelines.length; + var timelineData = spine.Utils.setArraySize(this.timelineData, timelinesCount); + this.timelineDipMix.length = 0; + var timelineDipMix = spine.Utils.setArraySize(this.timelineDipMix, timelinesCount); + outer: for (var i = 0; i < timelinesCount; i++) { + var id = timelines[i].getPropertyId(); + if (!propertyIDs.add(id)) + timelineData[i] = AnimationState.SUBSEQUENT; + else if (to == null || !to.hasTimeline(id)) + timelineData[i] = AnimationState.FIRST; + else { + for (var ii = mixingToLast; ii >= 0; ii--) { + var entry = mixingTo[ii]; + if (!entry.hasTimeline(id)) { + if (entry.mixDuration > 0) { + timelineData[i] = AnimationState.DIP_MIX; + timelineDipMix[i] = entry; + continue outer; + } + } + } + timelineData[i] = AnimationState.DIP; + } + } + return lastEntry; + }; + TrackEntry.prototype.hasTimeline = function (id) { + var timelines = this.animation.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + if (timelines[i].getPropertyId() == id) + return true; + return false; + }; TrackEntry.prototype.getAnimationTime = function () { if (this.loop) { var duration = this.animationEnd - this.animationStart; @@ -1557,6 +1826,7 @@ var spine; return EventQueue; }()); spine.EventQueue = EventQueue; + var EventType; (function (EventType) { EventType[EventType["start"] = 0] = "start"; EventType[EventType["interrupt"] = 1] = "interrupt"; @@ -1564,8 +1834,7 @@ var spine; EventType[EventType["dispose"] = 3] = "dispose"; EventType[EventType["complete"] = 4] = "complete"; EventType[EventType["event"] = 5] = "event"; - })(spine.EventType || (spine.EventType = {})); - var EventType = spine.EventType; + })(EventType = spine.EventType || (spine.EventType = {})); var AnimationStateAdapter2 = (function () { function AnimationStateAdapter2() { } @@ -1609,11 +1878,11 @@ var spine; throw new Error("from cannot be null."); if (to == null) throw new Error("to cannot be null."); - var key = from.name + to.name; + var key = from.name + "." + to.name; this.animationToMixTime[key] = duration; }; AnimationStateData.prototype.getMix = function (from, to) { - var key = from.name + to.name; + var key = from.name + "." + to.name; var value = this.animationToMixTime[key]; return value === undefined ? this.defaultMix : value; }; @@ -1633,31 +1902,58 @@ var spine; this.textureLoader = textureLoader; this.pathPrefix = pathPrefix; } + AssetManager.downloadText = function (url, success, error) { + var request = new XMLHttpRequest(); + request.open("GET", url, true); + request.onload = function () { + if (request.status == 200) { + success(request.responseText); + } + else { + error(request.status, request.responseText); + } + }; + request.onerror = function () { + error(request.status, request.responseText); + }; + request.send(); + }; + AssetManager.downloadBinary = function (url, success, error) { + var request = new XMLHttpRequest(); + request.open("GET", url, true); + request.responseType = "arraybuffer"; + request.onload = function () { + if (request.status == 200) { + success(new Uint8Array(request.response)); + } + else { + error(request.status, request.responseText); + } + }; + request.onerror = function () { + error(request.status, request.responseText); + }; + request.send(); + }; AssetManager.prototype.loadText = function (path, success, error) { var _this = this; if (success === void 0) { success = null; } if (error === void 0) { error = null; } path = this.pathPrefix + path; this.toLoad++; - var request = new XMLHttpRequest(); - request.onreadystatechange = function () { - if (request.readyState == XMLHttpRequest.DONE) { - if (request.status >= 200 && request.status < 300) { - _this.assets[path] = request.responseText; - if (success) - success(path, request.responseText); - } - else { - _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText; - if (error) - error(path, "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText); - } - _this.toLoad--; - _this.loaded++; - } - }; - request.open("GET", path, true); - request.send(); + AssetManager.downloadText(path, function (data) { + _this.assets[path] = data; + if (success) + success(path, data); + _this.toLoad--; + _this.loaded++; + }, function (state, responseText) { + _this.errors[path] = "Couldn't load text " + path + ": status " + status + ", " + responseText; + if (error) + error(path, "Couldn't load text " + path + ": status " + status + ", " + responseText); + _this.toLoad--; + _this.loaded++; + }); }; AssetManager.prototype.loadTexture = function (path, success, error) { var _this = this; @@ -1667,7 +1963,30 @@ var spine; this.toLoad++; var img = new Image(); img.crossOrigin = "anonymous"; + img.onload = function (ev) { + var texture = _this.textureLoader(img); + _this.assets[path] = texture; + _this.toLoad--; + _this.loaded++; + if (success) + success(path, img); + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + _this.toLoad--; + _this.loaded++; + if (error) + error(path, "Couldn't load image " + path); + }; img.src = path; + }; + AssetManager.prototype.loadTextureData = function (path, data, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var img = new Image(); img.onload = function (ev) { var texture = _this.textureLoader(img); _this.assets[path] = texture; @@ -1683,6 +2002,92 @@ var spine; if (error) error(path, "Couldn't load image " + path); }; + img.src = data; + }; + AssetManager.prototype.loadTextureAtlas = function (path, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + var parent = path.lastIndexOf("/") >= 0 ? path.substring(0, path.lastIndexOf("/")) : ""; + path = this.pathPrefix + path; + this.toLoad++; + AssetManager.downloadText(path, function (atlasData) { + var pagesLoaded = { count: 0 }; + var atlasPages = new Array(); + try { + var atlas = new spine.TextureAtlas(atlasData, function (path) { + atlasPages.push(parent + "/" + path); + var image = document.createElement("img"); + image.width = 16; + image.height = 16; + return new spine.FakeTexture(image); + }); + } + catch (e) { + var ex = e; + _this.errors[path] = "Couldn't load texture atlas " + path + ": " + ex.message; + if (error) + error(path, "Couldn't load texture atlas " + path + ": " + ex.message); + _this.toLoad--; + _this.loaded++; + return; + } + var _loop_1 = function (atlasPage) { + var pageLoadError = false; + _this.loadTexture(atlasPage, function (imagePath, image) { + pagesLoaded.count++; + if (pagesLoaded.count == atlasPages.length) { + if (!pageLoadError) { + try { + var atlas = new spine.TextureAtlas(atlasData, function (path) { + return _this.get(parent + "/" + path); + }); + _this.assets[path] = atlas; + if (success) + success(path, atlas); + _this.toLoad--; + _this.loaded++; + } + catch (e) { + var ex = e; + _this.errors[path] = "Couldn't load texture atlas " + path + ": " + ex.message; + if (error) + error(path, "Couldn't load texture atlas " + path + ": " + ex.message); + _this.toLoad--; + _this.loaded++; + } + } + else { + _this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path; + if (error) + error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path); + _this.toLoad--; + _this.loaded++; + } + } + }, function (imagePath, errorMessage) { + pageLoadError = true; + pagesLoaded.count++; + if (pagesLoaded.count == atlasPages.length) { + _this.errors[path] = "Couldn't load texture atlas page " + imagePath + "} of atlas " + path; + if (error) + error(path, "Couldn't load texture atlas page " + imagePath + " of atlas " + path); + _this.toLoad--; + _this.loaded++; + } + }); + }; + for (var _i = 0, atlasPages_1 = atlasPages; _i < atlasPages_1.length; _i++) { + var atlasPage = atlasPages_1[_i]; + _loop_1(atlasPage); + } + }, function (state, responseText) { + _this.errors[path] = "Couldn't load texture atlas " + path + ": status " + status + ", " + responseText; + if (error) + error(path, "Couldn't load texture atlas " + path + ": status " + status + ", " + responseText); + _this.toLoad--; + _this.loaded++; + }); }; AssetManager.prototype.get = function (path) { path = this.pathPrefix + path; @@ -1755,831 +2160,416 @@ var spine; AtlasAttachmentLoader.prototype.newPathAttachment = function (skin, name) { return new spine.PathAttachment(name); }; + AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { + return new spine.PointAttachment(name); + }; + AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) { + return new spine.ClippingAttachment(name); + }; return AtlasAttachmentLoader; }()); spine.AtlasAttachmentLoader = AtlasAttachmentLoader; })(spine || (spine = {})); var spine; (function (spine) { - var Attachment = (function () { - function Attachment(name) { - if (name == null) - throw new Error("name cannot be null."); - this.name = name; - } - return Attachment; - }()); - spine.Attachment = Attachment; - var VertexAttachment = (function (_super) { - __extends(VertexAttachment, _super); - function VertexAttachment(name) { - _super.call(this, name); - this.worldVerticesLength = 0; + var BlendMode; + (function (BlendMode) { + BlendMode[BlendMode["Normal"] = 0] = "Normal"; + BlendMode[BlendMode["Additive"] = 1] = "Additive"; + BlendMode[BlendMode["Multiply"] = 2] = "Multiply"; + BlendMode[BlendMode["Screen"] = 3] = "Screen"; + })(BlendMode = spine.BlendMode || (spine.BlendMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Bone = (function () { + function Bone(data, skeleton, parent) { + this.children = new Array(); + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 0; + this.scaleY = 0; + this.shearX = 0; + this.shearY = 0; + this.ax = 0; + this.ay = 0; + this.arotation = 0; + this.ascaleX = 0; + this.ascaleY = 0; + this.ashearX = 0; + this.ashearY = 0; + this.appliedValid = false; + this.a = 0; + this.b = 0; + this.worldX = 0; + this.c = 0; + this.d = 0; + this.worldY = 0; + this.sorted = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); } - VertexAttachment.prototype.computeWorldVertices = function (slot, worldVertices) { - this.computeWorldVerticesWith(slot, 0, this.worldVerticesLength, worldVertices, 0); + Bone.prototype.update = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); }; - VertexAttachment.prototype.computeWorldVerticesWith = function (slot, start, count, worldVertices, offset) { - count += offset; - var skeleton = slot.bone.skeleton; - var deformArray = slot.attachmentVertices; - var vertices = this.vertices; - var bones = this.bones; - if (bones == null) { - if (deformArray.length > 0) - vertices = deformArray; - var bone = slot.bone; - var x = bone.worldX; - var y = bone.worldY; - var a = bone.a, b = bone.b, c = bone.c, d = bone.d; - for (var v_1 = start, w = offset; w < count; v_1 += 2, w += 2) { - var vx = vertices[v_1], vy = vertices[v_1 + 1]; - worldVertices[w] = vx * a + vy * b + x; - worldVertices[w + 1] = vx * c + vy * d + y; - } + Bone.prototype.updateWorldTransform = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + var skeleton = this.skeleton; + if (skeleton.flipX) { + x = -x; + la = -la; + lb = -lb; + } + if (skeleton.flipY) { + y = -y; + lc = -lc; + ld = -ld; + } + this.a = la; + this.b = lb; + this.c = lc; + this.d = ld; + this.worldX = x + skeleton.x; + this.worldY = y + skeleton.y; return; } - var v = 0, skip = 0; - for (var i = 0; i < start; i += 2) { - var n = bones[v]; - v += n + 1; - skip += n; - } - var skeletonBones = skeleton.bones; - if (deformArray.length == 0) { - for (var w = offset, b = skip * 3; w < count; w += 2) { - var wx = 0, wy = 0; - var n = bones[v++]; - n += v; - for (; v < n; v++, b += 3) { - var bone = skeletonBones[bones[v]]; - var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; - wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; - wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.data.transformMode) { + case spine.TransformMode.Normal: { + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case spine.TransformMode.OnlyTranslation: { + var rotationY = rotation + 90 + shearY; + this.a = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + this.b = spine.MathUtils.cosDeg(rotationY) * scaleY; + this.c = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + this.d = spine.MathUtils.sinDeg(rotationY) * scaleY; + break; + } + case spine.TransformMode.NoRotationOrReflection: { + var s = pa * pa + pc * pc; + var prx = 0; + if (s > 0.0001) { + s = Math.abs(pa * pd - pb * pc) / s; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg; } - worldVertices[w] = wx; - worldVertices[w + 1] = wy; + else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * spine.MathUtils.radDeg; + } + var rx = rotation + shearX - prx; + var ry = rotation + shearY - prx + 90; + var la = spine.MathUtils.cosDeg(rx) * scaleX; + var lb = spine.MathUtils.cosDeg(ry) * scaleY; + var lc = spine.MathUtils.sinDeg(rx) * scaleX; + var ld = spine.MathUtils.sinDeg(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; } - } - else { - var deform = deformArray; - for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) { - var wx = 0, wy = 0; - var n = bones[v++]; - n += v; - for (; v < n; v++, b += 3, f += 2) { - var bone = skeletonBones[bones[v]]; - var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; - wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; - wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + case spine.TransformMode.NoScale: + case spine.TransformMode.NoScaleOrReflection: { + var cos = spine.MathUtils.cosDeg(rotation); + var sin = spine.MathUtils.sinDeg(rotation); + var za = pa * cos + pb * sin; + var zc = pc * cos + pd * sin; + var s = Math.sqrt(za * za + zc * zc); + if (s > 0.00001) + s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + var r = Math.PI / 2 + Math.atan2(zc, za); + var zb = Math.cos(r) * s; + var zd = Math.sin(r) * s; + var la = spine.MathUtils.cosDeg(shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(90 + shearY) * scaleY; + var lc = spine.MathUtils.sinDeg(shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(90 + shearY) * scaleY; + if (this.data.transformMode != spine.TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : this.skeleton.flipX != this.skeleton.flipY) { + zb = -zb; + zd = -zd; } - worldVertices[w] = wx; - worldVertices[w + 1] = wy; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + return; } } + if (this.skeleton.flipX) { + this.a = -this.a; + this.b = -this.b; + } + if (this.skeleton.flipY) { + this.c = -this.c; + this.d = -this.d; + } }; - VertexAttachment.prototype.applyDeform = function (sourceAttachment) { - return this == sourceAttachment; + Bone.prototype.setToSetupPose = function () { + var data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; }; - return VertexAttachment; - }(Attachment)); - spine.VertexAttachment = VertexAttachment; -})(spine || (spine = {})); -var spine; -(function (spine) { - (function (AttachmentType) { - AttachmentType[AttachmentType["Region"] = 0] = "Region"; - AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox"; - AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh"; - AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh"; - AttachmentType[AttachmentType["Path"] = 4] = "Path"; - })(spine.AttachmentType || (spine.AttachmentType = {})); - var AttachmentType = spine.AttachmentType; -})(spine || (spine = {})); -var spine; -(function (spine) { - var BoundingBoxAttachment = (function (_super) { - __extends(BoundingBoxAttachment, _super); - function BoundingBoxAttachment(name) { - _super.call(this, name); - this.color = new spine.Color(1, 1, 1, 1); - } - return BoundingBoxAttachment; - }(spine.VertexAttachment)); - spine.BoundingBoxAttachment = BoundingBoxAttachment; -})(spine || (spine = {})); -var spine; -(function (spine) { - var MeshAttachment = (function (_super) { - __extends(MeshAttachment, _super); - function MeshAttachment(name) { - _super.call(this, name); - this.color = new spine.Color(1, 1, 1, 1); - this.inheritDeform = false; - this.tempColor = new spine.Color(0, 0, 0, 0); - } - MeshAttachment.prototype.updateUVs = function () { - var regionUVs = this.regionUVs; - var verticesLength = regionUVs.length; - var worldVerticesLength = (verticesLength >> 1) * 8; - if (this.worldVertices == null || this.worldVertices.length != worldVerticesLength) - this.worldVertices = spine.Utils.newFloatArray(worldVerticesLength); - var u = 0, v = 0, width = 0, height = 0; - if (this.region == null) { - u = v = 0; - width = height = 1; - } - else { - u = this.region.u; - v = this.region.v; - width = this.region.u2 - u; - height = this.region.v2 - v; + Bone.prototype.getWorldRotationX = function () { + return Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldRotationY = function () { + return Math.atan2(this.d, this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.getWorldScaleX = function () { + return Math.sqrt(this.a * this.a + this.c * this.c); + }; + Bone.prototype.getWorldScaleY = function () { + return Math.sqrt(this.b * this.b + this.d * this.d); + }; + Bone.prototype.updateAppliedTransform = function () { + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + this.ax = this.worldX; + this.ay = this.worldY; + this.arotation = Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * spine.MathUtils.radDeg; + return; } - if (this.region.rotate) { - for (var i = 0, w = 6; i < verticesLength; i += 2, w += 8) { - this.worldVertices[w] = u + regionUVs[i + 1] * width; - this.worldVertices[w + 1] = v + height - regionUVs[i] * height; - } + var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + var pid = 1 / (pa * pd - pb * pc); + var dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = (dx * pd * pid - dy * pb * pid); + this.ay = (dy * pa * pid - dx * pc * pid); + var ia = pid * pd; + var id = pid * pa; + var ib = pid * pb; + var ic = pid * pc; + var ra = ia * this.a - ib * this.c; + var rb = ia * this.b - ib * this.d; + var rc = id * this.c - ic * this.a; + var rd = id * this.d - ic * this.b; + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 0.0001) { + var det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = Math.atan2(ra * rb + rc * rd, det) * spine.MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * spine.MathUtils.radDeg; } else { - for (var i = 0, w = 6; i < verticesLength; i += 2, w += 8) { - this.worldVertices[w] = u + regionUVs[i] * width; - this.worldVertices[w + 1] = v + regionUVs[i + 1] * height; - } + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * spine.MathUtils.radDeg; } }; - MeshAttachment.prototype.updateWorldVertices = function (slot, premultipliedAlpha) { - var skeleton = slot.bone.skeleton; - var skeletonColor = skeleton.color, slotColor = slot.color, meshColor = this.color; - var alpha = skeletonColor.a * slotColor.a * meshColor.a; - var multiplier = premultipliedAlpha ? alpha : 1; - var color = this.tempColor; - color.set(skeletonColor.r * slotColor.r * meshColor.r * multiplier, skeletonColor.g * slotColor.g * meshColor.g * multiplier, skeletonColor.b * slotColor.b * meshColor.b * multiplier, alpha); - var deformArray = slot.attachmentVertices; - var vertices = this.vertices, worldVertices = this.worldVertices; - var bones = this.bones; - if (bones == null) { - var verticesLength = vertices.length; - if (deformArray.length > 0) - vertices = deformArray; - var bone = slot.bone; - var x = bone.worldX; - var y = bone.worldY; - var a = bone.a, b = bone.b, c = bone.c, d = bone.d; - for (var v = 0, w = 0; v < verticesLength; v += 2, w += 8) { - var vx = vertices[v], vy = vertices[v + 1]; - worldVertices[w] = vx * a + vy * b + x; - worldVertices[w + 1] = vx * c + vy * d + y; - worldVertices[w + 2] = color.r; - worldVertices[w + 3] = color.g; - worldVertices[w + 4] = color.b; - worldVertices[w + 5] = color.a; - } - return worldVertices; - } - var skeletonBones = skeleton.bones; - if (deformArray.length == 0) { - for (var w = 0, v = 0, b = 0, n = bones.length; v < n; w += 8) { - var wx = 0, wy = 0; - var nn = bones[v++] + v; - for (; v < nn; v++, b += 3) { - var bone = skeletonBones[bones[v]]; - var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; - wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; - wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; - } - worldVertices[w] = wx; - worldVertices[w + 1] = wy; - worldVertices[w + 2] = color.r; - worldVertices[w + 3] = color.g; - worldVertices[w + 4] = color.b; - worldVertices[w + 5] = color.a; - } - } - else { - var deform = deformArray; - for (var w = 0, v = 0, b = 0, f = 0, n = bones.length; v < n; w += 8) { - var wx = 0, wy = 0; - var nn = bones[v++] + v; - for (; v < nn; v++, b += 3, f += 2) { - var bone = skeletonBones[bones[v]]; - var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; - wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; - wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; - } - worldVertices[w] = wx; - worldVertices[w + 1] = wy; - worldVertices[w + 2] = color.r; - worldVertices[w + 3] = color.g; - worldVertices[w + 4] = color.b; - worldVertices[w + 5] = color.a; - } - } - return worldVertices; + Bone.prototype.worldToLocal = function (world) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var invDet = 1 / (a * d - b * c); + var x = world.x - this.worldX, y = world.y - this.worldY; + world.x = (x * d * invDet - y * b * invDet); + world.y = (y * a * invDet - x * c * invDet); + return world; }; - MeshAttachment.prototype.applyDeform = function (sourceAttachment) { - return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment); + Bone.prototype.localToWorld = function (local) { + var x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; }; - MeshAttachment.prototype.getParentMesh = function () { - return this.parentMesh; + Bone.prototype.worldToLocalRotation = function (worldRotation) { + var sin = spine.MathUtils.sinDeg(worldRotation), cos = spine.MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * spine.MathUtils.radDeg; }; - MeshAttachment.prototype.setParentMesh = function (parentMesh) { - this.parentMesh = parentMesh; - if (parentMesh != null) { - this.bones = parentMesh.bones; - this.vertices = parentMesh.vertices; - this.regionUVs = parentMesh.regionUVs; - this.triangles = parentMesh.triangles; - this.hullLength = parentMesh.hullLength; - } + Bone.prototype.localToWorldRotation = function (localRotation) { + var sin = spine.MathUtils.sinDeg(localRotation), cos = spine.MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * spine.MathUtils.radDeg; }; - return MeshAttachment; - }(spine.VertexAttachment)); - spine.MeshAttachment = MeshAttachment; -})(spine || (spine = {})); -var spine; -(function (spine) { - var PathAttachment = (function (_super) { - __extends(PathAttachment, _super); - function PathAttachment(name) { - _super.call(this, name); - this.closed = false; - this.constantSpeed = false; - this.color = new spine.Color(1, 1, 1, 1); - } - return PathAttachment; - }(spine.VertexAttachment)); - spine.PathAttachment = PathAttachment; + Bone.prototype.rotateWorld = function (degrees) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + this.appliedValid = false; + }; + return Bone; + }()); + spine.Bone = Bone; })(spine || (spine = {})); var spine; (function (spine) { - var RegionAttachment = (function (_super) { - __extends(RegionAttachment, _super); - function RegionAttachment(name) { - _super.call(this, name); + var BoneData = (function () { + function BoneData(index, name, parent) { this.x = 0; this.y = 0; + this.rotation = 0; this.scaleX = 1; this.scaleY = 1; - this.rotation = 0; - this.width = 0; - this.height = 0; - this.color = new spine.Color(1, 1, 1, 1); - this.offset = spine.Utils.newFloatArray(8); - this.vertices = spine.Utils.newFloatArray(8 * 4); - this.tempColor = new spine.Color(1, 1, 1, 1); + this.shearX = 0; + this.shearY = 0; + this.transformMode = TransformMode.Normal; + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; } - RegionAttachment.prototype.setRegion = function (region) { - var vertices = this.vertices; - if (region.rotate) { - vertices[RegionAttachment.U2] = region.u; - vertices[RegionAttachment.V2] = region.v2; - vertices[RegionAttachment.U3] = region.u; - vertices[RegionAttachment.V3] = region.v; - vertices[RegionAttachment.U4] = region.u2; - vertices[RegionAttachment.V4] = region.v; - vertices[RegionAttachment.U1] = region.u2; - vertices[RegionAttachment.V1] = region.v2; - } - else { - vertices[RegionAttachment.U1] = region.u; - vertices[RegionAttachment.V1] = region.v2; - vertices[RegionAttachment.U2] = region.u; - vertices[RegionAttachment.V2] = region.v; - vertices[RegionAttachment.U3] = region.u2; - vertices[RegionAttachment.V3] = region.v; - vertices[RegionAttachment.U4] = region.u2; - vertices[RegionAttachment.V4] = region.v2; - } - this.region = region; - }; - RegionAttachment.prototype.updateOffset = function () { - var regionScaleX = this.width / this.region.originalWidth * this.scaleX; - var regionScaleY = this.height / this.region.originalHeight * this.scaleY; - var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; - var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; - var localX2 = localX + this.region.width * regionScaleX; - var localY2 = localY + this.region.height * regionScaleY; - var radians = this.rotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - var localXCos = localX * cos + this.x; - var localXSin = localX * sin; - var localYCos = localY * cos + this.y; - var localYSin = localY * sin; - var localX2Cos = localX2 * cos + this.x; - var localX2Sin = localX2 * sin; - var localY2Cos = localY2 * cos + this.y; - var localY2Sin = localY2 * sin; - var offset = this.offset; - offset[RegionAttachment.OX1] = localXCos - localYSin; - offset[RegionAttachment.OY1] = localYCos + localXSin; - offset[RegionAttachment.OX2] = localXCos - localY2Sin; - offset[RegionAttachment.OY2] = localY2Cos + localXSin; - offset[RegionAttachment.OX3] = localX2Cos - localY2Sin; - offset[RegionAttachment.OY3] = localY2Cos + localX2Sin; - offset[RegionAttachment.OX4] = localX2Cos - localYSin; - offset[RegionAttachment.OY4] = localYCos + localX2Sin; - }; - RegionAttachment.prototype.updateWorldVertices = function (slot, premultipliedAlpha) { - var skeleton = slot.bone.skeleton; - var skeletonColor = skeleton.color; - var slotColor = slot.color; - var regionColor = this.color; - var alpha = skeletonColor.a * slotColor.a * regionColor.a; - var multiplier = premultipliedAlpha ? alpha : 1; - var color = this.tempColor; - color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha); - var vertices = this.vertices; - var offset = this.offset; - var bone = slot.bone; - var x = bone.worldX, y = bone.worldY; - var a = bone.a, b = bone.b, c = bone.c, d = bone.d; - var offsetX = 0, offsetY = 0; - offsetX = offset[RegionAttachment.OX1]; - offsetY = offset[RegionAttachment.OY1]; - vertices[RegionAttachment.X1] = offsetX * a + offsetY * b + x; - vertices[RegionAttachment.Y1] = offsetX * c + offsetY * d + y; - vertices[RegionAttachment.C1R] = color.r; - vertices[RegionAttachment.C1G] = color.g; - vertices[RegionAttachment.C1B] = color.b; - vertices[RegionAttachment.C1A] = color.a; - offsetX = offset[RegionAttachment.OX2]; - offsetY = offset[RegionAttachment.OY2]; - vertices[RegionAttachment.X2] = offsetX * a + offsetY * b + x; - vertices[RegionAttachment.Y2] = offsetX * c + offsetY * d + y; - vertices[RegionAttachment.C2R] = color.r; - vertices[RegionAttachment.C2G] = color.g; - vertices[RegionAttachment.C2B] = color.b; - vertices[RegionAttachment.C2A] = color.a; - offsetX = offset[RegionAttachment.OX3]; - offsetY = offset[RegionAttachment.OY3]; - vertices[RegionAttachment.X3] = offsetX * a + offsetY * b + x; - vertices[RegionAttachment.Y3] = offsetX * c + offsetY * d + y; - vertices[RegionAttachment.C3R] = color.r; - vertices[RegionAttachment.C3G] = color.g; - vertices[RegionAttachment.C3B] = color.b; - vertices[RegionAttachment.C3A] = color.a; - offsetX = offset[RegionAttachment.OX4]; - offsetY = offset[RegionAttachment.OY4]; - vertices[RegionAttachment.X4] = offsetX * a + offsetY * b + x; - vertices[RegionAttachment.Y4] = offsetX * c + offsetY * d + y; - vertices[RegionAttachment.C4R] = color.r; - vertices[RegionAttachment.C4G] = color.g; - vertices[RegionAttachment.C4B] = color.b; - vertices[RegionAttachment.C4A] = color.a; - return vertices; - }; - RegionAttachment.OX1 = 0; - RegionAttachment.OY1 = 1; - RegionAttachment.OX2 = 2; - RegionAttachment.OY2 = 3; - RegionAttachment.OX3 = 4; - RegionAttachment.OY3 = 5; - RegionAttachment.OX4 = 6; - RegionAttachment.OY4 = 7; - RegionAttachment.X1 = 0; - RegionAttachment.Y1 = 1; - RegionAttachment.C1R = 2; - RegionAttachment.C1G = 3; - RegionAttachment.C1B = 4; - RegionAttachment.C1A = 5; - RegionAttachment.U1 = 6; - RegionAttachment.V1 = 7; - RegionAttachment.X2 = 8; - RegionAttachment.Y2 = 9; - RegionAttachment.C2R = 10; - RegionAttachment.C2G = 11; - RegionAttachment.C2B = 12; - RegionAttachment.C2A = 13; - RegionAttachment.U2 = 14; - RegionAttachment.V2 = 15; - RegionAttachment.X3 = 16; - RegionAttachment.Y3 = 17; - RegionAttachment.C3R = 18; - RegionAttachment.C3G = 19; - RegionAttachment.C3B = 20; - RegionAttachment.C3A = 21; - RegionAttachment.U3 = 22; - RegionAttachment.V3 = 23; - RegionAttachment.X4 = 24; - RegionAttachment.Y4 = 25; - RegionAttachment.C4R = 26; - RegionAttachment.C4G = 27; - RegionAttachment.C4B = 28; - RegionAttachment.C4A = 29; - RegionAttachment.U4 = 30; - RegionAttachment.V4 = 31; - return RegionAttachment; - }(spine.Attachment)); - spine.RegionAttachment = RegionAttachment; + return BoneData; + }()); + spine.BoneData = BoneData; + var TransformMode; + (function (TransformMode) { + TransformMode[TransformMode["Normal"] = 0] = "Normal"; + TransformMode[TransformMode["OnlyTranslation"] = 1] = "OnlyTranslation"; + TransformMode[TransformMode["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + TransformMode[TransformMode["NoScale"] = 3] = "NoScale"; + TransformMode[TransformMode["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + })(TransformMode = spine.TransformMode || (spine.TransformMode = {})); })(spine || (spine = {})); var spine; (function (spine) { - (function (BlendMode) { - BlendMode[BlendMode["Normal"] = 0] = "Normal"; - BlendMode[BlendMode["Additive"] = 1] = "Additive"; - BlendMode[BlendMode["Multiply"] = 2] = "Multiply"; - BlendMode[BlendMode["Screen"] = 3] = "Screen"; - })(spine.BlendMode || (spine.BlendMode = {})); - var BlendMode = spine.BlendMode; + var Event = (function () { + function Event(time, data) { + if (data == null) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + return Event; + }()); + spine.Event = Event; })(spine || (spine = {})); var spine; (function (spine) { - var Bone = (function () { - function Bone(data, skeleton, parent) { - this.children = new Array(); - this.x = 0; - this.y = 0; - this.rotation = 0; - this.scaleX = 0; - this.scaleY = 0; - this.shearX = 0; - this.shearY = 0; - this.ax = 0; - this.ay = 0; - this.arotation = 0; - this.ascaleX = 0; - this.ascaleY = 0; - this.ashearX = 0; - this.ashearY = 0; - this.appliedValid = false; - this.a = 0; - this.b = 0; - this.worldX = 0; - this.c = 0; - this.d = 0; - this.worldY = 0; - this.sorted = false; + var EventData = (function () { + function EventData(name) { + this.name = name; + } + return EventData; + }()); + spine.EventData = EventData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IkConstraint = (function () { + function IkConstraint(data, skeleton) { + this.mix = 1; + this.bendDirection = 0; if (data == null) throw new Error("data cannot be null."); if (skeleton == null) throw new Error("skeleton cannot be null."); this.data = data; - this.skeleton = skeleton; - this.parent = parent; - this.setToSetupPose(); + this.mix = data.mix; + this.bendDirection = data.bendDirection; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); } - Bone.prototype.update = function () { - this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + IkConstraint.prototype.getOrder = function () { + return this.data.order; }; - Bone.prototype.updateWorldTransform = function () { - this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + IkConstraint.prototype.apply = function () { + this.update(); }; - Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) { - this.ax = x; - this.ay = y; - this.arotation = rotation; - this.ascaleX = scaleX; - this.ascaleY = scaleY; - this.ashearX = shearX; - this.ashearY = shearY; - this.appliedValid = true; - var parent = this.parent; - if (parent == null) { - var rotationY = rotation + 90 + shearY; - var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; - var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; - var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; - var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; - var skeleton = this.skeleton; - if (skeleton.flipX) { - x = -x; - la = -la; - lb = -lb; - } - if (skeleton.flipY) { - y = -y; - lc = -lc; - ld = -ld; - } - this.a = la; - this.b = lb; - this.c = lc; - this.d = ld; - this.worldX = x + skeleton.x; - this.worldY = y + skeleton.y; - return; - } - var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; - this.worldX = pa * x + pb * y + parent.worldX; - this.worldY = pc * x + pd * y + parent.worldY; - switch (this.data.transformMode) { - case spine.TransformMode.Normal: { - var rotationY = rotation + 90 + shearY; - var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; - var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; - var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; - var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; - this.a = pa * la + pb * lc; - this.b = pa * lb + pb * ld; - this.c = pc * la + pd * lc; - this.d = pc * lb + pd * ld; - return; - } - case spine.TransformMode.OnlyTranslation: { - var rotationY = rotation + 90 + shearY; - this.a = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; - this.b = spine.MathUtils.cosDeg(rotationY) * scaleY; - this.c = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; - this.d = spine.MathUtils.sinDeg(rotationY) * scaleY; + IkConstraint.prototype.update = function () { + var target = this.target; + var bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.mix); break; - } - case spine.TransformMode.NoRotationOrReflection: { - var s = pa * pa + pc * pc; - var prx = 0; - if (s > 0.0001) { - s = Math.abs(pa * pd - pb * pc) / s; - pb = pc * s; - pd = pa * s; - prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg; - } - else { - pa = 0; - pc = 0; - prx = 90 - Math.atan2(pd, pb) * spine.MathUtils.radDeg; - } - var rx = rotation + shearX - prx; - var ry = rotation + shearY - prx + 90; - var la = spine.MathUtils.cosDeg(rx) * scaleX; - var lb = spine.MathUtils.cosDeg(ry) * scaleY; - var lc = spine.MathUtils.sinDeg(rx) * scaleX; - var ld = spine.MathUtils.sinDeg(ry) * scaleY; - this.a = pa * la - pb * lc; - this.b = pa * lb - pb * ld; - this.c = pc * la + pd * lc; - this.d = pc * lb + pd * ld; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.mix); break; - } - case spine.TransformMode.NoScale: - case spine.TransformMode.NoScaleOrReflection: { - var cos = spine.MathUtils.cosDeg(rotation); - var sin = spine.MathUtils.sinDeg(rotation); - var za = pa * cos + pb * sin; - var zc = pc * cos + pd * sin; - var s = Math.sqrt(za * za + zc * zc); - if (s > 0.00001) - s = 1 / s; - za *= s; - zc *= s; - s = Math.sqrt(za * za + zc * zc); - var r = Math.PI / 2 + Math.atan2(zc, za); - var zb = Math.cos(r) * s; - var zd = Math.sin(r) * s; - var la = spine.MathUtils.cosDeg(shearX) * scaleX; - var lb = spine.MathUtils.cosDeg(90 + shearY) * scaleY; - var lc = spine.MathUtils.sinDeg(shearX) * scaleX; - var ld = spine.MathUtils.sinDeg(90 + shearY) * scaleY; - this.a = za * la + zb * lc; - this.b = za * lb + zb * ld; - this.c = zc * la + zd * lc; - this.d = zc * lb + zd * ld; - if (this.data.transformMode != spine.TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : this.skeleton.flipX != this.skeleton.flipY) { - this.b = -this.b; - this.d = -this.d; - } - return; - } - } - if (this.skeleton.flipX) { - this.a = -this.a; - this.b = -this.b; - } - if (this.skeleton.flipY) { - this.c = -this.c; - this.d = -this.d; } }; - Bone.prototype.setToSetupPose = function () { - var data = this.data; - this.x = data.x; - this.y = data.y; - this.rotation = data.rotation; - this.scaleX = data.scaleX; - this.scaleY = data.scaleY; - this.shearX = data.shearX; - this.shearY = data.shearY; - }; - Bone.prototype.getWorldRotationX = function () { - return Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; - }; - Bone.prototype.getWorldRotationY = function () { - return Math.atan2(this.d, this.b) * spine.MathUtils.radDeg; - }; - Bone.prototype.getWorldScaleX = function () { - return Math.sqrt(this.a * this.a + this.c * this.c); - }; - Bone.prototype.getWorldScaleY = function () { - return Math.sqrt(this.b * this.b + this.d * this.d); - }; - Bone.prototype.worldToLocalRotationX = function () { - var parent = this.parent; - if (parent == null) - return this.arotation; - var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c; - return Math.atan2(pa * c - pc * a, pd * a - pb * c) * spine.MathUtils.radDeg; - }; - Bone.prototype.worldToLocalRotationY = function () { - var parent = this.parent; - if (parent == null) - return this.arotation; - var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d; - return Math.atan2(pa * d - pc * b, pd * b - pb * d) * spine.MathUtils.radDeg; - }; - Bone.prototype.rotateWorld = function (degrees) { - var a = this.a, b = this.b, c = this.c, d = this.d; - var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees); - this.a = cos * a - sin * c; - this.b = cos * b - sin * d; - this.c = sin * a + cos * c; - this.d = sin * b + cos * d; - this.appliedValid = false; + IkConstraint.prototype.apply1 = function (bone, targetX, targetY, alpha) { + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var p = bone.parent; + var id = 1 / (p.a * p.d - p.b * p.c); + var x = targetX - p.worldX, y = targetY - p.worldY; + var tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay; + var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.ashearX - bone.arotation; + if (bone.ascaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY); }; - Bone.prototype.updateAppliedTransform = function () { - this.appliedValid = true; - var parent = this.parent; - if (parent == null) { - this.ax = this.worldX; - this.ay = this.worldY; - this.arotation = Math.atan2(this.c, this.a) * spine.MathUtils.radDeg; - this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); - this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); - this.ashearX = 0; - this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * spine.MathUtils.radDeg; + IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, alpha) { + if (alpha == 0) { + child.updateWorldTransform(); return; } - var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; - var pid = 1 / (pa * pd - pb * pc); - var dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; - this.ax = (dx * pd * pid - dy * pb * pid); - this.ay = (dy * pa * pid - dx * pc * pid); - var ia = pid * pd; - var id = pid * pa; - var ib = pid * pb; - var ic = pid * pc; - var ra = ia * this.a - ib * this.c; - var rb = ia * this.b - ib * this.d; - var rc = id * this.c - ic * this.a; - var rd = id * this.d - ic * this.b; - this.ashearX = 0; - this.ascaleX = Math.sqrt(ra * ra + rc * rc); - if (this.ascaleX > 0.0001) { - var det = ra * rd - rb * rc; - this.ascaleY = det / this.ascaleX; - this.ashearY = Math.atan2(ra * rb + rc * rd, det) * spine.MathUtils.radDeg; - this.arotation = Math.atan2(rc, ra) * spine.MathUtils.radDeg; + if (!parent.appliedValid) + parent.updateAppliedTransform(); + if (!child.appliedValid) + child.updateAppliedTransform(); + var px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX; + var os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; } else { - this.ascaleX = 0; - this.ascaleY = Math.sqrt(rb * rb + rd * rd); - this.ashearY = 0; - this.arotation = 90 - Math.atan2(rd, rb) * spine.MathUtils.radDeg; - } - }; - Bone.prototype.worldToLocal = function (world) { - var a = this.a, b = this.b, c = this.c, d = this.d; - var invDet = 1 / (a * d - b * c); - var x = world.x - this.worldX, y = world.y - this.worldY; - world.x = (x * d * invDet - y * b * invDet); - world.y = (y * a * invDet - x * c * invDet); - return world; - }; - Bone.prototype.localToWorld = function (local) { - var x = local.x, y = local.y; - local.x = x * this.a + y * this.b + this.worldX; - local.y = x * this.c + y * this.d + this.worldY; - return local; - }; - return Bone; - }()); - spine.Bone = Bone; -})(spine || (spine = {})); -var spine; -(function (spine) { - var BoneData = (function () { - function BoneData(index, name, parent) { - this.x = 0; - this.y = 0; - this.rotation = 0; - this.scaleX = 1; - this.scaleY = 1; - this.shearX = 0; - this.shearY = 0; - this.transformMode = TransformMode.Normal; - if (index < 0) - throw new Error("index must be >= 0."); - if (name == null) - throw new Error("name cannot be null."); - this.index = index; - this.name = name; - this.parent = parent; - } - return BoneData; - }()); - spine.BoneData = BoneData; - (function (TransformMode) { - TransformMode[TransformMode["Normal"] = 0] = "Normal"; - TransformMode[TransformMode["OnlyTranslation"] = 1] = "OnlyTranslation"; - TransformMode[TransformMode["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; - TransformMode[TransformMode["NoScale"] = 3] = "NoScale"; - TransformMode[TransformMode["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; - })(spine.TransformMode || (spine.TransformMode = {})); - var TransformMode = spine.TransformMode; -})(spine || (spine = {})); -var spine; -(function (spine) { - var Event = (function () { - function Event(time, data) { - if (data == null) - throw new Error("data cannot be null."); - this.time = time; - this.data = data; - } - return Event; - }()); - spine.Event = Event; -})(spine || (spine = {})); -var spine; -(function (spine) { - var EventData = (function () { - function EventData(name) { - this.name = name; - } - return EventData; - }()); - spine.EventData = EventData; -})(spine || (spine = {})); -var spine; -(function (spine) { - var IkConstraint = (function () { - function IkConstraint(data, skeleton) { - this.mix = 1; - this.bendDirection = 0; - if (data == null) - throw new Error("data cannot be null."); - if (skeleton == null) - throw new Error("skeleton cannot be null."); - this.data = data; - this.mix = data.mix; - this.bendDirection = data.bendDirection; - this.bones = new Array(); - for (var i = 0; i < data.bones.length; i++) - this.bones.push(skeleton.findBone(data.bones[i].name)); - this.target = skeleton.findBone(data.target.name); - } - IkConstraint.prototype.getOrder = function () { - return this.data.order; - }; - IkConstraint.prototype.apply = function () { - this.update(); - }; - IkConstraint.prototype.update = function () { - var target = this.target; - var bones = this.bones; - switch (bones.length) { - case 1: - this.apply1(bones[0], target.worldX, target.worldY, this.mix); - break; - case 2: - this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.mix); - break; - } - }; - IkConstraint.prototype.apply1 = function (bone, targetX, targetY, alpha) { - if (!bone.appliedValid) - bone.updateAppliedTransform(); - var p = bone.parent; - var id = 1 / (p.a * p.d - p.b * p.c); - var x = targetX - p.worldX, y = targetY - p.worldY; - var tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay; - var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.ashearX - bone.arotation; - if (bone.ascaleX < 0) - rotationIK += 180; - if (rotationIK > 180) - rotationIK -= 360; - else if (rotationIK < -180) - rotationIK += 360; - bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY); - }; - IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, alpha) { - if (alpha == 0) { - child.updateWorldTransform(); - return; - } - if (!parent.appliedValid) - parent.updateAppliedTransform(); - if (!child.appliedValid) - child.updateAppliedTransform(); - var px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX; - var os1 = 0, os2 = 0, s2 = 0; - if (psx < 0) { - psx = -psx; - os1 = 180; - s2 = -1; - } - else { - os1 = 0; - s2 = 1; + os1 = 0; + s2 = 1; } if (psy < 0) { psy = -psy; @@ -2647,37 +2637,26 @@ var spine; break outer; } } - var minAngle = 0, minDist = Number.MAX_VALUE, minX = 0, minY = 0; - var maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0; - x = l1 + a; - d = x * x; - if (d > maxDist) { - maxAngle = 0; - maxDist = d; - maxX = x; - } - x = l1 - a; - d = x * x; - if (d < minDist) { - minAngle = spine.MathUtils.PI; - minDist = d; - minX = x; - } - var angle = Math.acos(-a * l1 / (aa - bb)); - x = a * Math.cos(angle) + l1; - y = b * Math.sin(angle); - d = x * x + y * y; - if (d < minDist) { - minAngle = angle; - minDist = d; - minX = x; - minY = y; - } - if (d > maxDist) { - maxAngle = angle; - maxDist = d; - maxX = x; - maxY = y; + var minAngle = spine.MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + var maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } } if (dd <= (minDist + maxDist) / 2) { a1 = ta - Math.atan2(minY * bendDir, minX); @@ -2775,11 +2754,19 @@ var spine; lengths = spine.Utils.setArraySize(this.lengths, boneCount); for (var i = 0, n = spacesCount - 1; i < n;) { var bone = bones[i]; - var length_1 = bone.data.length, x = length_1 * bone.a, y = length_1 * bone.c; - length_1 = Math.sqrt(x * x + y * y); - if (scale) - lengths[i] = length_1; - spaces[++i] = lengthSpacing ? Math.max(0, length_1 + spacing) : spacing; + var setupLength = bone.data.length; + if (setupLength < PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = 0; + } + else { + var x = setupLength * bone.a, y = setupLength * bone.c; + var length_1 = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length_1; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length_1 / setupLength; + } } } else { @@ -2875,7 +2862,7 @@ var spine; else if (p < 0) { if (prevCurve != PathConstraint.BEFORE) { prevCurve = PathConstraint.BEFORE; - path.computeWorldVerticesWith(target, 2, 4, world, 0); + path.computeWorldVertices(target, 2, 4, world, 0, 2); } this.addBeforePosition(p, world, 0, out, o); continue; @@ -2883,7 +2870,7 @@ var spine; else if (p > pathLength_1) { if (prevCurve != PathConstraint.AFTER) { prevCurve = PathConstraint.AFTER; - path.computeWorldVerticesWith(target, verticesLength - 6, 4, world, 0); + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); } this.addAfterPosition(p - pathLength_1, world, 0, out, o); continue; @@ -2903,11 +2890,11 @@ var spine; if (curve != prevCurve) { prevCurve = curve; if (closed && curve == curveCount) { - path.computeWorldVerticesWith(target, verticesLength - 4, 4, world, 0); - path.computeWorldVerticesWith(target, 0, 4, world, 4); + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); } else - path.computeWorldVerticesWith(target, curve * 6 + 2, 8, world, 0); + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); } this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0)); } @@ -2916,8 +2903,8 @@ var spine; if (closed) { verticesLength += 2; world = spine.Utils.setArraySize(this.world, verticesLength); - path.computeWorldVerticesWith(target, 2, verticesLength - 4, world, 0); - path.computeWorldVerticesWith(target, 0, 2, world, verticesLength - 4); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); world[verticesLength - 2] = world[0]; world[verticesLength - 1] = world[1]; } @@ -2925,7 +2912,7 @@ var spine; curveCount--; verticesLength -= 4; world = spine.Utils.setArraySize(this.world, verticesLength); - path.computeWorldVerticesWith(target, 2, verticesLength, world, 0); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); } var curves = spine.Utils.setArraySize(this.curves, curveCount); var pathLength = 0; @@ -3085,6 +3072,7 @@ var spine; PathConstraint.NONE = -1; PathConstraint.BEFORE = -2; PathConstraint.AFTER = -3; + PathConstraint.epsilon = 0.00001; return PathConstraint; }()); spine.PathConstraint = PathConstraint; @@ -3100,23 +3088,23 @@ var spine; return PathConstraintData; }()); spine.PathConstraintData = PathConstraintData; + var PositionMode; (function (PositionMode) { PositionMode[PositionMode["Fixed"] = 0] = "Fixed"; PositionMode[PositionMode["Percent"] = 1] = "Percent"; - })(spine.PositionMode || (spine.PositionMode = {})); - var PositionMode = spine.PositionMode; + })(PositionMode = spine.PositionMode || (spine.PositionMode = {})); + var SpacingMode; (function (SpacingMode) { SpacingMode[SpacingMode["Length"] = 0] = "Length"; SpacingMode[SpacingMode["Fixed"] = 1] = "Fixed"; SpacingMode[SpacingMode["Percent"] = 2] = "Percent"; - })(spine.SpacingMode || (spine.SpacingMode = {})); - var SpacingMode = spine.SpacingMode; + })(SpacingMode = spine.SpacingMode || (spine.SpacingMode = {})); + var RotateMode; (function (RotateMode) { RotateMode[RotateMode["Tangent"] = 0] = "Tangent"; RotateMode[RotateMode["Chain"] = 1] = "Chain"; RotateMode[RotateMode["ChainScale"] = 2] = "ChainScale"; - })(spine.RotateMode || (spine.RotateMode = {})); - var RotateMode = spine.RotateMode; + })(RotateMode = spine.RotateMode || (spine.RotateMode = {})); })(spine || (spine = {})); var spine; (function (spine) { @@ -3313,6 +3301,7 @@ var spine; Skeleton.prototype.updateCache = function () { var updateCache = this._updateCache; updateCache.length = 0; + this.updateCacheReset.length = 0; var bones = this.bones; for (var i = 0, n = bones.length; i < n; i++) bones[i].sorted = false; @@ -3370,27 +3359,38 @@ var spine; this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin) this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); - for (var ii = 0, nn = this.data.skins.length; ii < nn; ii++) - this.sortPathConstraintAttachment(this.data.skins[ii], slotIndex, slotBone); + for (var i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); var attachment = slot.getAttachment(); if (attachment instanceof spine.PathAttachment) this.sortPathConstraintAttachmentWith(attachment, slotBone); var constrained = constraint.bones; var boneCount = constrained.length; - for (var ii = 0; ii < boneCount; ii++) - this.sortBone(constrained[ii]); + for (var i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); this._updateCache.push(constraint); - for (var ii = 0; ii < boneCount; ii++) - this.sortReset(constrained[ii].children); - for (var ii = 0; ii < boneCount; ii++) - constrained[ii].sorted = true; + for (var i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (var i = 0; i < boneCount; i++) + constrained[i].sorted = true; }; Skeleton.prototype.sortTransformConstraint = function (constraint) { this.sortBone(constraint.target); var constrained = constraint.bones; var boneCount = constrained.length; - for (var ii = 0; ii < boneCount; ii++) - this.sortBone(constrained[ii]); + if (constraint.data.local) { + for (var i = 0; i < boneCount; i++) { + var child = constrained[i]; + this.sortBone(child.parent); + if (!(this._updateCache.indexOf(child) > -1)) + this.updateCacheReset.push(child); + } + } + else { + for (var i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } this._updateCache.push(constraint); for (var ii = 0; ii < boneCount; ii++) this.sortReset(constrained[ii].children); @@ -3633,7 +3633,7 @@ var spine; } return null; }; - Skeleton.prototype.getBounds = function (offset, size) { + Skeleton.prototype.getBounds = function (offset, size, temp) { if (offset == null) throw new Error("offset cannot be null."); if (size == null) @@ -3642,14 +3642,22 @@ var spine; var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; for (var i = 0, n = drawOrder.length; i < n; i++) { var slot = drawOrder[i]; + var verticesLength = 0; var vertices = null; var attachment = slot.getAttachment(); - if (attachment instanceof spine.RegionAttachment) - vertices = attachment.updateWorldVertices(slot, false); - else if (attachment instanceof spine.MeshAttachment) - vertices = attachment.updateWorldVertices(slot, true); + if (attachment instanceof spine.RegionAttachment) { + verticesLength = 8; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot.bone, vertices, 0, 2); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + } if (vertices != null) { - for (var ii = 0, nn = vertices.length; ii < nn; ii += 8) { + for (var ii = 0, nn = vertices.length; ii < nn; ii += 2) { var x = vertices[ii], y = vertices[ii + 1]; minX = Math.min(minX, x); minY = Math.min(minY, y); @@ -3704,7 +3712,7 @@ var spine; polygon = spine.Utils.newFloatArray(boundingBox.worldVerticesLength); } polygons.push(polygon); - boundingBox.computeWorldVertices(slot, polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); } } if (updateAabb) { @@ -3835,6 +3843,286 @@ var spine; spine.SkeletonBounds = SkeletonBounds; })(spine || (spine = {})); var spine; +(function (spine) { + var SkeletonClipping = (function () { + function SkeletonClipping() { + this.triangulator = new spine.Triangulator(); + this.clippingPolygon = new Array(); + this.clipOutput = new Array(); + this.clippedVertices = new Array(); + this.clippedTriangles = new Array(); + this.scratch = new Array(); + } + SkeletonClipping.prototype.clipStart = function (slot, clip) { + if (this.clipAttachment != null) + return 0; + this.clipAttachment = clip; + var n = clip.worldVerticesLength; + var vertices = spine.Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + var clippingPolygon = this.clippingPolygon; + SkeletonClipping.makeClockwise(clippingPolygon); + var clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) { + var polygon = clippingPolygons[i]; + SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + }; + SkeletonClipping.prototype.clipEndWithSlot = function (slot) { + if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data) + this.clipEnd(); + }; + SkeletonClipping.prototype.clipEnd = function () { + if (this.clipAttachment == null) + return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + }; + SkeletonClipping.prototype.isClipping = function () { + return this.clipAttachment != null; + }; + SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor, stride) { + var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + var clippedTriangles = this.clippedTriangles; + var polygons = this.clippingPolygons; + var polygonsCount = this.clippingPolygons.length; + var vertexSize = twoColor ? 12 : 8; + var index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + outer: for (var i = 0; i < trianglesLength; i += 3) { + var vertexOffset = triangles[i] * stride; + var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] * stride; + var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] * stride; + var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (var p = 0; p < polygonsCount; p++) { + var s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + var clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + var d = 1 / (d0 * d2 + d1 * (y1 - y3)); + var clipOutputCount = clipOutputLength >> 1; + var clipOutputItems = this.clipOutput; + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (var ii = 0; ii < clipOutputLength; ii += 2) { + var x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + var c0 = x - x3, c1 = y - y3; + var a = (d0 * c0 + d1 * c1) * d; + var b = (d4 * c0 + d2 * c1) * d; + var c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + s += vertexSize; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (var ii = 1; ii < clipOutputCount; ii++) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + ii); + clippedTrianglesItems[s + 2] = (index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } + else { + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } + else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + 1); + clippedTrianglesItems[s + 2] = (index + 2); + index += 3; + continue outer; + } + } + } + }; + SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) { + var originalOutput = output; + var clipped = false; + var input = null; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } + else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + var clippingVertices = clippingArea; + var clippingVerticesLast = clippingArea.length - 4; + for (var i = 0;; i += 2) { + var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + var inputVertices = input; + var inputVerticesLength = input.length - 2, outputStart = output.length; + for (var ii = 0; ii < inputVerticesLength; ii += 2) { + var inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } + else if (side2) { + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + output.push(inputX2); + output.push(inputY2); + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) + break; + var temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (var i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } + else + originalOutput.length = originalOutput.length - 2; + return clipped; + }; + SkeletonClipping.makeClockwise = function (polygon) { + var vertices = polygon; + var verticeslength = polygon.length; + var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (var i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) + return; + for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + var x = vertices[i], y = vertices[i + 1]; + var other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + }; + return SkeletonClipping; + }()); + spine.SkeletonClipping = SkeletonClipping; +})(spine || (spine = {})); +var spine; (function (spine) { var SkeletonData = (function () { function SkeletonData() { @@ -4023,6 +4311,11 @@ var spine; var color = this.getValue(slotMap, "color", null); if (color != null) data.color.setFromString(color); + var dark = this.getValue(slotMap, "dark", null); + if (dark != null) { + data.darkColor = new spine.Color(1, 1, 1, 1); + data.darkColor.setFromString(dark); + } data.attachmentName = this.getValue(slotMap, "attachment", null); data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal")); skeletonData.slots.push(data); @@ -4065,6 +4358,8 @@ var spine; data.target = skeletonData.findBone(targetName); if (data.target == null) throw new Error("Transform constraint target bone not found: " + targetName); + data.local = this.getValue(constraintMap, "local", false); + data.relative = this.getValue(constraintMap, "relative", false); data.offsetRotation = this.getValue(constraintMap, "rotation", 0); data.offsetX = this.getValue(constraintMap, "x", 0) * scale; data.offsetY = this.getValue(constraintMap, "y", 0) * scale; @@ -4119,7 +4414,7 @@ var spine; throw new Error("Slot not found: " + slotName); var slotMap = skinMap[slotName]; for (var entryName in slotMap) { - var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName); + var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData); if (attachment != null) skin.addAttachment(slotIndex, entryName, attachment); } @@ -4159,7 +4454,7 @@ var spine; } return skeletonData; }; - SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name) { + SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) { var scale = this.scale; name = this.getValue(map, "name", name); var type = this.getValue(map, "type", "region"); @@ -4227,13 +4522,43 @@ var spine; this.readVertices(map, path, vertexCount << 1); var lengths = spine.Utils.newArray(vertexCount / 3, 0); for (var i = 0; i < map.lengths.length; i++) - lengths[i++] = map.lengths[i] * scale; + lengths[i] = map.lengths[i] * scale; path.lengths = lengths; var color = this.getValue(map, "color", null); if (color != null) path.color.setFromString(color); return path; } + case "point": { + var point = this.attachmentLoader.newPointAttachment(skin, name); + if (point == null) + return null; + point.x = this.getValue(map, "x", 0) * scale; + point.y = this.getValue(map, "y", 0) * scale; + point.rotation = this.getValue(map, "rotation", 0); + var color = this.getValue(map, "color", null); + if (color != null) + point.color.setFromString(color); + return point; + } + case "clipping": { + var clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (clip == null) + return null; + var end = this.getValue(map, "end", null); + if (end != null) { + var slot = skeletonData.findSlot(end); + if (slot == null) + throw new Error("Clipping end slot not found: " + end); + clip.endSlot = slot; + } + var vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + clip.color.setFromString(color); + return clip; + } } return null; }; @@ -4242,11 +4567,12 @@ var spine; attachment.worldVerticesLength = verticesLength; var vertices = map.vertices; if (verticesLength == vertices.length) { + var scaledVertices = spine.Utils.toFloatArray(vertices); if (scale != 1) { for (var i = 0, n = vertices.length; i < n; i++) - vertices[i] *= scale; + scaledVertices[i] *= scale; } - attachment.vertices = spine.Utils.toFloatArray(vertices); + attachment.vertices = scaledVertices; return; } var weights = new Array(); @@ -4276,7 +4602,18 @@ var spine; throw new Error("Slot not found: " + slotName); for (var timelineName in slotMap) { var timelineMap = slotMap[timelineName]; - if (timelineName == "color") { + if (timelineName == "attachment") { + var timeline = new spine.AttachmentTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex++, valueMap.time, valueMap.name); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + else if (timelineName == "color") { var timeline = new spine.ColorTimeline(timelineMap.length); timeline.slotIndex = slotIndex; var frameIndex = 0; @@ -4291,16 +4628,22 @@ var spine; timelines.push(timeline); duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.ColorTimeline.ENTRIES]); } - else if (timelineName = "attachment") { - var timeline = new spine.AttachmentTimeline(timelineMap.length); + else if (timelineName == "twoColor") { + var timeline = new spine.TwoColorTimeline(timelineMap.length); timeline.slotIndex = slotIndex; var frameIndex = 0; for (var i = 0; i < timelineMap.length; i++) { var valueMap = timelineMap[i]; - timeline.setFrame(frameIndex++, valueMap.time, valueMap.name); + var light = new spine.Color(); + var dark = new spine.Color(); + light.setFromString(valueMap.light); + dark.setFromString(valueMap.dark); + timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; } timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TwoColorTimeline.ENTRIES]); } else throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); @@ -4481,877 +4824,1777 @@ var spine; deform[i] += vertices[i]; } } - timeline.setFrame(frameIndex, valueMap.time, deform); - this.readCurve(valueMap, timeline, frameIndex); - frameIndex++; + timeline.setFrame(frameIndex, valueMap.time, deform); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + } + } + } + var drawOrderNode = map.drawOrder; + if (drawOrderNode == null) + drawOrderNode = map.draworder; + if (drawOrderNode != null) { + var timeline = new spine.DrawOrderTimeline(drawOrderNode.length); + var slotCount = skeletonData.slots.length; + var frameIndex = 0; + for (var j = 0; j < drawOrderNode.length; j++) { + var drawOrderMap = drawOrderNode[j]; + var drawOrder = null; + var offsets = this.getValue(drawOrderMap, "offsets", null); + if (offsets != null) { + drawOrder = spine.Utils.newArray(slotCount, -1); + var unchanged = spine.Utils.newArray(slotCount - offsets.length, 0); + var originalIndex = 0, unchangedIndex = 0; + for (var i = 0; i < offsets.length; i++) { + var offsetMap = offsets[i]; + var slotIndex = skeletonData.findSlotIndex(offsetMap.slot); + if (slotIndex == -1) + throw new Error("Slot not found: " + offsetMap.slot); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (var i = slotCount - 1; i >= 0; i--) + if (drawOrder[i] == -1) + drawOrder[i] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frameIndex++, drawOrderMap.time, drawOrder); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (map.events) { + var timeline = new spine.EventTimeline(map.events.length); + var frameIndex = 0; + for (var i = 0; i < map.events.length; i++) { + var eventMap = map.events[i]; + var eventData = skeletonData.findEvent(eventMap.name); + if (eventData == null) + throw new Error("Event not found: " + eventMap.name); + var event_5 = new spine.Event(spine.Utils.toSinglePrecision(eventMap.time), eventData); + event_5.intValue = this.getValue(eventMap, "int", eventData.intValue); + event_5.floatValue = this.getValue(eventMap, "float", eventData.floatValue); + event_5.stringValue = this.getValue(eventMap, "string", eventData.stringValue); + timeline.setFrame(frameIndex++, event_5); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + if (isNaN(duration)) { + throw new Error("Error while parsing animation, duration is NaN"); + } + skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + }; + SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) { + if (!map.curve) + return; + if (map.curve === "stepped") + timeline.setStepped(frameIndex); + else if (Object.prototype.toString.call(map.curve) === '[object Array]') { + var curve = map.curve; + timeline.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); + } + }; + SkeletonJson.prototype.getValue = function (map, prop, defaultValue) { + return map[prop] !== undefined ? map[prop] : defaultValue; + }; + SkeletonJson.blendModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.BlendMode.Normal; + if (str == "additive") + return spine.BlendMode.Additive; + if (str == "multiply") + return spine.BlendMode.Multiply; + if (str == "screen") + return spine.BlendMode.Screen; + throw new Error("Unknown blend mode: " + str); + }; + SkeletonJson.positionModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "fixed") + return spine.PositionMode.Fixed; + if (str == "percent") + return spine.PositionMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.spacingModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "length") + return spine.SpacingMode.Length; + if (str == "fixed") + return spine.SpacingMode.Fixed; + if (str == "percent") + return spine.SpacingMode.Percent; + throw new Error("Unknown position mode: " + str); + }; + SkeletonJson.rotateModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "tangent") + return spine.RotateMode.Tangent; + if (str == "chain") + return spine.RotateMode.Chain; + if (str == "chainscale") + return spine.RotateMode.ChainScale; + throw new Error("Unknown rotate mode: " + str); + }; + SkeletonJson.transformModeFromString = function (str) { + str = str.toLowerCase(); + if (str == "normal") + return spine.TransformMode.Normal; + if (str == "onlytranslation") + return spine.TransformMode.OnlyTranslation; + if (str == "norotationorreflection") + return spine.TransformMode.NoRotationOrReflection; + if (str == "noscale") + return spine.TransformMode.NoScale; + if (str == "noscaleorreflection") + return spine.TransformMode.NoScaleOrReflection; + throw new Error("Unknown transform mode: " + str); + }; + return SkeletonJson; + }()); + spine.SkeletonJson = SkeletonJson; + var LinkedMesh = (function () { + function LinkedMesh(mesh, skin, slotIndex, parent) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + } + return LinkedMesh; + }()); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Skin = (function () { + function Skin(name) { + this.attachments = new Array(); + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + Skin.prototype.addAttachment = function (slotIndex, name, attachment) { + if (attachment == null) + throw new Error("attachment cannot be null."); + var attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + }; + Skin.prototype.getAttachment = function (slotIndex, name) { + var dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + }; + Skin.prototype.attachAll = function (skeleton, oldSkin) { + var slotIndex = 0; + for (var i = 0; i < skeleton.slots.length; i++) { + var slot = skeleton.slots[i]; + var slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + var dictionary = oldSkin.attachments[slotIndex]; + for (var key in dictionary) { + var skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + var attachment = this.getAttachment(slotIndex, key); + if (attachment != null) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + }; + return Skin; + }()); + spine.Skin = Skin; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Slot = (function () { + function Slot(data, bone) { + this.attachmentVertices = new Array(); + if (data == null) + throw new Error("data cannot be null."); + if (bone == null) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new spine.Color(); + this.darkColor = data.darkColor == null ? null : new spine.Color(); + this.setToSetupPose(); + } + Slot.prototype.getAttachment = function () { + return this.attachment; + }; + Slot.prototype.setAttachment = function (attachment) { + if (this.attachment == attachment) + return; + this.attachment = attachment; + this.attachmentTime = this.bone.skeleton.time; + this.attachmentVertices.length = 0; + }; + Slot.prototype.setAttachmentTime = function (time) { + this.attachmentTime = this.bone.skeleton.time - time; + }; + Slot.prototype.getAttachmentTime = function () { + return this.bone.skeleton.time - this.attachmentTime; + }; + Slot.prototype.setToSetupPose = function () { + this.color.setFromColor(this.data.color); + if (this.darkColor != null) + this.darkColor.setFromColor(this.data.darkColor); + if (this.data.attachmentName == null) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + }; + return Slot; + }()); + spine.Slot = Slot; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SlotData = (function () { + function SlotData(index, name, boneData) { + this.color = new spine.Color(1, 1, 1, 1); + if (index < 0) + throw new Error("index must be >= 0."); + if (name == null) + throw new Error("name cannot be null."); + if (boneData == null) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + return SlotData; + }()); + spine.SlotData = SlotData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Texture = (function () { + function Texture(image) { + this._image = image; + } + Texture.prototype.getImage = function () { + return this._image; + }; + Texture.filterFromString = function (text) { + switch (text.toLowerCase()) { + case "nearest": return TextureFilter.Nearest; + case "linear": return TextureFilter.Linear; + case "mipmap": return TextureFilter.MipMap; + case "mipmapnearestnearest": return TextureFilter.MipMapNearestNearest; + case "mipmaplinearnearest": return TextureFilter.MipMapLinearNearest; + case "mipmapnearestlinear": return TextureFilter.MipMapNearestLinear; + case "mipmaplinearlinear": return TextureFilter.MipMapLinearLinear; + default: throw new Error("Unknown texture filter " + text); + } + }; + Texture.wrapFromString = function (text) { + switch (text.toLowerCase()) { + case "mirroredtepeat": return TextureWrap.MirroredRepeat; + case "clamptoedge": return TextureWrap.ClampToEdge; + case "repeat": return TextureWrap.Repeat; + default: throw new Error("Unknown texture wrap " + text); + } + }; + return Texture; + }()); + spine.Texture = Texture; + var TextureFilter; + (function (TextureFilter) { + TextureFilter[TextureFilter["Nearest"] = 9728] = "Nearest"; + TextureFilter[TextureFilter["Linear"] = 9729] = "Linear"; + TextureFilter[TextureFilter["MipMap"] = 9987] = "MipMap"; + TextureFilter[TextureFilter["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter[TextureFilter["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter[TextureFilter["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter[TextureFilter["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + })(TextureFilter = spine.TextureFilter || (spine.TextureFilter = {})); + var TextureWrap; + (function (TextureWrap) { + TextureWrap[TextureWrap["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap[TextureWrap["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap[TextureWrap["Repeat"] = 10497] = "Repeat"; + })(TextureWrap = spine.TextureWrap || (spine.TextureWrap = {})); + var TextureRegion = (function () { + function TextureRegion() { + this.u = 0; + this.v = 0; + this.u2 = 0; + this.v2 = 0; + this.width = 0; + this.height = 0; + this.rotate = false; + this.offsetX = 0; + this.offsetY = 0; + this.originalWidth = 0; + this.originalHeight = 0; + } + return TextureRegion; + }()); + spine.TextureRegion = TextureRegion; + var FakeTexture = (function (_super) { + __extends(FakeTexture, _super); + function FakeTexture() { + return _super !== null && _super.apply(this, arguments) || this; + } + FakeTexture.prototype.setFilters = function (minFilter, magFilter) { }; + FakeTexture.prototype.setWraps = function (uWrap, vWrap) { }; + FakeTexture.prototype.dispose = function () { }; + return FakeTexture; + }(spine.Texture)); + spine.FakeTexture = FakeTexture; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TextureAtlas = (function () { + function TextureAtlas(atlasText, textureLoader) { + this.pages = new Array(); + this.regions = new Array(); + this.load(atlasText, textureLoader); + } + TextureAtlas.prototype.load = function (atlasText, textureLoader) { + if (textureLoader == null) + throw new Error("textureLoader cannot be null."); + var reader = new TextureAtlasReader(atlasText); + var tuple = new Array(4); + var page = null; + while (true) { + var line = reader.readLine(); + if (line == null) + break; + line = line.trim(); + if (line.length == 0) + page = null; + else if (!page) { + page = new TextureAtlasPage(); + page.name = line; + if (reader.readTuple(tuple) == 2) { + page.width = parseInt(tuple[0]); + page.height = parseInt(tuple[1]); + reader.readTuple(tuple); + } + reader.readTuple(tuple); + page.minFilter = spine.Texture.filterFromString(tuple[0]); + page.magFilter = spine.Texture.filterFromString(tuple[1]); + var direction = reader.readValue(); + page.uWrap = spine.TextureWrap.ClampToEdge; + page.vWrap = spine.TextureWrap.ClampToEdge; + if (direction == "x") + page.uWrap = spine.TextureWrap.Repeat; + else if (direction == "y") + page.vWrap = spine.TextureWrap.Repeat; + else if (direction == "xy") + page.uWrap = page.vWrap = spine.TextureWrap.Repeat; + page.texture = textureLoader(line); + page.texture.setFilters(page.minFilter, page.magFilter); + page.texture.setWraps(page.uWrap, page.vWrap); + page.width = page.texture.getImage().width; + page.height = page.texture.getImage().height; + this.pages.push(page); + } + else { + var region = new TextureAtlasRegion(); + region.name = line; + region.page = page; + region.rotate = reader.readValue() == "true"; + reader.readTuple(tuple); + var x = parseInt(tuple[0]); + var y = parseInt(tuple[1]); + reader.readTuple(tuple); + var width = parseInt(tuple[0]); + var height = parseInt(tuple[1]); + region.u = x / page.width; + region.v = y / page.height; + if (region.rotate) { + region.u2 = (x + height) / page.width; + region.v2 = (y + width) / page.height; + } + else { + region.u2 = (x + width) / page.width; + region.v2 = (y + height) / page.height; + } + region.x = x; + region.y = y; + region.width = Math.abs(width); + region.height = Math.abs(height); + if (reader.readTuple(tuple) == 4) { + if (reader.readTuple(tuple) == 4) { + reader.readTuple(tuple); + } + } + region.originalWidth = parseInt(tuple[0]); + region.originalHeight = parseInt(tuple[1]); + reader.readTuple(tuple); + region.offsetX = parseInt(tuple[0]); + region.offsetY = parseInt(tuple[1]); + region.index = parseInt(reader.readValue()); + region.texture = page.texture; + this.regions.push(region); + } + } + }; + TextureAtlas.prototype.findRegion = function (name) { + for (var i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + }; + TextureAtlas.prototype.dispose = function () { + for (var i = 0; i < this.pages.length; i++) { + this.pages[i].texture.dispose(); + } + }; + return TextureAtlas; + }()); + spine.TextureAtlas = TextureAtlas; + var TextureAtlasReader = (function () { + function TextureAtlasReader(text) { + this.index = 0; + this.lines = text.split(/\r\n|\r|\n/); + } + TextureAtlasReader.prototype.readLine = function () { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + }; + TextureAtlasReader.prototype.readValue = function () { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + return line.substring(colon + 1).trim(); + }; + TextureAtlasReader.prototype.readTuple = function (tuple) { + var line = this.readLine(); + var colon = line.indexOf(":"); + if (colon == -1) + throw new Error("Invalid line: " + line); + var i = 0, lastMatch = colon + 1; + for (; i < 3; i++) { + var comma = line.indexOf(",", lastMatch); + if (comma == -1) + break; + tuple[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + } + tuple[i] = line.substring(lastMatch).trim(); + return i + 1; + }; + return TextureAtlasReader; + }()); + var TextureAtlasPage = (function () { + function TextureAtlasPage() { + } + return TextureAtlasPage; + }()); + spine.TextureAtlasPage = TextureAtlasPage; + var TextureAtlasRegion = (function (_super) { + __extends(TextureAtlasRegion, _super); + function TextureAtlasRegion() { + return _super !== null && _super.apply(this, arguments) || this; + } + return TextureAtlasRegion; + }(spine.TextureRegion)); + spine.TextureAtlasRegion = TextureAtlasRegion; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraint = (function () { + function TransformConstraint(data, skeleton) { + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.temp = new spine.Vector2(); + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.rotateMix = data.rotateMix; + this.translateMix = data.translateMix; + this.scaleMix = data.scaleMix; + this.shearMix = data.shearMix; + this.bones = new Array(); + for (var i = 0; i < data.bones.length; i++) + this.bones.push(skeleton.findBone(data.bones[i].name)); + this.target = skeleton.findBone(data.target.name); + } + TransformConstraint.prototype.apply = function () { + this.update(); + }; + TransformConstraint.prototype.update = function () { + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } + else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + }; + TransformConstraint.prototype.applyAbsoluteWorld = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect; + var offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * translateMix; + bone.worldY += (temp.y - bone.worldY) * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + var ts = Math.sqrt(ta * ta + tc * tc); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleX) * scaleMix) / s; + bone.a *= s; + bone.c *= s; + s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + ts = Math.sqrt(tb * tb + td * td); + if (s > 0.00001) + s = (s + (ts - s + this.data.offsetScaleY) * scaleMix) / s; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var b = bone.b, d = bone.d; + var by = Math.atan2(d, b); + var r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r = by + (r + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.applyRelativeWorld = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * translateMix; + bone.worldY += temp.y * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * scaleMix + 1; + bone.a *= s; + bone.c *= s; + s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * scaleMix + 1; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + var b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - spine.MathUtils.PI / 2 + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.applyAbsoluteLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) { + var r = target.arotation - rotation + this.data.offsetRotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + rotation += r * rotateMix; + } + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax - x + this.data.offsetX) * translateMix; + y += (target.ay - y + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix > 0) { + if (scaleX > 0.00001) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * scaleMix) / scaleX; + if (scaleY > 0.00001) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * scaleMix) / scaleY; + } + var shearY = bone.ashearY; + if (shearMix > 0) { + var r = target.ashearY - shearY + this.data.offsetShearY; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.shearY += r * shearMix; + } + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; + TransformConstraint.prototype.applyRelativeLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) + rotation += (target.arotation + this.data.offsetRotation) * rotateMix; + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax + this.data.offsetX) * translateMix; + y += (target.ay + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix > 0) { + if (scaleX > 0.00001) + scaleX *= ((target.ascaleX - 1 + this.data.offsetScaleX) * scaleMix) + 1; + if (scaleY > 0.00001) + scaleY *= ((target.ascaleY - 1 + this.data.offsetScaleY) * scaleMix) + 1; + } + var shearY = bone.ashearY; + if (shearMix > 0) + shearY += (target.ashearY + this.data.offsetShearY) * shearMix; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; + TransformConstraint.prototype.getOrder = function () { + return this.data.order; + }; + return TransformConstraint; + }()); + spine.TransformConstraint = TransformConstraint; +})(spine || (spine = {})); +var spine; +(function (spine) { + var TransformConstraintData = (function () { + function TransformConstraintData(name) { + this.order = 0; + this.bones = new Array(); + this.rotateMix = 0; + this.translateMix = 0; + this.scaleMix = 0; + this.shearMix = 0; + this.offsetRotation = 0; + this.offsetX = 0; + this.offsetY = 0; + this.offsetScaleX = 0; + this.offsetScaleY = 0; + this.offsetShearY = 0; + this.relative = false; + this.local = false; + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return TransformConstraintData; + }()); + spine.TransformConstraintData = TransformConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Triangulator = (function () { + function Triangulator() { + this.convexPolygons = new Array(); + this.convexPolygonsIndices = new Array(); + this.indicesArray = new Array(); + this.isConcaveArray = new Array(); + this.triangles = new Array(); + this.polygonPool = new spine.Pool(function () { + return new Array(); + }); + this.polygonIndicesPool = new spine.Pool(function () { + return new Array(); + }); + } + Triangulator.prototype.triangulate = function (verticesArray) { + var vertices = verticesArray; + var vertexCount = verticesArray.length >> 1; + var indices = this.indicesArray; + indices.length = 0; + for (var i = 0; i < vertexCount; i++) + indices[i] = i; + var isConcave = this.isConcaveArray; + isConcave.length = 0; + for (var i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); + var triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + var previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: if (!isConcave[i]) { + var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + var p1x = vertices[p1], p1y = vertices[p1 + 1]; + var p2x = vertices[p2], p2y = vertices[p2 + 1]; + var p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) + continue; + var v = indices[ii] << 1; + var vx = vertices[v], vy = vertices[v + 1]; + if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) + break outer; + } } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); } + break; } + if (next == 0) { + do { + if (!isConcave[i]) + break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; } - } - var drawOrderNode = map.drawOrder; - if (drawOrderNode == null) - drawOrderNode = map.draworder; - if (drawOrderNode != null) { - var timeline = new spine.DrawOrderTimeline(drawOrderNode.length); - var slotCount = skeletonData.slots.length; - var frameIndex = 0; - for (var j = 0; j < drawOrderNode.length; j++) { - var drawOrderMap = drawOrderNode[j]; - var drawOrder = null; - var offsets = this.getValue(drawOrderMap, "offsets", null); - if (offsets != null) { - drawOrder = spine.Utils.newArray(slotCount, -1); - var unchanged = spine.Utils.newArray(slotCount - offsets.length, 0); - var originalIndex = 0, unchangedIndex = 0; - for (var i = 0; i < offsets.length; i++) { - var offsetMap = offsets[i]; - var slotIndex = skeletonData.findSlotIndex(offsetMap.slot); - if (slotIndex == -1) - throw new Error("Slot not found: " + offsetMap.slot); - while (originalIndex != slotIndex) - unchanged[unchangedIndex++] = originalIndex++; - drawOrder[originalIndex + offsetMap.offset] = originalIndex++; - } - while (originalIndex < slotCount) - unchanged[unchangedIndex++] = originalIndex++; - for (var i = slotCount - 1; i >= 0; i--) - if (drawOrder[i] == -1) - drawOrder[i] = unchanged[--unchangedIndex]; + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + var previousIndex = (vertexCount + i - 1) % vertexCount; + var nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + }; + Triangulator.prototype.decompose = function (verticesArray, triangles) { + var vertices = verticesArray; + var convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + var convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + var polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + var polygon = this.polygonPool.obtain(); + polygon.length = 0; + var fanBaseIndex = -1, lastWinding = 0; + for (var i = 0, n = triangles.length; i < n; i += 3) { + var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + var x1 = vertices[t1], y1 = vertices[t1 + 1]; + var x2 = vertices[t2], y2 = vertices[t2 + 1]; + var x3 = vertices[t3], y3 = vertices[t3 + 1]; + var merged = false; + if (fanBaseIndex == t1) { + var o = polygon.length - 4; + var winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + var winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; } - timeline.setFrame(frameIndex++, drawOrderMap.time, drawOrder); } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } } - if (map.events) { - var timeline = new spine.EventTimeline(map.events.length); - var frameIndex = 0; - for (var i = 0; i < map.events.length; i++) { - var eventMap = map.events[i]; - var eventData = skeletonData.findEvent(eventMap.name); - if (eventData == null) - throw new Error("Event not found: " + eventMap.name); - var event_5 = new spine.Event(eventMap.time, eventData); - event_5.intValue = this.getValue(eventMap, "int", eventData.intValue); - event_5.floatValue = this.getValue(eventMap, "float", eventData.floatValue); - event_5.stringValue = this.getValue(eventMap, "string", eventData.stringValue); - timeline.setFrame(frameIndex++, event_5); + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (var i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) + continue; + var firstIndex = polygonIndices[0]; + var lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + var o = polygon.length - 4; + var prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + var prevX = polygon[o + 2], prevY = polygon[o + 3]; + var firstX = polygon[0], firstY = polygon[1]; + var secondX = polygon[2], secondY = polygon[3]; + var winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (var ii = 0; ii < n; ii++) { + if (ii == i) + continue; + var otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) + continue; + var otherFirstIndex = otherIndices[0]; + var otherSecondIndex = otherIndices[1]; + var otherLastIndex = otherIndices[2]; + var otherPoly = convexPolygons[ii]; + var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + continue; + var winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + var winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } } - timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); } - if (isNaN(duration)) { - throw new Error("Error while parsing animation, duration is NaN"); + for (var i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } } - skeletonData.animations.push(new spine.Animation(name, timelines, duration)); + return convexPolygons; }; - SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) { - if (!map.curve) - return; - if (map.curve === "stepped") - timeline.setStepped(frameIndex); - else if (Object.prototype.toString.call(map.curve) === '[object Array]') { - var curve = map.curve; - timeline.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]); - } + Triangulator.isConcave = function (index, vertexCount, vertices, indices) { + var previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + var current = indices[index] << 1; + var next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); }; - SkeletonJson.prototype.getValue = function (map, prop, defaultValue) { - return map[prop] !== undefined ? map[prop] : defaultValue; + Triangulator.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; }; - SkeletonJson.blendModeFromString = function (str) { - str = str.toLowerCase(); - if (str == "normal") - return spine.BlendMode.Normal; - if (str == "additive") - return spine.BlendMode.Additive; - if (str == "multiply") - return spine.BlendMode.Multiply; - if (str == "screen") - return spine.BlendMode.Screen; - throw new Error("Unknown blend mode: " + str); + Triangulator.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) { + var px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; }; - SkeletonJson.positionModeFromString = function (str) { - str = str.toLowerCase(); - if (str == "fixed") - return spine.PositionMode.Fixed; - if (str == "percent") - return spine.PositionMode.Percent; - throw new Error("Unknown position mode: " + str); + return Triangulator; + }()); + spine.Triangulator = Triangulator; +})(spine || (spine = {})); +var spine; +(function (spine) { + var IntSet = (function () { + function IntSet() { + this.array = new Array(); + } + IntSet.prototype.add = function (value) { + var contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; }; - SkeletonJson.spacingModeFromString = function (str) { - str = str.toLowerCase(); - if (str == "length") - return spine.SpacingMode.Length; - if (str == "fixed") - return spine.SpacingMode.Fixed; - if (str == "percent") - return spine.SpacingMode.Percent; - throw new Error("Unknown position mode: " + str); + IntSet.prototype.contains = function (value) { + return this.array[value | 0] != undefined; }; - SkeletonJson.rotateModeFromString = function (str) { - str = str.toLowerCase(); - if (str == "tangent") - return spine.RotateMode.Tangent; - if (str == "chain") - return spine.RotateMode.Chain; - if (str == "chainscale") - return spine.RotateMode.ChainScale; - throw new Error("Unknown rotate mode: " + str); + IntSet.prototype.remove = function (value) { + this.array[value | 0] = undefined; }; - SkeletonJson.transformModeFromString = function (str) { - str = str.toLowerCase(); - if (str == "normal") - return spine.TransformMode.Normal; - if (str == "onlytranslation") - return spine.TransformMode.OnlyTranslation; - if (str == "norotationorreflection") - return spine.TransformMode.NoRotationOrReflection; - if (str == "noscale") - return spine.TransformMode.NoScale; - if (str == "noscaleorreflection") - return spine.TransformMode.NoScaleOrReflection; - throw new Error("Unknown transform mode: " + str); + IntSet.prototype.clear = function () { + this.array.length = 0; }; - return SkeletonJson; - }()); - spine.SkeletonJson = SkeletonJson; - var LinkedMesh = (function () { - function LinkedMesh(mesh, skin, slotIndex, parent) { - this.mesh = mesh; - this.skin = skin; - this.slotIndex = slotIndex; - this.parent = parent; - } - return LinkedMesh; + return IntSet; }()); -})(spine || (spine = {})); -var spine; -(function (spine) { - var Skin = (function () { - function Skin(name) { - this.attachments = new Array(); - if (name == null) - throw new Error("name cannot be null."); - this.name = name; + spine.IntSet = IntSet; + var Color = (function () { + function Color(r, g, b, a) { + if (r === void 0) { r = 0; } + if (g === void 0) { g = 0; } + if (b === void 0) { b = 0; } + if (a === void 0) { a = 0; } + this.r = r; + this.g = g; + this.b = b; + this.a = a; } - Skin.prototype.addAttachment = function (slotIndex, name, attachment) { - if (attachment == null) - throw new Error("attachment cannot be null."); - var attachments = this.attachments; - if (slotIndex >= attachments.length) - attachments.length = slotIndex + 1; - if (!attachments[slotIndex]) - attachments[slotIndex] = {}; - attachments[slotIndex][name] = attachment; + Color.prototype.set = function (r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + this.clamp(); + return this; }; - Skin.prototype.getAttachment = function (slotIndex, name) { - var dictionary = this.attachments[slotIndex]; - return dictionary ? dictionary[name] : null; + Color.prototype.setFromColor = function (c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; }; - Skin.prototype.attachAll = function (skeleton, oldSkin) { - var slotIndex = 0; - for (var i = 0; i < skeleton.slots.length; i++) { - var slot = skeleton.slots[i]; - var slotAttachment = slot.getAttachment(); - if (slotAttachment && slotIndex < oldSkin.attachments.length) { - var dictionary = oldSkin.attachments[slotIndex]; - for (var key in dictionary) { - var skinAttachment = dictionary[key]; - if (slotAttachment == skinAttachment) { - var attachment = this.getAttachment(slotIndex, key); - if (attachment != null) - slot.setAttachment(attachment); - break; - } - } - } - slotIndex++; - } + Color.prototype.setFromString = function (hex) { + hex = hex.charAt(0) == '#' ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255.0; + this.g = parseInt(hex.substr(2, 2), 16) / 255.0; + this.b = parseInt(hex.substr(4, 2), 16) / 255.0; + this.a = (hex.length != 8 ? 255 : parseInt(hex.substr(6, 2), 16)) / 255.0; + return this; + }; + Color.prototype.add = function (r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + this.clamp(); + return this; + }; + Color.prototype.clamp = function () { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; }; - return Skin; + Color.WHITE = new Color(1, 1, 1, 1); + Color.RED = new Color(1, 0, 0, 1); + Color.GREEN = new Color(0, 1, 0, 1); + Color.BLUE = new Color(0, 0, 1, 1); + Color.MAGENTA = new Color(1, 0, 1, 1); + return Color; }()); - spine.Skin = Skin; -})(spine || (spine = {})); -var spine; -(function (spine) { - var Slot = (function () { - function Slot(data, bone) { - this.attachmentVertices = new Array(); - if (data == null) - throw new Error("data cannot be null."); - if (bone == null) - throw new Error("bone cannot be null."); - this.data = data; - this.bone = bone; - this.color = new spine.Color(); - this.setToSetupPose(); + spine.Color = Color; + var MathUtils = (function () { + function MathUtils() { } - Slot.prototype.getAttachment = function () { - return this.attachment; + MathUtils.clamp = function (value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; }; - Slot.prototype.setAttachment = function (attachment) { - if (this.attachment == attachment) - return; - this.attachment = attachment; - this.attachmentTime = this.bone.skeleton.time; - this.attachmentVertices.length = 0; + MathUtils.cosDeg = function (degrees) { + return Math.cos(degrees * MathUtils.degRad); }; - Slot.prototype.setAttachmentTime = function (time) { - this.attachmentTime = this.bone.skeleton.time - time; + MathUtils.sinDeg = function (degrees) { + return Math.sin(degrees * MathUtils.degRad); }; - Slot.prototype.getAttachmentTime = function () { - return this.bone.skeleton.time - this.attachmentTime; + MathUtils.signum = function (value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; }; - Slot.prototype.setToSetupPose = function () { - this.color.setFromColor(this.data.color); - if (this.data.attachmentName == null) - this.attachment = null; - else { - this.attachment = null; - this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); - } + MathUtils.toInt = function (x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); }; - return Slot; - }()); - spine.Slot = Slot; -})(spine || (spine = {})); -var spine; -(function (spine) { - var SlotData = (function () { - function SlotData(index, name, boneData) { - this.color = new spine.Color(1, 1, 1, 1); - if (index < 0) - throw new Error("index must be >= 0."); - if (name == null) - throw new Error("name cannot be null."); - if (boneData == null) - throw new Error("boneData cannot be null."); - this.index = index; - this.name = name; - this.boneData = boneData; - } - return SlotData; - }()); - spine.SlotData = SlotData; -})(spine || (spine = {})); -var spine; -(function (spine) { - var Texture = (function () { - function Texture(image) { - this._image = image; - } - Texture.prototype.getImage = function () { - return this._image; + MathUtils.cbrt = function (x) { + var y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; }; - Texture.filterFromString = function (text) { - switch (text.toLowerCase()) { - case "nearest": return TextureFilter.Nearest; - case "linear": return TextureFilter.Linear; - case "mipmap": return TextureFilter.MipMap; - case "mipmapnearestnearest": return TextureFilter.MipMapNearestNearest; - case "mipmaplinearnearest": return TextureFilter.MipMapLinearNearest; - case "mipmapnearestlinear": return TextureFilter.MipMapNearestLinear; - case "mipmaplinearlinear": return TextureFilter.MipMapLinearLinear; - default: throw new Error("Unknown texture filter " + text); - } + MathUtils.randomTriangular = function (min, max) { + return MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); }; - Texture.wrapFromString = function (text) { - switch (text.toLowerCase()) { - case "mirroredtepeat": return TextureWrap.MirroredRepeat; - case "clamptoedge": return TextureWrap.ClampToEdge; - case "repeat": return TextureWrap.Repeat; - default: throw new Error("Unknown texture wrap " + text); - } + MathUtils.randomTriangularWith = function (min, max, mode) { + var u = Math.random(); + var d = max - min; + if (u <= (mode - min) / d) + return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); }; - return Texture; + MathUtils.PI = 3.1415927; + MathUtils.PI2 = MathUtils.PI * 2; + MathUtils.radiansToDegrees = 180 / MathUtils.PI; + MathUtils.radDeg = MathUtils.radiansToDegrees; + MathUtils.degreesToRadians = MathUtils.PI / 180; + MathUtils.degRad = MathUtils.degreesToRadians; + return MathUtils; }()); - spine.Texture = Texture; - (function (TextureFilter) { - TextureFilter[TextureFilter["Nearest"] = 9728] = "Nearest"; - TextureFilter[TextureFilter["Linear"] = 9729] = "Linear"; - TextureFilter[TextureFilter["MipMap"] = 9987] = "MipMap"; - TextureFilter[TextureFilter["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; - TextureFilter[TextureFilter["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; - TextureFilter[TextureFilter["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; - TextureFilter[TextureFilter["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; - })(spine.TextureFilter || (spine.TextureFilter = {})); - var TextureFilter = spine.TextureFilter; - (function (TextureWrap) { - TextureWrap[TextureWrap["MirroredRepeat"] = 33648] = "MirroredRepeat"; - TextureWrap[TextureWrap["ClampToEdge"] = 33071] = "ClampToEdge"; - TextureWrap[TextureWrap["Repeat"] = 10497] = "Repeat"; - })(spine.TextureWrap || (spine.TextureWrap = {})); - var TextureWrap = spine.TextureWrap; - var TextureRegion = (function () { - function TextureRegion() { - this.u = 0; - this.v = 0; - this.u2 = 0; - this.v2 = 0; - this.width = 0; - this.height = 0; - this.rotate = false; - this.offsetX = 0; - this.offsetY = 0; - this.originalWidth = 0; - this.originalHeight = 0; + spine.MathUtils = MathUtils; + var Interpolation = (function () { + function Interpolation() { } - return TextureRegion; + Interpolation.prototype.apply = function (start, end, a) { + return start + (end - start) * this.applyInternal(a); + }; + return Interpolation; }()); - spine.TextureRegion = TextureRegion; -})(spine || (spine = {})); -var spine; -(function (spine) { - var TextureAtlas = (function () { - function TextureAtlas(atlasText, textureLoader) { - this.pages = new Array(); - this.regions = new Array(); - this.load(atlasText, textureLoader); + spine.Interpolation = Interpolation; + var Pow = (function (_super) { + __extends(Pow, _super); + function Pow(power) { + var _this = _super.call(this) || this; + _this.power = 2; + _this.power = power; + return _this; } - TextureAtlas.prototype.load = function (atlasText, textureLoader) { - if (textureLoader == null) - throw new Error("textureLoader cannot be null."); - var reader = new TextureAtlasReader(atlasText); - var tuple = new Array(4); - var page = null; - while (true) { - var line = reader.readLine(); - if (line == null) - break; - line = line.trim(); - if (line.length == 0) - page = null; - else if (!page) { - page = new TextureAtlasPage(); - page.name = line; - if (reader.readTuple(tuple) == 2) { - page.width = parseInt(tuple[0]); - page.height = parseInt(tuple[1]); - reader.readTuple(tuple); - } - reader.readTuple(tuple); - page.minFilter = spine.Texture.filterFromString(tuple[0]); - page.magFilter = spine.Texture.filterFromString(tuple[1]); - var direction = reader.readValue(); - page.uWrap = spine.TextureWrap.ClampToEdge; - page.vWrap = spine.TextureWrap.ClampToEdge; - if (direction == "x") - page.uWrap = spine.TextureWrap.Repeat; - else if (direction == "y") - page.vWrap = spine.TextureWrap.Repeat; - else if (direction == "xy") - page.uWrap = page.vWrap = spine.TextureWrap.Repeat; - page.texture = textureLoader(line); - page.texture.setFilters(page.minFilter, page.magFilter); - page.texture.setWraps(page.uWrap, page.vWrap); - page.width = page.texture.getImage().width; - page.height = page.texture.getImage().height; - this.pages.push(page); - } - else { - var region = new TextureAtlasRegion(); - region.name = line; - region.page = page; - region.rotate = reader.readValue() == "true"; - reader.readTuple(tuple); - var x = parseInt(tuple[0]); - var y = parseInt(tuple[1]); - reader.readTuple(tuple); - var width = parseInt(tuple[0]); - var height = parseInt(tuple[1]); - region.u = x / page.width; - region.v = y / page.height; - if (region.rotate) { - region.u2 = (x + height) / page.width; - region.v2 = (y + width) / page.height; - } - else { - region.u2 = (x + width) / page.width; - region.v2 = (y + height) / page.height; - } - region.x = x; - region.y = y; - region.width = Math.abs(width); - region.height = Math.abs(height); - if (reader.readTuple(tuple) == 4) { - if (reader.readTuple(tuple) == 4) { - reader.readTuple(tuple); - } - } - region.originalWidth = parseInt(tuple[0]); - region.originalHeight = parseInt(tuple[1]); - reader.readTuple(tuple); - region.offsetX = parseInt(tuple[0]); - region.offsetY = parseInt(tuple[1]); - region.index = parseInt(reader.readValue()); - region.texture = page.texture; - this.regions.push(region); - } + Pow.prototype.applyInternal = function (a) { + if (a <= 0.5) + return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + }; + return Pow; + }(Interpolation)); + spine.Pow = Pow; + var PowOut = (function (_super) { + __extends(PowOut, _super); + function PowOut(power) { + return _super.call(this, power) || this; + } + PowOut.prototype.applyInternal = function (a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + }; + return PowOut; + }(Pow)); + spine.PowOut = PowOut; + var Utils = (function () { + function Utils() { + } + Utils.arrayCopy = function (source, sourceStart, dest, destStart, numElements) { + for (var i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + }; + Utils.setArraySize = function (array, size, value) { + if (value === void 0) { value = 0; } + var oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (var i = oldSize; i < size; i++) + array[i] = value; } + return array; }; - TextureAtlas.prototype.findRegion = function (name) { - for (var i = 0; i < this.regions.length; i++) { - if (this.regions[i].name == name) { - return this.regions[i]; - } + Utils.ensureArrayCapacity = function (array, size, value) { + if (value === void 0) { value = 0; } + if (array.length >= size) + return array; + return Utils.setArraySize(array, size, value); + }; + Utils.newArray = function (size, defaultValue) { + var array = new Array(size); + for (var i = 0; i < size; i++) + array[i] = defaultValue; + return array; + }; + Utils.newFloatArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Float32Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; } - return null; }; - TextureAtlas.prototype.dispose = function () { - for (var i = 0; i < this.pages.length; i++) { - this.pages[i].texture.dispose(); + Utils.newShortArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Int16Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; } }; - return TextureAtlas; + Utils.toFloatArray = function (array) { + return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + }; + Utils.toSinglePrecision = function (value) { + return Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + }; + Utils.webkit602BugfixHelper = function (alpha, pose) { + }; + Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined"; + return Utils; }()); - spine.TextureAtlas = TextureAtlas; - var TextureAtlasReader = (function () { - function TextureAtlasReader(text) { - this.index = 0; - this.lines = text.split(/\r\n|\r|\n/); + spine.Utils = Utils; + var DebugUtils = (function () { + function DebugUtils() { } - TextureAtlasReader.prototype.readLine = function () { - if (this.index >= this.lines.length) - return null; - return this.lines[this.index++]; + DebugUtils.logBones = function (skeleton) { + for (var i = 0; i < skeleton.bones.length; i++) { + var bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } }; - TextureAtlasReader.prototype.readValue = function () { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) - throw new Error("Invalid line: " + line); - return line.substring(colon + 1).trim(); + return DebugUtils; + }()); + spine.DebugUtils = DebugUtils; + var Pool = (function () { + function Pool(instantiator) { + this.items = new Array(); + this.instantiator = instantiator; + } + Pool.prototype.obtain = function () { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); }; - TextureAtlasReader.prototype.readTuple = function (tuple) { - var line = this.readLine(); - var colon = line.indexOf(":"); - if (colon == -1) - throw new Error("Invalid line: " + line); - var i = 0, lastMatch = colon + 1; - for (; i < 3; i++) { - var comma = line.indexOf(",", lastMatch); - if (comma == -1) - break; - tuple[i] = line.substr(lastMatch, comma - lastMatch).trim(); - lastMatch = comma + 1; + Pool.prototype.free = function (item) { + if (item.reset) + item.reset(); + this.items.push(item); + }; + Pool.prototype.freeAll = function (items) { + for (var i = 0; i < items.length; i++) { + if (items[i].reset) + items[i].reset(); + this.items[i] = items[i]; } - tuple[i] = line.substring(lastMatch).trim(); - return i + 1; }; - return TextureAtlasReader; + Pool.prototype.clear = function () { + this.items.length = 0; + }; + return Pool; }()); - var TextureAtlasPage = (function () { - function TextureAtlasPage() { + spine.Pool = Pool; + var Vector2 = (function () { + function Vector2(x, y) { + if (x === void 0) { x = 0; } + if (y === void 0) { y = 0; } + this.x = x; + this.y = y; } - return TextureAtlasPage; + Vector2.prototype.set = function (x, y) { + this.x = x; + this.y = y; + return this; + }; + Vector2.prototype.length = function () { + var x = this.x; + var y = this.y; + return Math.sqrt(x * x + y * y); + }; + Vector2.prototype.normalize = function () { + var len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + }; + return Vector2; }()); - spine.TextureAtlasPage = TextureAtlasPage; - var TextureAtlasRegion = (function (_super) { - __extends(TextureAtlasRegion, _super); - function TextureAtlasRegion() { - _super.apply(this, arguments); - } - return TextureAtlasRegion; - }(spine.TextureRegion)); - spine.TextureAtlasRegion = TextureAtlasRegion; -})(spine || (spine = {})); -var spine; -(function (spine) { - var TransformConstraint = (function () { - function TransformConstraint(data, skeleton) { - this.rotateMix = 0; - this.translateMix = 0; - this.scaleMix = 0; - this.shearMix = 0; - this.temp = new spine.Vector2(); - if (data == null) - throw new Error("data cannot be null."); - if (skeleton == null) - throw new Error("skeleton cannot be null."); - this.data = data; - this.rotateMix = data.rotateMix; - this.translateMix = data.translateMix; - this.scaleMix = data.scaleMix; - this.shearMix = data.shearMix; - this.bones = new Array(); - for (var i = 0; i < data.bones.length; i++) - this.bones.push(skeleton.findBone(data.bones[i].name)); - this.target = skeleton.findBone(data.target.name); + spine.Vector2 = Vector2; + var TimeKeeper = (function () { + function TimeKeeper() { + this.maxDelta = 0.064; + this.framesPerSecond = 0; + this.delta = 0; + this.totalTime = 0; + this.lastTime = Date.now() / 1000; + this.frameCount = 0; + this.frameTime = 0; } - TransformConstraint.prototype.apply = function () { - this.update(); - }; - TransformConstraint.prototype.update = function () { - var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; - var target = this.target; - var ta = target.a, tb = target.b, tc = target.c, td = target.d; - var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; - var offsetRotation = this.data.offsetRotation * degRadReflect; - var offsetShearY = this.data.offsetShearY * degRadReflect; - var bones = this.bones; - for (var i = 0, n = bones.length; i < n; i++) { - var bone = bones[i]; - var modified = false; - if (rotateMix != 0) { - var a = bone.a, b = bone.b, c = bone.c, d = bone.d; - var r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; - if (r > spine.MathUtils.PI) - r -= spine.MathUtils.PI2; - else if (r < -spine.MathUtils.PI) - r += spine.MathUtils.PI2; - r *= rotateMix; - var cos = Math.cos(r), sin = Math.sin(r); - bone.a = cos * a - sin * c; - bone.b = cos * b - sin * d; - bone.c = sin * a + cos * c; - bone.d = sin * b + cos * d; - modified = true; - } - if (translateMix != 0) { - var temp = this.temp; - target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); - bone.worldX += (temp.x - bone.worldX) * translateMix; - bone.worldY += (temp.y - bone.worldY) * translateMix; - modified = true; - } - if (scaleMix > 0) { - var s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); - var ts = Math.sqrt(ta * ta + tc * tc); - if (s > 0.00001) - s = (s + (ts - s + this.data.offsetScaleX) * scaleMix) / s; - bone.a *= s; - bone.c *= s; - s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); - ts = Math.sqrt(tb * tb + td * td); - if (s > 0.00001) - s = (s + (ts - s + this.data.offsetScaleY) * scaleMix) / s; - bone.b *= s; - bone.d *= s; - modified = true; - } - if (shearMix > 0) { - var b = bone.b, d = bone.d; - var by = Math.atan2(d, b); - var r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); - if (r > spine.MathUtils.PI) - r -= spine.MathUtils.PI2; - else if (r < -spine.MathUtils.PI) - r += spine.MathUtils.PI2; - r = by + (r + offsetShearY) * shearMix; - var s = Math.sqrt(b * b + d * d); - bone.b = Math.cos(r) * s; - bone.d = Math.sin(r) * s; - modified = true; - } - if (modified) - bone.appliedValid = false; + TimeKeeper.prototype.update = function () { + var now = Date.now() / 1000; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; } }; - TransformConstraint.prototype.getOrder = function () { - return this.data.order; + return TimeKeeper; + }()); + spine.TimeKeeper = TimeKeeper; + var WindowedMean = (function () { + function WindowedMean(windowSize) { + if (windowSize === void 0) { windowSize = 32; } + this.addedValues = 0; + this.lastValue = 0; + this.mean = 0; + this.dirty = true; + this.values = new Array(windowSize); + } + WindowedMean.prototype.hasEnoughData = function () { + return this.addedValues >= this.values.length; + }; + WindowedMean.prototype.addValue = function (value) { + if (this.addedValues < this.values.length) + this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) + this.lastValue = 0; + this.dirty = true; + }; + WindowedMean.prototype.getMean = function () { + if (this.hasEnoughData()) { + if (this.dirty) { + var mean = 0; + for (var i = 0; i < this.values.length; i++) { + mean += this.values[i]; + } + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + else { + return 0; + } }; - return TransformConstraint; + return WindowedMean; }()); - spine.TransformConstraint = TransformConstraint; + spine.WindowedMean = WindowedMean; })(spine || (spine = {})); +(function () { + if (!Math.fround) { + Math.fround = (function (array) { + return function (x) { + return array[0] = x, array[0]; + }; + })(new Float32Array(1)); + } +})(); var spine; (function (spine) { - var TransformConstraintData = (function () { - function TransformConstraintData(name) { - this.order = 0; - this.bones = new Array(); - this.rotateMix = 0; - this.translateMix = 0; - this.scaleMix = 0; - this.shearMix = 0; - this.offsetRotation = 0; - this.offsetX = 0; - this.offsetY = 0; - this.offsetScaleX = 0; - this.offsetScaleY = 0; - this.offsetShearY = 0; + var Attachment = (function () { + function Attachment(name) { if (name == null) throw new Error("name cannot be null."); this.name = name; } - return TransformConstraintData; - }()); - spine.TransformConstraintData = TransformConstraintData; -})(spine || (spine = {})); -var spine; -(function (spine) { - var IntSet = (function () { - function IntSet() { - this.array = new Array(); - } - IntSet.prototype.add = function (value) { - var contains = this.contains(value); - this.array[value | 0] = value | 0; - return !contains; - }; - IntSet.prototype.contains = function (value) { - return this.array[value | 0] != undefined; - }; - IntSet.prototype.remove = function (value) { - this.array[value | 0] = undefined; - }; - IntSet.prototype.clear = function () { - this.array.length = 0; - }; - return IntSet; + return Attachment; }()); - spine.IntSet = IntSet; - var Color = (function () { - function Color(r, g, b, a) { - if (r === void 0) { r = 0; } - if (g === void 0) { g = 0; } - if (b === void 0) { b = 0; } - if (a === void 0) { a = 0; } - this.r = r; - this.g = g; - this.b = b; - this.a = a; + spine.Attachment = Attachment; + var VertexAttachment = (function (_super) { + __extends(VertexAttachment, _super); + function VertexAttachment(name) { + var _this = _super.call(this, name) || this; + _this.id = (VertexAttachment.nextID++ & 65535) << 11; + _this.worldVerticesLength = 0; + return _this; } - Color.prototype.set = function (r, g, b, a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; - this.clamp(); - return this; - }; - Color.prototype.setFromColor = function (c) { - this.r = c.r; - this.g = c.g; - this.b = c.b; - this.a = c.a; - return this; - }; - Color.prototype.setFromString = function (hex) { - hex = hex.charAt(0) == '#' ? hex.substr(1) : hex; - this.r = parseInt(hex.substr(0, 2), 16) / 255.0; - this.g = parseInt(hex.substr(2, 2), 16) / 255.0; - this.b = parseInt(hex.substr(4, 2), 16) / 255.0; - this.a = (hex.length != 8 ? 255 : parseInt(hex.substr(6, 2), 16)) / 255.0; - return this; - }; - Color.prototype.add = function (r, g, b, a) { - this.r += r; - this.g += g; - this.b += b; - this.a += a; - this.clamp(); - return this; + VertexAttachment.prototype.computeWorldVertices = function (slot, start, count, worldVertices, offset, stride) { + count = offset + (count >> 1) * stride; + var skeleton = slot.bone.skeleton; + var deformArray = slot.attachmentVertices; + var vertices = this.vertices; + var bones = this.bones; + if (bones == null) { + if (deformArray.length > 0) + vertices = deformArray; + var bone = slot.bone; + var x = bone.worldX; + var y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (var v_1 = start, w = offset; w < count; v_1 += 2, w += stride) { + var vx = vertices[v_1], vy = vertices[v_1 + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + var v = 0, skip = 0; + for (var i = 0; i < start; i += 2) { + var n = bones[v]; + v += n + 1; + skip += n; + } + var skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (var w = offset, b = skip * 3; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + else { + var deform = deformArray; + for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } }; - Color.prototype.clamp = function () { - if (this.r < 0) - this.r = 0; - else if (this.r > 1) - this.r = 1; - if (this.g < 0) - this.g = 0; - else if (this.g > 1) - this.g = 1; - if (this.b < 0) - this.b = 0; - else if (this.b > 1) - this.b = 1; - if (this.a < 0) - this.a = 0; - else if (this.a > 1) - this.a = 1; - return this; + VertexAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment; }; - Color.WHITE = new Color(1, 1, 1, 1); - Color.RED = new Color(1, 0, 0, 1); - Color.GREEN = new Color(0, 1, 0, 1); - Color.BLUE = new Color(0, 0, 1, 1); - Color.MAGENTA = new Color(1, 0, 1, 1); - return Color; - }()); - spine.Color = Color; - var MathUtils = (function () { - function MathUtils() { + VertexAttachment.nextID = 0; + return VertexAttachment; + }(Attachment)); + spine.VertexAttachment = VertexAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AttachmentType; + (function (AttachmentType) { + AttachmentType[AttachmentType["Region"] = 0] = "Region"; + AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh"; + AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType[AttachmentType["Path"] = 4] = "Path"; + AttachmentType[AttachmentType["Point"] = 5] = "Point"; + })(AttachmentType = spine.AttachmentType || (spine.AttachmentType = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoundingBoxAttachment = (function (_super) { + __extends(BoundingBoxAttachment, _super); + function BoundingBoxAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; } - MathUtils.clamp = function (value, min, max) { - if (value < min) - return min; - if (value > max) - return max; - return value; - }; - MathUtils.cosDeg = function (degrees) { - return Math.cos(degrees * MathUtils.degRad); - }; - MathUtils.sinDeg = function (degrees) { - return Math.sin(degrees * MathUtils.degRad); - }; - MathUtils.signum = function (value) { - return value > 0 ? 1 : value < 0 ? -1 : 0; - }; - MathUtils.toInt = function (x) { - return x > 0 ? Math.floor(x) : Math.ceil(x); - }; - MathUtils.cbrt = function (x) { - var y = Math.pow(Math.abs(x), 1 / 3); - return x < 0 ? -y : y; - }; - MathUtils.PI = 3.1415927; - MathUtils.PI2 = MathUtils.PI * 2; - MathUtils.radiansToDegrees = 180 / MathUtils.PI; - MathUtils.radDeg = MathUtils.radiansToDegrees; - MathUtils.degreesToRadians = MathUtils.PI / 180; - MathUtils.degRad = MathUtils.degreesToRadians; - return MathUtils; - }()); - spine.MathUtils = MathUtils; - var Utils = (function () { - function Utils() { + return BoundingBoxAttachment; + }(spine.VertexAttachment)); + spine.BoundingBoxAttachment = BoundingBoxAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var ClippingAttachment = (function (_super) { + __extends(ClippingAttachment, _super); + function ClippingAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1); + return _this; } - Utils.arrayCopy = function (source, sourceStart, dest, destStart, numElements) { - for (var i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { - dest[j] = source[i]; + return ClippingAttachment; + }(spine.VertexAttachment)); + spine.ClippingAttachment = ClippingAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var MeshAttachment = (function (_super) { + __extends(MeshAttachment, _super); + function MeshAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + _this.inheritDeform = false; + _this.tempColor = new spine.Color(0, 0, 0, 0); + return _this; + } + MeshAttachment.prototype.updateUVs = function () { + var u = 0, v = 0, width = 0, height = 0; + if (this.region == null) { + u = v = 0; + width = height = 1; } - }; - Utils.setArraySize = function (array, size, value) { - if (value === void 0) { value = 0; } - var oldSize = array.length; - if (oldSize == size) - return array; - array.length = size; - if (oldSize < size) { - for (var i = oldSize; i < size; i++) - array[i] = value; + else { + u = this.region.u; + v = this.region.v; + width = this.region.u2 - u; + height = this.region.v2 - v; } - return array; - }; - Utils.ensureArrayCapacity = function (array, size, value) { - if (value === void 0) { value = 0; } - if (array.length >= size) - return array; - return Utils.setArraySize(array, size, value); - }; - Utils.newArray = function (size, defaultValue) { - var array = new Array(size); - for (var i = 0; i < size; i++) - array[i] = defaultValue; - return array; - }; - Utils.newFloatArray = function (size) { - if (Utils.SUPPORTS_TYPED_ARRAYS) { - return new Float32Array(size); + var regionUVs = this.regionUVs; + if (this.uvs == null || this.uvs.length != regionUVs.length) + this.uvs = spine.Utils.newFloatArray(regionUVs.length); + var uvs = this.uvs; + if (this.region.rotate) { + for (var i = 0, n = uvs.length; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + height - regionUVs[i] * height; + } } else { - var array = new Array(size); - for (var i = 0; i < array.length; i++) - array[i] = 0; - return array; + for (var i = 0, n = uvs.length; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } } }; - Utils.toFloatArray = function (array) { - return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + MeshAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment); }; - Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined"; - return Utils; - }()); - spine.Utils = Utils; - var DebugUtils = (function () { - function DebugUtils() { - } - DebugUtils.logBones = function (skeleton) { - for (var i = 0; i < skeleton.bones.length; i++) { - var bone = skeleton.bones[i]; - console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + MeshAttachment.prototype.getParentMesh = function () { + return this.parentMesh; + }; + MeshAttachment.prototype.setParentMesh = function (parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh != null) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; } }; - return DebugUtils; - }()); - spine.DebugUtils = DebugUtils; - var Pool = (function () { - function Pool(instantiator) { - this.items = new Array(); - this.instantiator = instantiator; + return MeshAttachment; + }(spine.VertexAttachment)); + spine.MeshAttachment = MeshAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathAttachment = (function (_super) { + __extends(PathAttachment, _super); + function PathAttachment(name) { + var _this = _super.call(this, name) || this; + _this.closed = false; + _this.constantSpeed = false; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; } - Pool.prototype.obtain = function () { - return this.items.length > 0 ? this.items.pop() : this.instantiator(); - }; - Pool.prototype.free = function (item) { - if (item.reset) - item.reset(); - this.items.push(item); + return PathAttachment; + }(spine.VertexAttachment)); + spine.PathAttachment = PathAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PointAttachment = (function (_super) { + __extends(PointAttachment, _super); + function PointAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.38, 0.94, 0, 1); + return _this; + } + PointAttachment.prototype.computeWorldPosition = function (bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + }; + PointAttachment.prototype.computeWorldRotation = function (bone) { + var cos = spine.MathUtils.cosDeg(this.rotation), sin = spine.MathUtils.sinDeg(this.rotation); + var x = cos * bone.a + sin * bone.b; + var y = cos * bone.c + sin * bone.d; + return Math.atan2(y, x) * spine.MathUtils.radDeg; + }; + return PointAttachment; + }(spine.VertexAttachment)); + spine.PointAttachment = PointAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var RegionAttachment = (function (_super) { + __extends(RegionAttachment, _super); + function RegionAttachment(name) { + var _this = _super.call(this, name) || this; + _this.x = 0; + _this.y = 0; + _this.scaleX = 1; + _this.scaleY = 1; + _this.rotation = 0; + _this.width = 0; + _this.height = 0; + _this.color = new spine.Color(1, 1, 1, 1); + _this.offset = spine.Utils.newFloatArray(8); + _this.uvs = spine.Utils.newFloatArray(8); + _this.tempColor = new spine.Color(1, 1, 1, 1); + return _this; + } + RegionAttachment.prototype.updateOffset = function () { + var regionScaleX = this.width / this.region.originalWidth * this.scaleX; + var regionScaleY = this.height / this.region.originalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + var localX2 = localX + this.region.width * regionScaleX; + var localY2 = localY + this.region.height * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[RegionAttachment.OX1] = localXCos - localYSin; + offset[RegionAttachment.OY1] = localYCos + localXSin; + offset[RegionAttachment.OX2] = localXCos - localY2Sin; + offset[RegionAttachment.OY2] = localY2Cos + localXSin; + offset[RegionAttachment.OX3] = localX2Cos - localY2Sin; + offset[RegionAttachment.OY3] = localY2Cos + localX2Sin; + offset[RegionAttachment.OX4] = localX2Cos - localYSin; + offset[RegionAttachment.OY4] = localYCos + localX2Sin; }; - Pool.prototype.freeAll = function (items) { - for (var i = 0; i < items.length; i++) { - if (items[i].reset) - items[i].reset(); - this.items[i] = items[i]; + RegionAttachment.prototype.setRegion = function (region) { + this.region = region; + var uvs = this.uvs; + if (region.rotate) { + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + uvs[0] = region.u2; + uvs[1] = region.v2; } + else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + }; + RegionAttachment.prototype.computeWorldVertices = function (bone, worldVertices, offset, stride) { + var vertexOffset = this.offset; + var x = bone.worldX, y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var offsetX = 0, offsetY = 0; + offsetX = vertexOffset[RegionAttachment.OX1]; + offsetY = vertexOffset[RegionAttachment.OY1]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX2]; + offsetY = vertexOffset[RegionAttachment.OY2]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX3]; + offsetY = vertexOffset[RegionAttachment.OY3]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX4]; + offsetY = vertexOffset[RegionAttachment.OY4]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; }; - Pool.prototype.clear = function () { - this.items.length = 0; - }; - return Pool; - }()); - spine.Pool = Pool; - var Vector2 = (function () { - function Vector2(x, y) { - if (x === void 0) { x = 0; } - if (y === void 0) { y = 0; } - this.x = x; - this.y = y; + RegionAttachment.OX1 = 0; + RegionAttachment.OY1 = 1; + RegionAttachment.OX2 = 2; + RegionAttachment.OY2 = 3; + RegionAttachment.OX3 = 4; + RegionAttachment.OY3 = 5; + RegionAttachment.OX4 = 6; + RegionAttachment.OY4 = 7; + RegionAttachment.X1 = 0; + RegionAttachment.Y1 = 1; + RegionAttachment.C1R = 2; + RegionAttachment.C1G = 3; + RegionAttachment.C1B = 4; + RegionAttachment.C1A = 5; + RegionAttachment.U1 = 6; + RegionAttachment.V1 = 7; + RegionAttachment.X2 = 8; + RegionAttachment.Y2 = 9; + RegionAttachment.C2R = 10; + RegionAttachment.C2G = 11; + RegionAttachment.C2B = 12; + RegionAttachment.C2A = 13; + RegionAttachment.U2 = 14; + RegionAttachment.V2 = 15; + RegionAttachment.X3 = 16; + RegionAttachment.Y3 = 17; + RegionAttachment.C3R = 18; + RegionAttachment.C3G = 19; + RegionAttachment.C3B = 20; + RegionAttachment.C3A = 21; + RegionAttachment.U3 = 22; + RegionAttachment.V3 = 23; + RegionAttachment.X4 = 24; + RegionAttachment.Y4 = 25; + RegionAttachment.C4R = 26; + RegionAttachment.C4G = 27; + RegionAttachment.C4B = 28; + RegionAttachment.C4A = 29; + RegionAttachment.U4 = 30; + RegionAttachment.V4 = 31; + return RegionAttachment; + }(spine.Attachment)); + spine.RegionAttachment = RegionAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var JitterEffect = (function () { + function JitterEffect(jitterX, jitterY) { + this.jitterX = 0; + this.jitterY = 0; + this.jitterX = jitterX; + this.jitterY = jitterY; } - Vector2.prototype.set = function (x, y) { - this.x = x; - this.y = y; - return this; + JitterEffect.prototype.begin = function (skeleton) { }; - Vector2.prototype.length = function () { - var x = this.x; - var y = this.y; - return Math.sqrt(x * x + y * y); + JitterEffect.prototype.transform = function (position, uv, light, dark) { + position.x += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); + position.y += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); }; - Vector2.prototype.normalize = function () { - var len = this.length(); - if (len != 0) { - this.x /= len; - this.y /= len; - } - return this; + JitterEffect.prototype.end = function () { }; - return Vector2; + return JitterEffect; }()); - spine.Vector2 = Vector2; - var TimeKeeper = (function () { - function TimeKeeper() { - this.maxDelta = 0.064; - this.framesPerSecond = 0; - this.delta = 0; - this.totalTime = 0; - this.lastTime = Date.now() / 1000; - this.frameCount = 0; - this.frameTime = 0; + spine.JitterEffect = JitterEffect; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SwirlEffect = (function () { + function SwirlEffect(radius) { + this.centerX = 0; + this.centerY = 0; + this.radius = 0; + this.angle = 0; + this.worldX = 0; + this.worldY = 0; + this.radius = radius; } - TimeKeeper.prototype.update = function () { - var now = Date.now() / 1000; - this.delta = now - this.lastTime; - this.frameTime += this.delta; - this.totalTime += this.delta; - if (this.delta > this.maxDelta) - this.delta = this.maxDelta; - this.lastTime = now; - this.frameCount++; - if (this.frameTime > 1) { - this.framesPerSecond = this.frameCount / this.frameTime; - this.frameTime = 0; - this.frameCount = 0; - } - }; - return TimeKeeper; + SwirlEffect.prototype.begin = function (skeleton) { + this.worldX = skeleton.x + this.centerX; + this.worldY = skeleton.y + this.centerY; + }; + SwirlEffect.prototype.transform = function (position, uv, light, dark) { + var radAngle = this.angle * spine.MathUtils.degreesToRadians; + var x = position.x - this.worldX; + var y = position.y - this.worldY; + var dist = Math.sqrt(x * x + y * y); + if (dist < this.radius) { + var theta = SwirlEffect.interpolation.apply(0, radAngle, (this.radius - dist) / this.radius); + var cos = Math.cos(theta); + var sin = Math.sin(theta); + position.x = cos * x - sin * y + this.worldX; + position.y = sin * x + cos * y + this.worldY; + } + }; + SwirlEffect.prototype.end = function () { + }; + SwirlEffect.interpolation = new spine.PowOut(2); + return SwirlEffect; }()); - spine.TimeKeeper = TimeKeeper; + spine.SwirlEffect = SwirlEffect; })(spine || (spine = {})); //# sourceMappingURL=spine-core.js.map diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 955823148ec..599c28c81f5 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -23,35 +23,54 @@ THE SOFTWARE. ****************************************************************************/ -const StencilManager = require('../../cocos2d/core/renderer/webgl/stencil-manager').sharedManager; const Skeleton = require('./Skeleton'); const spine = require('./lib/spine'); const renderer = require('../../cocos2d/core/renderer'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); const renderEngine = renderer.renderEngine; const gfx = renderEngine.gfx; -const SpriteMaterial = renderEngine.SpriteMaterial; - -const STENCIL_SEP = '@'; +const SpineMaterial = renderEngine.SpineMaterial; +const VertexFormat = require('../../cocos2d/core/renderer/webgl/vertex-format') +const VFOneColor = VertexFormat.vfmtPosUvColor; +const VFTwoColor = VertexFormat.vfmtPosUvTwoColor; +let _quadTriangles = [0, 1, 2, 2, 3, 0]; let _slotColor = cc.color(0, 0, 255, 255); let _boneColor = cc.color(255, 0, 0, 255); let _originColor = cc.color(0, 255, 0, 255); -let _debugMaterial = new SpriteMaterial(); -_debugMaterial.useModel = true; -_debugMaterial.useColor = false; -_debugMaterial.useTexture = false; -_debugMaterial.updateHash(); - -function _updateKeyWithStencilRef (key, stencilRef) { - return key.replace(/@\d+$/, STENCIL_SEP + stencilRef); + +let _finalColor = undefined; +let _darkColor = undefined; +if (!CC_JSB) { + _finalColor = new spine.Color(1, 1, 1, 1); + _darkColor = new spine.Color(1, 1, 1, 1); } -function _getSlotMaterial (comp, slot, tex, premultiAlpha) { +let _premultipliedAlpha; +let _multiplier; +let _slotRangeStart; +let _slotRangeEnd; +let _useTint; +let _debugSlots; +let _debugBones; +let _nodeR, + _nodeG, + _nodeB, + _nodeA; +let _finalColor32, _darkColor32; +let _vertexFormat; +let _perVertexSize; +let _perClipVertexSize; +let _vertexFloatCount = 0, _vertexFloatOffset = 0, _vertexOffset = 0, + _indexCount = 0, _indexOffset = 0; +let _tempr, _tempg, _tempb, _tempa; +let _inRange; + +function _getSlotMaterial (comp, slot, tex) { let src, dst; switch (slot.data.blendMode) { case spine.BlendMode.Additive: - src = premultiAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; + src = _premultipliedAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; dst = cc.macro.ONE; break; case spine.BlendMode.Multiply: @@ -64,13 +83,13 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { break; case spine.BlendMode.Normal: default: - src = premultiAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; + src = _premultipliedAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; dst = cc.macro.ONE_MINUS_SRC_ALPHA; break; } - let key = tex.url + src + dst + STENCIL_SEP + '0'; - comp._material = comp._material || new SpriteMaterial(); + let key = tex.url + src + dst; + comp._material = comp._material || new SpineMaterial(); let baseMaterial = comp._material; let materialCache = comp._materialCache; let material = materialCache[key]; @@ -84,11 +103,12 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { } material.useModel = true; - // update texture + // Update texture. material.texture = tex; - material.useColor = false; + // Update tint. + material.useTint = _useTint; - // update blend function + // Update blend function. let pass = material._mainTech.passes[0]; pass.setBlend( gfx.BLEND_FUNC_ADD, @@ -96,196 +116,307 @@ function _getSlotMaterial (comp, slot, tex, premultiAlpha) { gfx.BLEND_FUNC_ADD, src, dst ); - materialCache[key] = material; + if (materialCache[material._hash]) { + delete materialCache[material._hash]; + } material.updateHash(key); + materialCache[key] = material; } else if (material.texture !== tex) { + if (materialCache[material._hash]) { + delete materialCache[material._hash]; + } material.texture = tex; material.updateHash(key); + materialCache[key] = material; } return material; } var spineAssembler = { - // Use model to avoid per vertex transform + // Use model to avoid per vertex transform. useModel: true, - _readAttachmentData (comp, attachment, slot, premultipliedAlpha, renderData, dataOffset) { - // the vertices in format: - // X1, Y1, C1R, C1G, C1B, C1A, U1, V1 - // get the vertex data - let vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); - let vertexCount = vertices.length / 8; - // augment render data size to ensure capacity - renderData.dataLength += vertexCount; - let data = renderData._data; - let nodeColor = comp.node._color; - let nodeR = nodeColor.r, - nodeG = nodeColor.g, - nodeB = nodeColor.b, - nodeA = nodeColor.a; - for (let i = 0, n = vertices.length; i < n; i += 8) { - let r = vertices[i + 2] * nodeR, - g = vertices[i + 3] * nodeG, - b = vertices[i + 4] * nodeB, - a = vertices[i + 5] * nodeA; - let color = ((a<<24) >>> 0) + (b<<16) + (g<<8) + r; - let content = data[dataOffset]; - content.x = vertices[i]; - content.y = vertices[i + 1]; - content.color = color; - content.u = vertices[i + 6]; - content.v = vertices[i + 7]; - dataOffset++; + updateRenderData (comp, batchData) { + let skeleton = comp._skeleton; + if (skeleton) { + skeleton.updateWorldTransform(); } + }, - if (comp.debugSlots && vertexCount === 4) { - let graphics = comp._debugRenderer; - - // Debug Slot - let VERTEX = spine.RegionAttachment; - graphics.strokeColor = _slotColor; - graphics.lineWidth = 5; - graphics.moveTo(vertices[VERTEX.X1], vertices[VERTEX.Y1]); - graphics.lineTo(vertices[VERTEX.X2], vertices[VERTEX.Y2]); - graphics.lineTo(vertices[VERTEX.X3], vertices[VERTEX.Y3]); - graphics.lineTo(vertices[VERTEX.X4], vertices[VERTEX.Y4]); - graphics.close(); - graphics.stroke(); + fillVertices (skeletonColor, attachmentColor, slotColor, clipper, buffer) { + + let vbuf = buffer._vData, + ibuf = buffer._iData, + uintVData = buffer._uintVData; + + _tempa = slotColor.a * attachmentColor.a * skeletonColor.a * 255; + _multiplier = _premultipliedAlpha? _tempa : 255; + _tempr = _nodeR * attachmentColor.r * skeletonColor.r * _multiplier; + _tempg = _nodeG * attachmentColor.g * skeletonColor.g * _multiplier; + _tempb = _nodeB * attachmentColor.b * skeletonColor.b * _multiplier; + + _finalColor.r = _tempr * slotColor.r; + _finalColor.g = _tempg * slotColor.g; + _finalColor.b = _tempb * slotColor.b; + _finalColor.a = _tempa * _nodeA; + + if (slot.darkColor == null) { + _darkColor.set(0.0, 0, 0, 1.0); + } else { + _darkColor.r = slot.darkColor.r * _tempr; + _darkColor.g = slot.darkColor.g * _tempg; + _darkColor.b = slot.darkColor.b * _tempb; } + _darkColor.a = _premultipliedAlpha ? 255 : 0; + + if (!clipper.isClipping()) { + + _finalColor32 = ((_finalColor.a<<24) >>> 0) + (_finalColor.b<<16) + (_finalColor.g<<8) + _finalColor.r; + _darkColor32 = ((_darkColor.a<<24) >>> 0) + (_darkColor.b<<16) + (_darkColor.g<<8) + _darkColor.r; + + if (!_useTint) { + for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount, u = 0; v < n; v += _perVertexSize, u += 2) { + uintVData[v + 4] = _finalColor32; + } + } else { + for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount, u = 0; v < n; v += _perVertexSize, u += 2) { + uintVData[v + 4] = _finalColor32; // light color + uintVData[v + 5] = _darkColor32; // dark color + } + } - return vertexCount; + } else { + let uvs = vbuf.subarray(_vertexFloatOffset + 2); + clipper.clipTriangles(vbuf.subarray(_vertexFloatOffset), _vertexFloatCount, ibuf.subarray(_indexOffset), _indexCount, uvs, _finalColor, _darkColor, _useTint, _perVertexSize); + let clippedVertices = new Float32Array(clipper.clippedVertices); + let clippedTriangles = clipper.clippedTriangles; + + // insure capacity + _indexCount = clippedTriangles.length; + _vertexFloatCount = clippedVertices.length / _perClipVertexSize * _perVertexSize; + + buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + vbuf = buffer._vData, + ibuf = buffer._iData; + uintVData = buffer._uintVData; + + // fill indices + ibuf.set(clippedTriangles, _indexOffset); + + // fill vertices contain x y u v light color dark color + if (!_useTint) { + for (let v = 0, n = clippedVertices.length, offset = _vertexFloatOffset; v < n; v += 8, offset += _perVertexSize) { + vbuf[offset] = clippedVertices[v]; // x + vbuf[offset + 1] = clippedVertices[v + 1]; // y + vbuf[offset + 2] = clippedVertices[v + 6]; // u + vbuf[offset + 3] = clippedVertices[v + 7]; // v + + _finalColor32 = ((clippedVertices[v + 5]<<24) >>> 0) + (clippedVertices[v + 4]<<16) + (clippedVertices[v + 3]<<8) + clippedVertices[v + 2]; + uintVData[offset + 4] = _finalColor32; + } + } else { + for (let v = 0, n = clippedVertices.length, offset = _vertexFloatOffset; v < n; v += 12, offset += _perVertexSize) { + vbuf[offset] = clippedVertices[v]; // x + vbuf[offset + 1] = clippedVertices[v + 1]; // y + vbuf[offset + 2] = clippedVertices[v + 6]; // u + vbuf[offset + 3] = clippedVertices[v + 7]; // v + + _finalColor32 = ((clippedVertices[v + 5]<<24) >>> 0) + (clippedVertices[v + 4]<<16) + (clippedVertices[v + 3]<<8) + clippedVertices[v + 2]; + uintVData[offset + 4] = _finalColor32; + + _darkColor32 = ((clippedVertices[v + 11]<<24) >>> 0) + (clippedVertices[v + 10]<<16) + (clippedVertices[v + 9]<<8) + clippedVertices[v + 8]; + uintVData[offset + 5] = _darkColor32; + } + } + } }, - genRenderDatas (comp, batchData) { + fillBuffers (comp, renderer) { + + let node = comp.node; + node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; + + let nodeColor = node._color; + _nodeR = nodeColor.r / 255; + _nodeG = nodeColor.g / 255; + _nodeB = nodeColor.b / 255; + _nodeA = nodeColor.a / 255; + + _useTint = comp.useTint; + _vertexFormat = _useTint? VFTwoColor : VFOneColor; + let buffer = renderer.getBuffer('spine', _vertexFormat); + let vbuf; + let ibuf; + let locSkeleton = comp._skeleton; - let premultiAlpha = comp.premultipliedAlpha; + let skeletonColor = locSkeleton.color; let graphics = comp._debugRenderer; + let clipper = comp._clipper; + let material = null; + let attachment, attachmentColor, slotColor, uvs, triangles; - if (comp.debugBones || comp.debugSlots) { - graphics.clear(); - } + _premultipliedAlpha = comp.premultipliedAlpha; + _multiplier = 1.0; + + _slotRangeStart = comp._startSlotIndex; + _slotRangeEnd = comp._endSlotIndex; + _inRange = false; + if (_slotRangeStart == -1) _inRange = true; - let attachment, slot, isMesh, isRegion; - let dataId = 0, datas = comp._renderDatas, data = datas[dataId], newData = false; - if (!data) { - data = datas[dataId] = comp.requestRenderData(); + _debugSlots = comp.debugSlots; + _debugBones = comp.debugBones; + if (graphics && (_debugBones || _debugSlots)) { + graphics.clear(); + graphics.strokeColor = _slotColor; + graphics.lineWidth = 5; } - data.dataLength = 0; - let indices; - let material = null, currMaterial = null; - let vertexCount = 0, vertexOffset = 0; - let indiceCount = 0, indiceOffset = 0; - let materialCache = comp._materialCache; - for (let i = 0, n = locSkeleton.drawOrder.length; i < n; i++) { - slot = locSkeleton.drawOrder[i]; - if (!slot.attachment) + + // x y u v color1 color2 or x y u v color + _perVertexSize = _useTint ? 6 : 5; + // x y u v r1 g1 b1 a1 r2 g2 b2 a2 or x y u v r g b a + _perClipVertexSize = _useTint ? 12 : 8; + + _vertexFloatCount = 0; + _vertexFloatOffset = 0; + _vertexOffset = 0; + _indexCount = 0; + _indexOffset = 0; + + for (let slotIdx = 0, slotCount = locSkeleton.drawOrder.length; slotIdx < slotCount; slotIdx++) { + slot = locSkeleton.drawOrder[slotIdx]; + + if (_slotRangeStart >= 0 && _slotRangeStart == slot.data.index) { + _inRange = true; + } + + if (!_inRange) { + clipper.clipEndWithSlot(slot); continue; - attachment = slot.attachment; - isMesh = (attachment instanceof spine.MeshAttachment); - isRegion = (attachment instanceof spine.RegionAttachment); - - // get the vertices length - vertexCount = 0; - if (isRegion) { - vertexCount = 4; - indiceCount = 6; } - else if (isMesh) { - vertexCount = attachment.regionUVs.length / 2; - indiceCount = attachment.triangles.length; + + if (_slotRangeEnd >= 0 && _slotRangeEnd == slot.data.index) { + _inRange = false; + } + + _vertexFloatCount = 0; + _indexCount = 0; + + _indexOffset = buffer.indiceOffset, + _vertexOffset = buffer.vertexOffset, + _vertexFloatOffset = buffer.byteOffset >> 2; + + attachment = slot.getAttachment(); + if (!attachment) continue; + + if (attachment instanceof spine.RegionAttachment) { + + triangles = _quadTriangles; + + // insure capacity + _vertexFloatCount = 4 * _perVertexSize; + _indexCount = 6; + + buffer.request(4, 6); + vbuf = buffer._vData, + ibuf = buffer._iData; + uintVData = buffer._uintVData; + + // compute vertex and fill x y + attachment.computeWorldVertices(slot.bone, vbuf, _vertexFloatOffset, _perVertexSize); + + // draw debug slots if enabled graphics + if (graphics && _debugSlots) { + graphics.moveTo(vbuf[_vertexFloatOffset], vbuf[_vertexFloatOffset + 1]); + for (let ii = _vertexFloatOffset + _perVertexSize, nn = _vertexFloatOffset + _vertexFloatCount; ii < nn; ii += _perVertexSize) { + graphics.lineTo(vbuf[ii], vbuf[ii + 1]); + } + graphics.close(); + graphics.stroke(); + } + } + else if (attachment instanceof spine.MeshAttachment) { + + triangles = attachment.triangles; + + // insure capacity + _vertexFloatCount = (attachment.worldVerticesLength >> 1) * _perVertexSize; + _indexCount = triangles.length; + + buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + vbuf = buffer._vData, + ibuf = buffer._iData; + uintVData = buffer._uintVData; + + // compute vertex and fill x y + attachment.computeWorldVertices(slot, 0, attachment.worldVerticesLength, vbuf, _vertexFloatOffset, _perVertexSize); + } + else if (attachment instanceof spine.ClippingAttachment) { + clipper.clipStart(slot, attachment); + continue; } else { continue; } - - // no vertices to render - if (vertexCount === 0) { + + if (_vertexFloatCount == 0 || _indexCount == 0) { continue; } + + // fill indices + ibuf.set(triangles, _indexOffset); + + // fill u v + uvs = attachment.uvs; + for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount, u = 0; v < n; v += _perVertexSize, u += 2) { + vbuf[v + 2] = uvs[u]; // u + vbuf[v + 3] = uvs[u + 1]; // v + } - newData = false; - material = _getSlotMaterial(comp, slot, attachment.region.texture._texture, premultiAlpha); + material = _getSlotMaterial(comp, slot, attachment.region.texture._texture); if (!material) { continue; } - // Check break - if (currMaterial !== material) { - if (currMaterial) { - newData = true; - data.material = currMaterial; - } - else { - // Init data material - data.material = material; - } - currMaterial = material; + + if (slotIdx == 0 || material._hash !== renderer.material._hash) { + renderer._flush(); + renderer.node = node; + renderer.material = material; } - // Request new render data and new vertex content - if (newData) { - // set old data vertex indice - data.vertexCount = vertexOffset; - data.indiceCount = indiceOffset; - // gen new data - dataId++; - data = datas[dataId]; - if (!data) { - data = datas[dataId] = comp.requestRenderData(); - } - data.dataLength = vertexCount; - data.material = currMaterial; - // reset offset - vertexOffset = 0; - indiceOffset = 0; - } + attachmentColor = attachment.color, + slotColor = slot.color; - // Fill up indices - indices = data._indices; - if (isRegion) { - indices[indiceOffset] = vertexOffset; - indices[indiceOffset + 1] = vertexOffset + 1; - indices[indiceOffset + 2] = vertexOffset + 2; - indices[indiceOffset + 3] = vertexOffset + 0; - indices[indiceOffset + 4] = vertexOffset + 2; - indices[indiceOffset + 5] = vertexOffset + 3; - } else { - let triangles = attachment.triangles; - for (let t = 0; t < triangles.length; t++) { - indices[indiceOffset + t] = vertexOffset + triangles[t]; + this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper, buffer); + + if (_indexCount > 0) { + for (let ii = _indexOffset, nn = _indexOffset + _indexCount; ii < nn; ii++) { + ibuf[ii] += _vertexOffset; } + buffer.adjust(_vertexFloatCount / _perVertexSize, _indexCount); } - indiceOffset += indiceCount; - // Fill up vertex render data - vertexOffset += this._readAttachmentData(comp, attachment, slot, premultiAlpha, data, vertexOffset); + + clipper.clipEndWithSlot(slot); } - - data.vertexCount = vertexOffset; - data.indiceCount = indiceOffset; - // Check for last data valid or not - if (vertexOffset > 0 && indiceOffset > 0) { - datas.length = dataId + 1; - } - else { - datas.length = dataId; - } - - if (comp.debugBones) { + + clipper.clipEnd(); + + if (graphics && _debugBones) { let bone; - graphics.lineWidth = 5; graphics.strokeColor = _boneColor; graphics.fillColor = _slotColor; // Root bone color is same as slot color. - + for (let i = 0, n = locSkeleton.bones.length; i < n; i++) { bone = locSkeleton.bones[i]; + if (bone.parent == null) continue; let x = bone.data.length * bone.a + bone.worldX; let y = bone.data.length * bone.c + bone.worldY; - + // Bone lengths. graphics.moveTo(bone.worldX, bone.worldY); graphics.lineTo(x, y); graphics.stroke(); - + // Bone origins. graphics.circle(bone.worldX, bone.worldY, Math.PI * 2); graphics.fill(); @@ -294,81 +425,10 @@ var spineAssembler = { } } } - }, - - updateRenderData (comp, batchData) { - let skeleton = comp._skeleton; - if (skeleton) { - skeleton.updateWorldTransform(); - this.genRenderDatas(comp, batchData); - } - else { - comp._renderDatas.length = 0; - } - }, - - fillBuffers (comp, renderer) { - let renderDatas = comp._renderDatas; - let materialCache = comp._materialCache; - for (let index = 0, length = renderDatas.length; index < length; index++) { - let data = renderDatas[index]; - - // For generate new material for skeleton render data nested in mask, - // otherwise skeleton inside/outside mask with same material will interfere each other - let key = data.material._hash; - let newKey = _updateKeyWithStencilRef(key, StencilManager.getStencilRef()); - if (key !== newKey) { - data.material = materialCache[newKey] || data.material.clone(); - data.material.updateHash(newKey); - if (!materialCache[newKey]) { - materialCache[newKey] = data.material; - } - } - - if (data.material !== renderer.material) { - renderer._flush(); - renderer.node = comp.node; - renderer.material = data.material; - } - - let vertexs = data._data; - let indices = data._indices; - - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, - vertexCount = data.vertexCount; - - let indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; - - buffer.request(vertexCount, data.indiceCount); - - // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - ibuf = buffer._iData, - uintbuf = buffer._uintVData; - - // fill vertex buffer - let vert; - for (let i = 0, l = data.dataLength; i < l; i++) { - vert = vertexs[i]; - vbuf[vertexOffset++] = vert.x; - vbuf[vertexOffset++] = vert.y; - vbuf[vertexOffset++] = vert.u; - vbuf[vertexOffset++] = vert.v; - uintbuf[vertexOffset++] = vert.color; - } - - // index buffer - for (let i = 0, l = indices.length; i < l; i ++) { - ibuf[indiceOffset++] = vertexId + indices[i]; - } - } - - comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; + } }; Skeleton._assembler = spineAssembler; -module.exports = spineAssembler; \ No newline at end of file +module.exports = spineAssembler; From d069d6d8024062dc465ca6b4e4a62a05b996a56c Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 10 Jan 2019 14:36:29 +0800 Subject: [PATCH 0388/1631] fix call onDestroy twice on fireball (#3736) --- cocos2d/core/node-activator.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/node-activator.js b/cocos2d/core/node-activator.js index 77f171cb1c1..44fe8b5b0bb 100644 --- a/cocos2d/core/node-activator.js +++ b/cocos2d/core/node-activator.js @@ -333,6 +333,7 @@ var NodeActivator = cc.Class({ if (comp.onDestroy && (comp._objFlags & IsOnLoadCalled)) { if (cc.engine._isPlaying || comp.constructor._executeInEditMode) { callOnDestroyInTryCatch(comp); + comp._objFlags &= ~IsOnLoadCalled; // In case call onDestroy twice in undo operation } } } : function (comp) { From 8db497e39809a69818983712f3bb9c148661e032 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 10 Jan 2019 17:35:58 +0800 Subject: [PATCH 0389/1631] Use packToDynamicAtlas instead of _calDynamicAtlas --- cocos2d/core/components/CCLabel.js | 14 -------------- cocos2d/core/components/CCMask.js | 15 --------------- cocos2d/core/components/CCSprite.js | 15 --------------- cocos2d/core/renderer/utils/label/ttf.js | 10 ++++++---- .../{webgl/assemblers/sprite => utils}/utils.js | 13 +++++++------ .../webgl/assemblers/sprite/2d/bar-filled.js | 9 ++------- .../renderer/webgl/assemblers/sprite/2d/mesh.js | 5 ++--- .../webgl/assemblers/sprite/2d/radial-filled.js | 6 ++---- .../renderer/webgl/assemblers/sprite/2d/simple.js | 5 ++--- .../renderer/webgl/assemblers/sprite/2d/sliced.js | 5 ++--- .../renderer/webgl/assemblers/sprite/2d/tiled.js | 5 ++--- 11 files changed, 25 insertions(+), 77 deletions(-) rename cocos2d/core/renderer/{webgl/assemblers/sprite => utils}/utils.js (50%) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index c112d68487a..56ea90b03df 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -653,20 +653,6 @@ let Label = cc.Class({ } }, - _calDynamicAtlas () { - if (!dynamicAtlasManager) return; - - if (!this._frame._original) { - let frame = dynamicAtlasManager.insertSpriteFrame(this._frame); - if (frame) { - this._frame._setDynamicAtlasFrame(frame); - } - } - if (this._material._texture !== this._frame._texture) { - this._activateMaterial(true); - } - }, - _enableBold (enabled) { this._isBold = !!enabled; }, diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 1be5526045a..73238722c7a 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -501,21 +501,6 @@ let Mask = cc.Class({ this.node._renderFlag &= ~(RenderFlow.FLAG_RENDER | RenderFlow.FLAG_UPDATE_RENDER_DATA | RenderFlow.FLAG_POST_RENDER); }, - - _calDynamicAtlas () - { - if (!this._spriteFrame) return; - - if (!this._spriteFrame._original && dynamicAtlasManager) { - let frame = dynamicAtlasManager.insertSpriteFrame(this._spriteFrame); - if (frame) { - this._spriteFrame._setDynamicAtlasFrame(frame); - } - } - if (this._material._texture !== this._spriteFrame._texture) { - this._activateMaterial(); - } - } }); cc.Mask = module.exports = Mask; diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 7ae9e4777cf..2a2205e35e7 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -655,21 +655,6 @@ var Sprite = cc.Class({ } } }, - - _calDynamicAtlas () - { - if (!this._spriteFrame) return; - - if (!this._spriteFrame._original && dynamicAtlasManager) { - let frame = dynamicAtlasManager.insertSpriteFrame(this._spriteFrame); - if (frame) { - this._spriteFrame._setDynamicAtlasFrame(frame); - } - } - if (this._material._texture !== this._spriteFrame._texture) { - this._activateMaterial(); - } - } }); if (CC_EDITOR) { diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 1c122b5c0df..41d4a387883 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -30,6 +30,7 @@ const Component = require('../../../components/CCComponent'); const Label = require('../../../components/CCLabel'); const LabelOutline = require('../../../components/CCLabelOutline'); const Overflow = Label.Overflow; +const packToDynamicAtlas = require('../utils').packToDynamicAtlas; const WHITE = cc.Color.WHITE; const OUTLINE_SUPPORTED = cc.js.isChildClassOf(LabelOutline, Component); @@ -290,13 +291,14 @@ module.exports = { }, _calDynamicAtlas (comp) { - if(!comp.batchAsBitmap) return; + if (!comp.batchAsBitmap) return; - if (!comp._frame._original) { - comp._frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height)); + let frame = comp._frame; + if (!frame._original) { + frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height)); } // Add font images to the dynamic atlas for batch rendering. - comp._calDynamicAtlas(); + packToDynamicAtlas(comp, frame); }, _updateLabelDimensions () { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/utils.js b/cocos2d/core/renderer/utils/utils.js similarity index 50% rename from cocos2d/core/renderer/webgl/assemblers/sprite/utils.js rename to cocos2d/core/renderer/utils/utils.js index 9e1637f606c..f932af9aa4c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/utils.js +++ b/cocos2d/core/renderer/utils/utils.js @@ -1,17 +1,18 @@ const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); module.exports = { - packToDynamicAtlas (sprite) { - let frame = sprite._spriteFrame; - + packToDynamicAtlas (comp, frame) { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here if (frame) { if (!frame._original && dynamicAtlasManager) { - dynamicAtlasManager.insertSpriteFrame(frame); + let packedFrame = dynamicAtlasManager.insertSpriteFrame(frame); + if (packedFrame) { + frame._setDynamicAtlasFrame(packedFrame); + } } - if (sprite.sharedMaterials[0].getProperty('texture') !== frame._texture) { - sprite._activateMaterial(); + if (comp.sharedMaterials[0].getProperty('texture') !== frame._texture) { + comp._activateMaterial(); } } } diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js index 277823561dd..9f2b1980e8c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/bar-filled.js @@ -25,17 +25,12 @@ const Sprite = require('../../../../../components/CCSprite'); const FillType = Sprite.FillType; -const utils = require('../utils'); - +const packToDynamicAtlas = require('../../../../utils/utils').packToDynamicAtlas; const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; module.exports = { updateRenderData (sprite) { - utils.packToDynamicAtlas(sprite); - - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - sprite._calDynamicAtlas(); + packToDynamicAtlas(sprite, sprite._spriteFrame); let renderData = sprite._renderData; if (!renderData || !sprite.spriteFrame) return; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js index 4cfe8f366e2..a43080d82bc 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/mesh.js @@ -24,6 +24,7 @@ ****************************************************************************/ const fillVerticesWithoutCalc = require('../../utils').fillVerticesWithoutCalc; +const packToDynamicAtlas = require('../../../../utils/utils').packToDynamicAtlas; module.exports = { createData (sprite) { @@ -31,9 +32,7 @@ module.exports = { }, updateRenderData (sprite) { - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - sprite._calDynamicAtlas(); + packToDynamicAtlas(sprite, sprite._spriteFrame); let renderData = sprite._renderData; let frame = sprite.spriteFrame; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js index 91a4625740f..9e8c4ae4707 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js @@ -24,10 +24,10 @@ ****************************************************************************/ const fillVertices = require('../../utils').fillVertices; +const packToDynamicAtlas = require('../../../../utils/utils').packToDynamicAtlas; const PI_2 = Math.PI * 2; - let _vertPos = [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)]; let _vertices = [0, 0, 0, 0]; let _uvs = [0, 0, 0, 0, 0, 0, 0, 0]; @@ -221,9 +221,7 @@ module.exports = { if (!renderData.vertDirty && !renderData.uvDirty) return; let data = renderData._data; - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - sprite._calDynamicAtlas(); + packToDynamicAtlas(sprite, frame); //do round fill start [0,1), include 0, exclude 1 while (fillStart >= 1.0) fillStart -= 1.0; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js index fc2ac403fa5..e30ea49d405 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/simple.js @@ -23,11 +23,10 @@ THE SOFTWARE. ****************************************************************************/ +const packToDynamicAtlas = require('../../../../utils/utils').packToDynamicAtlas; module.exports = { updateRenderData (sprite) { - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - sprite._calDynamicAtlas(); + packToDynamicAtlas(sprite, sprite._spriteFrame); let renderData = sprite._renderData; if (!renderData || !sprite.spriteFrame) return; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js index e6f8098b391..cbb4ccfc70c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/sliced.js @@ -23,6 +23,7 @@ THE SOFTWARE. ****************************************************************************/ +const packToDynamicAtlas = require('../../../../utils/utils').packToDynamicAtlas; module.exports = { createData (sprite) { let renderData = sprite.requestRenderData(); @@ -36,9 +37,7 @@ module.exports = { }, updateRenderData (sprite) { - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - sprite._calDynamicAtlas(); + packToDynamicAtlas(sprite, sprite._spriteFrame); let renderData = sprite._renderData; if (!renderData || !sprite.spriteFrame) return; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js index a9d8f1d1df5..88f54a04fe0 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/tiled.js @@ -23,6 +23,7 @@ THE SOFTWARE. ****************************************************************************/ +const packToDynamicAtlas = require('../../../../utils/utils').packToDynamicAtlas; module.exports = { vertexOffset: 5, uvOffset: 2, @@ -33,9 +34,7 @@ module.exports = { }, updateRenderData (sprite) { - // TODO: Material API design and export from editor could affect the material activation process - // need to update the logic here - sprite._calDynamicAtlas(); + packToDynamicAtlas(sprite, sprite._spriteFrame); let renderData = sprite._renderData; let frame = sprite.spriteFrame; From f03dc280120d815dd3b2ac33016b5bc4a43341c7 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 10 Jan 2019 17:39:39 +0800 Subject: [PATCH 0390/1631] add excludeAllDepends utils (#3714) * add excludeAllDepends utils * refine code * refine code --- gulp/tasks/engine.js | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index 25c938bacc7..85ea099f44f 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -28,6 +28,7 @@ const Utils = require('../util/utils'); const createBundler = require('../util/create-bundler'); const Path = require('path'); +const Fs = require('fs-extra'); const Source = require('vinyl-source-stream'); const Gulp = require('gulp'); @@ -386,4 +387,49 @@ exports.buildRuntimeMin = function (sourceFile, outputFile, excludes, opt_macroF .on('end', callback); }; +exports.excludeAllDepends = function (excludedModules) { + let modules = Fs.readJsonSync(Path.join(__dirname, '../../modules.json')); + if (modules && modules.length > 0) { + function _excludeMudules (muduleName) { + if (excMudules[muduleName]) { + return; + } + for (let module of modules) { + if (module.name === muduleName) { + excMudules[muduleName] = module; + break; + } + } + + modules.forEach(module => { + if (module.dependencies && module.dependencies.indexOf(muduleName) !== -1) { + _excludeMudules(module.name); + } + }); + } + + // exclude all mudules + let excMudules = Object.create(null); + + excludedModules.forEach(_excludeMudules); + + let excludes = []; + for (let key in excMudules) { + let module = excMudules[key]; + if (module.entries) { + module.entries.forEach(function (file) { + let path = Path.join(__dirname, '../engine', file); + if (excludes.indexOf(path) === -1) { + excludes.push(path); + } + }); + } + } + return excludes; + } + else { + return []; + } +}; + exports.jsbSkipModules = jsbSkipModules; From b87c2fb5ac460e878b7908a738ff0d60d8c7e9f3 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 10 Jan 2019 17:46:59 +0800 Subject: [PATCH 0391/1631] Fix merge issue --- cocos2d/core/CCNode.js | 9 --------- cocos2d/core/renderer/webgl/assemblers/utils.js | 6 ++---- cocos2d/renderer/render-data/render-data.js | 3 +-- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 95d8bb01818..f95ff6fe06d 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -3216,15 +3216,6 @@ let NodeDefines = { eventManager.pauseTarget(this); } }, - - // traversal the node tree, child cullingMask must keep the same with the parent. - _getActualGroupIndex (node) { - let groupIndex = node.groupIndex; - if (groupIndex === 0 && node.parent) { - groupIndex = this._getActualGroupIndex(node.parent); - } - return groupIndex; - }, }; if (CC_EDITOR) { diff --git a/cocos2d/core/renderer/webgl/assemblers/utils.js b/cocos2d/core/renderer/webgl/assemblers/utils.js index 7426d6925c1..ab0676b8053 100644 --- a/cocos2d/core/renderer/webgl/assemblers/utils.js +++ b/cocos2d/core/renderer/webgl/assemblers/utils.js @@ -54,8 +54,7 @@ function fillMeshVertices (node, buffer, renderData, color) { } // fill indice data - for (let i = 0, count = vertexCount / 4; i < count; i++) - { + for (let i = 0, count = vertexCount / 4; i < count; i++) { let start = vertexId + i * 4; ibuf[indiceOffset++] = start; ibuf[indiceOffset++] = start + 1; @@ -122,8 +121,7 @@ function fillMeshVertices3D (node, buffer, renderData, color) { } // fill indice data - for (let i = 0, count = vertexCount / 4; i < count; i++) - { + for (let i = 0, count = vertexCount / 4; i < count; i++) { let start = vertexId + i * 4; ibuf[indiceOffset++] = start; ibuf[indiceOffset++] = start + 1; diff --git a/cocos2d/renderer/render-data/render-data.js b/cocos2d/renderer/render-data/render-data.js index 8f161c81bbe..32fab10d26b 100644 --- a/cocos2d/renderer/render-data/render-data.js +++ b/cocos2d/renderer/render-data/render-data.js @@ -64,8 +64,7 @@ export default class RenderData extends BaseRenderData { if (width !== this._width || height !== this._height || pivotX !== this._pivotX || - pivotY !== this._pivotY) - { + pivotY !== this._pivotY) { this._width = width; this._height = height; this._pivotX = pivotX; From 54cf703be72f84ed5238455e1f44c8f01f3e92cc Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 10 Jan 2019 17:56:39 +0800 Subject: [PATCH 0392/1631] Fix require path --- cocos2d/core/renderer/utils/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/utils/utils.js b/cocos2d/core/renderer/utils/utils.js index f932af9aa4c..1a1b3002fb9 100644 --- a/cocos2d/core/renderer/utils/utils.js +++ b/cocos2d/core/renderer/utils/utils.js @@ -1,4 +1,4 @@ -const dynamicAtlasManager = require('../../../utils/dynamic-atlas/manager'); +const dynamicAtlasManager = require('./dynamic-atlas/manager'); module.exports = { packToDynamicAtlas (comp, frame) { From df3bf29164e9ea2bd47887b9fc230494e7dfc1b6 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 10 Jan 2019 20:11:54 +0800 Subject: [PATCH 0393/1631] Fix dragonbones type issue --- extensions/dragonbones/webgl-assembler.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index def30c1cfce..93c468f16c0 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -95,7 +95,6 @@ function _getSlotMaterial (comp, slot, premultiAlpha) { let _vertexOffset, _indiceOffset, _nodeR, _nodeG, _nodeB, _nodeA, - _worldMatrix; _material, _currMaterial, _dataId, _datas, _data, _newData; @@ -232,7 +231,6 @@ let armatureAssembler = { if (!armature) return; let renderDatas = comp._renderDatas; - let materialCache = comp._materialCache; for (let index = 0, length = renderDatas.length; index < length; index++) { let data = renderDatas[index]; From dc09df79bad8cc5255ebbb9f6f2c56e9d51c78de Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Thu, 10 Jan 2019 20:16:07 +0800 Subject: [PATCH 0394/1631] =?UTF-8?q?fix=20when=20use=20multiple=20dragonb?= =?UTF-8?q?ones=20texture=EF=BC=8Cmay=20not=20renderer=20bug=20(#3738)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extensions/dragonbones/lib/dragonBones.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/dragonbones/lib/dragonBones.js b/extensions/dragonbones/lib/dragonBones.js index 6552d86ce8d..fba16d6baeb 100644 --- a/extensions/dragonbones/lib/dragonBones.js +++ b/extensions/dragonbones/lib/dragonBones.js @@ -13677,7 +13677,9 @@ var dragonBones; if (imageDisplayData.texture === null) { imageDisplayData.texture = this._getTextureData(dataName, displayData.path); } - else if (dataPackage !== null && dataPackage.textureAtlasName.length > 0) { + + if (imageDisplayData.texture === null || + (dataPackage !== null && dataPackage.textureAtlasName.length > 0)) { imageDisplayData.texture = this._getTextureData(dataPackage.textureAtlasName, displayData.path); } if (rawDisplayData !== null && rawDisplayData.type === 2 /* Mesh */ && this._isSupportMesh()) { From 2a2ff156aa0f5a0d9f0531a45e94e13c96e749a5 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 10 Jan 2019 20:22:35 +0800 Subject: [PATCH 0395/1631] Fixed Label rendering issue --- cocos2d/core/components/CCLabel.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 56ea90b03df..6662249bffb 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -27,7 +27,6 @@ const macro = require('../platform/CCMacro'); const RenderComponent = require('./CCRenderComponent'); const Material = require('../assets/material/CCMaterial'); -const dynamicAtlasManager = require('../renderer/utils/dynamic-atlas/manager'); const LabelFrame = require('../renderer/utils/label/label-frame'); /** @@ -631,7 +630,7 @@ let Label = cc.Class({ else { this._srcBlendFactor = cc.macro.BlendFactor.SRC_ALPHA; } - material.setProperty('texture', this._texture); + material.setProperty('texture', this._frame._texture); this.setMaterial(0, material); } From e4a42ca843d832110716c49ff9eedbcfd2d3fb77 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Thu, 10 Jan 2019 22:30:38 +0800 Subject: [PATCH 0396/1631] move _childArrivalOrder to Ctor (#3741) --- cocos2d/core/CCNode.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 98daff3dc0a..ecf647278b6 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -574,7 +574,7 @@ var Node = cc.Class({ default: 0, serializable: false }, - _childArrivalOrder: 1, + // internal properties @@ -1161,6 +1161,7 @@ var Node = cc.Class({ this._eventMask = 0; this._cullingMask = 1; + this._childArrivalOrder = 1; }, statics: { From 84de706d49378d8959ca19f616cf024d4bccdede Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 11 Jan 2019 10:43:45 +0800 Subject: [PATCH 0397/1631] fix mask _hitTest invalid (#3743) --- cocos2d/core/components/CCMask.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 4e7c0425686..4de028dbca0 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -465,14 +465,19 @@ let Mask = cc.Class({ testPt.x += node._anchorPoint.x * w; testPt.y += node._anchorPoint.y * h; + let result = false; if (this.type === MaskType.RECT || this.type === MaskType.IMAGE_STENCIL) { - return testPt.x >= 0 && testPt.y >= 0 && testPt.x <= w && testPt.y <= h; + result = testPt.x >= 0 && testPt.y >= 0 && testPt.x <= w && testPt.y <= h; } else if (this.type === MaskType.ELLIPSE) { let rx = w / 2, ry = h / 2; let px = testPt.x - 0.5 * w, py = testPt.y - 0.5 * h; - return px * px / (rx * rx) + py * py / (ry * ry) < 1; + reult = px * px / (rx * rx) + py * py / (ry * ry) < 1; } + if (this.inverted) { + result = !result; + } + return result; }, markForUpdateRenderData (enable) { From f93457709da42e367c1e33970d489b6db94d9b2b Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Fri, 11 Jan 2019 11:25:38 +0800 Subject: [PATCH 0398/1631] compatible vec3 prop methods (#3737) --- cocos2d/core/value-types/vec2.js | 2 + cocos2d/core/value-types/vec3.js | 82 +++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/value-types/vec2.js b/cocos2d/core/value-types/vec2.js index 8ba14000d14..9b36f476fc7 100644 --- a/cocos2d/core/value-types/vec2.js +++ b/cocos2d/core/value-types/vec2.js @@ -68,6 +68,8 @@ CCClass.fastDefine('cc.Vec2', Vec2, { x: 0, y: 0 }); var proto = Vec2.prototype; +// compatible with vec3 +js.value(proto, 'z', 0); /** * !#en clone a Vec2 object diff --git a/cocos2d/core/value-types/vec3.js b/cocos2d/core/value-types/vec3.js index 4bbf3e7694e..ffaab06cb74 100644 --- a/cocos2d/core/value-types/vec3.js +++ b/cocos2d/core/value-types/vec3.js @@ -29,6 +29,7 @@ const js = require('../platform/js'); const CCClass = require('../platform/CCClass'); const math = require('../renderer/render-engine').math; const misc = require('../utils/misc'); +const Vec2 = require('./vec2'); /** * !#en Representation of 3D vectors and points. @@ -447,14 +448,91 @@ proto.normalize = function (out) { * Transforms the vec3 with a mat4. 4th vector component is implicitly '1' * @method transformMat4 * @param {mat4} m matrix to transform with - * @param {vec3} [out] the receiving vector, you can pass the same vec3 to save result to itself, if not provided, a new vec3 will be created - * @returns {vec3} out + * @param {Vec3} [out] the receiving vector, you can pass the same vec3 to save result to itself, if not provided, a new vec3 will be created + * @returns {Vec3} out */ proto.transformMat4 = function (m, out) { out = out || new Vec3(); math.vec3.transformMat4(out, this, m); }; +/** + * !#en Get angle in radian between this and vector. + * !#zh 夹角的弧度。 + * @method angle + * @param {Vec3} vector + * @return {number} from 0 to Math.PI + */ +proto.angle = Vec2.angle; + +/** + * !#en Calculates the projection of the current vector over the given vector. + * !#zh 返回当前向量在指定 vector 向量上的投影向量。 + * @method project + * @param {Vec3} vector + * @return {Vec3} + * @example + * var v1 = cc.v3(20, 20, 20); + * var v2 = cc.v3(5, 5, 5); + * v1.project(v2); // Vec3 {x: 20, y: 20, z: 20}; + */ +proto.project = Vec2.project; + +/** + * !#en return a Vec3 object with x = 1, y = 1, z = 1. + * !#zh 新 Vec3 对象。 + * @property ONE + * @type Vec3 + * @static + */ +js.get(Vec3, 'ONE', function () { + return new Vec3(1.0, 1.0, 1.0); +}); + +/** + * !#en return a Vec3 object with x = 0, y = 0, z = 0. + * !#zh 返回 x = 0,y = 0,z = 0 的 Vec3 对象。 + * @property ZERO + * @type Vec3 + * @static + */ +js.get(Vec3, 'ZERO', function () { + return new Vec3(0.0, 0.0, 0.0); +}); + +/** + * !#en return a Vec3 object with x = 0, y = 1, z = 0. + * !#zh 返回 x = 0, y = 1, z = 0 的 Vec3 对象。 + * @property UP + * @type Vec3 + * @static + */ +js.get(Vec3, 'UP', function () { + return new Vec3(0.0, 1.0, 0.0); +}); + +/** + * !#en return a Vec3 object with x = 1, y = 0, z = 0. + * !#zh 返回 x = 1,y = 0,z = 0 的 Vec3 对象。 + * @property RIGHT + * @type Vec3 + * @static + */ +js.get(Vec3, 'RIGHT', function () { + return new Vec3(1.0, 0.0, 0.0); +}); + +/** + * !#en return a Vec3 object with x = 0, y = 0, z = 1. + * !#zh 返回 x = 0,y = 0,z = 1 的 Vec3 对象。 + * @property FRONT + * @type Vec3 + * @static + */ +js.get(Vec3, 'FRONT', function () { + return new Vec3(0.0, 0.0, 1.0); +}); + /** * !#en The convenience method to create a new {{#crossLink "Vec3"}}cc.Vec3{{/crossLink}}. * !#zh 通过该简便的函数进行创建 {{#crossLink "Vec3"}}cc.Vec3{{/crossLink}} 对象。 From 6c28860522469f9ccfe33ca18767bcec5813ef57 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Fri, 11 Jan 2019 11:30:07 +0800 Subject: [PATCH 0399/1631] fix spine may not flush bug (#3742) * fix spine not flush bug * fix spine not flush bug --- extensions/spine/spine-assembler.js | 50 ++++++++++++++++------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 599c28c81f5..5d2d383a1af 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -116,9 +116,6 @@ function _getSlotMaterial (comp, slot, tex) { gfx.BLEND_FUNC_ADD, src, dst ); - if (materialCache[material._hash]) { - delete materialCache[material._hash]; - } material.updateHash(key); materialCache[key] = material; } @@ -255,6 +252,8 @@ var spineAssembler = { let clipper = comp._clipper; let material = null; let attachment, attachmentColor, slotColor, uvs, triangles; + let hasFlush = false; + let isRegion, isMesh, isClip; _premultipliedAlpha = comp.premultipliedAlpha; _multiplier = 1.0; @@ -309,7 +308,30 @@ var spineAssembler = { attachment = slot.getAttachment(); if (!attachment) continue; - if (attachment instanceof spine.RegionAttachment) { + isRegion = attachment instanceof spine.RegionAttachment; + isMesh = attachment instanceof spine.MeshAttachment; + isClip = attachment instanceof spine.ClippingAttachment; + + if (isClip) { + clipper.clipStart(slot, attachment); + continue; + } + + if (!isRegion && !isMesh) continue; + + material = _getSlotMaterial(comp, slot, attachment.region.texture._texture); + if (!material) { + continue; + } + + if (!hasFlush || material._hash !== renderer.material._hash) { + hasFlush = true; + renderer._flush(); + renderer.node = node; + renderer.material = material; + } + + if (isRegion) { triangles = _quadTriangles; @@ -335,7 +357,7 @@ var spineAssembler = { graphics.stroke(); } } - else if (attachment instanceof spine.MeshAttachment) { + else if (isMesh) { triangles = attachment.triangles; @@ -351,13 +373,6 @@ var spineAssembler = { // compute vertex and fill x y attachment.computeWorldVertices(slot, 0, attachment.worldVerticesLength, vbuf, _vertexFloatOffset, _perVertexSize); } - else if (attachment instanceof spine.ClippingAttachment) { - clipper.clipStart(slot, attachment); - continue; - } - else { - continue; - } if (_vertexFloatCount == 0 || _indexCount == 0) { continue; @@ -373,17 +388,6 @@ var spineAssembler = { vbuf[v + 3] = uvs[u + 1]; // v } - material = _getSlotMaterial(comp, slot, attachment.region.texture._texture); - if (!material) { - continue; - } - - if (slotIdx == 0 || material._hash !== renderer.material._hash) { - renderer._flush(); - renderer.node = node; - renderer.material = material; - } - attachmentColor = attachment.color, slotColor = slot.color; From 5419ff70158b254322b038b3d7d53be27a95dd1c Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 11 Jan 2019 11:54:54 +0800 Subject: [PATCH 0400/1631] Use RenderFlow to drive scene visit process (#3740) * Use RenderFlow to drive scene visit process (#3370) * Use RenderFlow to drive scene visit process * Fix tests * Remove useless code * Improve batcher walking setting * Fix vec3 undefined issue --- cocos2d/core/camera/CCCamera.js | 3 +- cocos2d/core/renderer/canvas/index.js | 2 +- ...r-walker.js => render-component-handle.js} | 39 +++++------ cocos2d/core/renderer/index.js | 20 +++--- cocos2d/core/renderer/render-flow.js | 67 ++++++++++--------- .../webgl/assemblers/graphics/impl.js | 2 +- cocos2d/core/renderer/webgl/mesh-buffer.js | 14 ++-- ...r-component-walker.js => model-batcher.js} | 36 +++------- cocos2d/particle/particle-system-assembler.js | 2 +- modules.json | 2 +- 10 files changed, 90 insertions(+), 97 deletions(-) rename cocos2d/core/renderer/canvas/{canvas-render-walker.js => render-component-handle.js} (84%) rename cocos2d/core/renderer/webgl/{render-component-walker.js => model-batcher.js} (89%) diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 6ad76444bda..76866cc19e5 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -27,6 +27,7 @@ const AffineTrans = require('../utils/affine-transform'); const renderEngine = require('../renderer/render-engine'); const renderer = require('../renderer/index'); +const RenderFlow = require('../renderer/render-flow'); const game = require('../CCGame'); const mat4 = cc.vmath.mat4; @@ -499,7 +500,7 @@ let Camera = cc.Class({ // force update node world matrix this.node.getWorldMatrix(_mat4_temp_1); this.beforeDraw(); - renderer._walker.visit(root); + RenderFlow.visit(root); renderer._forward.renderCamera(this._camera, renderer.scene); }, diff --git a/cocos2d/core/renderer/canvas/index.js b/cocos2d/core/renderer/canvas/index.js index ee89ef484ba..73e553b574e 100644 --- a/cocos2d/core/renderer/canvas/index.js +++ b/cocos2d/core/renderer/canvas/index.js @@ -25,6 +25,6 @@ module.exports = { ForwardRenderer: require('./forward-renderer'), - RenderComponentWalker: require('./canvas-render-walker'), + RenderComponentHandle: require('./render-component-handle'), _renderers: require('./renderers') }; \ No newline at end of file diff --git a/cocos2d/core/renderer/canvas/canvas-render-walker.js b/cocos2d/core/renderer/canvas/render-component-handle.js similarity index 84% rename from cocos2d/core/renderer/canvas/canvas-render-walker.js rename to cocos2d/core/renderer/canvas/render-component-handle.js index 9906b1de5d2..78b87d9e153 100644 --- a/cocos2d/core/renderer/canvas/canvas-render-walker.js +++ b/cocos2d/core/renderer/canvas/render-component-handle.js @@ -23,11 +23,9 @@ THE SOFTWARE. ****************************************************************************/ -const js = require('../../platform/js'); -const RenderFlow = require('../render-flow'); require('./renderers'); -let RenderComponentWalker = function (device, defaultCamera) { +let RenderComponentHandle = function (device, defaultCamera) { this._device = device; // let vx = this._device._vx; // let vy = this._device._vy; @@ -37,36 +35,35 @@ let RenderComponentWalker = function (device, defaultCamera) { this.parentOpacity = 1; this.parentOpacityDirty = 0; this.worldMatDirty = 0; - - RenderFlow.init(this); + this.walking = false; }; -RenderComponentWalker.prototype = { - constructor: RenderComponentWalker, +RenderComponentHandle.prototype = { + constructor: RenderComponentHandle, - reset() {}, - - _commitComp (comp, assembler) { - let ctx = this._device._ctx; - let cam = this._camera; - ctx.setTransform(cam.a, cam.b, cam.c, cam.d, cam.tx, cam.ty); - ctx.scale(1, -1); - assembler.draw(ctx, comp); - }, - - visit (scene) { + reset() { let ctx = this._device._ctx; let canvas = this._device._canvas; - let color = cc.Camera.main.backgroundColor; + var color = cc.Camera.main ? cc.Camera.main.backgroundColor : cc.color(); let rgba = `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a/255})`; ctx.fillStyle = rgba; ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height); this._device._stats.drawcalls = 0; + }, + + terminate () { + this.walking = false; + }, - RenderFlow.render(scene); + _commitComp (comp, assembler) { + let ctx = this._device._ctx; + let cam = this._camera; + ctx.setTransform(cam.a, cam.b, cam.c, cam.d, cam.tx, cam.ty); + ctx.scale(1, -1); + assembler.draw(ctx, comp); } }; -module.exports = RenderComponentWalker; \ No newline at end of file +module.exports = RenderComponentHandle; \ No newline at end of file diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index a0ccc9c12a7..20e993a1980 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -24,9 +24,10 @@ ****************************************************************************/ const renderEngine = require('./render-engine'); -const math = renderEngine.math; +const RenderFlow = require('./render-flow'); +const vec3 = cc.vmath.vec3; -let _pos = math.vec3.create(); +let _pos = vec3.create(); function _initBuiltins(device) { let defaultTexture = new renderEngine.Texture2D(device, { @@ -92,14 +93,15 @@ cc.renderer = module.exports = { * @type {Number} */ drawCalls: 0, - _walker: null, + // Render component handler + _handle: null, _cameraNode: null, _camera: null, _forward: null, initWebGL (canvas, opts) { require('./webgl/assemblers'); - const RenderComponentWalker = require('./webgl/render-component-walker'); + const ModelBatcher = require('./webgl/model-batcher'); this.Texture2D = renderEngine.Texture2D; @@ -114,7 +116,8 @@ cc.renderer = module.exports = { this.scene = new renderEngine.Scene(); - this._walker = new RenderComponentWalker(this.device, this.scene); + this._handle = new ModelBatcher(this.device, this.scene); + RenderFlow.init(this._handle); if (CC_EDITOR) { this._cameraNode = new cc.Node(); @@ -159,7 +162,8 @@ cc.renderer = module.exports = { this._camera = { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }; - this._walker = new canvasRenderer.RenderComponentWalker(this.device, this._camera); + this._handle = new canvasRenderer.RenderComponentHandle(this.device, this._camera); + RenderFlow.init(this._handle); this._forward = new canvasRenderer.ForwardRenderer(); }, @@ -198,7 +202,7 @@ cc.renderer = module.exports = { this.device._stats.drawcalls = 0; if (ecScene) { // walk entity component scene to generate models - this._walker.visit(ecScene); + RenderFlow.visit(ecScene); // Render models in renderer scene this._forward.render(this.scene); this.drawCalls = this.device._stats.drawcalls; @@ -206,7 +210,7 @@ cc.renderer = module.exports = { }, clear () { - this._walker.reset(); + this._handle.reset(); this._forward._reset(); } }; \ No newline at end of file diff --git a/cocos2d/core/renderer/render-flow.js b/cocos2d/core/renderer/render-flow.js index 0c0edd2c967..b4488e3ce69 100644 --- a/cocos2d/core/renderer/render-flow.js +++ b/cocos2d/core/renderer/render-flow.js @@ -12,7 +12,8 @@ const POST_UPDATE_RENDER_DATA = 1 << 8; const POST_RENDER = 1 << 9; const FINAL = 1 << 10; -let _walker = null; +let _batcher; +let _cullingMask = 0; function RenderFlow () { this._func = init; @@ -51,7 +52,7 @@ function mul (out, a, b) { } _proto._worldTransform = function (node) { - _walker.worldMatDirty ++; + _batcher.worldMatDirty ++; let t = node._matrix; let position = node._position; @@ -62,7 +63,7 @@ _proto._worldTransform = function (node) { node._renderFlag &= ~WORLD_TRANSFORM; this._next._func(node); - _walker.worldMatDirty --; + _batcher.worldMatDirty --; }; _proto._color = function (node) { @@ -77,12 +78,12 @@ _proto._color = function (node) { }; _proto._opacity = function (node) { - _walker.parentOpacityDirty++; + _batcher.parentOpacityDirty++; node._renderFlag &= ~OPACITY; this._next._func(node); - _walker.parentOpacityDirty--; + _batcher.parentOpacityDirty--; }; _proto._updateRenderData = function (node) { @@ -94,22 +95,25 @@ _proto._updateRenderData = function (node) { _proto._render = function (node) { let comp = node._renderComponent; - _walker._commitComp(comp, comp._assembler, node._cullingMask); + _batcher._commitComp(comp, comp._assembler, node._cullingMask); this._next._func(node); }; _proto._customIARender = function (node) { let comp = node._renderComponent; - _walker._commitIA(comp, comp._assembler, node._cullingMask); + _batcher._commitIA(comp, comp._assembler, node._cullingMask); this._next._func(node); }; _proto._children = function (node) { - let parentOpacity = _walker.parentOpacity; - let opacity = (_walker.parentOpacity *= (node._opacity / 255)); + let cullingMask = _cullingMask; + let batcher = _batcher; - let worldTransformFlag = _walker.worldMatDirty ? WORLD_TRANSFORM : 0; - let worldOpacityFlag = _walker.parentOpacityDirty ? COLOR : 0; + let parentOpacity = batcher.parentOpacity; + let opacity = (batcher.parentOpacity *= (node._opacity / 255)); + + let worldTransformFlag = batcher.worldMatDirty ? WORLD_TRANSFORM : 0; + let worldOpacityFlag = batcher.parentOpacityDirty ? COLOR : 0; let worldDirtyFlag = worldTransformFlag | worldOpacityFlag; let children = node._children; @@ -126,7 +130,7 @@ _proto._children = function (node) { c._color._val = colorVal; } - _walker.parentOpacity = parentOpacity; + batcher.parentOpacity = parentOpacity; this._next._func(node); }; @@ -140,7 +144,7 @@ _proto._postUpdateRenderData = function (node) { _proto._postRender = function (node) { let comp = node._renderComponent; - _walker._commitComp(comp, comp._postAssembler, node._cullingMask); + _batcher._commitComp(comp, comp._postAssembler, node._cullingMask); this._next._func(node); }; @@ -204,38 +208,41 @@ function getFlow (flag) { return flow; } +// +function init (node) { + let flag = node._renderFlag; + let r = flows[flag] = getFlow(flag); + r._func(node); +} + +RenderFlow.flows = flows; +RenderFlow.createFlow = createFlow; +RenderFlow.visit = function (scene) { + _batcher.reset(); + _batcher.walking = true; + + _cullingMask = 1 << scene.groupIndex; -function render (scene) { if (scene._renderFlag & WORLD_TRANSFORM) { - _walker.worldMatDirty ++; + _batcher.worldMatDirty ++; scene._calculWorldMatrix(); scene._renderFlag &= ~WORLD_TRANSFORM; flows[scene._renderFlag]._func(scene); - _walker.worldMatDirty --; + _batcher.worldMatDirty --; } else { flows[scene._renderFlag]._func(scene); } -} -// -function init (node) { - let flag = node._renderFlag; - let r = flows[flag] = getFlow(flag); - r._func(node); -} - -RenderFlow.flows = flows; -RenderFlow.createFlow = createFlow; -RenderFlow.render = render; + _batcher.terminate(); +}; -RenderFlow.init = function (walker) { - _walker = walker; +RenderFlow.init = function (batcher) { + _batcher = batcher; flows[0] = EMPTY_FLOW; - for (let i = 1; i < FINAL; i++) { flows[i] = new RenderFlow(); } diff --git a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js index f66d48931bb..76946c8a764 100644 --- a/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js +++ b/cocos2d/core/renderer/webgl/assemblers/graphics/impl.js @@ -217,7 +217,7 @@ cc.js.mixin(Impl.prototype, { requestRenderData () { let renderData = new IARenderData(); - let meshbuffer = new MeshBuffer(renderer._walker, vfmtPosColor); + let meshbuffer = new MeshBuffer(renderer._handle, vfmtPosColor); renderData.meshbuffer = meshbuffer; this._renderDatas.push(renderData); diff --git a/cocos2d/core/renderer/webgl/mesh-buffer.js b/cocos2d/core/renderer/webgl/mesh-buffer.js index e8e7e3a530a..0d49d4bc915 100644 --- a/cocos2d/core/renderer/webgl/mesh-buffer.js +++ b/cocos2d/core/renderer/webgl/mesh-buffer.js @@ -3,7 +3,7 @@ const gfx = renderEngine.gfx; let MeshBuffer = cc.Class({ name: 'cc.MeshBuffer', - ctor (renderer, vertexFormat) { + ctor (batcher, vertexFormat) { this.byteStart = 0; this.byteOffset = 0; this.indiceStart = 0; @@ -15,7 +15,7 @@ let MeshBuffer = cc.Class({ this._vertexBytes = this._vertexFormat._bytes; this._vb = new gfx.VertexBuffer( - renderer._device, + batcher._device, vertexFormat, gfx.USAGE_DYNAMIC, new ArrayBuffer(), @@ -23,7 +23,7 @@ let MeshBuffer = cc.Class({ ); this._ib = new gfx.IndexBuffer( - renderer._device, + batcher._device, gfx.INDEX_FMT_UINT16, gfx.USAGE_STATIC, new ArrayBuffer(), @@ -34,7 +34,7 @@ let MeshBuffer = cc.Class({ this._iData = null; this._uintVData = null; - this._renderer = renderer; + this._batcher = batcher; this._initVDataCount = 256 * vertexFormat._bytes; // actually 256 * 4 * (vertexFormat._bytes / 4) this._initIDataCount = 256 * 6; @@ -87,9 +87,9 @@ let MeshBuffer = cc.Class({ }, request (vertexCount, indiceCount) { - if (this._renderer._buffer !== this) { - this._renderer._flush(); - this._renderer._buffer = this; + if (this._batcher._buffer !== this) { + this._batcher._flush(); + this._batcher._buffer = this; } this.requestStatic(vertexCount, indiceCount); diff --git a/cocos2d/core/renderer/webgl/render-component-walker.js b/cocos2d/core/renderer/webgl/model-batcher.js similarity index 89% rename from cocos2d/core/renderer/webgl/render-component-walker.js rename to cocos2d/core/renderer/webgl/model-batcher.js index 121d8707818..54a73616a74 100644 --- a/cocos2d/core/renderer/webgl/render-component-walker.js +++ b/cocos2d/core/renderer/webgl/model-batcher.js @@ -23,35 +23,24 @@ THE SOFTWARE. ****************************************************************************/ -const macro = require('../../platform/CCMacro'); const renderEngine = require('../render-engine'); const defaultVertexFormat = require('./vertex-format').vfmtPosUvColor; const StencilManager = require('./stencil-manager'); -const dynamicAtlasManager = require('../utils/dynamic-atlas/manager'); -const RenderFlow = require('../render-flow'); const QuadBuffer = require('./quad-buffer'); const MeshBuffer = require('./mesh-buffer'); const SpineBuffer = require('./spine-buffer'); let idGenerater = new (require('../../platform/id-generater'))('VertextFormat'); -const gfx = renderEngine.gfx; const RecyclePool = renderEngine.RecyclePool; const InputAssembler = renderEngine.InputAssembler; -const FLOATS_PER_VERT = defaultVertexFormat._bytes / 4; -const BYTE_PER_INDEX = 2; -const MAX_VERTEX = macro.BATCH_VERTEX_COUNT; -const MAX_VERTEX_BYTES = MAX_VERTEX * defaultVertexFormat._bytes; -const MAX_INDICE = MAX_VERTEX * BYTE_PER_INDEX; -const MAX_INDICE_BYTES = MAX_INDICE * 2; - let _buffers = {}; const empty_material = new renderEngine.Material(); empty_material.updateHash(); -var RenderComponentWalker = function (device, renderScene) { +var ModelBatcher = function (device, renderScene) { this._renderScene = renderScene; this._device = device; this._stencilMgr = StencilManager.sharedManager; @@ -82,12 +71,10 @@ var RenderComponentWalker = function (device, renderScene) { this.parentOpacity = 1; this.parentOpacityDirty = 0; this.worldMatDirty = 0; - - RenderFlow.init(this); }; -RenderComponentWalker.prototype = { - constructor: RenderComponentWalker, +ModelBatcher.prototype = { + constructor: ModelBatcher, reset() { // Reset pools @@ -208,21 +195,18 @@ RenderComponentWalker.prototype = { assembler.renderIA(comp, this); }, - visit (scene) { - this.reset(); - this.walking = true; - - RenderFlow.render(scene); - - if (dynamicAtlasManager) { - dynamicAtlasManager.update(); + terminate () { + if (cc.dynamicAtlasManager && cc.dynamicAtlasManager.enabled) { + cc.dynamicAtlasManager.update(); } - + + // flush current rest Model this._flush(); for (let key in _buffers) { _buffers[key].uploadData(); } + this.walking = false; }, @@ -255,4 +239,4 @@ RenderComponentWalker.prototype = { } } -module.exports = RenderComponentWalker; \ No newline at end of file +module.exports = ModelBatcher; \ No newline at end of file diff --git a/cocos2d/particle/particle-system-assembler.js b/cocos2d/particle/particle-system-assembler.js index d99be29df89..d9968d1229c 100644 --- a/cocos2d/particle/particle-system-assembler.js +++ b/cocos2d/particle/particle-system-assembler.js @@ -38,7 +38,7 @@ var particleSystemAssembler = { comp._vertexFormat = vfmtPosUvColor; // Create quad buffer for vertex and index - comp._buffer = new QuadBuffer(renderer._walker, vfmtPosUvColor); + comp._buffer = new QuadBuffer(renderer._handle, vfmtPosUvColor); comp._ia = new renderEngine.InputAssembler(); comp._ia._vertexBuffer = comp._buffer._vb; diff --git a/modules.json b/modules.json index 9b598fb8c38..d77fcf651d4 100644 --- a/modules.json +++ b/modules.json @@ -34,7 +34,7 @@ { "name": "WebGL Renderer", "entries": [ - "./cocos2d/core/renderer/webgl/render-component-walker.js", + "./cocos2d/core/renderer/webgl/model-batcher.js", "./cocos2d/core/renderer/webgl/assemblers/index.js", "./extensions/dragonbones/webgl-assembler.js" ] From 830bfbebe2734cdd4a2aa18d72b8319019289cb7 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Fri, 11 Jan 2019 14:32:47 +0800 Subject: [PATCH 0401/1631] fix spine debug draw recreate bug (#3744) * fix spine debug draw recreate bug * fix spine debug draw recreate bug --- extensions/spine/Skeleton.js | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 65a24839cc3..a5660f2b0b2 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -336,7 +336,7 @@ sp.Skeleton = cc.Class({ editorOnly: true, tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.debug_slots', notify () { - this._initDebugDraw(); + this._updateDebugDraw(); } }, @@ -351,7 +351,7 @@ sp.Skeleton = cc.Class({ editorOnly: true, tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.debug_bones', notify () { - this._initDebugDraw(); + this._updateDebugDraw(); } }, @@ -365,13 +365,7 @@ sp.Skeleton = cc.Class({ default: false, tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.use_tint', notify () { - var cache = this._materialCache - for (var mKey in cache) { - var material = cache[mKey]; - if (material) { - material.useTint = this.useTint; - } - } + this._updateUseTint(); } } }, @@ -395,6 +389,16 @@ sp.Skeleton = cc.Class({ this._materialCache = {}; }, + _updateUseTint () { + var cache = this._materialCache + for (var mKey in cache) { + var material = cache[mKey]; + if (material) { + material.useTint = this.useTint; + } + } + }, + /** * !#en * Sets runtime skeleton data to sp.Skeleton.
@@ -455,6 +459,17 @@ sp.Skeleton = cc.Class({ } this._updateSkeletonData(); + + var children = this.node.children; + for (var i = 0, n = children.length; i < n; i++) { + var child = children[i]; + if (child && child._name === "DEBUG_DRAW_NODE" ) { + child.destroy(); + } + } + + this._updateDebugDraw(); + this._updateUseTint(); }, update (dt) { @@ -979,7 +994,7 @@ sp.Skeleton = cc.Class({ Editor.Utils.refreshSelectedInspector('node', this.node.uuid); }, - _initDebugDraw: function () { + _updateDebugDraw: function () { if (this.debugBones || this.debugSlots) { if (!this._debugRenderer) { let debugDrawNode = new cc.PrivateNode(); From a2b9c2ab3e44b09e94b862afc3ed0100c05e2f08 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 11 Jan 2019 14:53:21 +0800 Subject: [PATCH 0402/1631] fix dragonBones eventManager undefined for 2d-tasks/issues/1034 (#3745) --- extensions/dragonbones/CCFactory.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index 687da520443..9ee9b623157 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -55,7 +55,8 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ }, ctor () { - this._dragonBones = new dragonBones.DragonBones(); + let eventManager = new dragonBones.CCArmatureDisplay(); + this._dragonBones = new dragonBones.DragonBones(eventManager); if (!CC_JSB && !CC_EDITOR && cc.director._scheduler) { cc.game.on(cc.game.EVENT_RESTART, this.initUpdate, this); From 1dd21f6b231e92983d7a31ab11bded5ea1892681 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 14 Jan 2019 16:12:29 +0800 Subject: [PATCH 0403/1631] add 3d primitive (#3748) * add 3d primitive * add light inspector * refine mesh * remove unused code * add a_color to phong shader * fixed shadow * add primitve module --- cocos2d/core/3d/CCLightComponent.js | 3 +- cocos2d/core/3d/index.js | 1 + cocos2d/core/3d/primitive/box.js | 130 ++++++++++ cocos2d/core/3d/primitive/capsule.js | 203 +++++++++++++++ cocos2d/core/3d/primitive/cone.js | 16 ++ cocos2d/core/3d/primitive/cylinder.js | 237 ++++++++++++++++++ cocos2d/core/3d/primitive/index.js | 20 ++ cocos2d/core/3d/primitive/plane.js | 75 ++++++ cocos2d/core/3d/primitive/quad.js | 46 ++++ cocos2d/core/3d/primitive/sphere.js | 67 +++++ cocos2d/core/3d/primitive/torus.js | 69 +++++ cocos2d/core/3d/primitive/utils.js | 65 +++++ cocos2d/core/mesh/CCMesh.js | 12 + cocos2d/core/mesh/CCMeshRenderer.js | 1 + cocos2d/renderer/build/build-chunks.js | 20 -- cocos2d/renderer/build/build-shader.js | 104 -------- cocos2d/renderer/build/chunks/index.js | 17 -- cocos2d/renderer/build/chunks/phong-fs.inc | 35 +-- cocos2d/renderer/build/chunks/phong-vs.inc | 13 +- .../renderer/build/chunks/shadow-mapping.inc | 76 +++--- cocos2d/renderer/scene/light.js | 14 +- modules.json | 7 + 22 files changed, 1033 insertions(+), 198 deletions(-) create mode 100644 cocos2d/core/3d/primitive/box.js create mode 100644 cocos2d/core/3d/primitive/capsule.js create mode 100644 cocos2d/core/3d/primitive/cone.js create mode 100644 cocos2d/core/3d/primitive/cylinder.js create mode 100644 cocos2d/core/3d/primitive/index.js create mode 100644 cocos2d/core/3d/primitive/plane.js create mode 100644 cocos2d/core/3d/primitive/quad.js create mode 100644 cocos2d/core/3d/primitive/sphere.js create mode 100644 cocos2d/core/3d/primitive/torus.js create mode 100644 cocos2d/core/3d/primitive/utils.js delete mode 100644 cocos2d/renderer/build/build-chunks.js delete mode 100644 cocos2d/renderer/build/build-shader.js delete mode 100644 cocos2d/renderer/build/chunks/index.js diff --git a/cocos2d/core/3d/CCLightComponent.js b/cocos2d/core/3d/CCLightComponent.js index e933ce3997d..297776d2fb3 100644 --- a/cocos2d/core/3d/CCLightComponent.js +++ b/cocos2d/core/3d/CCLightComponent.js @@ -31,7 +31,7 @@ import { toRadian } from '../vmath'; const renderer = require('../renderer/index'); const Enum = require('../platform/CCEnum'); const CCComponent = require('../components/CCComponent'); -const { ccclass, menu, property, executeInEditMode } = require('../platform/CCClassDecorator'); +const { ccclass, menu, inspector, property, executeInEditMode } = require('../platform/CCClassDecorator'); /** * !#en The light source type @@ -117,6 +117,7 @@ const LightShadowType = Enum({ @ccclass('cc.LightComponent') @menu('i18n:MAIN_MENU.component.renderers/LightComponent') @executeInEditMode +@inspector('packages://inspector/inspectors/comps/light.js') export default class LightComponent extends CCComponent { @property _type = LightType.DIRECTIONAL; diff --git a/cocos2d/core/3d/index.js b/cocos2d/core/3d/index.js index dcdd71098bf..eb1c71fc90c 100644 --- a/cocos2d/core/3d/index.js +++ b/cocos2d/core/3d/index.js @@ -2,6 +2,7 @@ if (!CC_TEST && (!CC_EDITOR || !Editor.isMainProcess)) { require('./polyfill-3d'); require('./geom-utils'); + require('./primitive'); } require('./CCModel'); diff --git a/cocos2d/core/3d/primitive/box.js b/cocos2d/core/3d/primitive/box.js new file mode 100644 index 00000000000..21446fb5677 --- /dev/null +++ b/cocos2d/core/3d/primitive/box.js @@ -0,0 +1,130 @@ +'use strict'; + +import { vec3 } from '../../vmath'; + +let temp1 = vec3.create(0, 0, 0); +let temp2 = vec3.create(0, 0, 0); +let temp3 = vec3.create(0, 0, 0); +let r = vec3.create(0, 0, 0); +let c0 = vec3.create(0, 0, 0); +let c1 = vec3.create(0, 0, 0); +let c2 = vec3.create(0, 0, 0); +let c3 = vec3.create(0, 0, 0); +let c4 = vec3.create(0, 0, 0); +let c5 = vec3.create(0, 0, 0); +let c6 = vec3.create(0, 0, 0); +let c7 = vec3.create(0, 0, 0); + +/** + * @param {Number} width + * @param {Number} height + * @param {Number} length + * @param {Object} opts + * @param {Number} opts.widthSegments + * @param {Number} opts.heightSegments + * @param {Number} opts.lengthSegments + */ +export default function (width = 1, height = 1, length = 1, opts = {}) { + let ws = opts.widthSegments !== undefined ? opts.widthSegments : 1; + let hs = opts.heightSegments !== undefined ? opts.heightSegments : 1; + let ls = opts.lengthSegments !== undefined ? opts.lengthSegments : 1; + let inv = opts.invWinding !== undefined ? opts.invWinding : false; + + let hw = width * 0.5; + let hh = height * 0.5; + let hl = length * 0.5; + + let corners = [ + vec3.set(c0, -hw, -hh, hl), + vec3.set(c1, hw, -hh, hl), + vec3.set(c2, hw, hh, hl), + vec3.set(c3, -hw, hh, hl), + vec3.set(c4, hw, -hh, -hl), + vec3.set(c5, -hw, -hh, -hl), + vec3.set(c6, -hw, hh, -hl), + vec3.set(c7, hw, hh, -hl), + ]; + + let faceAxes = [ + [ 2, 3, 1 ], // FRONT + [ 4, 5, 7 ], // BACK + [ 7, 6, 2 ], // TOP + [ 1, 0, 4 ], // BOTTOM + [ 1, 4, 2 ], // RIGHT + [ 5, 0, 6 ] // LEFT + ]; + + let faceNormals = [ + [ 0, 0, 1 ], // FRONT + [ 0, 0, -1 ], // BACK + [ 0, 1, 0 ], // TOP + [ 0, -1, 0 ], // BOTTOM + [ 1, 0, 0 ], // RIGHT + [ -1, 0, 0 ] // LEFT + ]; + + let positions = []; + let normals = []; + let uvs = []; + let indices = []; + let minPos = vec3.create(-hw, -hh, -hl); + let maxPos = vec3.create(hw, hh, hl); + let boundingRadius = Math.sqrt(hw * hw + hh * hh + hl * hl); + + function _buildPlane (side, uSegments, vSegments) { + let u, v; + let ix, iy; + let offset = positions.length / 3; + let faceAxe = faceAxes[side]; + let faceNormal = faceNormals[side]; + + for (iy = 0; iy <= vSegments; iy++) { + for (ix = 0; ix <= uSegments; ix++) { + u = ix / uSegments; + v = iy / vSegments; + + vec3.lerp(temp1, corners[faceAxe[0]], corners[faceAxe[1]], u); + vec3.lerp(temp2, corners[faceAxe[0]], corners[faceAxe[2]], v); + vec3.sub(temp3, temp2, corners[faceAxe[0]]); + vec3.add(r, temp1, temp3); + + positions.push(r.x, r.y, r.z); + normals.push(faceNormal[0], faceNormal[1], faceNormal[2]); + uvs.push(u, v); + + if ((ix < uSegments) && (iy < vSegments)) { + let useg1 = uSegments + 1; + let a = ix + iy * useg1; + let b = ix + (iy + 1) * useg1; + let c = (ix + 1) + (iy + 1) * useg1; + let d = (ix + 1) + iy * useg1; + + if (inv) { + indices.push(offset + a, offset + b, offset + d); + indices.push(offset + d, offset + b, offset + c); + } else { + indices.push(offset + a, offset + d, offset + b); + indices.push(offset + b, offset + d, offset + c); + } + } + } + } + } + + _buildPlane(0, ws, hs); // FRONT + _buildPlane(4, ls, hs); // RIGHT + _buildPlane(1, ws, hs); // BACK + _buildPlane(5, ls, hs); // LEFT + _buildPlane(3, ws, ls); // BOTTOM + _buildPlane(2, ws, ls); // TOP + + return { + positions, + normals, + uvs, + indices, + minPos, + maxPos, + boundingRadius + }; +} diff --git a/cocos2d/core/3d/primitive/capsule.js b/cocos2d/core/3d/primitive/capsule.js new file mode 100644 index 00000000000..6bfb705897e --- /dev/null +++ b/cocos2d/core/3d/primitive/capsule.js @@ -0,0 +1,203 @@ +'use strict'; + +import { vec3 } from '../../vmath'; + +let temp1 = vec3.create(0, 0, 0); +let temp2 = vec3.create(0, 0, 0); + +/** + * @param {Number} radiusTop + * @param {Number} radiusBottom + * @param {Number} height + * @param {Object} opts + * @param {Number} opts.sides + * @param {Number} opts.heightSegments + * @param {Boolean} opts.capped + * @param {Number} opts.arc + */ +export default function (radiusTop = 0.5, radiusBottom = 0.5, height = 2, opts = {}) { + let torsoHeight = height - radiusTop - radiusBottom; + let sides = opts.sides || 32; + let heightSegments = opts.heightSegments || 32; + let bottomProp = radiusBottom / height; + let torProp = torsoHeight / height; + let topProp = radiusTop / height; + let bottomSegments = Math.floor(heightSegments * bottomProp); + let topSegments = Math.floor(heightSegments * topProp); + let torSegments = Math.floor(heightSegments * torProp); + let topOffset = torsoHeight + radiusBottom - height / 2; + let torOffset = radiusBottom - height / 2; + let bottomOffset = radiusBottom - height / 2; + + let arc = opts.arc || 2.0 * Math.PI; + + // calculate vertex count + let positions = []; + let normals = []; + let uvs = []; + let indices = []; + let maxRadius = Math.max(radiusTop, radiusBottom); + let minPos = vec3.create(-maxRadius, -height / 2, -maxRadius); + let maxPos = vec3.create(maxRadius, height / 2, maxRadius); + let boundingRadius = height / 2; + + let index = 0; + let indexArray = []; + + generateBottom(); + + generateTorso(); + + generateTop(); + + return { + positions, + normals, + uvs, + indices, + minPos, + maxPos, + boundingRadius + }; + + // ======================= + // internal fucntions + // ======================= + + function generateTorso() { + // this will be used to calculate the normal + let slope = (radiusTop - radiusBottom) / torsoHeight; + + // generate positions, normals and uvs + for (let y = 0; y <= torSegments; y++) { + + let indexRow = []; + let lat = y / torSegments; + let radius = lat * (radiusTop - radiusBottom) + radiusBottom; + + for (let x = 0; x <= sides; ++x) { + let u = x / sides; + let v = lat * torProp + bottomProp; + let theta = u * arc - (arc / 4); + + let sinTheta = Math.sin(theta); + let cosTheta = Math.cos(theta); + + // vertex + positions.push(radius * sinTheta); + positions.push(lat * torsoHeight + torOffset); + positions.push(radius * cosTheta); + + // normal + vec3.normalize(temp1, vec3.set(temp2, sinTheta, -slope, cosTheta)); + normals.push(temp1.x); + normals.push(temp1.y); + normals.push(temp1.z); + + // uv + uvs.push(u,v); + // save index of vertex in respective row + indexRow.push(index); + + // increase index + ++index; + } + + // now save positions of the row in our index array + indexArray.push(indexRow); + } + + // generate indices + for (let y = 0; y < torSegments; ++y) { + for (let x = 0; x < sides; ++x) { + // we use the index array to access the correct indices + let i1 = indexArray[y][x]; + let i2 = indexArray[y + 1][x]; + let i3 = indexArray[y + 1][x + 1]; + let i4 = indexArray[y][x + 1]; + + // face one + indices.push(i1); + indices.push(i4); + indices.push(i2); + + // face two + indices.push(i4); + indices.push(i3); + indices.push(i2); + } + } + } + + function generateBottom() { + for (let lat = 0; lat <= bottomSegments; ++lat) { + let theta = lat * Math.PI / bottomSegments / 2; + let sinTheta = Math.sin(theta); + let cosTheta = -Math.cos(theta); + + for (let lon = 0; lon <= sides; ++lon) { + let phi = lon * 2 * Math.PI / sides - Math.PI / 2.0; + let sinPhi = Math.sin(phi); + let cosPhi = Math.cos(phi); + + let x = sinPhi * sinTheta; + let y = cosTheta; + let z = cosPhi * sinTheta; + let u = lon / sides; + let v = lat / heightSegments; + + positions.push(x * radiusBottom, y * radiusBottom + bottomOffset, z * radiusBottom); + normals.push(x, y, z); + uvs.push(u, v); + + if ((lat < bottomSegments) && (lon < sides)) { + let seg1 = sides + 1; + let a = seg1 * lat + lon; + let b = seg1 * (lat + 1) + lon; + let c = seg1 * (lat + 1) + lon + 1; + let d = seg1 * lat + lon + 1; + + indices.push(a, d, b); + indices.push(d, c, b); + } + + ++index; + } + } + } + + function generateTop() { + for (let lat = 0; lat <= topSegments; ++lat) { + let theta = lat * Math.PI / topSegments / 2 + Math.PI / 2; + let sinTheta = Math.sin(theta); + let cosTheta = -Math.cos(theta); + + for (let lon = 0; lon <= sides; ++lon) { + let phi = lon * 2 * Math.PI / sides - Math.PI / 2.0; + let sinPhi = Math.sin(phi); + let cosPhi = Math.cos(phi); + + let x = sinPhi * sinTheta; + let y = cosTheta; + let z = cosPhi * sinTheta; + let u = lon / sides; + let v = lat / heightSegments + (1-topProp); + + positions.push(x * radiusTop, y * radiusTop + topOffset, z * radiusTop); + normals.push(x, y, z); + uvs.push(u, v); + + if ((lat < topSegments) && (lon < sides)) { + let seg1 = sides + 1; + let a = seg1 * lat + lon + indexArray[torSegments][sides] + 1; + let b = seg1 * (lat + 1) + lon + indexArray[torSegments][sides] + 1; + let c = seg1 * (lat + 1) + lon + 1 + indexArray[torSegments][sides] + 1; + let d = seg1 * lat + lon + 1 + indexArray[torSegments][sides] + 1; + + indices.push(a, d, b); + indices.push(d, c, b); + } + } + } + } +} diff --git a/cocos2d/core/3d/primitive/cone.js b/cocos2d/core/3d/primitive/cone.js new file mode 100644 index 00000000000..984ea25005e --- /dev/null +++ b/cocos2d/core/3d/primitive/cone.js @@ -0,0 +1,16 @@ +'use strict'; + +import cylinder from './cylinder'; + +/** + * @param {Number} radius + * @param {Number} height + * @param {Object} opts + * @param {Number} opts.radialSegments + * @param {Number} opts.heightSegments + * @param {Boolean} opts.capped + * @param {Number} opts.arc + */ +export default function (radius = 0.5, height = 1, opts = {}) { + return cylinder(0, radius, height, opts); +} diff --git a/cocos2d/core/3d/primitive/cylinder.js b/cocos2d/core/3d/primitive/cylinder.js new file mode 100644 index 00000000000..706df1a92d6 --- /dev/null +++ b/cocos2d/core/3d/primitive/cylinder.js @@ -0,0 +1,237 @@ +'use strict'; + +import { vec3 } from '../../vmath'; + +let temp1 = vec3.create(0, 0, 0); +let temp2 = vec3.create(0, 0, 0); + +/** + * @param {Number} radiusTop + * @param {Number} radiusBottom + * @param {Number} height + * @param {Object} opts + * @param {Number} opts.radialSegments + * @param {Number} opts.heightSegments + * @param {Boolean} opts.capped + * @param {Number} opts.arc + */ +export default function (radiusTop = 0.5, radiusBottom = 0.5, height = 2, opts = {}) { + let halfHeight = height * 0.5; + let radialSegments = opts.radialSegments || 32; + let heightSegments = opts.heightSegments || 1; + let capped = opts.capped !== undefined ? opts.capped : true; + let arc = opts.arc || 2.0 * Math.PI; + + let cntCap = 0; + if (!capped) { + if (radiusTop > 0) { + cntCap++; + } + + if (radiusBottom > 0) { + cntCap++; + } + } + + // calculate vertex count + let vertCount = (radialSegments + 1) * (heightSegments + 1); + if (capped) { + vertCount += ((radialSegments + 1) * cntCap) + (radialSegments * cntCap); + } + + // calculate index count + let indexCount = radialSegments * heightSegments * 2 * 3; + if (capped) { + indexCount += radialSegments * cntCap * 3; + } + + let indices = new Array(indexCount); + let positions = new Array(vertCount * 3); + let normals = new Array(vertCount * 3); + let uvs = new Array(vertCount * 2); + let maxRadius = Math.max(radiusTop, radiusBottom); + let minPos = vec3.create(-maxRadius, -halfHeight, -maxRadius); + let maxPos = vec3.create(maxRadius, halfHeight, maxRadius); + let boundingRadius = Math.sqrt(maxRadius * maxRadius + halfHeight * halfHeight); + + let index = 0; + let indexOffset = 0; + + generateTorso(); + + if (capped) { + if (radiusBottom > 0) { + generateCap(false); + } + + if (radiusTop > 0) { + generateCap(true); + } + } + + return { + positions, + normals, + uvs, + indices, + minPos, + maxPos, + boundingRadius + }; + + // ======================= + // internal fucntions + // ======================= + + function generateTorso() { + let indexArray = []; + + // this will be used to calculate the normal + let r = radiusTop - radiusBottom; + let slope = r * r / height * Math.sign(r); + + // generate positions, normals and uvs + for (let y = 0; y <= heightSegments; y++) { + let indexRow = []; + let v = y / heightSegments; + + // calculate the radius of the current row + let radius = v * r + radiusBottom; + + for (let x = 0; x <= radialSegments; ++x) { + let u = x / radialSegments; + let theta = u * arc; + + let sinTheta = Math.sin(theta); + let cosTheta = Math.cos(theta); + + // vertex + positions[3 * index] = radius * sinTheta; + positions[3 * index + 1] = v * height - halfHeight; + positions[3 * index + 2] = radius * cosTheta; + + // normal + vec3.normalize(temp1, vec3.set(temp2, sinTheta, -slope, cosTheta)); + normals[3 * index] = temp1.x; + normals[3 * index + 1] = temp1.y; + normals[3 * index + 2] = temp1.z; + + // uv + uvs[2 * index] = (1 - u) * 2 % 1; + uvs[2 * index + 1] = v; + + // save index of vertex in respective row + indexRow.push(index); + + // increase index + ++index; + } + + // now save positions of the row in our index array + indexArray.push(indexRow); + } + + // generate indices + for (let y = 0; y < heightSegments; ++y) { + for (let x = 0; x < radialSegments; ++x) { + // we use the index array to access the correct indices + let i1 = indexArray[y][x]; + let i2 = indexArray[y + 1][x]; + let i3 = indexArray[y + 1][x + 1]; + let i4 = indexArray[y][x + 1]; + + // face one + indices[indexOffset] = i1; ++indexOffset; + indices[indexOffset] = i4; ++indexOffset; + indices[indexOffset] = i2; ++indexOffset; + + // face two + indices[indexOffset] = i4; ++indexOffset; + indices[indexOffset] = i3; ++indexOffset; + indices[indexOffset] = i2; ++indexOffset; + } + } + } + + function generateCap(top) { + let centerIndexStart, centerIndexEnd; + + let radius = top ? radiusTop : radiusBottom; + let sign = top ? 1 : - 1; + + // save the index of the first center vertex + centerIndexStart = index; + + // first we generate the center vertex data of the cap. + // because the geometry needs one set of uvs per face, + // we must generate a center vertex per face/segment + + for (let x = 1; x <= radialSegments; ++x) { + // vertex + positions[3 * index] = 0; + positions[3 * index + 1] = halfHeight * sign; + positions[3 * index + 2] = 0; + + // normal + normals[3 * index] = 0; + normals[3 * index + 1] = sign; + normals[3 * index + 2] = 0; + + // uv + uvs[2 * index] = 0.5; + uvs[2 * index + 1] = 0.5; + + // increase index + ++index; + } + + // save the index of the last center vertex + centerIndexEnd = index; + + // now we generate the surrounding positions, normals and uvs + + for (let x = 0; x <= radialSegments; ++x) { + let u = x / radialSegments; + let theta = u * arc; + + let cosTheta = Math.cos(theta); + let sinTheta = Math.sin(theta); + + // vertex + positions[3 * index] = radius * sinTheta; + positions[3 * index + 1] = halfHeight * sign; + positions[3 * index + 2] = radius * cosTheta; + + // normal + normals[3 * index] = 0; + normals[3 * index + 1] = sign; + normals[3 * index + 2] = 0; + + // uv + uvs[2 * index] = 0.5 - (sinTheta * 0.5 * sign); + uvs[2 * index + 1] = 0.5 + (cosTheta * 0.5); + + // increase index + ++index; + } + + // generate indices + + for (let x = 0; x < radialSegments; ++x) { + let c = centerIndexStart + x; + let i = centerIndexEnd + x; + + if (top) { + // face top + indices[indexOffset] = i + 1; ++indexOffset; + indices[indexOffset] = c; ++indexOffset; + indices[indexOffset] = i; ++indexOffset; + } else { + // face bottom + indices[indexOffset] = c; ++indexOffset; + indices[indexOffset] = i + 1; ++indexOffset; + indices[indexOffset] = i; ++indexOffset; + } + } + } +} diff --git a/cocos2d/core/3d/primitive/index.js b/cocos2d/core/3d/primitive/index.js new file mode 100644 index 00000000000..89057242895 --- /dev/null +++ b/cocos2d/core/3d/primitive/index.js @@ -0,0 +1,20 @@ +import utils from './utils'; +import box from './box'; +import cone from './cone'; +import cylinder from './cylinder'; +import plane from './plane'; +import quad from './quad'; +import sphere from './sphere'; +import torus from './torus'; +import capsule from './capsule'; + +cc.primitive = Object.assign({ + box: box, + cone: cone, + cylinder: cylinder, + plane: plane, + quad: quad, + sphere: sphere, + torus: torus, + capsule: capsule, +}, utils); diff --git a/cocos2d/core/3d/primitive/plane.js b/cocos2d/core/3d/primitive/plane.js new file mode 100644 index 00000000000..4223f0e3c70 --- /dev/null +++ b/cocos2d/core/3d/primitive/plane.js @@ -0,0 +1,75 @@ +'use strict'; + +import { vec3 } from '../../vmath'; + +let temp1 = vec3.create(0, 0, 0); +let temp2 = vec3.create(0, 0, 0); +let temp3 = vec3.create(0, 0, 0); +let r = vec3.create(0, 0, 0); +let c00 = vec3.create(0, 0, 0); +let c10 = vec3.create(0, 0, 0); +let c01 = vec3.create(0, 0, 0); + +/** + * @param {Number} width + * @param {Number} length + * @param {Object} opts + * @param {Number} opts.widthSegments + * @param {Number} opts.lengthSegments + */ +export default function (width = 10, length = 10, opts = {}) { + let uSegments = opts.widthSegments !== undefined ? opts.widthSegments : 10; + let vSegments = opts.lengthSegments !== undefined ? opts.lengthSegments : 10; + + let hw = width * 0.5; + let hl = length * 0.5; + + let positions = []; + let normals = []; + let uvs = []; + let indices = []; + let minPos = vec3.create(-hw, 0, -hl); + let maxPos = vec3.create(hw, 0, hl); + let boundingRadius = Math.sqrt(width * width + length * length); + + vec3.set(c00, -hw, 0, hl); + vec3.set(c10, hw, 0, hl); + vec3.set(c01, -hw, 0, -hl); + + for (let y = 0; y <= vSegments; y++) { + for (let x = 0; x <= uSegments; x++) { + let u = x / uSegments; + let v = y / vSegments; + + vec3.lerp(temp1, c00, c10, u); + vec3.lerp(temp2, c00, c01, v); + vec3.sub(temp3, temp2, c00); + vec3.add(r, temp1, temp3); + + positions.push(r.x, r.y, r.z); + normals.push(0, 1, 0); + uvs.push(u, v); + + if ((x < uSegments) && (y < vSegments)) { + let useg1 = uSegments + 1; + let a = x + y * useg1; + let b = x + (y + 1) * useg1; + let c = (x + 1) + (y + 1) * useg1; + let d = (x + 1) + y * useg1; + + indices.push(a, d, b); + indices.push(d, c, b); + } + } + } + + return { + positions, + normals, + uvs, + indices, + minPos, + maxPos, + boundingRadius + }; +} diff --git a/cocos2d/core/3d/primitive/quad.js b/cocos2d/core/3d/primitive/quad.js new file mode 100644 index 00000000000..15ae9912dc8 --- /dev/null +++ b/cocos2d/core/3d/primitive/quad.js @@ -0,0 +1,46 @@ +'use strict'; + +import { vec3 } from '../../vmath'; + +let positions = [ + -0.5, -0.5, 0, // bottom-left + -0.5, 0.5, 0, // top-left + 0.5, 0.5, 0, // top-right + 0.5, -0.5, 0, // bottom-right +]; + +let normals = [ + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, +]; + +let uvs = [ + 0, 0, + 0, 1, + 1, 1, + 1, 0, +]; + +let indices = [ + 0, 3, 1, + 3, 2, 1 +]; + +// TODO: ? +let minPos = vec3.create(-0.5, -0.5, 0); +let maxPos = vec3.create(0.5, 0.5, 0); +let boundingRadius = Math.sqrt(0.5 * 0.5 + 0.5 * 0.5); + +export default function () { + return { + positions, + indices, + normals, + uvs, + minPos, + maxPos, + boundingRadius + }; +} diff --git a/cocos2d/core/3d/primitive/sphere.js b/cocos2d/core/3d/primitive/sphere.js new file mode 100644 index 00000000000..29730f534cd --- /dev/null +++ b/cocos2d/core/3d/primitive/sphere.js @@ -0,0 +1,67 @@ +'use strict'; + +import { vec3 } from '../../vmath'; + +/** + * @param {Number} radius + * @param {Object} opts + * @param {Number} opts.segments + */ +export default function (radius = 0.5, opts = {}) { + let segments = opts.segments !== undefined ? opts.segments : 32; + + // lat === latitude + // lon === longitude + + let positions = []; + let normals = []; + let uvs = []; + let indices = []; + let minPos = vec3.create(-radius, -radius, -radius); + let maxPos = vec3.create(radius, radius, radius); + let boundingRadius = radius; + + for (let lat = 0; lat <= segments; ++lat) { + let theta = lat * Math.PI / segments; + let sinTheta = Math.sin(theta); + let cosTheta = -Math.cos(theta); + + for (let lon = 0; lon <= segments; ++lon) { + let phi = lon * 2 * Math.PI / segments - Math.PI / 2.0; + let sinPhi = Math.sin(phi); + let cosPhi = Math.cos(phi); + + let x = sinPhi * sinTheta; + let y = cosTheta; + let z = cosPhi * sinTheta; + let u = lon / segments; + let v = lat / segments; + + positions.push(x * radius, y * radius, z * radius); + normals.push(x, y, z); + uvs.push(u, v); + + + if ((lat < segments) && (lon < segments)) { + let seg1 = segments + 1; + let a = seg1 * lat + lon; + let b = seg1 * (lat + 1) + lon; + let c = seg1 * (lat + 1) + lon + 1; + let d = seg1 * lat + lon + 1; + + indices.push(a, d, b); + indices.push(d, c, b); + } + } + } + + return { + positions, + indices, + normals, + uvs, + minPos, + maxPos, + boundingRadius + }; +} diff --git a/cocos2d/core/3d/primitive/torus.js b/cocos2d/core/3d/primitive/torus.js new file mode 100644 index 00000000000..1a827512843 --- /dev/null +++ b/cocos2d/core/3d/primitive/torus.js @@ -0,0 +1,69 @@ +'use strict'; + +import { vec3 } from '../../vmath'; +/** + * @param {Number} radius + * @param {Number} tube + * @param {Object} opts + * @param {Number} opts.radialSegments + * @param {Number} opts.tubularSegments + * @param {Number} opts.arc + */ +export default function (radius = 0.4, tube = 0.1, opts = {}) { + let radialSegments = opts.radialSegments || 32; + let tubularSegments = opts.tubularSegments || 32; + let arc = opts.arc || 2.0 * Math.PI; + + let positions = []; + let normals = []; + let uvs = []; + let indices = []; + let minPos = vec3.create(-radius - tube, -tube, -radius - tube); + let maxPos = vec3.create(radius + tube, tube, radius + tube); + let boundingRadius = radius + tube; + + for (let j = 0; j <= radialSegments; j++) { + for (let i = 0; i <= tubularSegments; i++) { + let u = i / tubularSegments; + let v = j / radialSegments; + + let u1 = u * arc; + let v1 = v * Math.PI * 2; + + // vertex + let x = (radius + tube * Math.cos(v1)) * Math.sin(u1); + let y = tube * Math.sin(v1); + let z = (radius + tube * Math.cos(v1)) * Math.cos(u1); + + // this vector is used to calculate the normal + let nx = Math.sin(u1) * Math.cos(v1); + let ny = Math.sin(v1); + let nz = Math.cos(u1) * Math.cos(v1); + + positions.push(x, y, z); + normals.push(nx, ny, nz); + uvs.push(u, v); + + if ((i < tubularSegments) && (j < radialSegments)) { + let seg1 = tubularSegments + 1; + let a = seg1 * j + i; + let b = seg1 * (j + 1) + i; + let c = seg1 * (j + 1) + i + 1; + let d = seg1 * j + i + 1; + + indices.push(a, d, b); + indices.push(d, c, b); + } + } + } + + return { + positions, + normals, + uvs, + indices, + minPos, + maxPos, + boundingRadius + }; +} diff --git a/cocos2d/core/3d/primitive/utils.js b/cocos2d/core/3d/primitive/utils.js new file mode 100644 index 00000000000..c0f7ffbe6ec --- /dev/null +++ b/cocos2d/core/3d/primitive/utils.js @@ -0,0 +1,65 @@ + +export function wireframe(indices) { + const offsets = [[0, 1], [1, 2], [2, 0]]; + let lines = []; + let lineIDs = {}; + + for (let i = 0; i < indices.length; i += 3) { + for (let k = 0; k < 3; ++k) { + let i1 = indices[i + offsets[k][0]]; + let i2 = indices[i + offsets[k][1]]; + + // check if we already have the line in our lines + let id = (i1 > i2) ? ((i2 << 16) | i1) : ((i1 << 16) | i2); + if (lineIDs[id] === undefined) { + lineIDs[id] = 0; + lines.push(i1, i2); + } + } + } + + return lines; +} + +export function invWinding(indices) { + let newIB = []; + for (let i = 0; i < indices.length; i += 3) + newIB.push(indices[i], indices[i + 2], indices[i + 1]); + return newIB; +} + +export function toWavefrontOBJ(primitive, scale = 1) { + let v = primitive.positions, t = primitive.uvs, n = primitive.normals, IB = primitive.indices; + let V = i => `${IB[i]+1}/${IB[i]+1}/${IB[i]+1}`; + let content = ''; + for (let i = 0; i < v.length; i += 3) + content += `v ${v[i]*scale} ${v[i+1]*scale} ${v[i+2]*scale}\n`; + for (let i = 0; i < t.length; i += 2) + content += `vt ${t[i]} ${t[i+1]}\n`; + for (let i = 0; i < n.length; i += 3) + content += `vn ${n[i]} ${n[i+1]} ${n[i+2]}\n`; + for (let i = 0; i < IB.length; i += 3) + content += `f ${V(i)} ${V(i+1)} ${V(i+2)}\n`; + return content; +} + +export function normals(positions, normals, length = 1) { + let verts = new Array(2 * positions.length); + + for (let i = 0; i < positions.length/3; ++i) { + let i3 = 3*i; + let i6 = 6*i; + + // line start + verts[i6 + 0] = positions[i3 + 0]; + verts[i6 + 1] = positions[i3 + 1]; + verts[i6 + 2] = positions[i3 + 2]; + + // line end + verts[i6 + 3] = positions[i3 + 0] + normals[i3 + 0] * length; + verts[i6 + 4] = positions[i3 + 1] + normals[i3 + 1] * length; + verts[i6 + 5] = positions[i3 + 2] + normals[i3 + 2] * length; + } + + return verts; +} diff --git a/cocos2d/core/mesh/CCMesh.js b/cocos2d/core/mesh/CCMesh.js index 5bee7ca80b3..5a860123583 100644 --- a/cocos2d/core/mesh/CCMesh.js +++ b/cocos2d/core/mesh/CCMesh.js @@ -290,6 +290,18 @@ let Mesh = cc.Class({ vbs.length = 0; }, + /** + * !#en Set mesh bounding box + * !#zh 设置网格的包围盒 + * @method setBoundingBox + * @param {Vec3} min + * @param {Vec3} max + */ + setBoundingBox (min, max) { + this._minPos = min; + this._maxPos = max; + }, + destroy () { this.clear(); }, diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index f5769377d29..08c900dea54 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -228,6 +228,7 @@ let MeshRenderer = cc.Class({ let attr2el = subMeshes[0]._vertexBuffer._format._attr2el; this._customProperties.define('_USE_ATTRIBUTE_COLOR', !!attr2el[gfx.ATTR_COLOR]); this._customProperties.define('_USE_ATTRIBUTE_UV0', !!attr2el[gfx.ATTR_UV0]); + this._customProperties.define('_USE_ATTRIBUTE_NORMAL', !!attr2el[gfx.ATTR_NORMAL]); } }); diff --git a/cocos2d/renderer/build/build-chunks.js b/cocos2d/renderer/build/build-chunks.js deleted file mode 100644 index c47cbb73740..00000000000 --- a/cocos2d/renderer/build/build-chunks.js +++ /dev/null @@ -1,20 +0,0 @@ -const path_ = require('path'); -const fs = require('fs'); -const shdcLib = require('./shdc-lib'); - -let defaultChunkPath = path_.join(__dirname, './chunks'), chunksCache = {}; -let updateBuiltinChunks = function(path = defaultChunkPath) { - const fsJetpack = require('fs-jetpack'); - - let files = fsJetpack.find(path, { matching: ['**/*.inc'] }); - for (let i = 0; i < files.length; ++i) { - let name = path_.basename(files[i], '.inc'); - let content = fs.readFileSync(files[i], { encoding: 'utf8' }); - chunksCache[name] = shdcLib.glslStripComment(content); - } - - let content = 'module.exports = ' + JSON.stringify(chunksCache, null, 2); - fs.writeFileSync(path_.join(__dirname, './chunks/index.js'), content); -}; - -updateBuiltinChunks(); diff --git a/cocos2d/renderer/build/build-shader.js b/cocos2d/renderer/build/build-shader.js deleted file mode 100644 index b5cb577567b..00000000000 --- a/cocos2d/renderer/build/build-shader.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -const sha1 = require('js-sha1'); - -const shdcLib = require('./shdc-lib'); -const mappings = require('./mappings'); -const chunksCache = require('./chunks'); - -let queueRE = /(\w+)(?:([+-])(\d+))?/; -let parseQueue = function (queue) { - let m = queueRE.exec(queue); - if (m === null) return 0; - let q = mappings.RenderQueue[m[1].toUpperCase()]; - if (m.length === 4) { - if (m[2] === '+') q += parseInt(m[3]); - if (m[2] === '-') q -= parseInt(m[3]); - } - return q; -}; - -function mapPassParam(p) { - let num; - switch (typeof p) { - case 'string': - num = parseInt(p); - return isNaN(num) ? mappings.passParams[p.toUpperCase()] : num; - case 'object': - return ((p[0] * 255) << 24 | (p[1] * 255) << 16 | (p[2] * 255) << 8 | (p[3] || 0) * 255) >>> 0; - } - return p; -} - -function buildEffectJSON(json) { - // map param's type offline. - for (let j = 0; j < json.techniques.length; ++j) { - let jsonTech = json.techniques[j]; - if (jsonTech.queue) jsonTech.queue = parseQueue(jsonTech.queue); - for (let k = 0; k < jsonTech.passes.length; ++k) { - let pass = jsonTech.passes[k]; - for (let key in pass) { - if (key === "vert" || key === 'frag') continue; - pass[key] = mapPassParam(pass[key]); - } - } - } - for (let prop in json.properties) { - let info = json.properties[prop]; - info.type = mappings.typeParams[info.type.toUpperCase()]; - } - return json; -} - -let parseEffect = (function() { - let effectRE = /%{([^%]+)%}/; - let blockRE = /%%\s*([\w-]+)\s*{([^]+)}/; - let parenRE = /[{}]/g; - let trimToSize = content => { - let level = 1, end = content.length; - content.replace(parenRE, (p, i) => { - if (p === '{') level++; - else if (level === 1) { end = i; level = 1e9; } - else level--; - }); - return content.substring(0, end); - }; - return function (content) { - let effectCap = effectRE.exec(content); - let effect = JSON.parse(`{${effectCap[1]}}`), templates = {}; - content = content.substring(effectCap.index + effectCap[0].length); - let blockCap = blockRE.exec(content); - while (blockCap) { - let str = templates[blockCap[1]] = trimToSize(blockCap[2]); - content = content.substring(blockCap.index + str.length); - blockCap = blockRE.exec(content); - } - return { effect, templates }; - }; -})(); - -// ============================================================ -// build -// ============================================================ - -function buildEffect(content) { - let { effect, templates } = parseEffect(content); - effect = buildEffectJSON(effect); - Object.assign(templates, chunksCache); - let shaders = []; - for (let j = 0; j < effect.techniques.length; ++j) { - let jsonTech = effect.techniques[j]; - for (let k = 0; k < jsonTech.passes.length; ++k) { - let pass = jsonTech.passes[k]; - let vert = pass.vert, frag = pass.frag; - let shader = shdcLib.assembleAndBuild(vert, frag, templates); - let name = sha1(shader.vert + shader.frag); - shader.name = pass.program = name; - delete pass.vert; delete pass.frag; - shaders.push(shader); - } - } - return { effect, shaders }; -} - -module.exports = buildEffect; \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/index.js b/cocos2d/renderer/build/chunks/index.js deleted file mode 100644 index 497e2b77f33..00000000000 --- a/cocos2d/renderer/build/chunks/index.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - "common": "\n\n\n\n\n#define PI 3.14159265359\n#define PI2 6.28318530718\n#define EPSILON 1e-6\n#define LOG2 1.442695\n\n\n#define saturate(a) clamp( a, 0.0, 1.0 )", - "gamma-correction": "\n\n\n\nvec3 gammaToLinearSpaceRGB(vec3 sRGB) { \n return sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878);\n}\n\nvec3 linearToGammaSpaceRGB(vec3 RGB) { \n vec3 S1 = sqrt(RGB);\n vec3 S2 = sqrt(S1);\n vec3 S3 = sqrt(S2);\n return 0.585122381 * S1 + 0.783140355 * S2 - 0.368262736 * S3;\n}\n\nvec4 gammaToLinearSpaceRGBA(vec4 sRGBA) {\n return vec4(gammaToLinearSpaceRGB(sRGBA.rgb), sRGBA.a);\n}\n\nvec4 linearToGammaSpaceRGBA(vec4 RGBA) {\n return vec4(linearToGammaSpaceRGB(RGBA.rgb), RGBA.a);\n}\n\n\nfloat gammaToLinearSpaceExact(float val) {\n if (val <= 0.04045) {\n return val / 12.92;\n } else if (val < 1.0) {\n return pow((val + 0.055) / 1.055, 2.4);\n } else {\n return pow(val, 2.2);\n }\n}\n\nfloat linearToGammaSpaceExact(float val) {\n if (val <= 0.0) {\n return 0.0;\n } else if (val <= 0.0031308) {\n return 12.92 * val;\n } else if (val < 1.0) {\n return 1.055 * pow(val, 0.4166667) - 0.055;\n } else {\n return pow(val, 0.45454545);\n }\n}", - "packing": "\n\nvec4 packDepthToRGBA(float depth) {\n vec4 ret = vec4(1.0, 255.0, 65025.0, 160581375.0) * depth;\n ret = fract(ret);\n ret -= ret.yzww * vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0);\n return ret;\n}\n\nfloat unpackRGBAToDepth(vec4 color) {\n return dot(color, vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 160581375.0));\n}", - "pbr-fs": "\n\n#if USE_NORMAL_TEXTURE\n#extension GL_OES_standard_derivatives : enable\n#endif\n\n#if USE_TEX_LOD\n#extension GL_EXT_shader_texture_lod: enable\n#endif\n\n#include \n#include \n\nstruct LightInfo {\n vec3 lightDir;\n vec3 radiance;\n};\n\n#if _NUM_DIR_LIGHTS > 0\n #pragma for id in range(0, _NUM_DIR_LIGHTS)\n uniform vec3 _dir_light{id}_direction;\n uniform vec3 _dir_light{id}_color;\n #pragma endFor\n#endif\n\n#if _NUM_POINT_LIGHTS > 0\n #pragma for id in range(0, _NUM_POINT_LIGHTS)\n uniform vec3 _point_light{id}_position;\n uniform vec3 _point_light{id}_color;\n uniform float _point_light{id}_range;\n #pragma endFor\n#endif\n\n#if _NUM_SPOT_LIGHTS > 0\n #pragma for id in range(0, _NUM_SPOT_LIGHTS)\n uniform vec3 _spot_light{id}_position;\n uniform vec3 _spot_light{id}_direction;\n uniform vec3 _spot_light{id}_color;\n uniform vec2 _spot_light{id}_spot;\n uniform float _spot_light{id}_range;\n #pragma endFor\n#endif\n\n\nLightInfo computeDirectionalLighting(\n vec3 lightDirection,\n vec3 lightColor\n) {\n LightInfo ret;\n ret.lightDir = -normalize(lightDirection);\n ret.radiance = lightColor;\n\n return ret;\n}\n\n\nLightInfo computePointLighting(\n vec3 lightPosition,\n vec3 positionW,\n vec3 lightColor,\n float lightRange\n) {\n LightInfo ret;\n vec3 lightDir = lightPosition - positionW;\n float attenuation = max(0.0, 1.0 - length(lightDir) / lightRange);\n ret.lightDir = normalize(lightDir);\n ret.radiance = lightColor * attenuation;\n\n return ret;\n}\n\n\nLightInfo computeSpotLighting(\n vec3 lightPosition,\n vec3 positionW,\n vec3 lightDirection,\n vec3 lightColor,\n vec2 lightSpot,\n float lightRange\n) {\n LightInfo ret;\n vec3 lightDir = lightPosition - positionW;\n float attenuation = max(0., 1.0 - length(lightDir) / lightRange);\n float cosConeAngle = max(0., dot(lightDirection, -lightDir));\n cosConeAngle = cosConeAngle < lightSpot.x ? 0.0 : cosConeAngle;\n cosConeAngle = pow(cosConeAngle,lightSpot.y);\n ret.lightDir = normalize(lightDir);\n ret.radiance = lightColor * attenuation * cosConeAngle;\n\n return ret;\n}\n\n#include \n\n#if _USE_SHADOW_MAP\n #include \n #include \n#endif\n\nuniform vec3 _eye;\n\nvarying vec3 pos_w;\nvarying vec3 normal_w;\n\n#if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_EMISSIVE_TEXTURE\n varying vec2 uv0;\n#endif\n\n#if USE_IBL\n uniform samplerCube diffuseEnvTexture;\n uniform samplerCube specularEnvTexture;\n uniform sampler2D brdfLUT;\n #if USE_TEX_LOD\n uniform float maxReflectionLod;\n #endif\n#endif\n\n\nuniform vec4 albedo;\n#if USE_ALBEDO_TEXTURE\n uniform sampler2D albedo_texture;\n#endif\n\n#if USE_MRA_TEXTURE\n uniform sampler2D mra_texture;\n#endif\n\nuniform float metallic;\n#if USE_METALLIC_TEXTURE\n uniform sampler2D metallic_texture;\n#endif\n\nuniform float roughness;\n#if USE_ROUGHNESS_TEXTURE\n uniform sampler2D roughness_texture;\n#endif\n\nuniform float ao;\n#if USE_AO_TEXTURE\n uniform sampler2D ao_texture;\n#endif\n\n#if USE_EMISSIVE\n uniform vec3 emissive;\n #if USE_EMISSIVE_TEXTURE\n uniform sampler2D emissive_texture;\n #endif\n#endif\n\n#if USE_ALPHA_TEST\n uniform float alphaTestThreshold;\n#endif\n\n#if USE_NORMAL_TEXTURE\n uniform sampler2D normal_texture;\n \n vec3 getNormalFromTexture() {\n vec3 tangentNormal = texture2D(normal_texture, uv0).rgb * 2.0 - 1.0;\n vec3 q1 = dFdx(pos_w);\n vec3 q2 = dFdy(pos_w);\n vec2 st1 = dFdx(uv0);\n vec2 st2 = dFdy(uv0);\n vec3 N = normalize(normal_w);\n vec3 T = normalize(q1*st2.t - q2*st1.t);\n vec3 B = -normalize(cross(N, T));\n mat3 TBN = mat3(T, B, N);\n\n return normalize(TBN * tangentNormal);\n }\n#endif\n\n\n\n\nfloat distributionGGX(vec3 N, vec3 H, float roughness) {\n float a = roughness * roughness;\n float a2 = a * a;\n float NdotH = max(dot(N, H), 0.0);\n float NdotH2 = NdotH * NdotH;\n float nom = a2;\n float denom = (NdotH2 * (a2 - 1.0) + 1.0);\n denom = PI * denom * denom;\n\n return nom / denom;\n}\n\n\nfloat geometrySchlickGGX(float NdotV, float roughness) {\n float r = (roughness + 1.0);\n float k = (r * r) / 8.0;\n float nom = NdotV;\n float denom = NdotV * (1.0 - k) + k;\n\n return nom / denom;\n}\nfloat geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {\n float NdotV = max(dot(N, V), 0.0);\n float NdotL = max(dot(N, L), 0.0);\n float ggx2 = geometrySchlickGGX(NdotV, roughness);\n float ggx1 = geometrySchlickGGX(NdotL, roughness);\n\n return ggx1 * ggx2;\n}\n\n\n\nvec3 fresnelSchlick(float cosTheta, vec3 F0) {\n float fresnel = exp2((-5.55473 * cosTheta - 6.98316) * cosTheta);\n return F0 + (1.0 - F0) * fresnel;\n}\nvec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) {\n float fresnel = exp2((-5.55473 * cosTheta - 6.98316) * cosTheta);\n return F0 + (max(vec3(1.0 - roughness), F0) - F0) * fresnel;\n}\n\n\nvec3 brdf(LightInfo lightInfo, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) {\n vec3 H = normalize(V + lightInfo.lightDir);\n float NDF = distributionGGX(N, H, roughness);\n float G = geometrySmith(N, V, lightInfo.lightDir, roughness);\n vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);\n vec3 nominator = NDF * G * F;\n float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, lightInfo.lightDir), 0.0) + 0.001; \n vec3 specular = nominator / denominator;\n \n vec3 kS = F;\n \n \n \n vec3 kD = vec3(1.0) - kS;\n \n \n \n kD *= 1.0 - metallic;\n float NdotL = max(dot(N, lightInfo.lightDir), 0.0);\n\n return (kD * albedo / PI + specular) * lightInfo.radiance * NdotL;\n}\n\nvec4 frag() {\n float opacity = 1.0;\n\n #if USE_ALBEDO_TEXTURE\n vec4 baseColor = albedo * gammaToLinearSpaceRGBA(texture2D(albedo_texture, uv0));\n vec3 albedo = baseColor.rgb;\n opacity = baseColor.a;\n #else\n opacity = albedo.a;\n vec3 albedo = albedo.rgb;\n #endif\n\n #if USE_ALPHA_TEST\n if(opacity < alphaTestThreshold) discard;\n #endif\n\n #if USE_MRA_TEXTURE\n vec3 metalRoughness = texture2D(mra_texture, uv0).rgb;\n float metallic = metalRoughness.r;\n float roughness = metalRoughness.g;\n float ao = metalRoughness.b;\n #else\n #if USE_METALLIC_TEXTURE\n float metallic = texture2D(metallic_texture, uv0).r;\n #endif\n #if USE_ROUGHNESS_TEXTURE\n float roughness = texture2D(roughness_texture, uv0).r;\n #endif\n #if USE_AO_TEXTURE\n float ao = texture2D(ao_texture, uv0).r;\n #endif\n #endif\n\n vec3 N = normalize(normal_w);\n #if USE_NORMAL_TEXTURE\n N = getNormalFromTexture();\n #endif\n vec3 V = normalize(_eye - pos_w);\n\n \n \n vec3 F0 = vec3(0.04);\n F0 = mix(F0, albedo, metallic);\n\n \n vec3 Lo = vec3(0.0);\n\n \n #if _NUM_POINT_LIGHTS > 0\n #pragma for id in range(0, _NUM_POINT_LIGHTS)\n LightInfo pointLight{id};\n pointLight{id} = computePointLighting(_point_light{id}_position, pos_w, _point_light{id}_color, _point_light{id}_range);\n Lo += brdf(pointLight{id}, N, V, F0, albedo, metallic, roughness);\n #pragma endFor\n #endif\n\n #if _NUM_DIR_LIGHTS > 0\n #pragma for id in range(0, _NUM_DIR_LIGHTS)\n LightInfo directionalLight{id};\n directionalLight{id} = computeDirectionalLighting(_dir_light{id}_direction, _dir_light{id}_color);\n Lo += brdf(directionalLight{id}, N, V, F0, albedo, metallic, roughness);\n #pragma endFor\n #endif\n\n #if _NUM_SPOT_LIGHTS > 0\n #pragma for id in range(0, _NUM_SPOT_LIGHTS)\n LightInfo spotLight{id};\n spotLight{id} = computeSpotLighting(_spot_light{id}_position, pos_w, _spot_light{id}_direction, _spot_light{id}_color, _spot_light{id}_spot, _spot_light{id}_range);\n Lo += brdf(spotLight{id}, N, V, F0, albedo, metallic, roughness);\n #pragma endFor\n #endif\n\n #if USE_EMISSIVE\n vec3 emissiveColor = emissive;\n #if USE_EMISSIVE_TEXTURE\n emissiveColor *= gammaToLinearSpaceRGB(texture2D(emissive_texture, uv0).rgb);\n #endif\n Lo += emissiveColor;\n #endif\n\n \n vec3 ambient = vec3(0.03) * albedo * ao;\n\n #if USE_IBL\n \n vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness);\n vec3 kS = F;\n vec3 kD = vec3(1.0) - kS;\n kD *= 1.0 - metallic;\n #if USE_RGBE_IBL_DIFFUSE\n vec3 diffuseEnv = unpackRGBE(textureCube(diffuseEnvTexture, N));\n #else\n vec3 diffuseEnv = textureCube(diffuseEnvTexture, N).rgb;\n #endif\n vec3 diffuse = diffuseEnv * albedo;\n \n vec3 R = reflect(-V, N);\n #if USE_TEX_LOD\n #if USE_RGBE_IBL_SPECULAR\n vec3 specularEnv = unpackRGBE(textureCubeLodEXT(specularEnvTexture, R, roughness * maxReflectionLod));\n #else\n vec3 specularEnv = textureCubeLodEXT(specularEnvTexture, R, roughness * maxReflectionLod).rgb;\n #endif\n #else\n #if USE_RGBE_IBL_SPECULAR\n vec3 specularEnv = unpackRGBE(textureCube(specularEnvTexture, R));\n #else\n vec3 specularEnv = textureCube(specularEnvTexture, R).rgb;\n #endif\n #endif\n vec2 brdf = texture2D(brdfLUT, vec2(max(dot(N, V), 0.0), 1.0 - roughness)).rg;\n vec3 specular = specularEnv * (F * brdf.x + brdf.y);\n ambient = (kD * diffuse + specular) * ao;\n #endif\n\n #if _USE_SHADOW_MAP\n float shadow = 1.0;\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n shadow *= computeShadowESM(_shadowMap_{id}, pos_lightspace_{id}, vDepth_{id}, _depthScale_{id}, _darkness_{id}, _frustumEdgeFalloff_{id});\n #pragma endFor\n #endif\n vec3 color = (ambient + Lo) * shadow;\n #else\n vec3 color = ambient + Lo;\n #endif\n\n \n color = color / (color + vec3(1.0));\n \n vec4 finalColor = vec4(color, opacity);\n\n return linearToGammaSpaceRGBA(finalColor);\n}\n", - "pbr-vs": "\n\nattribute vec3 a_position;\nattribute vec3 a_normal;\n\nvarying vec3 pos_w;\nvarying vec3 normal_w;\n\nuniform mat4 _model;\nuniform mat4 _viewProj;\nuniform mat3 _normalMatrix;\n\n#if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_MRA_TEXTURE || USE_EMISSIVE_TEXTURE\n attribute vec2 a_uv0;\n uniform vec2 mainTiling;\n uniform vec2 mainOffset;\n varying vec2 uv0;\n#endif\n\n#if _USE_SKINNING\n #include \n#endif\n\n#if _USE_SHADOW_MAP\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n uniform mat4 _lightViewProjMatrix_{id};\n uniform float _minDepth_{id};\n uniform float _maxDepth_{id};\n varying vec4 pos_lightspace_{id};\n varying float vDepth_{id};\n #pragma endFor\n #endif\n#endif\n\nvec4 vert () {\n vec4 pos = vec4(a_position, 1);\n\n #if _USE_SKINNING\n mat4 skinMat = skinMatrix();\n pos = skinMat * pos;\n #endif\n\n pos_w = (_model * pos).xyz;\n pos = _viewProj * _model * pos;\n\n #if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_MRA_TEXTURE || USE_EMISSIVE_TEXTURE\n uv0 = a_uv0 * mainTiling + mainOffset;\n #endif\n\n vec4 normal = vec4(a_normal, 0);\n #if _USE_SKINNING\n normal = skinMat * normal;\n #endif\n normal_w = _normalMatrix * normal.xyz;\n\n #if _USE_SHADOW_MAP\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n pos_lightspace_{id} = _lightViewProjMatrix_{id} * vec4(pos_w, 1.0);\n vDepth_{id} = (pos_lightspace_{id}.z + _minDepth_{id}) / (_minDepth_{id} + _maxDepth_{id});\n #pragma endFor\n #endif\n #endif\n\n return pos;\n}\n", - "phong-fs": "\n\n#if USE_NORMAL_TEXTURE\n#extension GL_OES_standard_derivatives : enable\n#endif\n\n#include \n#include \n\nstruct LightInfo {\n vec3 diffuse;\n vec3 specular;\n};\n\nLightInfo computeDirectionalLighting(\n vec3 lightDirection,\n vec3 lightColor,\n vec3 normal,\n vec3 viewDirection,\n float glossiness\n) {\n LightInfo lightingResult;\n float ndl = 0.0;\n float ndh = 0.0;\n vec3 lightDir = -normalize(lightDirection);\n ndl = max(0.0, dot(normal, lightDir));\n lightingResult.diffuse = lightColor * ndl;\n\n vec3 dirH = normalize(viewDirection + lightDir);\n ndh = max(0.0, dot(normal, dirH));\n ndh = (ndl == 0.0) ? 0.0: ndh;\n ndh = pow(ndh, max(1.0, glossiness * 128.0));\n lightingResult.specular = lightColor * ndh;\n\n return lightingResult;\n}\n\nLightInfo computePointLighting(\n vec3 lightPosition,\n vec3 lightColor,\n float lightRange,\n vec3 normal,\n vec3 positionW,\n vec3 viewDirection,\n float glossiness\n) {\n LightInfo lightingResult;\n float ndl = 0.0;\n float ndh = 0.0;\n vec3 lightDir = vec3(0, 0, 0);\n float attenuation = 1.0;\n lightDir = lightPosition - positionW;\n attenuation = max(0., 1.0 - length(lightDir) / lightRange);\n lightDir = normalize(lightDir);\n ndl = max(0.0, dot(normal, lightDir));\n lightingResult.diffuse = lightColor * ndl * attenuation;\n\n vec3 dirH = normalize(viewDirection + lightDir);\n ndh = max(0.0, dot(normal, dirH));\n ndh = (ndl == 0.0) ? 0.0: ndh;\n ndh = pow(ndh, max(1.0, glossiness * 128.0));\n lightingResult.specular = lightColor * ndh * attenuation;\n\n return lightingResult;\n}\n\nLightInfo computeSpotLighting(\n vec3 lightPosition,\n vec3 lightDirection,\n vec3 lightColor,\n float lightRange,\n vec2 lightSpot,\n vec3 normal,\n vec3 positionW,\n vec3 viewDirection,\n float glossiness\n) {\n LightInfo lightingResult;\n float ndl = 0.0;\n float ndh = 0.0;\n vec3 lightDir = vec3(0, 0, 0);\n float attenuation = 1.0;\n float cosConeAngle = 1.0;\n\n lightDir = lightPosition - positionW;\n attenuation = max(0., 1.0 - length(lightDir) / lightRange);\n lightDir = normalize(lightDir);\n cosConeAngle = max(0., dot(lightDirection, -lightDir));\n cosConeAngle = cosConeAngle < lightSpot.x ? 0.0 : cosConeAngle;\n cosConeAngle = pow(cosConeAngle,lightSpot.y);\n ndl = max(0.0, dot(normal, lightDir));\n lightingResult.diffuse = lightColor * ndl * attenuation * cosConeAngle;\n\n vec3 dirH = normalize(viewDirection + lightDir);\n ndh = max(0.0, dot(normal, dirH));\n ndh = (ndl == 0.0) ? 0.0: ndh;\n ndh = pow(ndh, max(1.0, glossiness * 128.0));\n lightingResult.specular = lightColor * ndh * attenuation * cosConeAngle;\n\n return lightingResult;\n}\n\n#if _NUM_DIR_LIGHTS > 0\n #pragma for id in range(0, _NUM_DIR_LIGHTS)\n uniform vec3 _dir_light{id}_direction;\n uniform vec3 _dir_light{id}_color;\n #pragma endFor\n#endif\n\n#if _NUM_POINT_LIGHTS > 0\n #pragma for id in range(0, _NUM_POINT_LIGHTS)\n uniform vec3 _point_light{id}_position;\n uniform vec3 _point_light{id}_color;\n uniform float _point_light{id}_range;\n #pragma endFor\n#endif\n\n#if _NUM_SPOT_LIGHTS > 0\n #pragma for id in range(0, _NUM_SPOT_LIGHTS)\n uniform vec3 _spot_light{id}_position;\n uniform vec3 _spot_light{id}_direction;\n uniform vec3 _spot_light{id}_color;\n uniform float _spot_light{id}_range;\n uniform vec2 _spot_light{id}_spot;\n #pragma endFor\n#endif\n\nLightInfo getPhongLighting(\n vec3 normal,\n vec3 positionW,\n vec3 viewDirection,\n float glossiness\n) {\n LightInfo result;\n result.diffuse = vec3(0, 0, 0);\n result.specular = vec3(0, 0, 0);\n LightInfo dirLighting;\n #if _NUM_DIR_LIGHTS > 0\n #pragma for id in range(0, _NUM_DIR_LIGHTS)\n dirLighting = computeDirectionalLighting(_dir_light{id}_direction,_dir_light{id}_color,normal, viewDirection, glossiness);\n result.diffuse += dirLighting.diffuse;\n result.specular += dirLighting.specular;\n #pragma endFor\n #endif\n\n LightInfo pointLighting;\n #if _NUM_POINT_LIGHTS > 0\n #pragma for id in range(0, _NUM_POINT_LIGHTS)\n pointLighting = computePointLighting(_point_light{id}_position, _point_light{id}_color, _point_light{id}_range,\n normal, positionW, viewDirection, glossiness);\n result.diffuse += pointLighting.diffuse;\n result.specular += pointLighting.specular;\n #pragma endFor\n #endif\n\n LightInfo spotLighting;\n #if _NUM_SPOT_LIGHTS > 0\n #pragma for id in range(0, _NUM_SPOT_LIGHTS)\n spotLighting = computeSpotLighting(_spot_light{id}_position, _spot_light{id}_direction, _spot_light{id}_color,\n _spot_light{id}_range, _spot_light{id}_spot,normal, positionW, viewDirection, glossiness);\n result.diffuse += spotLighting.diffuse;\n result.specular += spotLighting.specular;\n #pragma endFor\n #endif\n return result;\n}\n\n#if _USE_SHADOW_MAP\n #include \n #include \n#endif\n\nuniform vec3 _eye;\nuniform vec3 ambient;\n\nvarying vec3 normal_w;\nvarying vec3 pos_w;\n\n#if USE_NORMAL_TEXTURE || USE_DIFFUSE_TEXTURE || USE_EMISSIVE_TEXTURE\n varying vec2 uv0;\n#endif\n\nstruct phongMaterial\n{\n vec3 diffuse;\n vec3 emissive;\n vec3 specular;\n float glossiness;\n float opacity;\n};\n\nuniform vec4 diffuseColor;\n#if USE_DIFFUSE_TEXTURE\n uniform sampler2D diffuse_texture;\n#endif\n\n#if USE_EMISSIVE\n uniform vec3 emissiveColor;\n #if USE_EMISSIVE_TEXTURE\n uniform sampler2D emissive_texture;\n #endif\n#endif\n\n#if USE_SPECULAR\n uniform vec3 specularColor;\n uniform float glossiness;\n #if USE_SPECULAR_TEXTURE\n uniform sampler2D specular_texture;\n #endif\n#endif\n\n#if USE_NORMAL_TEXTURE\n uniform sampler2D normal_texture;\n uniform float normalScale; \n vec3 getNormal(vec3 pos, vec3 normal) {\n vec3 q0 = vec3( dFdx( pos.x ), dFdx( pos.y ), dFdx( pos.z ) );\n vec3 q1 = vec3( dFdy( pos.x ), dFdy( pos.y ), dFdy( pos.z ) );\n vec2 st0 = dFdx( uv0.st );\n vec2 st1 = dFdy( uv0.st );\n vec3 S = normalize( q0 * st1.t - q1 * st0.t );\n vec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n vec3 N = normal;\n vec3 mapN = texture2D(normal_texture, uv0).rgb * 2.0 - 1.0;\n mapN.xy = 1.0 * mapN.xy;\n mat3 tsn = mat3( S, T, N );\n return normalize( tsn * mapN );\n }\n#endif\n\n#if USE_ALPHA_TEST\n uniform float alphaTestThreshold;\n#endif\n\nphongMaterial getPhongMaterial() {\n phongMaterial result;\n\n #if USE_DIFFUSE_TEXTURE\n vec4 baseColor = diffuseColor * gammaToLinearSpaceRGBA(texture2D(diffuse_texture, uv0));\n result.diffuse = baseColor.rgb;\n result.opacity = baseColor.a;\n #else\n result.diffuse = diffuseColor.rgb;\n result.opacity = diffuseColor.a;\n #endif\n\n #if USE_EMISSIVE\n result.emissive = gammaToLinearSpaceRGB(emissiveColor);\n #if USE_EMISSIVE_TEXTURE\n result.emissive *= gammaToLinearSpaceRGB(texture2D(emissive_texture, uv0).rgb);\n #endif\n #endif\n\n #if USE_SPECULAR\n result.specular = gammaToLinearSpaceRGB(specularColor);\n #if USE_SPECULAR_TEXTURE\n result.specular = gammaToLinearSpaceRGB(texture2D(specular_texture, uv0).rgb);\n #endif\n\n result.glossiness = glossiness;\n #endif\n\n return result;\n}\n\nvec4 composePhongShading(LightInfo lighting, phongMaterial mtl, float shadow)\n{\n vec4 o = vec4(0.0, 0.0, 0.0, 1.0);\n\n \n o.xyz = lighting.diffuse * mtl.diffuse;\n #if USE_EMISSIVE\n o.xyz += mtl.emissive;\n #endif\n #if USE_SPECULAR\n o.xyz += lighting.specular * mtl.specular;\n #endif\n o.xyz *= shadow;\n o.w = mtl.opacity;\n\n return o;\n}\n\nvec4 frag () {\n LightInfo phongLighting;\n vec3 viewDirection = normalize(_eye - pos_w);\n\n phongMaterial mtl = getPhongMaterial();\n #if USE_ALPHA_TEST\n if(mtl.opacity < alphaTestThreshold) discard;\n #endif\n vec3 normal = normalize(normal_w);\n #if USE_NORMAL_TEXTURE\n normal = getNormal(pos_w, normal);\n #endif\n phongLighting = getPhongLighting(normal, pos_w, viewDirection, mtl.glossiness);\n phongLighting.diffuse += ambient;\n\n #if _USE_SHADOW_MAP\n float shadow = 1.0;\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n shadow *= computeShadowESM(_shadowMap_{id}, pos_lightspace_{id}, vDepth_{id}, _depthScale_{id}, _darkness_{id}, _frustumEdgeFalloff_{id});\n #pragma endFor\n #endif\n vec4 finalColor = composePhongShading(phongLighting, mtl, shadow);\n #else\n vec4 finalColor = composePhongShading(phongLighting, mtl, 1.0);\n #endif\n\n return linearToGammaSpaceRGBA(finalColor);\n}\n", - "phong-vs": "\n\nattribute vec3 a_position;\nattribute vec3 a_normal;\n\nuniform mat4 _model;\nuniform mat4 _viewProj;\nuniform mat3 _normalMatrix;\n\nvarying vec3 normal_w;\nvarying vec3 pos_w;\n\n#if USE_NORMAL_TEXTURE || USE_DIFFUSE_TEXTURE || USE_EMISSIVE_TEXTURE\n attribute vec2 a_uv0;\n uniform vec2 mainTiling;\n uniform vec2 mainOffset;\n varying vec2 uv0;\n#endif\n\n#if _USE_SKINNING\n #include \n#endif\n\n#if _USE_SHADOW_MAP\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n uniform mat4 _lightViewProjMatrix_{id};\n uniform float _minDepth_{id};\n uniform float _maxDepth_{id};\n varying vec4 pos_lightspace_{id};\n varying float vDepth_{id};\n #pragma endFor\n #endif\n#endif\n\nvec4 vert () {\n vec4 pos = vec4(a_position, 1);\n\n #if _USE_SKINNING\n mat4 skinMat = skinMatrix();\n pos = skinMat * pos;\n #endif\n\n pos_w = (_model * pos).xyz;\n pos = _viewProj * _model * pos;\n\n #if USE_NORMAL_TEXTURE || USE_DIFFUSE_TEXTURE || USE_EMISSIVE_TEXTURE\n uv0 = a_uv0 * mainTiling + mainOffset;\n #endif\n\n vec4 normal = vec4(a_normal, 0);\n #if _USE_SKINNING\n normal = skinMat * normal;\n #endif\n normal_w = _normalMatrix * normal.xyz;\n\n #if _USE_SHADOW_MAP\n #if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n pos_lightspace_{id} = _lightViewProjMatrix_{id} * vec4(pos_w, 1.0);\n vDepth_{id} = (pos_lightspace_{id}.z + _minDepth_{id}) / (_minDepth_{id} + _maxDepth_{id});\n #pragma endFor\n #endif\n #endif\n\n return pos;\n}\n", - "rect-area-light": "\n\nmat3 transpose(mat3 v) {\n mat3 tmp;\n tmp[0] = vec3(v[0].x, v[1].x, v[2].x);\n tmp[1] = vec3(v[0].y, v[1].y, v[2].y);\n tmp[2] = vec3(v[0].z, v[1].z, v[2].z);\n\n return tmp;\n}\n\nvoid ClipQuadToHorizon(inout vec3 L[5], out int n) {\n \n int config = 0;\n if (L[0].z > 0.0) config += 1;\n if (L[1].z > 0.0) config += 2;\n if (L[2].z > 0.0) config += 4;\n if (L[3].z > 0.0) config += 8;\n config = 15;\n\n \n n = 0;\n\n if (config == 0)\n {\n \n }\n else if (config == 1) \n {\n n = 3;\n L[1] = -L[1].z * L[0] + L[0].z * L[1];\n L[2] = -L[3].z * L[0] + L[0].z * L[3];\n }\n else if (config == 2) \n {\n n = 3;\n L[0] = -L[0].z * L[1] + L[1].z * L[0];\n L[2] = -L[2].z * L[1] + L[1].z * L[2];\n }\n else if (config == 3) \n {\n n = 4;\n L[2] = -L[2].z * L[1] + L[1].z * L[2];\n L[3] = -L[3].z * L[0] + L[0].z * L[3];\n }\n else if (config == 4) \n {\n n = 3;\n L[0] = -L[3].z * L[2] + L[2].z * L[3];\n L[1] = -L[1].z * L[2] + L[2].z * L[1];\n }\n else if (config == 5) \n {\n n = 0;\n }\n else if (config == 6) \n {\n n = 4;\n L[0] = -L[0].z * L[1] + L[1].z * L[0];\n L[3] = -L[3].z * L[2] + L[2].z * L[3];\n }\n else if (config == 7) \n {\n n = 5;\n L[4] = -L[3].z * L[0] + L[0].z * L[3];\n L[3] = -L[3].z * L[2] + L[2].z * L[3];\n }\n else if (config == 8) \n {\n n = 3;\n L[0] = -L[0].z * L[3] + L[3].z * L[0];\n L[1] = -L[2].z * L[3] + L[3].z * L[2];\n L[2] = L[3];\n }\n else if (config == 9) \n {\n n = 4;\n L[1] = -L[1].z * L[0] + L[0].z * L[1];\n L[2] = -L[2].z * L[3] + L[3].z * L[2];\n }\n else if (config == 10) \n {\n n = 0;\n }\n else if (config == 11) \n {\n n = 5;\n L[4] = L[3];\n L[3] = -L[2].z * L[3] + L[3].z * L[2];\n L[2] = -L[2].z * L[1] + L[1].z * L[2];\n }\n else if (config == 12) \n {\n n = 4;\n L[1] = -L[1].z * L[2] + L[2].z * L[1];\n L[0] = -L[0].z * L[3] + L[3].z * L[0];\n }\n else if (config == 13) \n {\n n = 5;\n L[4] = L[3];\n L[3] = L[2];\n L[2] = -L[1].z * L[2] + L[2].z * L[1];\n L[1] = -L[1].z * L[0] + L[0].z * L[1];\n }\n else if (config == 14) \n {\n n = 5;\n L[4] = -L[0].z * L[3] + L[3].z * L[0];\n L[0] = -L[0].z * L[1] + L[1].z * L[0];\n }\n else if (config == 15) \n {\n n = 4;\n }\n\n if (n == 3)\n L[3] = L[0];\n if (n == 4)\n L[4] = L[0];\n}\n\n\nfloat IntegrateEdge(vec3 v1, vec3 v2) {\n float cosTheta = dot(v1, v2);\n float theta = acos(cosTheta);\n return cross(v1, v2).z * ((theta > 0.001) ? theta/sin(theta) : 4.0);\n}\n\nvec3 LTC_Evaluate(vec3 N, vec3 V, vec3 P, mat3 Minv, vec3 points[4]) {\n \n vec3 T1, T2;\n T1 = normalize(V - N*dot(V, N));\n T2 = cross(N, T1);\n\n \n Minv = Minv * transpose(mat3(T1, T2, N));\n\n \n vec3 L[5];\n L[0] = Minv * (points[0] - P);\n L[1] = Minv * (points[1] - P);\n L[2] = Minv * (points[2] - P);\n L[3] = Minv * (points[3] - P);\n\n int n;\n ClipQuadToHorizon(L, n);\n\n if (n == 0)\n return vec3(0, 0, 0);\n\n \n L[0] = normalize(L[0]);\n L[1] = normalize(L[1]);\n L[2] = normalize(L[2]);\n L[3] = normalize(L[3]);\n L[4] = normalize(L[4]);\n\n \n float sum = 0.0;\n\n sum += IntegrateEdge(L[0], L[1]);\n sum += IntegrateEdge(L[1], L[2]);\n sum += IntegrateEdge(L[2], L[3]);\n if (n >= 4)\n sum += IntegrateEdge(L[3], L[4]);\n if (n == 5)\n sum += IntegrateEdge(L[4], L[0]);\n\n sum = max(0.0, sum);\n\n vec3 Lo_i = vec3(sum, sum, sum);\n\n return Lo_i;\n}\n", - "shadow-depth-fs": "\n\nuniform float _depthScale;\nvarying float vDepth;\n\n#include \n\nvec4 frag() {\n \n \n return packDepthToRGBA(vDepth);\n \n \n}\n", - "shadow-depth-vs": "\n\nattribute vec3 a_position;\n\nuniform mat4 _model;\nuniform mat4 _lightViewProjMatrix;\nuniform float _minDepth;\nuniform float _maxDepth;\nuniform float _bias;\nvarying float vDepth;\n\n#if _USE_SKINNING\n #include \n#endif\n\nvec4 vert() {\n vec4 pos = vec4(a_position, 1);\n\n #if _USE_SKINNING\n mat4 skinMat = skinMatrix();\n pos = skinMat * pos;\n #endif\n\n \n vDepth = ((gl_Position.z + _minDepth) / (_minDepth + _maxDepth)) + _bias;\n return _lightViewProjMatrix * _model * pos;\n}\n", - "shadow-mapping": "\n\n#if _NUM_SHADOW_LIGHTS > 0\n #pragma for id in range(0, _NUM_SHADOW_LIGHTS)\n uniform sampler2D _shadowMap_{id};\n uniform float _darkness_{id};\n uniform float _depthScale_{id};\n uniform float _frustumEdgeFalloff_{id};\n uniform float _bias_{id};\n uniform vec2 _texelSize_{id};\n varying vec4 pos_lightspace_{id};\n varying float vDepth_{id};\n #pragma endFor\n#endif\n\nfloat computeShadow(sampler2D shadowMap, vec4 pos_lightspace, float bias) {\n vec3 projCoords = pos_lightspace.xyz / pos_lightspace.w;\n projCoords = projCoords * 0.5 + 0.5;\n float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, projCoords.xy));\n float currentDepth = projCoords.z;\n float shadow = (currentDepth - bias > closestDepth) ? 0.0 : 1.0;\n return shadow;\n}\n\nfloat computeFallOff(float esm, vec2 coords, float frustumEdgeFalloff) {\n float mask = smoothstep(1.0 - frustumEdgeFalloff, 1.0, clamp(dot(coords, coords), 0.0, 1.0));\n return mix(esm, 1.0, mask);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nfloat computeShadowESM(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float depthScale, float darkness, float frustumEdgeFalloff) {\n vec2 projCoords = pos_lightspace.xy / pos_lightspace.w;\n vec2 shadowUV = projCoords * 0.5 + vec2(0.5);\n if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) {\n return 1.0;\n }\n float currentDepth = clamp(vDepth, 0.0, 1.0);\n float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, shadowUV));\n \n float esm = clamp(exp(-depthScale * (currentDepth - closestDepth)), 1.0 - darkness, 1.0);\n return computeFallOff(esm, projCoords, frustumEdgeFalloff);\n}\n\nfloat computeShadowPCF(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float darkness, vec2 texelSize, float frustumEdgeFalloff) {\n vec2 projCoords = pos_lightspace.xy / pos_lightspace.w;\n vec2 shadowUV = projCoords * 0.5 + vec2(0.5);\n if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) {\n return 1.0;\n }\n float currentDepth = clamp(vDepth, 0.0, 1.0);\n float visibility = 1.0;\n vec2 poissonDisk[4];\n poissonDisk[0] = vec2(-0.94201624, -0.39906216);\n poissonDisk[1] = vec2(0.94558609, -0.76890725);\n poissonDisk[2] = vec2(-0.094184101, -0.92938870);\n poissonDisk[3] = vec2(0.34495938, 0.29387760);\n if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[0] * texelSize)) < currentDepth) visibility -= 0.25;\n if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[1] * texelSize)) < currentDepth) visibility -= 0.25;\n if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[2] * texelSize)) < currentDepth) visibility -= 0.25;\n if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[3] * texelSize)) < currentDepth) visibility -= 0.25;\n\n return computeFallOff(min(1.0, visibility + 1.0 - darkness), projCoords, frustumEdgeFalloff);\n}", - "skinning": "\n\nattribute vec4 a_weights;\nattribute vec4 a_joints;\n\n#if _USE_JOINTS_TEXTRUE\nuniform sampler2D _jointsTexture;\nuniform float _jointsTextureSize;\n\nmat4 getBoneMatrix(const in float i) {\n float size = _jointsTextureSize;\n float j = i * 4.0;\n float x = mod(j, size);\n float y = floor(j / size);\n\n float dx = 1.0 / size;\n float dy = 1.0 / size;\n\n y = dy * (y + 0.5);\n\n vec4 v1 = texture2D(_jointsTexture, vec2(dx * (x + 0.5), y));\n vec4 v2 = texture2D(_jointsTexture, vec2(dx * (x + 1.5), y));\n vec4 v3 = texture2D(_jointsTexture, vec2(dx * (x + 2.5), y));\n vec4 v4 = texture2D(_jointsTexture, vec2(dx * (x + 3.5), y));\n\n return mat4(v1, v2, v3, v4);\n}\n#else\nuniform mat4 _jointMatrices[64];\n\nmat4 getBoneMatrix(const in float i) {\n return _jointMatrices[int(i)];\n}\n#endif\n\nmat4 skinMatrix() {\n return\n getBoneMatrix(a_joints.x) * a_weights.x +\n getBoneMatrix(a_joints.y) * a_weights.y +\n getBoneMatrix(a_joints.z) * a_weights.z +\n getBoneMatrix(a_joints.w) * a_weights.w\n ;\n}", - "unlit-fs": "\n\n#if USE_TEXTURE\n uniform sampler2D texture;\n#endif\n\n#if _USE_ATTRIBUTE_UV0\n varying vec2 v_uv0;\n#endif\n\n#if _USE_ATTRIBUTE_COLOR\n varying vec4 v_color;\n#endif\n\nuniform vec4 color;\n\nvec4 frag () {\n vec4 o = color;\n \n #if _USE_ATTRIBUTE_COLOR\n o *= v_color;\n #endif\n\n #if USE_TEXTURE && _USE_ATTRIBUTE_UV0\n o *= texture2D(texture, v_uv0);\n #endif\n\n return o;\n}", - "unlit-vs": "\n\nuniform mat4 _viewProj;\nuniform mat4 _model;\n\nattribute vec3 a_position;\n\n#if _USE_ATTRIBUTE_COLOR\n attribute lowp vec4 a_color;\n varying lowp vec4 v_color;\n#endif\n\n#if _USE_ATTRIBUTE_UV0\n attribute vec2 a_uv0;\n varying vec2 v_uv0;\n#endif\n\n#if _USE_SKINNING\n #include \n#endif\n\nvec4 vert () {\n mat4 mvp = _viewProj * _model;\n\n #if _USE_SKINNING\n mvp = mvp * skinMatrix();\n #endif\n\n vec4 pos = mvp * vec4(a_position, 1);\n\n #if _USE_ATTRIBUTE_UV0\n v_uv0 = a_uv0;\n #endif\n\n #if _USE_ATTRIBUTE_COLOR\n v_color = a_color;\n #endif\n\n return pos;\n}", - "unpack": "\n\nvec3 unpackNormal(vec4 nmap) {\n return nmap.xyz * 2.0 - 1.0;\n}\n\nvec3 unpackRGBE(vec4 rgbe) {\n return rgbe.rgb * pow(2.0, rgbe.a * 255.0 - 128.0);\n}" -} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/phong-fs.inc b/cocos2d/renderer/build/chunks/phong-fs.inc index 2ad3bc88f81..740359b8e38 100644 --- a/cocos2d/renderer/build/chunks/phong-fs.inc +++ b/cocos2d/renderer/build/chunks/phong-fs.inc @@ -7,6 +7,10 @@ #include #include +#if _USE_ATTRIBUTE_COLOR + varying vec4 v_color; +#endif + struct LightInfo { vec3 diffuse; vec3 specular; @@ -171,13 +175,12 @@ LightInfo getPhongLighting( #endif uniform vec3 _eye; -uniform vec3 ambient; varying vec3 normal_w; varying vec3 pos_w; #if USE_DIFFUSE_TEXTURE || USE_NORMAL_TEXTURE || USE_EMISSIVE_TEXTURE - varying vec2 uv0; + varying vec2 v_uv0; #endif struct phongMaterial @@ -215,12 +218,12 @@ uniform vec4 diffuseColor; vec3 getNormal(vec3 pos, vec3 normal) { vec3 q0 = vec3( dFdx( pos.x ), dFdx( pos.y ), dFdx( pos.z ) ); vec3 q1 = vec3( dFdy( pos.x ), dFdy( pos.y ), dFdy( pos.z ) ); - vec2 st0 = dFdx( uv0.st ); - vec2 st1 = dFdy( uv0.st ); + vec2 st0 = dFdx( v_uv0.st ); + vec2 st1 = dFdy( v_uv0.st ); vec3 S = normalize( q0 * st1.t - q1 * st0.t ); vec3 T = normalize( -q0 * st1.s + q1 * st0.s ); vec3 N = normal; - vec3 mapN = texture2D(normal_texture, uv0).rgb * 2.0 - 1.0; + vec3 mapN = texture2D(normal_texture, v_uv0).rgb * 2.0 - 1.0; mapN.xy = 1.0 * mapN.xy; mat3 tsn = mat3( S, T, N ); return normalize( tsn * mapN ); @@ -234,26 +237,31 @@ uniform vec4 diffuseColor; phongMaterial getPhongMaterial() { phongMaterial result; + result.diffuse = diffuseColor.rgb; + result.opacity = diffuseColor.a; + + #if _USE_ATTRIBUTE_COLOR + result.diffuse *= v_color.rgb; + result.opacity *= v_color.a; + #endif + #if USE_DIFFUSE_TEXTURE - vec4 baseColor = diffuseColor * gammaToLinearSpaceRGBA(texture2D(diffuse_texture, uv0)); - result.diffuse = baseColor.rgb; - result.opacity = baseColor.a; - #else - result.diffuse = diffuseColor.rgb; - result.opacity = diffuseColor.a; + vec4 baseColor = gammaToLinearSpaceRGBA(texture2D(diffuse_texture, v_uv0)); + result.diffuse *= baseColor.rgb; + result.opacity *= baseColor.a; #endif #if USE_EMISSIVE result.emissive = gammaToLinearSpaceRGB(emissiveColor); #if USE_EMISSIVE_TEXTURE - result.emissive *= gammaToLinearSpaceRGB(texture2D(emissive_texture, uv0).rgb); + result.emissive *= gammaToLinearSpaceRGB(texture2D(emissive_texture, v_uv0).rgb); #endif #endif #if USE_SPECULAR result.specular = gammaToLinearSpaceRGB(specularColor); #if USE_SPECULAR_TEXTURE - result.specular = gammaToLinearSpaceRGB(texture2D(specular_texture, uv0).rgb); + result.specular = gammaToLinearSpaceRGB(texture2D(specular_texture, v_uv0).rgb); #endif result.glossiness = glossiness; @@ -293,7 +301,6 @@ vec4 frag () { normal = getNormal(pos_w, normal); #endif phongLighting = getPhongLighting(normal, pos_w, viewDirection, mtl.glossiness); - phongLighting.diffuse += ambient; #if _USE_SHADOW_MAP vec4 finalColor = composePhongShading(phongLighting, mtl, computeShadow()); diff --git a/cocos2d/renderer/build/chunks/phong-vs.inc b/cocos2d/renderer/build/chunks/phong-vs.inc index 47ebab374a3..dc3b421211b 100644 --- a/cocos2d/renderer/build/chunks/phong-vs.inc +++ b/cocos2d/renderer/build/chunks/phong-vs.inc @@ -3,6 +3,11 @@ attribute vec3 a_position; attribute vec3 a_normal; +#if _USE_ATTRIBUTE_COLOR + attribute lowp vec4 a_color; + varying lowp vec4 v_color; +#endif + uniform mat4 _model; uniform mat4 _viewProj; uniform mat3 _normalMatrix; @@ -14,7 +19,7 @@ varying vec3 pos_w; attribute vec2 a_uv0; uniform vec2 mainTiling; uniform vec2 mainOffset; - varying vec2 uv0; + varying vec2 v_uv0; #endif #if _USE_SKINNING @@ -43,7 +48,11 @@ vec4 vert () { #endif #if USE_DIFFUSE_TEXTURE || USE_NORMAL_TEXTURE || USE_EMISSIVE_TEXTURE - uv0 = a_uv0 * mainTiling + mainOffset; + v_uv0 = a_uv0 * mainTiling + mainOffset; + #endif + + #if _USE_ATTRIBUTE_COLOR + v_color = a_color; #endif return pos; diff --git a/cocos2d/renderer/build/chunks/shadow-mapping.inc b/cocos2d/renderer/build/chunks/shadow-mapping.inc index 9bcafb9eba4..4824d0e07d1 100644 --- a/cocos2d/renderer/build/chunks/shadow-mapping.inc +++ b/cocos2d/renderer/build/chunks/shadow-mapping.inc @@ -13,24 +13,6 @@ #pragma endFor #endif -// float computeShadow(sampler2D shadowMap, vec4 pos_lightspace, float bias) { -// vec3 projCoords = pos_lightspace.xyz / pos_lightspace.w; -// projCoords = projCoords * 0.5 + 0.5; -// float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, projCoords.xy)); -// float currentDepth = projCoords.z; -// float shadow = (currentDepth - bias > closestDepth) ? 0.0 : 1.0; -// return shadow; -// } - -float computeShadow() { - float shadow = 1.0; - #if _NUM_SHADOW_LIGHTS > 0 - #pragma for id in range(0, _NUM_SHADOW_LIGHTS) - shadow *= computeShadowESM(_shadowMap_{id}, pos_lightspace_{id}, vDepth_{id}, _depthScale_{id}, _darkness_{id}, _frustumEdgeFalloff_{id}); - #pragma endFor - #endif - return shadow; -} float computeFallOff(float esm, vec2 coords, float frustumEdgeFalloff) { float mask = smoothstep(1.0 - frustumEdgeFalloff, 1.0, clamp(dot(coords, coords), 0.0, 1.0)); @@ -63,23 +45,43 @@ float computeShadowESM(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, f return computeFallOff(esm, projCoords, frustumEdgeFalloff); } -float computeShadowPCF(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float darkness, vec2 texelSize, float frustumEdgeFalloff) { - vec2 projCoords = pos_lightspace.xy / pos_lightspace.w; - vec2 shadowUV = projCoords * 0.5 + vec2(0.5); - if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) { - return 1.0; - } - float currentDepth = clamp(vDepth, 0.0, 1.0); - float visibility = 1.0; - vec2 poissonDisk[4]; - poissonDisk[0] = vec2(-0.94201624, -0.39906216); - poissonDisk[1] = vec2(0.94558609, -0.76890725); - poissonDisk[2] = vec2(-0.094184101, -0.92938870); - poissonDisk[3] = vec2(0.34495938, 0.29387760); - if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[0] * texelSize)) < currentDepth) visibility -= 0.25; - if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[1] * texelSize)) < currentDepth) visibility -= 0.25; - if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[2] * texelSize)) < currentDepth) visibility -= 0.25; - if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[3] * texelSize)) < currentDepth) visibility -= 0.25; +// float computeShadowPCF(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float darkness, vec2 texelSize, float frustumEdgeFalloff) { +// vec2 projCoords = pos_lightspace.xy / pos_lightspace.w; +// vec2 shadowUV = projCoords * 0.5 + vec2(0.5); +// if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) { +// return 1.0; +// } +// float currentDepth = clamp(vDepth, 0.0, 1.0); +// float visibility = 1.0; +// vec2 poissonDisk[4]; +// poissonDisk[0] = vec2(-0.94201624, -0.39906216); +// poissonDisk[1] = vec2(0.94558609, -0.76890725); +// poissonDisk[2] = vec2(-0.094184101, -0.92938870); +// poissonDisk[3] = vec2(0.34495938, 0.29387760); +// if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[0] * texelSize)) < currentDepth) visibility -= 0.25; +// if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[1] * texelSize)) < currentDepth) visibility -= 0.25; +// if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[2] * texelSize)) < currentDepth) visibility -= 0.25; +// if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[3] * texelSize)) < currentDepth) visibility -= 0.25; + +// return computeFallOff(min(1.0, visibility + 1.0 - darkness), projCoords, frustumEdgeFalloff); +// } + + +float computeShadow(sampler2D shadowMap, vec4 pos_lightspace, float bias) { + vec3 projCoords = pos_lightspace.xyz / pos_lightspace.w; + projCoords = projCoords * 0.5 + 0.5; + float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, projCoords.xy)); + float currentDepth = projCoords.z; + float shadow = (currentDepth - bias > closestDepth) ? 0.0 : 1.0; + return shadow; +} - return computeFallOff(min(1.0, visibility + 1.0 - darkness), projCoords, frustumEdgeFalloff); -} \ No newline at end of file +float computeShadow() { + float shadow = 1.0; + #if _NUM_SHADOW_LIGHTS > 0 + #pragma for id in range(0, _NUM_SHADOW_LIGHTS) + shadow *= computeShadowESM(_shadowMap_{id}, pos_lightspace_{id}, vDepth_{id}, _depthScale_{id}, _darkness_{id}, _frustumEdgeFalloff_{id}); + #pragma endFor + #endif + return shadow; +} diff --git a/cocos2d/renderer/scene/light.js b/cocos2d/renderer/scene/light.js index 672efe6125f..5887cb62b2c 100644 --- a/cocos2d/renderer/scene/light.js +++ b/cocos2d/renderer/scene/light.js @@ -37,7 +37,7 @@ function _computePointLightViewProjMatrix(light, outView, outProj) { light._node.getWorldRT(outView); mat4.invert(outView, outView); - // The transformation from Cartesian to polar coordinates is not a linear function, + // The transformation from Cartesian to polar coordinates is not a linear function, // so it cannot be achieved by means of a fixed matrix multiplication. // Here we just use a nearly 180 degree perspective matrix instead. mat4.perspective(outProj, toRadian(179), 1, light._shadowMinDepth, light._shadowMaxDepth); @@ -90,7 +90,15 @@ export default class Light { } /** - * set the hosting node of this light + * Get the hosting node of this camera + * @returns {Node} the hosting node + */ + getNode() { + return this._node; + } + + /** + * Set the hosting node of this camera * @param {Node} node the hosting node */ setNode(node) { @@ -489,4 +497,4 @@ export default class Light { } } -} \ No newline at end of file +} diff --git a/modules.json b/modules.json index 79b69a02912..106897a5c95 100644 --- a/modules.json +++ b/modules.json @@ -272,6 +272,13 @@ ], "dependencies": ["Mesh", "WebGL Renderer"] }, + { + "name": "3D Primitive", + "entries": [ + "./cocos2d/core/3d/primitive/index.js" + ], + "dependencies": ["3D"] + }, { "name": "Mesh", "entries": [ From 18325d3837b91219c0386e27aac9c2dbeb76b91b Mon Sep 17 00:00:00 2001 From: pandamicro Date: Mon, 14 Jan 2019 17:39:49 +0800 Subject: [PATCH 0404/1631] Upgrade renderer & gfx for native renderer --- cocos2d/core/assets/material/CCMaterial.js | 3 + .../core/renderer/webgl/assemblers/utils.js | 8 +-- cocos2d/renderer/gfx/device.js | 16 ++++- cocos2d/renderer/render-data/render-data.js | 59 ++++++------------- cocos2d/renderer/scene/camera.js | 13 ++++ cocos2d/renderer/scene/model.js | 18 ------ cocos2d/renderer/scene/scene.js | 11 ---- 7 files changed, 54 insertions(+), 74 deletions(-) diff --git a/cocos2d/core/assets/material/CCMaterial.js b/cocos2d/core/assets/material/CCMaterial.js index 12b0710c773..3c58f85d560 100644 --- a/cocos2d/core/assets/material/CCMaterial.js +++ b/cocos2d/core/assets/material/CCMaterial.js @@ -179,6 +179,9 @@ let Material = cc.Class({ updateHash (hash) { this._dirty = false; this._hash = hash; + if (CC_JSB && this._effect) { + this._effect.updateHash(this._hash); + } }, getHash () { diff --git a/cocos2d/core/renderer/webgl/assemblers/utils.js b/cocos2d/core/renderer/webgl/assemblers/utils.js index f983bd603fb..c28bf2d5fef 100644 --- a/cocos2d/core/renderer/webgl/assemblers/utils.js +++ b/cocos2d/core/renderer/webgl/assemblers/utils.js @@ -27,7 +27,7 @@ function fillVertices (node, buffer, renderData, color) { } function fillMeshVertices (node, buffer, renderData, color) { - let data = renderData._data, + let verts = renderData.vertices, vertexOffset = buffer.byteOffset >> 2; let vertexCount = renderData.vertexCount, @@ -45,7 +45,7 @@ function fillMeshVertices (node, buffer, renderData, color) { let a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; for (let i = 0; i < vertexCount; i++) { - let vert = data[i]; + let vert = verts[i]; vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; vbuf[vertexOffset++] = vert.u; @@ -92,7 +92,7 @@ function fillVertices3D (node, buffer, renderData, color) { } function fillMeshVertices3D (node, buffer, renderData, color) { - let data = renderData._data, + let verts = renderData.vertices, vertexOffset = buffer.byteOffset >> 2; let vertexCount = renderData.vertexCount, @@ -109,7 +109,7 @@ function fillMeshVertices3D (node, buffer, renderData, color) { let matrix = node._worldMatrix; for (let i = 0; i < vertexCount; i++) { - let vert = data[i]; + let vert = verts[i]; vec3.set(vec3_temp, vert.x, vert.y, 0); vec3.transformMat4(vec3_temp, vec3_temp, matrix); vbuf[vertexOffset++] = vec3_temp.x; diff --git a/cocos2d/renderer/gfx/device.js b/cocos2d/renderer/gfx/device.js index 62c9df8c338..9f317200d57 100644 --- a/cocos2d/renderer/gfx/device.js +++ b/cocos2d/renderer/gfx/device.js @@ -1216,6 +1216,20 @@ export default class Device { this._next.primitiveType = type; } + /** + * @method resetDrawCalls + */ + resetDrawCalls () { + this._stats.drawcalls = 0; + } + + /** + * @method getDrawCalls + */ + getDrawCalls () { + return this._stats.drawcalls; + } + /** * @method draw * @param {Number} base @@ -1309,7 +1323,7 @@ export default class Device { // } // update stats - this._stats.drawcalls += 1; + this._stats.drawcalls++; // reset states cur.set(next); diff --git a/cocos2d/renderer/render-data/render-data.js b/cocos2d/renderer/render-data/render-data.js index 32fab10d26b..19e9398b5ea 100644 --- a/cocos2d/renderer/render-data/render-data.js +++ b/cocos2d/renderer/render-data/render-data.js @@ -4,7 +4,7 @@ import { Pool } from '../memop'; import BaseRenderData from './base-render-data'; var _pool; -var _dataPool = new Pool(() => { +var _vertsPool = new Pool(() => { return { x: 0.0, y: 0.0, @@ -25,16 +25,9 @@ var _dataPool = new Pool(() => { export default class RenderData extends BaseRenderData { constructor () { super(); - this._data = []; - this._indices = []; - - this._pivotX = 0; - this._pivotY = 0; - this._width = 0; - this._height = 0; - - this.uvDirty = true; - this.vertDirty = true; + this.vertices = []; + this.indices = []; + this.material = null; } get type () { @@ -42,34 +35,21 @@ export default class RenderData extends BaseRenderData { } get dataLength () { - return this._data.length; + return this.vertices.length; } set dataLength (length) { - let data = this._data; - if (data.length !== length) { - // Free extra data - for (let i = length; i < data.length; i++) { - _dataPool.free(data[i]); + let verts = this.vertices; + if (verts.length !== length) { + // Free extra vertices + for (let i = length; i < verts.length; i++) { + _vertsPool.free(verts[i]); } - // Alloc needed data - for (let i = data.length; i < length; i++) { - data[i] = _dataPool.alloc(); + // Alloc needed vertices + for (let i = verts.length; i < length; i++) { + verts[i] = _vertsPool.alloc(); } - data.length = length; - } - } - - updateSizeNPivot (width, height, pivotX, pivotY) { - if (width !== this._width || - height !== this._height || - pivotX !== this._pivotX || - pivotY !== this._pivotY) { - this._width = width; - this._height = height; - this._pivotX = pivotX; - this._pivotY = pivotY; - this.vertDirty = true; + verts.length = length; } } @@ -79,14 +59,13 @@ export default class RenderData extends BaseRenderData { static free (data) { if (data instanceof RenderData) { - for (let i = data.length-1; i > 0; i--) { - _dataPool.free(data._data[i]); + let verts = data.vertices; + for (let i = verts.length-1; i > 0; i--) { + _vertsPool.free(verts[i]); } - data._data.length = 0; - data._indices.length = 0; + data.vertices.length = 0; + data.indices.length = 0; data.material = null; - data.uvDirty = true; - data.vertDirty = true; data.vertexCount = 0; data.indiceCount = 0; _pool.free(data); diff --git a/cocos2d/renderer/scene/camera.js b/cocos2d/renderer/scene/camera.js index 67660f54503..3fe2f721396 100644 --- a/cocos2d/renderer/scene/camera.js +++ b/cocos2d/renderer/scene/camera.js @@ -53,6 +53,19 @@ export default class Camera { this._cullingMask = 0xffffffff; } + // culling mask + get cullingMask() { + return this._cullingMask; + } + + set cullingMask(mask) { + this._cullingMask = mask; + } + + setCullingMask (mask) { + this._cullingMask = mask; + } + /** * Get the hosting node of this camera * @returns {Node} the hosting node diff --git a/cocos2d/renderer/scene/model.js b/cocos2d/renderer/scene/model.js index 6e0291bacf9..4f3f31c52d5 100644 --- a/cocos2d/renderer/scene/model.js +++ b/cocos2d/renderer/scene/model.js @@ -24,24 +24,6 @@ export default class Model { this._uniforms = null; } - _updateTransform() { - if (!this._node._hasChanged || !this._boundingShape) return; - this._node.updateWorldTransformFull(); - this._bsModelSpace.transform(this._node._mat, this._node._pos, - this._node._rot, this._node._scale, this._boundingShape); - } - - /** - * Create the bounding shape of this model - * @param {vec3} minPos the min position of the model - * @param {vec3} maxPos the max position of the model - */ - createBoundingShape(minPos, maxPos) { - if (!minPos || !maxPos) return; - this._bsModelSpace = aabb.fromPoints(aabb.create(), minPos, maxPos); - this._boundingShape = aabb.clone(this._bsModelSpace); - } - /** * Set the hosting node of this model * @param {Node} node the hosting node diff --git a/cocos2d/renderer/scene/scene.js b/cocos2d/renderer/scene/scene.js index 0f338ba1969..5af28211e90 100644 --- a/cocos2d/renderer/scene/scene.js +++ b/cocos2d/renderer/scene/scene.js @@ -39,17 +39,6 @@ class Scene { item._poolID = -1; } - /** - * update built-in bounding shapes if needed, - * used in the frustum culling process - */ - tick() { - for (let i = 0; i < this._models.length; ++i) { - let model = this._models.data[i]; - model._updateTransform(); - } - } - /** * reset the model viewIDs */ From 52bb99c9f32d2e907b2fcfc3743f7000efa5c607 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 15 Jan 2019 13:59:59 +0800 Subject: [PATCH 0405/1631] refine shader (#3749) * 1. change '_' to 'cc_' as the builtin in uniform prefix 2. split phong shader to modules * 1. add ignore defines 2. fixed color tag 3. shdc-lib should use Editor.error to output error * refine output program link error info * refine get attribute properties * support shader tags --- cocos2d/core/components/CCMask.js | 2 +- cocos2d/core/mesh/mesh-renderer.js | 8 +- cocos2d/renderer/build/chunks/alpha-test.inc | 16 + cocos2d/renderer/build/chunks/cc-global.inc | 21 + cocos2d/renderer/build/chunks/cc-local.inc | 4 + .../build/chunks/common-attribute.inc | 98 +++++ cocos2d/renderer/build/chunks/common.inc | 2 +- cocos2d/renderer/build/chunks/diffuse.inc | 42 ++ cocos2d/renderer/build/chunks/emissive.inc | 46 +++ cocos2d/renderer/build/chunks/encodings.inc | 39 ++ .../build/chunks/gamma-correction.inc | 45 --- .../renderer/build/chunks/lights-phong.inc | 90 +++++ cocos2d/renderer/build/chunks/lights.inc | 76 ++++ cocos2d/renderer/build/chunks/normal.inc | 27 ++ cocos2d/renderer/build/chunks/pbr-fs.inc | 366 ------------------ cocos2d/renderer/build/chunks/pbr-vs.inc | 49 --- cocos2d/renderer/build/chunks/phong-fs.inc | 312 --------------- cocos2d/renderer/build/chunks/phong-vs.inc | 59 --- .../renderer/build/chunks/shader/phong-fs.inc | 42 ++ .../renderer/build/chunks/shader/phong-vs.inc | 26 ++ .../chunks/{ => shader}/shadow-depth-fs.inc | 4 +- .../build/chunks/shader/shadow-depth-vs.inc | 22 ++ .../renderer/build/chunks/shader/unlit-fs.inc | 13 + .../renderer/build/chunks/shader/unlit-vs.inc | 16 + .../renderer/build/chunks/shadow-depth-vs.inc | 27 -- .../renderer/build/chunks/shadow-prepare.inc | 20 - .../build/chunks/shadowmap-declare-frag.inc | 45 +++ .../build/chunks/shadowmap-declare-vert.inc | 24 ++ cocos2d/renderer/build/chunks/skinning.inc | 102 ++--- cocos2d/renderer/build/chunks/specular.inc | 46 +++ cocos2d/renderer/build/chunks/unlit-fs.inc | 29 -- cocos2d/renderer/build/chunks/unlit-vs.inc | 40 -- cocos2d/renderer/build/shdc-lib.js | 58 ++- cocos2d/renderer/core/base-renderer.js | 8 +- cocos2d/renderer/core/effect.js | 17 +- cocos2d/renderer/core/program-lib.js | 21 +- cocos2d/renderer/gfx/program.js | 15 +- .../renderer/renderers/forward-renderer.js | 117 ++++-- 38 files changed, 916 insertions(+), 1078 deletions(-) create mode 100644 cocos2d/renderer/build/chunks/alpha-test.inc create mode 100644 cocos2d/renderer/build/chunks/cc-global.inc create mode 100644 cocos2d/renderer/build/chunks/cc-local.inc create mode 100644 cocos2d/renderer/build/chunks/common-attribute.inc create mode 100644 cocos2d/renderer/build/chunks/diffuse.inc create mode 100644 cocos2d/renderer/build/chunks/emissive.inc create mode 100644 cocos2d/renderer/build/chunks/encodings.inc delete mode 100644 cocos2d/renderer/build/chunks/gamma-correction.inc create mode 100644 cocos2d/renderer/build/chunks/lights-phong.inc create mode 100644 cocos2d/renderer/build/chunks/lights.inc create mode 100644 cocos2d/renderer/build/chunks/normal.inc delete mode 100644 cocos2d/renderer/build/chunks/pbr-fs.inc delete mode 100644 cocos2d/renderer/build/chunks/pbr-vs.inc delete mode 100644 cocos2d/renderer/build/chunks/phong-fs.inc delete mode 100644 cocos2d/renderer/build/chunks/phong-vs.inc create mode 100644 cocos2d/renderer/build/chunks/shader/phong-fs.inc create mode 100644 cocos2d/renderer/build/chunks/shader/phong-vs.inc rename cocos2d/renderer/build/chunks/{ => shader}/shadow-depth-fs.inc (74%) create mode 100644 cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc create mode 100644 cocos2d/renderer/build/chunks/shader/unlit-fs.inc create mode 100644 cocos2d/renderer/build/chunks/shader/unlit-vs.inc delete mode 100644 cocos2d/renderer/build/chunks/shadow-depth-vs.inc delete mode 100644 cocos2d/renderer/build/chunks/shadow-prepare.inc create mode 100644 cocos2d/renderer/build/chunks/shadowmap-declare-frag.inc create mode 100644 cocos2d/renderer/build/chunks/shadowmap-declare-vert.inc create mode 100644 cocos2d/renderer/build/chunks/specular.inc delete mode 100644 cocos2d/renderer/build/chunks/unlit-fs.inc delete mode 100644 cocos2d/renderer/build/chunks/unlit-vs.inc diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 73238722c7a..39ee7a7bda3 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -366,7 +366,7 @@ let Mask = cc.Class({ let material = this.sharedMaterials[0]; if (!material) { material = Material.getInstantiatedBuiltinMaterial('sprite', this); - material.define('ALPHA_TEST', true); + material.define('USE_ALPHA_TEST', true); } // Reset material diff --git a/cocos2d/core/mesh/mesh-renderer.js b/cocos2d/core/mesh/mesh-renderer.js index b39570a5fdc..eafc62ab1ed 100644 --- a/cocos2d/core/mesh/mesh-renderer.js +++ b/cocos2d/core/mesh/mesh-renderer.js @@ -26,6 +26,7 @@ import gfx from '../../renderer/gfx'; import InputAssembler from '../../renderer/core/input-assembler'; import IARenderData from '../../renderer/render-data/ia-render-data'; +const Material = require('../assets/material/CCMaterial'); const MeshRenderer = require('./CCMeshRenderer'); @@ -47,9 +48,10 @@ let meshRendererAssembler = { createWireFrameData (ia, oldIbData, material, renderer) { let data = new IARenderData(); - let m = material.clone(); - m.setProperty('color', BLACK_COLOR); - m.define('USE_TEXTURE', false); + let m = new Material(); + m.copy(Material.getBuiltinMaterial('unlit')); + m.setProperty('diffuseColor', BLACK_COLOR); + m.define('USE_DIFFUSE_TEXTURE', false); data.material = m; let indices = []; diff --git a/cocos2d/renderer/build/chunks/alpha-test.inc b/cocos2d/renderer/build/chunks/alpha-test.inc new file mode 100644 index 00000000000..4956eb182df --- /dev/null +++ b/cocos2d/renderer/build/chunks/alpha-test.inc @@ -0,0 +1,16 @@ + +#if USE_ALPHA_TEST + uniform float alphaThreshold; +#endif + +void ALPHA_TEST (in vec4 color) { + #if USE_ALPHA_TEST + if (color.a < alphaThreshold) discard; + #endif +} + +void ALPHA_TEST (in float alpha) { + #if USE_ALPHA_TEST + if (alpha < alphaThreshold) discard; + #endif +} diff --git a/cocos2d/renderer/build/chunks/cc-global.inc b/cocos2d/renderer/build/chunks/cc-global.inc new file mode 100644 index 00000000000..ca6d0356669 --- /dev/null +++ b/cocos2d/renderer/build/chunks/cc-global.inc @@ -0,0 +1,21 @@ +// transforms +// uniform mat4 cc_matProj; +// uniform mat4 cc_matProjInv; +uniform mat4 cc_matView; +// uniform mat4 cc_matViewInv; +uniform mat4 cc_matViewProj; +// uniform mat4 cc_matViewProjInv; +// constants +// uniform vec4 cc_time; // x +// uniform vec4 cc_screenSize; // xy +// uniform vec4 cc_screenScale; // xy +// uniform vec4 cc_cameraSize; // xy +uniform vec3 cc_cameraPos; // xyz + +// shadows +// uniform mat4 cc_matViewProjLight; +// uniform vec4 cc_shadowParam1; // vec4(minDepth, maxDepth, bias, depthScale) +// uniform vec4 cc_shadowParam2; // vec4(darkness, edgeFalloff, texelSize.x, texelSize.y) + +// ambient config +uniform vec3 cc_sceneAmbient; // xyz diff --git a/cocos2d/renderer/build/chunks/cc-local.inc b/cocos2d/renderer/build/chunks/cc-local.inc new file mode 100644 index 00000000000..9f00ac83ebb --- /dev/null +++ b/cocos2d/renderer/build/chunks/cc-local.inc @@ -0,0 +1,4 @@ + +// transforms +uniform mat4 cc_matWorld; +uniform mat3 cc_matWorldIT; diff --git a/cocos2d/renderer/build/chunks/common-attribute.inc b/cocos2d/renderer/build/chunks/common-attribute.inc new file mode 100644 index 00000000000..c949e3bc30f --- /dev/null +++ b/cocos2d/renderer/build/chunks/common-attribute.inc @@ -0,0 +1,98 @@ + +#ifndef USE_DIFFUSE_TEXTURE + #ifndef USE_EMISSIVE_TEXTURE + #ifndef USE_SPECULAR_TEXTURE + #define _NOT_USE_TEXTURE 1 + #endif + #endif +#endif + +#if USE_TILING_OFFSET && _USE_ATTRIBUTE_UV0 + #property + uniform vec2 mainTiling; + #property + uniform vec2 mainOffset; +#endif + +#ifdef _IS_VERT_SHADER + attribute vec3 a_position; +#endif + +// attribute uv0 +#ifndef _NOT_USE_TEXTURE + + #if _USE_ATTRIBUTE_UV0 + #ifdef _IS_VERT_SHADER + attribute mediump vec2 a_uv0; + #endif + + varying mediump vec2 v_uv0; + #endif + +#endif + +// attribute color +#if _USE_ATTRIBUTE_COLOR + + #ifdef _IS_VERT_SHADER + attribute lowp vec4 a_color; + #endif + + varying lowp vec4 v_color; +#endif + +// attribute normal +#if _USE_ATTRIBUTE_NORMAL + #ifdef _IS_VERT_SHADER + attribute vec3 a_normal; + #endif +#endif + +// helper defines +#ifdef _IS_VERT_SHADER + + void ATTRIBUTE_TO_VARYING () { + + #if _USE_ATTRIBUTE_COLOR + v_color = a_color; + #endif + + #ifndef _NOT_USE_TEXTURE + #if _USE_ATTRIBUTE_UV0 + v_uv0 = a_uv0; + + #if USE_TILING_OFFSET + v_uv0 = v_uv0 * mainTiling + mainOffset; + #endif + #endif + #endif + + } + +#endif + + +void MUL_ATTR_COLOR (inout vec4 color) { + #if _USE_ATTRIBUTE_COLOR + #ifdef _IS_VERT_SHADER + color *= a_color; + #else + color *= v_color; + #endif + #endif +} + +void MUL_ATTR_NORMAL (inout vec3 normal) { + #if _USE_ATTRIBUTE_NORMAL + #ifdef _IS_VERT_SHADER + normal *= a_normal; + #endif + #endif +} +void MUL_ATTR_NORMAL (inout vec4 normal) { + #if _USE_ATTRIBUTE_NORMAL + #ifdef _IS_VERT_SHADER + normal.xyz *= a_normal; + #endif + #endif +} diff --git a/cocos2d/renderer/build/chunks/common.inc b/cocos2d/renderer/build/chunks/common.inc index d1865226c8d..bfe90fe7981 100644 --- a/cocos2d/renderer/build/chunks/common.inc +++ b/cocos2d/renderer/build/chunks/common.inc @@ -9,4 +9,4 @@ #define LOG2 1.442695 // common function -#define saturate(a) clamp( a, 0.0, 1.0 ) \ No newline at end of file +#define saturate(a) clamp( a, 0.0, 1.0 ) diff --git a/cocos2d/renderer/build/chunks/diffuse.inc b/cocos2d/renderer/build/chunks/diffuse.inc new file mode 100644 index 00000000000..a9846ab0c30 --- /dev/null +++ b/cocos2d/renderer/build/chunks/diffuse.inc @@ -0,0 +1,42 @@ + +#property #color4 +uniform vec4 diffuseColor; + +#if USE_DIFFUSE_TEXTURE + #property + uniform sampler2D diffuseTexture; +#endif + +void MULTIPLY_DIFFUSE_TEXTRUE_COLOR (inout vec4 color, in vec2 uv) { + #if USE_DIFFUSE_TEXTURE && _USE_ATTRIBUTE_UV0 + vec4 diffuseTextureColor = texture2D(diffuseTexture, uv); + color *= TEXEL_TO_LINEAR(diffuseTextureColor); + #endif +} + +void MULTIPLY_DIFFUSE_TEXTRUE_COLOR (inout vec4 color) { + #if USE_DIFFUSE_TEXTURE && _USE_ATTRIBUTE_UV0 + + #ifdef _IS_VERT_SHADER + vec2 uv = a_uv0; + #else + vec2 uv = v_uv0; + #endif + + MULTIPLY_DIFFUSE_TEXTRUE_COLOR(color, uv); + #endif +} + +void CALC_DIFFUSE (inout vec4 diffuse, in vec2 uv) { + diffuse = diffuseColor; + + MUL_ATTR_COLOR(diffuse); + MULTIPLY_DIFFUSE_TEXTRUE_COLOR(diffuse, uv); +} + +void CALC_DIFFUSE (inout vec4 diffuse) { + diffuse = diffuseColor; + + MUL_ATTR_COLOR(diffuse); + MULTIPLY_DIFFUSE_TEXTRUE_COLOR(diffuse); +} diff --git a/cocos2d/renderer/build/chunks/emissive.inc b/cocos2d/renderer/build/chunks/emissive.inc new file mode 100644 index 00000000000..d0088675b94 --- /dev/null +++ b/cocos2d/renderer/build/chunks/emissive.inc @@ -0,0 +1,46 @@ + +#if USE_EMISSIVE + #property #color3 + uniform vec3 emissiveColor; + + #if USE_EMISSIVE_TEXTURE + #property + uniform sampler2D emissiveTexture; + #endif + +#endif + +void MULTIPLY_EMISSIVE_TEXTRUE_COLOR (inout vec3 color, in vec2 uv) { + #if USE_EMISSIVE_TEXTURE && _USE_ATTRIBUTE_UV0 + vec4 emissiveTextureColor = texture2D(emissiveTexture, uv); + emissiveTextureColor = TEXEL_TO_LINEAR(emissiveTextureColor); + color *= emissiveTextureColor.rgb; + #endif +} + +void MULTIPLY_EMISSIVE_TEXTRUE_COLOR (inout vec3 color) { + #if USE_EMISSIVE_TEXTURE && _USE_ATTRIBUTE_UV0 + + #ifdef _IS_VERT_SHADER + vec2 uv = a_uv0; + #else + vec2 uv = v_uv0; + #endif + + MULTIPLY_EMISSIVE_TEXTRUE_COLOR(color, uv); + #endif +} + +void CALC_EMISSIVE (inout vec3 emissive, in vec2 uv) { + #if USE_EMISSIVE + emissive = emissiveColor; + MULTIPLY_EMISSIVE_TEXTRUE_COLOR(emissive, uv); + #endif +} + +void CALC_EMISSIVE (inout vec3 emissive) { + #if USE_EMISSIVE + emissive = emissiveColor; + MULTIPLY_EMISSIVE_TEXTRUE_COLOR(emissive); + #endif +} diff --git a/cocos2d/renderer/build/chunks/encodings.inc b/cocos2d/renderer/build/chunks/encodings.inc new file mode 100644 index 00000000000..eeb4d57a092 --- /dev/null +++ b/cocos2d/renderer/build/chunks/encodings.inc @@ -0,0 +1,39 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +// sRGB-linear transform approximation +// http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html +vec3 gammaToLinearSpaceRGB(in vec3 sRGB) { // TODO: use half maybe better. + return sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878); +} + +vec3 linearToGammaSpaceRGB(in vec3 RGB) { // TODO: use half maybe better. + vec3 S1 = sqrt(RGB); + vec3 S2 = sqrt(S1); + vec3 S3 = sqrt(S2); + return 0.585122381 * S1 + 0.783140355 * S2 - 0.368262736 * S3; +} + +vec4 gammaToLinearSpaceRGBA(in vec4 sRGBA) { + return vec4(gammaToLinearSpaceRGB(sRGBA.rgb), sRGBA.a); +} + +vec4 linearToGammaSpaceRGBA(in vec4 RGBA) { + return vec4(linearToGammaSpaceRGB(RGBA.rgb), RGBA.a); +} + +vec4 linearToLinear (in vec4 value) { + return value; +} + + +#if INPUT_IS_GAMMA + #define TEXEL_TO_LINEAR gammaToLinearSpaceRGBA +#else + #define TEXEL_TO_LINEAR linearToLinear +#endif + +#if OUTPUT_TO_GAMMA + #define LINEAR_TO_OUTPUT_TEXEL linearToGammaSpaceRGBA +#else + #define LINEAR_TO_OUTPUT_TEXEL linearToLinear +#endif diff --git a/cocos2d/renderer/build/chunks/gamma-correction.inc b/cocos2d/renderer/build/chunks/gamma-correction.inc deleted file mode 100644 index a824b2b1221..00000000000 --- a/cocos2d/renderer/build/chunks/gamma-correction.inc +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -// sRGB-linear transform approximation -// http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html -vec3 gammaToLinearSpaceRGB(vec3 sRGB) { // TODO: use half maybe better. - return sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878); -} - -vec3 linearToGammaSpaceRGB(vec3 RGB) { // TODO: use half maybe better. - vec3 S1 = sqrt(RGB); - vec3 S2 = sqrt(S1); - vec3 S3 = sqrt(S2); - return 0.585122381 * S1 + 0.783140355 * S2 - 0.368262736 * S3; -} - -vec4 gammaToLinearSpaceRGBA(vec4 sRGBA) { - return vec4(gammaToLinearSpaceRGB(sRGBA.rgb), sRGBA.a); -} - -vec4 linearToGammaSpaceRGBA(vec4 RGBA) { - return vec4(linearToGammaSpaceRGB(RGBA.rgb), RGBA.a); -} - -// exact version -float gammaToLinearSpaceExact(float val) { - if (val <= 0.04045) { - return val / 12.92; - } else if (val < 1.0) { - return pow((val + 0.055) / 1.055, 2.4); - } else { - return pow(val, 2.2); - } -} - -float linearToGammaSpaceExact(float val) { - if (val <= 0.0) { - return 0.0; - } else if (val <= 0.0031308) { - return 12.92 * val; - } else if (val < 1.0) { - return 1.055 * pow(val, 0.4166667) - 0.055; - } else { - return pow(val, 0.45454545); - } -} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/lights-phong.inc b/cocos2d/renderer/build/chunks/lights-phong.inc new file mode 100644 index 00000000000..4e2c9140cbf --- /dev/null +++ b/cocos2d/renderer/build/chunks/lights-phong.inc @@ -0,0 +1,90 @@ + +#include + +#property +uniform float glossiness; + +struct PhongMaterial { + vec3 diffuse; + vec3 emissive; + vec3 specular; + float opacity; +}; + +struct Lighting { + vec3 diffuse; + vec3 specular; +}; + +void brdf (inout Lighting result, LightInfo info, vec3 normal, vec3 viewDirection, float glossiness) { + float ndh = 0.0; + // Get the half direction in world space + vec3 halfDir = normalize(viewDirection + info.lightDir); + float NdotH = max(0.0, dot(normal, halfDir)); + NdotH = pow(NdotH, max(1.0, glossiness * 128.0)); + + vec3 diffuse = info.radiance * max(0.0, dot(normal, info.lightDir)); + vec3 specular = info.radiance * NdotH; + + result.diffuse += diffuse; + result.specular += specular; +} + +Lighting getPhongLighting (vec3 normal, vec3 worldPos, vec3 viewDirection, float glossiness) { + Lighting result; + result.diffuse = vec3(0, 0, 0); + result.specular = vec3(0, 0, 0); + + #if _NUM_DIR_LIGHTS > 0 + for (int i = 0; i < _NUM_DIR_LIGHTS; i++) { + LightInfo info = computeDirectionalLighting(cc_dirLightDirection[i], cc_dirLightColor[i]); + brdf(result, info, normal, viewDirection, glossiness); + } + #endif + + #if _NUM_POINT_LIGHTS > 0 + for (int i = 0; i < _NUM_POINT_LIGHTS; i++) { + LightInfo info = computePointLighting(worldPos, cc_pointLightPositionAndRange[i], cc_pointLightColor[i]); + brdf(result, info, normal, viewDirection, glossiness); + } + #endif + + #if _NUM_SPOT_LIGHTS > 0 + for (int i = 0; i < _NUM_SPOT_LIGHTS; i++) { + LightInfo info = computeSpotLighting(worldPos, cc_spotLightPositionAndRange[i], cc_spotLightDirection[i], cc_spotLightColor[i]); + brdf(result, info, normal, viewDirection, glossiness); + } + #endif + + result.diffuse += cc_sceneAmbient; + + return result; +} + +vec4 composePhongShading (Lighting lighting, PhongMaterial mtl) { + vec4 o = vec4(0.0, 0.0, 0.0, 1.0); + + //diffuse is always calculated + o.rgb = lighting.diffuse * mtl.diffuse; + + #if USE_EMISSIVE + o.rgb += mtl.emissive; + #endif + + #if USE_SPECULAR + o.rgb += lighting.specular * mtl.specular; + #endif + + #if _USE_SHADOW_MAP + o.rgb *= computeShadow(); + #endif + + o.a = mtl.opacity; + + return o; +} + +void CALC_PHONG_LIGHTING (inout vec4 outColor, in PhongMaterial material, in vec3 normal, in vec3 worldPosition, in vec3 viewDirection) { + Lighting phongLighting = getPhongLighting(normal, worldPosition, viewDirection, glossiness); + outColor = composePhongShading(phongLighting, material); +} diff --git a/cocos2d/renderer/build/chunks/lights.inc b/cocos2d/renderer/build/chunks/lights.inc new file mode 100644 index 00000000000..7d205c09713 --- /dev/null +++ b/cocos2d/renderer/build/chunks/lights.inc @@ -0,0 +1,76 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#include + +// TODO: lights uniform should move back to cc-global + +// directional lights +#if _NUM_DIR_LIGHTS > 0 + uniform vec4 cc_dirLightDirection[_NUM_DIR_LIGHTS]; // xyz + uniform vec4 cc_dirLightColor[_NUM_DIR_LIGHTS]; // xyz +#endif + +// point lights +#if _NUM_POINT_LIGHTS > 0 + uniform vec4 cc_pointLightPositionAndRange[_NUM_POINT_LIGHTS]; // xyz range + uniform vec4 cc_pointLightColor[_NUM_POINT_LIGHTS]; // xyz +#endif + +// spot lights +#if _NUM_SPOT_LIGHTS > 0 + uniform vec4 cc_spotLightPositionAndRange[_NUM_SPOT_LIGHTS]; // xyz range + uniform vec4 cc_spotLightDirection[_NUM_SPOT_LIGHTS]; // xyz spotAngle + uniform vec4 cc_spotLightColor[_NUM_SPOT_LIGHTS]; // xyz spotExp +#endif + + +struct LightInfo { + vec3 lightDir; + vec3 radiance; +}; + +// directional light +LightInfo computeDirectionalLighting( + vec4 lightDirection, + vec4 lightColor +) { + LightInfo ret; + ret.lightDir = -normalize(lightDirection.xyz); + ret.radiance = lightColor.rgb; + return ret; +} + +// point light +LightInfo computePointLighting( + vec3 worldPosition, + vec4 lightPositionAndRange, + vec4 lightColor +) { + LightInfo ret; + vec3 lightDir = lightPositionAndRange.xyz - worldPosition; + float attenuation = max(0., 1.0 - length(lightDir) / lightPositionAndRange.w); + + ret.lightDir = normalize(lightDir); + ret.radiance = lightColor.rgb * attenuation; + return ret; +} + +// spot light +LightInfo computeSpotLighting( + vec3 worldPosition, + vec4 lightPositionAndRange, + vec4 lightDirection, + vec4 lightColor +) { + LightInfo ret; + vec3 lightDir = lightPositionAndRange.xyz - worldPosition; + float attenuation = max(0., 1.0 - length(lightDir) / lightPositionAndRange.w); + lightDir = normalize(lightDir); + float cosConeAngle = max(0., dot(lightDirection.xyz, -lightDir)); + cosConeAngle = cosConeAngle < lightDirection.w ? 0. : cosConeAngle; + cosConeAngle = pow(cosConeAngle, lightColor.w); + + ret.lightDir = lightDir; + ret.radiance = lightColor.rgb * attenuation * cosConeAngle; + return ret; +} diff --git a/cocos2d/renderer/build/chunks/normal.inc b/cocos2d/renderer/build/chunks/normal.inc new file mode 100644 index 00000000000..bceea3d454c --- /dev/null +++ b/cocos2d/renderer/build/chunks/normal.inc @@ -0,0 +1,27 @@ + +#if USE_NORMAL_TEXTURE + #property + uniform sampler2D normalTexture; + + vec3 getNormal(vec3 pos, vec3 normal) { + vec3 q0 = vec3( dFdx( pos.x ), dFdx( pos.y ), dFdx( pos.z ) ); + vec3 q1 = vec3( dFdy( pos.x ), dFdy( pos.y ), dFdy( pos.z ) ); + vec2 st0 = dFdx( v_uv0.st ); + vec2 st1 = dFdy( v_uv0.st ); + vec3 S = normalize( q0 * st1.t - q1 * st0.t ); + vec3 T = normalize( -q0 * st1.s + q1 * st0.s ); + vec3 N = normal; + vec3 mapN = texture2D(normalTexture, v_uv0).rgb * 2.0 - 1.0; + mapN.xy = 1.0 * mapN.xy; + mat3 tsn = mat3( S, T, N ); + return normalize( tsn * mapN ); + } +#endif + +void CALC_NORMAL (inout vec3 normal, in vec3 worldPos, in vec3 worldNormal) { + normal = normalize(worldNormal); + + #if USE_NORMAL_TEXTURE + normal = getNormal(worldPos, normal); + #endif +} diff --git a/cocos2d/renderer/build/chunks/pbr-fs.inc b/cocos2d/renderer/build/chunks/pbr-fs.inc deleted file mode 100644 index 97b33cbc724..00000000000 --- a/cocos2d/renderer/build/chunks/pbr-fs.inc +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -#if USE_NORMAL_TEXTURE -#extension GL_OES_standard_derivatives : enable -#endif - -#if USE_TEX_LOD -#extension GL_EXT_shader_texture_lod: enable -#endif - -#include -#include - -struct LightInfo { - vec3 lightDir; - vec3 radiance; -}; - -#if _NUM_DIR_LIGHTS > 0 - #pragma for id in range(0, _NUM_DIR_LIGHTS) - uniform vec3 _dir_light{id}_direction; - uniform vec3 _dir_light{id}_color; - #pragma endFor -#endif - -#if _NUM_POINT_LIGHTS > 0 - #pragma for id in range(0, _NUM_POINT_LIGHTS) - uniform vec3 _point_light{id}_position; - uniform vec3 _point_light{id}_color; - uniform float _point_light{id}_range; - #pragma endFor -#endif - -#if _NUM_SPOT_LIGHTS > 0 - #pragma for id in range(0, _NUM_SPOT_LIGHTS) - uniform vec3 _spot_light{id}_position; - uniform vec3 _spot_light{id}_direction; - uniform vec3 _spot_light{id}_color; - uniform vec2 _spot_light{id}_spot; - uniform float _spot_light{id}_range; - #pragma endFor -#endif - -// directional light -LightInfo computeDirectionalLighting( - vec3 lightDirection, - vec3 lightColor -) { - LightInfo ret; - ret.lightDir = -normalize(lightDirection); - ret.radiance = lightColor; - - return ret; -} - -// point light -LightInfo computePointLighting( - vec3 lightPosition, - vec3 positionW, - vec3 lightColor, - float lightRange -) { - LightInfo ret; - vec3 lightDir = lightPosition - positionW; - float attenuation = max(0.0, 1.0 - length(lightDir) / lightRange); - ret.lightDir = normalize(lightDir); - ret.radiance = lightColor * attenuation; - - return ret; -} - -// spot light -LightInfo computeSpotLighting( - vec3 lightPosition, - vec3 positionW, - vec3 lightDirection, - vec3 lightColor, - vec2 lightSpot, - float lightRange -) { - LightInfo ret; - vec3 lightDir = lightPosition - positionW; - float attenuation = max(0., 1.0 - length(lightDir) / lightRange); - float cosConeAngle = max(0., dot(lightDirection, -lightDir)); - cosConeAngle = cosConeAngle < lightSpot.x ? 0.0 : cosConeAngle; - cosConeAngle = pow(cosConeAngle,lightSpot.y); - ret.lightDir = normalize(lightDir); - ret.radiance = lightColor * attenuation * cosConeAngle; - - return ret; -} - -#include - -#if _USE_SHADOW_MAP - #include - #include -#endif - -uniform vec3 _eye; - -varying vec3 pos_w; -varying vec3 normal_w; - -#if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_EMISSIVE_TEXTURE - varying vec2 uv0; -#endif - -#if USE_IBL - uniform samplerCube diffuseEnvTexture; - uniform samplerCube specularEnvTexture; - uniform sampler2D brdfLUT; - #if USE_TEX_LOD - uniform float maxReflectionLod; - #endif -#endif - -// material parameters -uniform vec4 albedo; -#if USE_ALBEDO_TEXTURE - uniform sampler2D albedo_texture; -#endif - -#if USE_MRA_TEXTURE - uniform sampler2D mra_texture; -#endif - -uniform float metallic; -#if USE_METALLIC_TEXTURE - uniform sampler2D metallic_texture; -#endif - -uniform float roughness; -#if USE_ROUGHNESS_TEXTURE - uniform sampler2D roughness_texture; -#endif - -uniform float ao; -#if USE_AO_TEXTURE - uniform sampler2D ao_texture; -#endif - -#if USE_EMISSIVE - uniform vec3 emissive; - #if USE_EMISSIVE_TEXTURE - uniform sampler2D emissive_texture; - #endif -#endif - -#if USE_ALPHA_TEST - uniform float alphaTestThreshold; -#endif - -#if USE_NORMAL_TEXTURE - uniform sampler2D normal_texture; - // get world-space normal from normal texture - vec3 getNormalFromTexture() { - vec3 tangentNormal = texture2D(normal_texture, uv0).rgb * 2.0 - 1.0; - vec3 q1 = dFdx(pos_w); - vec3 q2 = dFdy(pos_w); - vec2 st1 = dFdx(uv0); - vec2 st2 = dFdy(uv0); - vec3 N = normalize(normal_w); - vec3 T = normalize(q1*st2.t - q2*st1.t); - vec3 B = -normalize(cross(N, T)); - mat3 TBN = mat3(T, B, N); - - return normalize(TBN * tangentNormal); - } -#endif - -// Cook-Torrance BRDF _model -// D() Normal distribution function (Trowbridge-Reitz GGX) -// https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf -float distributionGGX(vec3 N, vec3 H, float roughness) { - float a = roughness * roughness; - float a2 = a * a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH * NdotH; - float nom = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = PI * denom * denom; - - return nom / denom; -} -// G() Geometry function (Smith's Schlick GGX) -// https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf -float geometrySchlickGGX(float NdotV, float roughness) { - float r = (roughness + 1.0); - float k = (r * r) / 8.0; - float nom = NdotV; - float denom = NdotV * (1.0 - k) + k; - - return nom / denom; -} -float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - float ggx2 = geometrySchlickGGX(NdotV, roughness); - float ggx1 = geometrySchlickGGX(NdotL, roughness); - - return ggx1 * ggx2; -} -// F() Fresnel equation (Fresnel-Schlick approximation) -// Optimized variant (presented by Epic at SIGGRAPH '13) -// https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf -vec3 fresnelSchlick(float cosTheta, vec3 F0) { - float fresnel = exp2((-5.55473 * cosTheta - 6.98316) * cosTheta); - return F0 + (1.0 - F0) * fresnel; -} -vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) { - float fresnel = exp2((-5.55473 * cosTheta - 6.98316) * cosTheta); - return F0 + (max(vec3(1.0 - roughness), F0) - F0) * fresnel; -} - -// BRDF equation -vec3 brdf(LightInfo lightInfo, vec3 N, vec3 V, vec3 F0, vec3 albedo, float metallic, float roughness) { - vec3 H = normalize(V + lightInfo.lightDir); - float NDF = distributionGGX(N, H, roughness); - float G = geometrySmith(N, V, lightInfo.lightDir, roughness); - vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); - vec3 nominator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, lightInfo.lightDir), 0.0) + 0.001; // 0.001 to prevent divide by zero. - vec3 specular = nominator / denominator; - // kS is equal to Fresnel - vec3 kS = F; - // for energy conservation, the diffuse and specular light can't - // be above 1.0 (unless the surface emits light); to preserve this - // relationship the diffuse component (kD) should equal 1.0 - kS. - vec3 kD = vec3(1.0) - kS; - // multiply kD by the inverse metalness such that only non-metals - // have diffuse lighting, or a linear blend if partly metal (pure metals - // have no diffuse light). - kD *= 1.0 - metallic; - float NdotL = max(dot(N, lightInfo.lightDir), 0.0); - - return (kD * albedo / PI + specular) * lightInfo.radiance * NdotL; -} - -vec4 frag() { - float opacity = 1.0; - - #if USE_ALBEDO_TEXTURE - vec4 baseColor = albedo * gammaToLinearSpaceRGBA(texture2D(albedo_texture, uv0)); - vec3 albedo = baseColor.rgb; - opacity = baseColor.a; - #else - opacity = albedo.a; - vec3 albedo = albedo.rgb; - #endif - - #if USE_ALPHA_TEST - if(opacity < alphaTestThreshold) discard; - #endif - - #if USE_MRA_TEXTURE - vec3 metalRoughness = texture2D(mra_texture, uv0).rgb; - float metallic = metalRoughness.r; - float roughness = metalRoughness.g; - float ao = metalRoughness.b; - #else - #if USE_METALLIC_TEXTURE - float metallic = texture2D(metallic_texture, uv0).r; - #endif - #if USE_ROUGHNESS_TEXTURE - float roughness = texture2D(roughness_texture, uv0).r; - #endif - #if USE_AO_TEXTURE - float ao = texture2D(ao_texture, uv0).r; - #endif - #endif - - vec3 N = normalize(normal_w); - #if USE_NORMAL_TEXTURE - N = getNormalFromTexture(); - #endif - vec3 V = normalize(_eye - pos_w); - - // calculate reflectance at normal incidence; if dia-electric (like plastic) use F0 - // of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow) - vec3 F0 = vec3(0.04); - F0 = mix(F0, albedo, metallic); - - // reflection - vec3 Lo = vec3(0.0); - - // point light (a 'for' loop to accumulate all light sources) - #if _NUM_POINT_LIGHTS > 0 - #pragma for id in range(0, _NUM_POINT_LIGHTS) - LightInfo pointLight{id}; - pointLight{id} = computePointLighting(_point_light{id}_position, pos_w, _point_light{id}_color, _point_light{id}_range); - Lo += brdf(pointLight{id}, N, V, F0, albedo, metallic, roughness); - #pragma endFor - #endif - - #if _NUM_DIR_LIGHTS > 0 - #pragma for id in range(0, _NUM_DIR_LIGHTS) - LightInfo directionalLight{id}; - directionalLight{id} = computeDirectionalLighting(_dir_light{id}_direction, _dir_light{id}_color); - Lo += brdf(directionalLight{id}, N, V, F0, albedo, metallic, roughness); - #pragma endFor - #endif - - #if _NUM_SPOT_LIGHTS > 0 - #pragma for id in range(0, _NUM_SPOT_LIGHTS) - LightInfo spotLight{id}; - spotLight{id} = computeSpotLighting(_spot_light{id}_position, pos_w, _spot_light{id}_direction, _spot_light{id}_color, _spot_light{id}_spot, _spot_light{id}_range); - Lo += brdf(spotLight{id}, N, V, F0, albedo, metallic, roughness); - #pragma endFor - #endif - - #if USE_EMISSIVE - vec3 emissiveColor = emissive; - #if USE_EMISSIVE_TEXTURE - emissiveColor *= gammaToLinearSpaceRGB(texture2D(emissive_texture, uv0).rgb); - #endif - Lo += emissiveColor; - #endif - - // ambient lighting, will be replaced by IBL if IBL used. - vec3 ambient = vec3(0.03) * albedo * ao; - - #if USE_IBL - // generate ambient when using IBL. - vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness); - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - #if USE_RGBE_IBL_DIFFUSE - vec3 diffuseEnv = unpackRGBE(textureCube(diffuseEnvTexture, N)); - #else - vec3 diffuseEnv = textureCube(diffuseEnvTexture, N).rgb; - #endif - vec3 diffuse = diffuseEnv * albedo; - // sample both the specularEnvTexture and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part. - vec3 R = reflect(-V, N); - #if USE_TEX_LOD - #if USE_RGBE_IBL_SPECULAR - vec3 specularEnv = unpackRGBE(textureCubeLodEXT(specularEnvTexture, R, roughness * maxReflectionLod)); - #else - vec3 specularEnv = textureCubeLodEXT(specularEnvTexture, R, roughness * maxReflectionLod).rgb; - #endif - #else - #if USE_RGBE_IBL_SPECULAR - vec3 specularEnv = unpackRGBE(textureCube(specularEnvTexture, R)); - #else - vec3 specularEnv = textureCube(specularEnvTexture, R).rgb; - #endif - #endif - vec2 brdf = texture2D(brdfLUT, vec2(max(dot(N, V), 0.0), 1.0 - roughness)).rg; - vec3 specular = specularEnv * (F * brdf.x + brdf.y); - ambient = (kD * diffuse + specular) * ao; - #endif - - vec3 color = ambient + Lo; - #if _USE_SHADOW_MAP - color *= computeShadow(); - #endif - - // HDR tone mapping. - color = color / (color + vec3(1.0)); - // gamma correction. - vec4 finalColor = vec4(color, opacity); - - return linearToGammaSpaceRGBA(finalColor); -} diff --git a/cocos2d/renderer/build/chunks/pbr-vs.inc b/cocos2d/renderer/build/chunks/pbr-vs.inc deleted file mode 100644 index 020b96eb8eb..00000000000 --- a/cocos2d/renderer/build/chunks/pbr-vs.inc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -attribute vec3 a_position; -attribute vec3 a_normal; - -varying vec3 pos_w; -varying vec3 normal_w; - -uniform mat4 _model; -uniform mat4 _viewProj; -uniform mat3 _normalMatrix; - -#if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_MRA_TEXTURE || USE_EMISSIVE_TEXTURE - attribute vec2 a_uv0; - uniform vec2 mainTiling; - uniform vec2 mainOffset; - varying vec2 uv0; -#endif - -#if _USE_SKINNING - #include -#endif - -#if _USE_SHADOW_MAP - #include -#endif - -vec4 vert () { - vec4 pos = vec4(a_position, 1); - vec4 normal = vec4(a_normal, 0); - - #if _USE_SKINNING - skinVertex(pos, normal); - #endif - - pos_w = (_model * pos).xyz; - pos = _viewProj * _model * pos; - normal_w = _normalMatrix * normal.xyz; - - #if USE_ALBEDO_TEXTURE || USE_NORMAL_TEXTURE || USE_MRA_TEXTURE || USE_METALLIC_TEXTURE || USE_ROUGHNESS_TEXTURE || USE_AO_TEXTURE || USE_MRA_TEXTURE || USE_EMISSIVE_TEXTURE - uv0 = a_uv0 * mainTiling + mainOffset; - #endif - - #if _USE_SHADOW_MAP - prepareShadowData(pos_w); - #endif - - return pos; -} diff --git a/cocos2d/renderer/build/chunks/phong-fs.inc b/cocos2d/renderer/build/chunks/phong-fs.inc deleted file mode 100644 index 740359b8e38..00000000000 --- a/cocos2d/renderer/build/chunks/phong-fs.inc +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -#if USE_NORMAL_TEXTURE -#extension GL_OES_standard_derivatives : enable -#endif - -#include -#include - -#if _USE_ATTRIBUTE_COLOR - varying vec4 v_color; -#endif - -struct LightInfo { - vec3 diffuse; - vec3 specular; -}; - -LightInfo computeDirectionalLighting( - vec3 lightDirection, - vec3 lightColor, - vec3 normal, - vec3 viewDirection, - float glossiness -) { - LightInfo lightingResult; - float ndl = 0.0; - float ndh = 0.0; - vec3 lightDir = -normalize(lightDirection); - ndl = max(0.0, dot(normal, lightDir)); - lightingResult.diffuse = lightColor * ndl; - - vec3 dirH = normalize(viewDirection + lightDir); - ndh = max(0.0, dot(normal, dirH)); - ndh = (ndl == 0.0) ? 0.0: ndh; - ndh = pow(ndh, max(1.0, glossiness * 128.0)); - lightingResult.specular = lightColor * ndh; - - return lightingResult; -} - -LightInfo computePointLighting( - vec3 lightPosition, - vec3 lightColor, - float lightRange, - vec3 normal, - vec3 positionW, - vec3 viewDirection, - float glossiness -) { - LightInfo lightingResult; - float ndl = 0.0; - float ndh = 0.0; - vec3 lightDir = vec3(0, 0, 0); - float attenuation = 1.0; - lightDir = lightPosition - positionW; - attenuation = max(0., 1.0 - length(lightDir) / lightRange); - lightDir = normalize(lightDir); - ndl = max(0.0, dot(normal, lightDir)); - lightingResult.diffuse = lightColor * ndl * attenuation; - - vec3 dirH = normalize(viewDirection + lightDir); - ndh = max(0.0, dot(normal, dirH)); - ndh = (ndl == 0.0) ? 0.0: ndh; - ndh = pow(ndh, max(1.0, glossiness * 128.0)); - lightingResult.specular = lightColor * ndh * attenuation; - - return lightingResult; -} - -LightInfo computeSpotLighting( - vec3 lightPosition, - vec3 lightDirection, - vec3 lightColor, - float lightRange, - vec2 lightSpot, - vec3 normal, - vec3 positionW, - vec3 viewDirection, - float glossiness -) { - LightInfo lightingResult; - float ndl = 0.0; - float ndh = 0.0; - vec3 lightDir = vec3(0, 0, 0); - float attenuation = 1.0; - float cosConeAngle = 1.0; - - lightDir = lightPosition - positionW; - attenuation = max(0., 1.0 - length(lightDir) / lightRange); - lightDir = normalize(lightDir); - cosConeAngle = max(0., dot(lightDirection, -lightDir)); - cosConeAngle = cosConeAngle < lightSpot.x ? 0.0 : cosConeAngle; - cosConeAngle = pow(cosConeAngle,lightSpot.y); - ndl = max(0.0, dot(normal, lightDir)); - lightingResult.diffuse = lightColor * ndl * attenuation * cosConeAngle; - - vec3 dirH = normalize(viewDirection + lightDir); - ndh = max(0.0, dot(normal, dirH)); - ndh = (ndl == 0.0) ? 0.0: ndh; - ndh = pow(ndh, max(1.0, glossiness * 128.0)); - lightingResult.specular = lightColor * ndh * attenuation * cosConeAngle; - - return lightingResult; -} - -#if _NUM_DIR_LIGHTS > 0 - #pragma for id in range(0, _NUM_DIR_LIGHTS) - uniform vec3 _dir_light{id}_direction; - uniform vec3 _dir_light{id}_color; - #pragma endFor -#endif - -#if _NUM_POINT_LIGHTS > 0 - #pragma for id in range(0, _NUM_POINT_LIGHTS) - uniform vec3 _point_light{id}_position; - uniform vec3 _point_light{id}_color; - uniform float _point_light{id}_range; - #pragma endFor -#endif - -#if _NUM_SPOT_LIGHTS > 0 - #pragma for id in range(0, _NUM_SPOT_LIGHTS) - uniform vec3 _spot_light{id}_position; - uniform vec3 _spot_light{id}_direction; - uniform vec3 _spot_light{id}_color; - uniform float _spot_light{id}_range; - uniform vec2 _spot_light{id}_spot; - #pragma endFor -#endif - -LightInfo getPhongLighting( - vec3 normal, - vec3 positionW, - vec3 viewDirection, - float glossiness -) { - LightInfo result; - result.diffuse = vec3(0, 0, 0); - result.specular = vec3(0, 0, 0); - LightInfo dirLighting; - #if _NUM_DIR_LIGHTS > 0 - #pragma for id in range(0, _NUM_DIR_LIGHTS) - dirLighting = computeDirectionalLighting(_dir_light{id}_direction,_dir_light{id}_color,normal, viewDirection, glossiness); - result.diffuse += dirLighting.diffuse; - result.specular += dirLighting.specular; - #pragma endFor - #endif - - LightInfo pointLighting; - #if _NUM_POINT_LIGHTS > 0 - #pragma for id in range(0, _NUM_POINT_LIGHTS) - pointLighting = computePointLighting(_point_light{id}_position, _point_light{id}_color, _point_light{id}_range, - normal, positionW, viewDirection, glossiness); - result.diffuse += pointLighting.diffuse; - result.specular += pointLighting.specular; - #pragma endFor - #endif - - LightInfo spotLighting; - #if _NUM_SPOT_LIGHTS > 0 - #pragma for id in range(0, _NUM_SPOT_LIGHTS) - spotLighting = computeSpotLighting(_spot_light{id}_position, _spot_light{id}_direction, _spot_light{id}_color, - _spot_light{id}_range, _spot_light{id}_spot,normal, positionW, viewDirection, glossiness); - result.diffuse += spotLighting.diffuse; - result.specular += spotLighting.specular; - #pragma endFor - #endif - return result; -} - -#if _USE_SHADOW_MAP - #include - #include -#endif - -uniform vec3 _eye; - -varying vec3 normal_w; -varying vec3 pos_w; - -#if USE_DIFFUSE_TEXTURE || USE_NORMAL_TEXTURE || USE_EMISSIVE_TEXTURE - varying vec2 v_uv0; -#endif - -struct phongMaterial -{ - vec3 diffuse; - vec3 emissive; - vec3 specular; - float glossiness; - float opacity; -}; - -uniform vec4 diffuseColor; -#if USE_DIFFUSE_TEXTURE - uniform sampler2D diffuse_texture; -#endif - -#if USE_EMISSIVE - uniform vec3 emissiveColor; - #if USE_EMISSIVE_TEXTURE - uniform sampler2D emissive_texture; - #endif -#endif - -#if USE_SPECULAR - uniform vec3 specularColor; - uniform float glossiness; - #if USE_SPECULAR_TEXTURE - uniform sampler2D specular_texture; - #endif -#endif - -#if USE_NORMAL_TEXTURE - uniform sampler2D normal_texture; - uniform float normalScale; //this is not used yet - vec3 getNormal(vec3 pos, vec3 normal) { - vec3 q0 = vec3( dFdx( pos.x ), dFdx( pos.y ), dFdx( pos.z ) ); - vec3 q1 = vec3( dFdy( pos.x ), dFdy( pos.y ), dFdy( pos.z ) ); - vec2 st0 = dFdx( v_uv0.st ); - vec2 st1 = dFdy( v_uv0.st ); - vec3 S = normalize( q0 * st1.t - q1 * st0.t ); - vec3 T = normalize( -q0 * st1.s + q1 * st0.s ); - vec3 N = normal; - vec3 mapN = texture2D(normal_texture, v_uv0).rgb * 2.0 - 1.0; - mapN.xy = 1.0 * mapN.xy; - mat3 tsn = mat3( S, T, N ); - return normalize( tsn * mapN ); - } -#endif - -#if USE_ALPHA_TEST - uniform float alphaTestThreshold; -#endif - -phongMaterial getPhongMaterial() { - phongMaterial result; - - result.diffuse = diffuseColor.rgb; - result.opacity = diffuseColor.a; - - #if _USE_ATTRIBUTE_COLOR - result.diffuse *= v_color.rgb; - result.opacity *= v_color.a; - #endif - - #if USE_DIFFUSE_TEXTURE - vec4 baseColor = gammaToLinearSpaceRGBA(texture2D(diffuse_texture, v_uv0)); - result.diffuse *= baseColor.rgb; - result.opacity *= baseColor.a; - #endif - - #if USE_EMISSIVE - result.emissive = gammaToLinearSpaceRGB(emissiveColor); - #if USE_EMISSIVE_TEXTURE - result.emissive *= gammaToLinearSpaceRGB(texture2D(emissive_texture, v_uv0).rgb); - #endif - #endif - - #if USE_SPECULAR - result.specular = gammaToLinearSpaceRGB(specularColor); - #if USE_SPECULAR_TEXTURE - result.specular = gammaToLinearSpaceRGB(texture2D(specular_texture, v_uv0).rgb); - #endif - - result.glossiness = glossiness; - #endif - - return result; -} - -vec4 composePhongShading(LightInfo lighting, phongMaterial mtl, float shadow) -{ - vec4 o = vec4(0.0, 0.0, 0.0, 1.0); - - //diffuse is always calculated - o.xyz = lighting.diffuse * mtl.diffuse; - #if USE_EMISSIVE - o.xyz += mtl.emissive; - #endif - #if USE_SPECULAR - o.xyz += lighting.specular * mtl.specular; - #endif - o.xyz *= shadow; - o.w = mtl.opacity; - - return o; -} - -vec4 frag () { - LightInfo phongLighting; - vec3 viewDirection = normalize(_eye - pos_w); - - phongMaterial mtl = getPhongMaterial(); - #if USE_ALPHA_TEST - if(mtl.opacity < alphaTestThreshold) discard; - #endif - vec3 normal = normalize(normal_w); - #if USE_NORMAL_TEXTURE - normal = getNormal(pos_w, normal); - #endif - phongLighting = getPhongLighting(normal, pos_w, viewDirection, mtl.glossiness); - - #if _USE_SHADOW_MAP - vec4 finalColor = composePhongShading(phongLighting, mtl, computeShadow()); - #else - vec4 finalColor = composePhongShading(phongLighting, mtl, 1.0); - #endif - - return linearToGammaSpaceRGBA(finalColor); -} diff --git a/cocos2d/renderer/build/chunks/phong-vs.inc b/cocos2d/renderer/build/chunks/phong-vs.inc deleted file mode 100644 index dc3b421211b..00000000000 --- a/cocos2d/renderer/build/chunks/phong-vs.inc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -attribute vec3 a_position; -attribute vec3 a_normal; - -#if _USE_ATTRIBUTE_COLOR - attribute lowp vec4 a_color; - varying lowp vec4 v_color; -#endif - -uniform mat4 _model; -uniform mat4 _viewProj; -uniform mat3 _normalMatrix; - -varying vec3 normal_w; -varying vec3 pos_w; - -#if USE_DIFFUSE_TEXTURE || USE_NORMAL_TEXTURE || USE_EMISSIVE_TEXTURE - attribute vec2 a_uv0; - uniform vec2 mainTiling; - uniform vec2 mainOffset; - varying vec2 v_uv0; -#endif - -#if _USE_SKINNING - #include -#endif - -#if _USE_SHADOW_MAP - #include -#endif - -vec4 vert () { - vec4 pos = vec4(a_position, 1); - vec4 normal = vec4(a_normal, 0); - - #if _USE_SKINNING - skinVertex(pos, normal); - #endif - - pos_w = (_model * pos).xyz; - pos = _viewProj * _model * pos; - - normal_w = _normalMatrix * normal.xyz; - - #if _USE_SHADOW_MAP - prepareShadowData(pos_w); - #endif - - #if USE_DIFFUSE_TEXTURE || USE_NORMAL_TEXTURE || USE_EMISSIVE_TEXTURE - v_uv0 = a_uv0 * mainTiling + mainOffset; - #endif - - #if _USE_ATTRIBUTE_COLOR - v_color = a_color; - #endif - - return pos; -} diff --git a/cocos2d/renderer/build/chunks/shader/phong-fs.inc b/cocos2d/renderer/build/chunks/shader/phong-fs.inc new file mode 100644 index 00000000000..75f59e4145a --- /dev/null +++ b/cocos2d/renderer/build/chunks/shader/phong-fs.inc @@ -0,0 +1,42 @@ + +#if USE_NORMAL_TEXTURE +#extension GL_OES_standard_derivatives : enable +#endif + +#include +#include +#include + +#include + +varying vec3 v_worldNormal; +varying vec3 v_worldPos; + +#include +#include +#include +#include +#include +#include + +void main () { + vec4 diffuse; + CALC_DIFFUSE(diffuse); + ALPHA_TEST(diffuse); + + PhongMaterial material; + material.diffuse = diffuse.rgb; + material.opacity = diffuse.a; + + CALC_EMISSIVE(material.emissive); + CALC_SPECULAR(material.specular); + + vec3 viewDirection = normalize(cc_cameraPos.xyz - v_worldPos); + vec3 normal; + vec4 phongColor; + + CALC_NORMAL(normal, v_worldPos, v_worldNormal); + CALC_PHONG_LIGHTING(phongColor, material, normal, v_worldPos, viewDirection); + + gl_FragColor = LINEAR_TO_OUTPUT_TEXEL( phongColor ); +} diff --git a/cocos2d/renderer/build/chunks/shader/phong-vs.inc b/cocos2d/renderer/build/chunks/shader/phong-vs.inc new file mode 100644 index 00000000000..db47f924065 --- /dev/null +++ b/cocos2d/renderer/build/chunks/shader/phong-vs.inc @@ -0,0 +1,26 @@ + +#include +#include + +varying vec3 v_worldNormal; +varying vec3 v_worldPos; + +#include +#include +#include + +void main () { + vec4 position = vec4(a_position, 1); + vec4 normal = vec4(1, 1, 1, 0); + + MUL_ATTR_NORMAL(normal); + SKIN_VERTEX(position, normal); + + v_worldPos = (cc_matWorld * position).xyz; + v_worldNormal = cc_matWorldIT * normal.xyz; + + CLAC_SHADOW(); + ATTRIBUTE_TO_VARYING(); + + gl_Position = cc_matViewProj * cc_matWorld * position; +} diff --git a/cocos2d/renderer/build/chunks/shadow-depth-fs.inc b/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc similarity index 74% rename from cocos2d/renderer/build/chunks/shadow-depth-fs.inc rename to cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc index 432da9a9c7f..6c545bc702f 100644 --- a/cocos2d/renderer/build/chunks/shadow-depth-fs.inc +++ b/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc @@ -1,13 +1,13 @@ // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -uniform float _depthScale; +uniform float cc_depthScale; varying float vDepth; #include vec4 frag() { // doing exp() here will cause float precision issue. - //float depth = clamp(exp(-min(87.0, _depthScale * vDepth)), 0.0, 1.0); + //float depth = clamp(exp(-min(87.0, cc_depthScale * vDepth)), 0.0, 1.0); return packDepthToRGBA(vDepth); // TODO: if support float32 * 4 color buffer? //gl_FragColor = vec4(depth, 1.0, 1.0, 1.0); diff --git a/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc b/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc new file mode 100644 index 00000000000..2f07a845ffa --- /dev/null +++ b/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc @@ -0,0 +1,22 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +attribute vec3 a_position; + +uniform mat4 cc_matWorld; +uniform mat4 cc_lightViewProjMatrix; +uniform float cc_minDepth; +uniform float cc_maxDepth; +uniform float cc_bias; +varying float vDepth; + +#include + +vec4 vert() { + vec4 position = vec4(a_position, 1); + + SKIN_VERTEX(position); + + // compute vDepth according to active camera's minDepth and maxDepth. + vDepth = ((gl_Position.z + cc_minDepth) / (cc_minDepth + cc_maxDepth)) + cc_bias; + return cc_lightViewProjMatrix * cc_matWorld * position; +} diff --git a/cocos2d/renderer/build/chunks/shader/unlit-fs.inc b/cocos2d/renderer/build/chunks/shader/unlit-fs.inc new file mode 100644 index 00000000000..ff9f864a9cf --- /dev/null +++ b/cocos2d/renderer/build/chunks/shader/unlit-fs.inc @@ -0,0 +1,13 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#include +#include +#include +#include + +void main () { + vec4 diffuse; + CALC_DIFFUSE(diffuse); + ALPHA_TEST(diffuse); + gl_FragColor = LINEAR_TO_OUTPUT_TEXEL( diffuse ); +} diff --git a/cocos2d/renderer/build/chunks/shader/unlit-vs.inc b/cocos2d/renderer/build/chunks/shader/unlit-vs.inc new file mode 100644 index 00000000000..65dab7aa4cd --- /dev/null +++ b/cocos2d/renderer/build/chunks/shader/unlit-vs.inc @@ -0,0 +1,16 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#include +#include + +#include +#include + +void main () { + vec4 position = vec4(a_position, 1); + + SKIN_VERTEX(position); + ATTRIBUTE_TO_VARYING(); + + gl_Position = cc_matViewProj * cc_matWorld * position; +} diff --git a/cocos2d/renderer/build/chunks/shadow-depth-vs.inc b/cocos2d/renderer/build/chunks/shadow-depth-vs.inc deleted file mode 100644 index c9309beff43..00000000000 --- a/cocos2d/renderer/build/chunks/shadow-depth-vs.inc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -attribute vec3 a_position; - -uniform mat4 _model; -uniform mat4 _lightViewProjMatrix; -uniform float _minDepth; -uniform float _maxDepth; -uniform float _bias; -varying float vDepth; - -#if _USE_SKINNING - #include -#endif - -vec4 vert() { - vec4 pos = vec4(a_position, 1); - - #if _USE_SKINNING - mat4 skinMat = skinMatrix(); - pos = skinMat * pos; - #endif - - // compute vDepth according to active camera's minDepth and maxDepth. - vDepth = ((gl_Position.z + _minDepth) / (_minDepth + _maxDepth)) + _bias; - return _lightViewProjMatrix * _model * pos; -} diff --git a/cocos2d/renderer/build/chunks/shadow-prepare.inc b/cocos2d/renderer/build/chunks/shadow-prepare.inc deleted file mode 100644 index c1d7befe86b..00000000000 --- a/cocos2d/renderer/build/chunks/shadow-prepare.inc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - #if _NUM_SHADOW_LIGHTS > 0 - #pragma for id in range(0, _NUM_SHADOW_LIGHTS) - uniform mat4 _lightViewProjMatrix_{id}; - uniform float _minDepth_{id}; - uniform float _maxDepth_{id}; - varying vec4 pos_lightspace_{id}; - varying float vDepth_{id}; - #pragma endFor - #endif - - void prepareShadowData(vec3 pos_w) { - #if _NUM_SHADOW_LIGHTS > 0 - #pragma for id in range(0, _NUM_SHADOW_LIGHTS) - pos_lightspace_{id} = _lightViewProjMatrix_{id} * vec4(pos_w, 1.0); - vDepth_{id} = (pos_lightspace_{id}.z + _minDepth_{id}) / (_minDepth_{id} + _maxDepth_{id}); - #pragma endFor - #endif - } \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/shadowmap-declare-frag.inc b/cocos2d/renderer/build/chunks/shadowmap-declare-frag.inc new file mode 100644 index 00000000000..54380a1ba8f --- /dev/null +++ b/cocos2d/renderer/build/chunks/shadowmap-declare-frag.inc @@ -0,0 +1,45 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#if _USE_SHADOW_MAP + #include + + #if _NUM_SHADOW_LIGHTS > 0 + #pragma for id in range(0, _NUM_SHADOW_LIGHTS) + uniform sampler2D cc_shadowMap_{id}; + uniform float cc_darkness_{id}; + uniform float cc_depthScale_{id}; + uniform float cc_frustumEdgeFalloff_{id}; + varying vec4 v_posLightSpace{id}; + varying float v_depth{id}; + #pragma endFor + #endif + + float computeFallOff(float esm, vec2 coords, float frustumEdgeFalloff) { + float mask = smoothstep(1.0 - frustumEdgeFalloff, 1.0, clamp(dot(coords, coords), 0.0, 1.0)); + return mix(esm, 1.0, mask); + } + + float computeShadowESM(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float depthScale, float darkness, float frustumEdgeFalloff) { + vec2 projCoords = pos_lightspace.xy / pos_lightspace.w; + vec2 shadowUV = projCoords * 0.5 + vec2(0.5); + if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) { + return 1.0; + } + float currentDepth = clamp(vDepth, 0.0, 1.0); + float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, shadowUV)); + //float esm = clamp(exp(min(87.0, -depthScale * (currentDepth - closestDepth))), 1.0 - darkness, 1.0); + float esm = clamp(exp(-depthScale * (currentDepth - closestDepth)), 1.0 - darkness, 1.0); + return computeFallOff(esm, projCoords, frustumEdgeFalloff); + } + + float computeShadow() { + float shadow = 1.0; + #if _NUM_SHADOW_LIGHTS > 0 + #pragma for id in range(0, _NUM_SHADOW_LIGHTS) + shadow *= computeShadowESM(cc_shadowMap_{id}, v_posLightSpace{id}, v_depth{id}, cc_depthScale_{id}, cc_darkness_{id}, cc_frustumEdgeFalloff_{id}); + #pragma endFor + #endif + return shadow; + } + +#endif \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/shadowmap-declare-vert.inc b/cocos2d/renderer/build/chunks/shadowmap-declare-vert.inc new file mode 100644 index 00000000000..9b7bee154e0 --- /dev/null +++ b/cocos2d/renderer/build/chunks/shadowmap-declare-vert.inc @@ -0,0 +1,24 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#if _USE_SHADOW_MAP + #if _NUM_SHADOW_LIGHTS > 0 + #pragma for id in range(0, _NUM_SHADOW_LIGHTS) + uniform mat4 cc_lightViewProjMatrix_{id}; + uniform float cc_minDepth_{id}; + uniform float cc_maxDepth_{id}; + varying vec4 v_posLightSpace{id}; + varying float v_depth{id}; + #pragma endFor + #endif +#endif + +void CLAC_SHADOW () { + #if _USE_SHADOW_MAP + #if _NUM_SHADOW_LIGHTS > 0 + #pragma for id in range(0, _NUM_SHADOW_LIGHTS) + v_posLightSpace{id} = cc_lightViewProjMatrix_{id} * vec4(v_worldPos, 1.0); + v_depth{id} = (v_posLightSpace{id}.z + cc_minDepth_{id}) / (cc_minDepth_{id} + cc_maxDepth_{id}); + #pragma endFor + #endif + #endif +} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/skinning.inc b/cocos2d/renderer/build/chunks/skinning.inc index 554fd3cc4ca..c5de5c7e9d2 100644 --- a/cocos2d/renderer/build/chunks/skinning.inc +++ b/cocos2d/renderer/build/chunks/skinning.inc @@ -1,61 +1,71 @@ // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -attribute vec4 a_weights; -attribute vec4 a_joints; +#if _USE_SKINNING -#if _USE_JOINTS_TEXTRUE -uniform sampler2D _jointsTexture; -uniform float _jointsTextureSize; + attribute vec4 a_weights; + attribute vec4 a_joints; -mat4 getBoneMatrix(const in float i) { - float size = _jointsTextureSize; - float j = i * 4.0; - float x = mod(j, size); - float y = floor(j / size); + #if _USE_JOINTS_TEXTRUE + uniform sampler2D _jointsTexture; + uniform float _jointsTextureSize; - float dx = 1.0 / size; - float dy = 1.0 / size; + mat4 getBoneMatrix(const in float i) { + float size = _jointsTextureSize; + float j = i * 4.0; + float x = mod(j, size); + float y = floor(j / size); - y = dy * (y + 0.5); + float dx = 1.0 / size; + float dy = 1.0 / size; - vec4 v1 = texture2D(_jointsTexture, vec2(dx * (x + 0.5), y)); - vec4 v2 = texture2D(_jointsTexture, vec2(dx * (x + 1.5), y)); - vec4 v3 = texture2D(_jointsTexture, vec2(dx * (x + 2.5), y)); - vec4 v4 = texture2D(_jointsTexture, vec2(dx * (x + 3.5), y)); + y = dy * (y + 0.5); - return mat4(v1, v2, v3, v4); -} -#else -uniform mat4 _jointMatrices[64]; + vec4 v1 = texture2D(_jointsTexture, vec2(dx * (x + 0.5), y)); + vec4 v2 = texture2D(_jointsTexture, vec2(dx * (x + 1.5), y)); + vec4 v3 = texture2D(_jointsTexture, vec2(dx * (x + 2.5), y)); + vec4 v4 = texture2D(_jointsTexture, vec2(dx * (x + 3.5), y)); -mat4 getBoneMatrix(const in float i) { - return _jointMatrices[int(i)]; -} + return mat4(v1, v2, v3, v4); + } + #else + uniform mat4 _jointMatrices[64]; + + mat4 getBoneMatrix(const in float i) { + return _jointMatrices[int(i)]; + } + #endif + + mat4 skinMatrix() { + return + getBoneMatrix(a_joints.x) * a_weights.x + + getBoneMatrix(a_joints.y) * a_weights.y + + getBoneMatrix(a_joints.z) * a_weights.z + + getBoneMatrix(a_joints.w) * a_weights.w + ; + } #endif -mat4 skinMatrix() { - return - getBoneMatrix(a_joints.x) * a_weights.x + - getBoneMatrix(a_joints.y) * a_weights.y + - getBoneMatrix(a_joints.z) * a_weights.z + - getBoneMatrix(a_joints.w) * a_weights.w - ; -} -void skinVertex(inout vec4 a1) { - mat4 m = skinMatrix(); - a1 = m * a1; +void SKIN_VERTEX(inout vec4 a1) { + #if _USE_SKINNING + mat4 m = skinMatrix(); + a1 = m * a1; + #endif } - -void skinVertex(inout vec4 a1, inout vec4 a2) { - mat4 m = skinMatrix(); - a1 = m * a1; - a2 = m * a2; + +void SKIN_VERTEX(inout vec4 a1, inout vec4 a2) { + #if _USE_SKINNING + mat4 m = skinMatrix(); + a1 = m * a1; + a2 = m * a2; + #endif } -void skinVertex(inout vec4 a1, inout vec4 a2, inout vec4 a3) { - mat4 m = skinMatrix(); - a1 = m * a1; - a2 = m * a2; - a3 = m * a3; -} \ No newline at end of file +void SKIN_VERTEX(inout vec4 a1, inout vec4 a2, inout vec4 a3) { + #if _USE_SKINNING + mat4 m = skinMatrix(); + a1 = m * a1; + a2 = m * a2; + a3 = m * a3; + #endif +} diff --git a/cocos2d/renderer/build/chunks/specular.inc b/cocos2d/renderer/build/chunks/specular.inc new file mode 100644 index 00000000000..94056b156fa --- /dev/null +++ b/cocos2d/renderer/build/chunks/specular.inc @@ -0,0 +1,46 @@ + +#if USE_SPECULAR + #property #color3 + uniform vec3 specularColor; + + #if USE_SPECULAR_TEXTURE + #property + uniform sampler2D specularTexture; + #endif + +#endif + +void MULTIPLY_SPECULAR_TEXTRUE_COLOR (inout vec3 color, in vec2 uv) { + #if USE_SPECULAR_TEXTURE && _USE_ATTRIBUTE_UV0 + vec4 specularTextureColor = texture2D(specularTexture, uv); + specularTextureColor = TEXEL_TO_LINEAR(specularTextureColor); + color *= specularTextureColor.rgb; + #endif +} + +void MULTIPLY_SPECULAR_TEXTRUE_COLOR (inout vec3 color) { + #if USE_SPECULAR_TEXTURE && _USE_ATTRIBUTE_UV0 + + #ifdef _IS_VERT_SHADER + vec2 uv = a_uv0; + #else + vec2 uv = v_uv0; + #endif + + MULTIPLY_SPECULAR_TEXTRUE_COLOR(color, uv); + #endif +} + +void CALC_SPECULAR (inout vec3 specular, in vec2 uv) { + #if USE_SPECULAR + specular = specularColor; + MULTIPLY_SPECULAR_TEXTRUE_COLOR(specular, uv); + #endif +} + +void CALC_SPECULAR (inout vec3 specular) { + #if USE_SPECULAR + specular = specularColor; + MULTIPLY_SPECULAR_TEXTRUE_COLOR(specular); + #endif +} diff --git a/cocos2d/renderer/build/chunks/unlit-fs.inc b/cocos2d/renderer/build/chunks/unlit-fs.inc deleted file mode 100644 index 56be8ea6c30..00000000000 --- a/cocos2d/renderer/build/chunks/unlit-fs.inc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -#if USE_TEXTURE - uniform sampler2D texture; -#endif - -#if _USE_ATTRIBUTE_UV0 - varying vec2 v_uv0; -#endif - -#if _USE_ATTRIBUTE_COLOR - varying vec4 v_color; -#endif - -uniform vec4 color; - -vec4 frag () { - vec4 o = color; - - #if _USE_ATTRIBUTE_COLOR - o *= v_color; - #endif - - #if USE_TEXTURE && _USE_ATTRIBUTE_UV0 - o *= texture2D(texture, v_uv0); - #endif - - return o; -} \ No newline at end of file diff --git a/cocos2d/renderer/build/chunks/unlit-vs.inc b/cocos2d/renderer/build/chunks/unlit-vs.inc deleted file mode 100644 index 621f889810c..00000000000 --- a/cocos2d/renderer/build/chunks/unlit-vs.inc +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -uniform mat4 _viewProj; -uniform mat4 _model; - -attribute vec3 a_position; - -#if _USE_ATTRIBUTE_COLOR - attribute lowp vec4 a_color; - varying lowp vec4 v_color; -#endif - -#if _USE_ATTRIBUTE_UV0 - attribute vec2 a_uv0; - varying vec2 v_uv0; -#endif - -#if _USE_SKINNING - #include -#endif - -vec4 vert () { - mat4 mvp = _viewProj * _model; - - #if _USE_SKINNING - mvp = mvp * skinMatrix(); - #endif - - vec4 pos = mvp * vec4(a_position, 1); - - #if _USE_ATTRIBUTE_UV0 - v_uv0 = a_uv0; - #endif - - #if _USE_ATTRIBUTE_COLOR - v_color = a_color; - #endif - - return pos; -} \ No newline at end of file diff --git a/cocos2d/renderer/build/shdc-lib.js b/cocos2d/renderer/build/shdc-lib.js index 1cf09284bca..9df850eceb9 100644 --- a/cocos2d/renderer/build/shdc-lib.js +++ b/cocos2d/renderer/build/shdc-lib.js @@ -17,7 +17,12 @@ let rangePragma = /range\(([\d.,\s]+)\)\s(\w+)/; let defaultPragma = /default\(([\d.,]+)\)/; let namePragma = /name\(([^)]+)\)/; let precision = /(low|medium|high)p/; -let builtins = /^_\w+$/; +let builtins = /^(_|cc_)\w+$/; + +const vertHeader = '#define _IS_VERT_SHADER 1\n'; +const fragHeader = '#define _IS_FRAG_SHADER 1\n'; + +let ignoreDefines = {}; function convertType(t) { let tp = mappings.typeParams[t.toUpperCase()]; return tp === undefined ? t : tp; } @@ -25,17 +30,26 @@ function unwindIncludes(str, chunks) { function replace(match, include) { let replace = chunks[include]; if (replace === undefined) { - console.error(`can not resolve #include <${include}>`); + Editor.error(`can not resolve #include <${include}>`); } return unwindIncludes(replace, chunks); } return str.replace(includeRE, replace); } -function glslStripComment(code) { - let tokens = tokenizer(code); - +function glslStrip(code, cache) { + // strip tag lines let result = ''; + let codes = code.split('\n'); + for (let i = 1; i <= codes.length; i++) { + if (cache.tagLines.indexOf(i) === -1) { + result += codes[i-1] + '\n'; + } + } + + // strip comment + let tokens = tokenizer(result); + result = ''; for (let i = 0; i < tokens.length; ++i) { let t = tokens[i]; if (t.type != 'block-comment' && t.type != 'line-comment' && t.type != 'eof') { @@ -43,6 +57,9 @@ function glslStripComment(code) { } } + // strip multiple line break + result = result.replace(/\n\n+/g, '\n\n'); + return result; } @@ -81,6 +98,10 @@ function extractDefines(tokens, defines, cache) { }; for (let i = 0; i < tokens.length; ) { let t = tokens[i], str = t.data, id, df; + if (str.startsWith('#define')) { + ignoreDefines[str.split(whitespaces)[1]] = true; + i++; continue; + } if (t.type !== 'preprocessor' || str.startsWith('#extension')) { i++; continue; } tokens.splice(i, 1); // strip out other preprocessor tokens for parser to work str = str.split(whitespaces); @@ -107,12 +128,13 @@ function extractDefines(tokens, defines, cache) { def.range = JSON.parse(`[${mc[1]}]`); } continue; - } else if (!ifprocessor.test(str[0])) continue; + } else if (!ifprocessor.test(str[0])) { cache[t.line] = str; cache.tagLines.push(t.line); continue; } // tags if (str[0] === '#elif') { curDefs.pop(); save(t.line); } // pop one level up let defs = []; str.splice(1).some(s => { id = s.match(ident); if (id) { // is identifier + if (ignoreDefines[id[0]]) return; let d = curDefs.reduce((acc, val) => acc.concat(val), defs.slice()); df = defines.find(d => d.name === id[0]); if (df) { if (d.length < df.defines.length) df.defines = d; } @@ -160,8 +182,9 @@ function extractParams(tokens, cache, uniforms, attributes, extensions) { if (mc) param.displayName = mc[1]; for (let j = 0; j < tags.length; j++) { let tag = tags[j]; - if (tag === '#color') param.type = convertType(param.type); + if (tag.startsWith('#color')) param.type = convertType(tag.substring(1)); else if (tag === '#property') param.property = true; + // else if (tag === '#value') param.value = ; } } } @@ -264,7 +287,7 @@ let getChunkByName = (function() { let entryRE = /([\w-]+)(?::(\w+))?/; return function(name, cache) { let entryCap = entryRE.exec(name), entry = entryCap[2] || 'main', content = cache[entryCap[1]]; - if (!content) { console.error(`shader ${entryCap[1]} not found!`); return [ '', entry ]; } + if (!content) { Editor.error(`shader ${entryCap[1]} not found!`); return [ '', entry ]; } return [ content, entry ]; }; })(); @@ -273,7 +296,7 @@ let wrapEntry = (function() { let wrapperFactory = (vert, fn) => `\nvoid main() { ${vert ? 'gl_Position' : 'gl_FragColor'} = ${fn}(); }\n`; return function(content, name, entry, ast, isVert) { if (!ast.scope[entry] || ast.scope[entry].parent.type !== 'function') - console.error(`entry function ${name} not found`); + Editor.error(`entry function ${name} not found`); return entry === 'main' ? content : content + wrapperFactory(isVert, entry); }; })(); @@ -282,10 +305,10 @@ let buildShader = function(vertName, fragName, cache) { let [ vert, vEntry ] = getChunkByName(vertName, cache, true); let [ frag, fEntry ] = getChunkByName(fragName, cache); - let defines = [], defCache = { lines: [] }, tokens, ast; + let defines = [], defCache = { lines: [], tagLines: [] }, tokens, ast; let uniforms = [], attributes = [], extensions = []; - vert = glslStripComment(vert); + vert = vertHeader + vert; vert = unwindIncludes(vert, cache); vert = expandStructMacro(vert); tokens = tokenizer(vert); @@ -294,10 +317,11 @@ let buildShader = function(vertName, fragName, cache) { try { ast = parser(tokens); vert = wrapEntry(vert, vertName, vEntry, ast, true); - } catch (e) { console.error(`parse ${vertName} failed: ${e}`); } + } catch (e) { Editor.error(`parse ${vertName} failed: ${e}`); } + vert = glslStrip(vert, defCache); - defCache = { lines: [] }; - frag = glslStripComment(frag); + defCache = { lines: [], tagLines: [] }; + frag = fragHeader + frag; frag = unwindIncludes(frag, cache); frag = expandStructMacro(frag); tokens = tokenizer(frag); @@ -306,7 +330,8 @@ let buildShader = function(vertName, fragName, cache) { try { ast = parser(tokens); frag = wrapEntry(frag, fragName, fEntry, ast); - } catch (e) { console.error(`parse ${fragName} failed: ${e}`); } + } catch (e) { Editor.error(`parse ${fragName} failed: ${e}`); } + frag = glslStrip(frag, defCache); return { vert, frag, defines, uniforms, attributes, extensions }; }; @@ -401,12 +426,13 @@ let addChunksCache = function(chunksDir) { for (let i = 0; i < files.length; ++i) { let name = path_.basename(files[i], '.inc'); let content = fs.readFileSync(files[i], { encoding: 'utf8' }); - chunksCache[name] = glslStripComment(content); + chunksCache[name] = content; //glslStrip(content); } return chunksCache; }; let buildEffect = function (name, content) { + ignoreDefines = {}; let { effect, templates } = parseEffect(content); effect = buildEffectJSON(effect); effect.name = name; Object.assign(templates, chunksCache); diff --git a/cocos2d/renderer/core/base-renderer.js b/cocos2d/renderer/core/base-renderer.js index 4408ffd87d4..be4a249bf7c 100644 --- a/cocos2d/renderer/core/base-renderer.js +++ b/cocos2d/renderer/core/base-renderer.js @@ -523,7 +523,7 @@ export default class Base { _draw(item) { const device = this._device; const programLib = this._programLib; - const { node, ia, uniforms, technique, defines } = item; + const { node, ia, uniforms, technique, defines, effect } = item; // reset the pool // NOTE: we can use drawCounter optimize this @@ -543,12 +543,12 @@ export default class Base { // TODO: try commit this depends on effect // { node.getWorldMatrix(_m4_tmp); - device.setUniform('_model', mat4.array(_float16_pool.add(), _m4_tmp)); + device.setUniform('cc_matWorld', mat4.array(_float16_pool.add(), _m4_tmp)); let inverse = mat3.invert(_m3_tmp, mat3.fromMat4(_m3_tmp, _m4_tmp)); if (inverse) { mat3.transpose(_m3_tmp, inverse); - device.setUniform('_normalMatrix', mat3.array(_float9_pool.add(), _m3_tmp)); + device.setUniform('cc_matWorldIT', mat3.array(_float9_pool.add(), _m3_tmp)); } // } @@ -574,7 +574,7 @@ export default class Base { device.setPrimitiveType(ia._primitiveType); // set program - let program = programLib.getProgram(pass._programName, defines); + let program = programLib.getProgram(pass._programName, defines, null, effect._name); device.setProgram(program); // cull mode diff --git a/cocos2d/renderer/core/effect.js b/cocos2d/renderer/core/effect.js index 5583b5136b1..07065a41cbd 100644 --- a/cocos2d/renderer/core/effect.js +++ b/cocos2d/renderer/core/effect.js @@ -19,7 +19,8 @@ class Effect { /** * @param {Array} techniques */ - constructor(techniques, properties = {}, defines = {}, dependencies = []) { + constructor(name, techniques, properties = {}, defines = {}, dependencies = []) { + this._name = name; this._techniques = techniques; this._properties = properties; this._defines = defines; @@ -56,7 +57,7 @@ class Effect { getProperty(name) { if (!this._properties[name]) { - console.warn(`Failed to get property ${name}, property not found.`); + cc.warn(`${this._name} : Failed to get property ${name}, property not found.`); return null; } return this._properties[name].value; @@ -65,11 +66,11 @@ class Effect { setProperty(name, value) { let prop = this._properties[name]; if (!prop) { - console.warn(`Failed to set property ${name}, property not found.`); + cc.warn(`${this._name} : Failed to set property ${name}, property not found.`); return; } // else if (!typeCheck(value, prop.type)) { // re-enable this after 3.x migration - // console.warn(`Failed to set property ${name}, property type mismatch.`); + // cc.warn(`Failed to set property ${name}, property type mismatch.`); // return; // } this._properties[name].value = value; @@ -78,7 +79,7 @@ class Effect { getDefine(name) { let def = this._defines[name]; if (def === undefined) { - console.warn(`Failed to get define ${name}, define not found.`); + cc.warn(`${this._name} : Failed to get define ${name}, define not found.`); } return def; @@ -87,7 +88,7 @@ class Effect { define(name, value) { let def = this._defines[name]; if (def === undefined) { - console.warn(`Failed to set define ${name}, define not found.`); + cc.warn(`${this._name} : Failed to set define ${name}, define not found.`); return; } @@ -166,7 +167,7 @@ let parseProperties = (function() { } // the property is not defined in all the shaders used in techs if (!uniformInfo) { - console.warn(`illegal property: ${prop}`); + cc.warn(`${json.name} : illegal property: ${prop}`); continue; } // TODO: different param with same name for different passes @@ -223,7 +224,7 @@ Effect.parseEffect = function(effect) { let extensions = programs.reduce((acc, cur) => acc = acc.concat(cur.extensions), []); extensions = cloneObjArray(extensions); - return new Effect(techniques, uniforms, defines, extensions); + return new Effect(effect.name, techniques, uniforms, defines, extensions); }; if (CC_EDITOR) { diff --git a/cocos2d/renderer/core/program-lib.js b/cocos2d/renderer/core/program-lib.js index 6d4543f9e21..2fecddebc4c 100644 --- a/cocos2d/renderer/core/program-lib.js +++ b/cocos2d/renderer/core/program-lib.js @@ -182,8 +182,9 @@ export default class ProgramLib { * @param {string} name * @param {Object} defines * @param {Object} extensions + * @param {String} errPrefix */ - getProgram(name, defines, extensions) { + getProgram(name, defines, extensions, errPrefix) { let key = this.getKey(name, defines); let program = this._cache[key]; if (program) { @@ -202,7 +203,23 @@ export default class ProgramLib { vert, frag }); - program.link(); + let errors = program.link(); + if (errors) { + let vertLines = vert.split('\n'); + let fragLines = frag.split('\n'); + let defineLength = Object.keys(defines).length; + errors.forEach(err => { + let line = err.line - 1; + let originLine = err.line - defineLength; + + let lines = err.type === 'vs' ? vertLines : fragLines; + // let source = ` ${lines[line-1]}\n>${lines[line]}\n ${lines[line+1]}`; + let source = lines[line]; + + let info = err.info || `Failed to compile ${err.type} ${err.fileID} (ln ${originLine}): \n ${err.message}: \n ${source}`; + cc.error(`${errPrefix} : ${info}`); + }) + } this._cache[key] = program; return program; diff --git a/cocos2d/renderer/gfx/program.js b/cocos2d/renderer/gfx/program.js index 6961b73372f..c76aa984041 100644 --- a/cocos2d/renderer/gfx/program.js +++ b/cocos2d/renderer/gfx/program.js @@ -13,7 +13,7 @@ function _parseError(out, type, errorLog) { fileID: parts[1] | 0, line: parts[2] | 0, message: parts[3].trim() - }); + }) } else if (msg.length > 0) { out.push({ type: type, @@ -98,19 +98,12 @@ export default class Program { gl.deleteShader(fragShader); if (failed) { - errors.forEach(err => { - console.error(`Failed to compile ${err.type} ${err.fileID} (ln ${err.line}): ${err.message}`); - }); - return; + return errors; } if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - console.error(`Failed to link shader program: ${gl.getProgramInfoLog(program)}`); - failed = true; - } - - if (failed) { - return; + errors.push({info: `Failed to link shader program: ${gl.getProgramInfoLog(program)}`}); + return errors; } this._glID = program; diff --git a/cocos2d/renderer/renderers/forward-renderer.js b/cocos2d/renderer/renderers/forward-renderer.js index 0ca65738fe5..39ad72cb513 100644 --- a/cocos2d/renderer/renderers/forward-renderer.js +++ b/cocos2d/renderer/renderers/forward-renderer.js @@ -3,6 +3,7 @@ import { vec3, mat4 } from '../../core/vmath'; import BaseRenderer from '../core/base-renderer'; import enums from '../enums'; +import { RecyclePool } from '../memop'; let _a16_view = new Float32Array(16); let _a16_proj = new Float32Array(16); @@ -14,6 +15,10 @@ let _camPos = vec3.create(0, 0, 0); let _camFwd = vec3.create(0, 0, 0); let _v3_tmp1 = vec3.create(0, 0, 0); +let _float16_pool = new RecyclePool(() => { + return new Float32Array(16); +}, 8); + export default class ForwardRenderer extends BaseRenderer { constructor(device, builtin) { super(device, builtin); @@ -22,6 +27,7 @@ export default class ForwardRenderer extends BaseRenderer { this._pointLights = []; this._spotLights = []; this._shadowLights = []; + this._sceneAmbient = new Float32Array([0, 0, 0]); this._numLights = 0; @@ -30,6 +36,16 @@ export default class ForwardRenderer extends BaseRenderer { this._registerStage('transparent', this._transparentStage.bind(this)); } + get sceneAmbient () { + let ambient = this._sceneAmbient; + return cc.color(ambient.r * 255, ambient.g * 255, ambient.b * 255, 255); + } + set sceneAmbient (val) { + this._sceneAmbient[0] = val.r /255; + this._sceneAmbient[1] = val.g /255; + this._sceneAmbient[2] = val.b /255; + } + reset () { this._reset(); } @@ -88,55 +104,82 @@ export default class ForwardRenderer extends BaseRenderer { _submitLightsUniforms () { let device = this._device; + device.setUniform('cc_sceneAmbient', this._sceneAmbient); + + _float16_pool.reset(); if (this._directionalLights.length > 0) { - for (let index = 0; index < this._directionalLights.length; ++index) { - let light = this._directionalLights[index]; - device.setUniform(`_dir_light${index}_direction`, light._directionUniform); - device.setUniform(`_dir_light${index}_color`, light._colorUniform); + let directions = _float16_pool.add(); + let colors = _float16_pool.add(); + + for (let i = 0; i < this._directionalLights.length; ++i) { + let light = this._directionalLights[i]; + let index = i * 4; + directions.set(light._directionUniform, index); + colors.set(light._colorUniform, index); } + + device.setUniform('cc_dirLightDirection', directions); + device.setUniform('cc_dirLightColor', colors); } if (this._pointLights.length > 0) { - for (let index = 0; index < this._pointLights.length; ++index) { - let light = this._pointLights[index]; - device.setUniform(`_point_light${index}_position`, light._positionUniform); - device.setUniform(`_point_light${index}_color`, light._colorUniform); - device.setUniform(`_point_light${index}_range`, light._range); + let positionAndRanges = _float16_pool.add(); + let colors = _float16_pool.add(); + for (let i = 0; i < this._pointLights.length; ++i) { + let light = this._pointLights[i]; + let index = i * 4; + positionAndRanges.set(light._positionUniform, index); + positionAndRanges[index+3] = light._range; + colors.set(light._colorUniform, index); } + + device.setUniform('cc_pointLightPositionAndRange', positionAndRanges); + device.setUniform('cc_pointLightColor', colors); } if (this._spotLights.length > 0) { - for (let index = 0; index < this._spotLights.length; ++index) { - let light = this._spotLights[index]; - device.setUniform(`_spot_light${index}_position`, light._positionUniform); - device.setUniform(`_spot_light${index}_direction`, light._directionUniform); - device.setUniform(`_spot_light${index}_color`, light._colorUniform); - device.setUniform(`_spot_light${index}_range`, light._range); - device.setUniform(`_spot_light${index}_spot`, light._spotUniform); + let positionAndRanges = _float16_pool.add(); + let directions = _float16_pool.add(); + let colors = _float16_pool.add(); + for (let i = 0; i < this._spotLights.length; ++i) { + let light = this._spotLights[i]; + let index = i * 4; + + positionAndRanges.set(light._positionUniform, index); + positionAndRanges[index+3] = light._range; + + directions.set(light._directionUniform, index); + directions[index+3] = light._spotUniform[0]; + + colors.set(light._colorUniform, index); + colors[index+3] = light._spotUniform[1]; } + + device.setUniform('cc_spotLightPositionAndRange', positionAndRanges); + device.setUniform('cc_spotLightDirection', directions); + device.setUniform('cc_spotLightColor', colors); } } _submitShadowStageUniforms(view) { let light = view._shadowLight; - this._device.setUniform('_minDepth', light.shadowMinDepth); - this._device.setUniform('_maxDepth', light.shadowMaxDepth); - this._device.setUniform('_bias', light.shadowBias); - this._device.setUniform('_depthScale', light.shadowDepthScale); + this._device.setUniform('cc_minDepth', light.shadowMinDepth); + this._device.setUniform('cc_maxDepth', light.shadowMaxDepth); + this._device.setUniform('cc_bias', light.shadowBias); + this._device.setUniform('cc_depthScale', light.shadowDepthScale); } _submitOtherStagesUniforms() { for (let index = 0; index < this._shadowLights.length; ++index) { let light = this._shadowLights[index]; - this._device.setUniform(`_lightViewProjMatrix_${index}`, mat4.array(_a16_lightViewProj, light.viewProjMatrix)); - this._device.setUniform(`_minDepth_${index}`, light.shadowMinDepth); - this._device.setUniform(`_maxDepth_${index}`, light.shadowMaxDepth); - this._device.setUniform(`_bias_${index}`, light.shadowBias); - this._device.setUniform(`_depthScale_${index}`, light.shadowDepthScale); - this._device.setUniform(`_darkness_${index}`, light.shadowDarkness); - this._device.setUniform(`_frustumEdgeFalloff_${index}`, light.frustumEdgeFalloff); - this._device.setUniform(`_texelSize_${index}`, new Float32Array([1.0 / light.shadowResolution, 1.0 / light.shadowResolution])); + this._device.setUniform(`cc_lightViewProjMatrix_${index}`, mat4.array(_a16_lightViewProj, light.viewProjMatrix)); + this._device.setUniform(`cc_minDepth_${index}`, light.shadowMinDepth); + this._device.setUniform(`cc_maxDepth_${index}`, light.shadowMaxDepth); + this._device.setUniform(`cc_bias_${index}`, light.shadowBias); + this._device.setUniform(`cc_depthScale_${index}`, light.shadowDepthScale); + this._device.setUniform(`cc_darkness_${index}`, light.shadowDarkness); + this._device.setUniform(`cc_frustumEdgeFalloff_${index}`, light.frustumEdgeFalloff); } } @@ -169,7 +212,7 @@ export default class ForwardRenderer extends BaseRenderer { } _shadowStage (view, items) { - this._device.setUniform('_lightViewProjMatrix', mat4.array(_a16_viewProj, view._matViewProj)); + this._device.setUniform('cc_lightViewProjMatrix', mat4.array(_a16_viewProj, view._matViewProj)); // update rendering this._submitShadowStageUniforms(view); @@ -213,10 +256,10 @@ export default class ForwardRenderer extends BaseRenderer { view.getPosition(_camPos); // update uniforms - this._device.setUniform('_view', mat4.array(_a16_view, view._matView)); - this._device.setUniform('_proj', mat4.array(_a16_proj, view._matProj)); - this._device.setUniform('_viewProj', mat4.array(_a16_viewProj, view._matViewProj)); - this._device.setUniform('_eye', vec3.array(_a3_camPos, _camPos)); + this._device.setUniform('cc_matView', mat4.array(_a16_view, view._matView)); + this._device.setUniform('cc_matpProj', mat4.array(_a16_proj, view._matProj)); + this._device.setUniform('cc_matViewProj', mat4.array(_a16_viewProj, view._matViewProj)); + this._device.setUniform('cc_cameraPos', vec3.array(_a3_camPos, _camPos)); // update rendering this._submitLightsUniforms(); @@ -230,10 +273,10 @@ export default class ForwardRenderer extends BaseRenderer { view.getForward(_camFwd); // update uniforms - this._device.setUniform('_view', mat4.array(_a16_view, view._matView)); - this._device.setUniform('_proj', mat4.array(_a16_proj, view._matProj)); - this._device.setUniform('_viewProj', mat4.array(_a16_viewProj, view._matViewProj)); - this._device.setUniform('_eye', vec3.array(_a3_camPos, _camPos)); + this._device.setUniform('cc_matView', mat4.array(_a16_view, view._matView)); + this._device.setUniform('cc_matpProj', mat4.array(_a16_proj, view._matProj)); + this._device.setUniform('cc_matViewProj', mat4.array(_a16_viewProj, view._matViewProj)); + this._device.setUniform('cc_cameraPos', vec3.array(_a3_camPos, _camPos)); this._submitLightsUniforms(); this._submitOtherStagesUniforms(); From e465f7e8ee50a314219cb5656aeaade031025d53 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Tue, 15 Jan 2019 19:11:55 +0800 Subject: [PATCH 0406/1631] remove redundant right shift for bitwise operation (#3754) --- cocos2d/core/value-types/color.js | 4 ++-- cocos2d/particle/particle-simulator.js | 2 +- cocos2d/tilemap/CCTiledMap.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/value-types/color.js b/cocos2d/core/value-types/color.js index 2b25ff83efd..722b9f1c611 100644 --- a/cocos2d/core/value-types/color.js +++ b/cocos2d/core/value-types/color.js @@ -336,12 +336,12 @@ var Color = (function () { */ proto.setA = function (alpha) { alpha = ~~cc.misc.clampf(alpha, 0, 255); - this._val = ((this._val & 0x00ffffff) | ((alpha << 24) >>> 0)) >>> 0; + this._val = ((this._val & 0x00ffffff) | (alpha << 24)) >>> 0; return this; }; proto._fastSetA = function (alpha) { - this._val = ((this._val & 0x00ffffff) | ((alpha << 24) >>> 0)) >>> 0; + this._val = ((this._val & 0x00ffffff) | (alpha << 24)) >>> 0; }; js.getset(proto, 'r', proto.getR, proto.setR, true); diff --git a/cocos2d/particle/particle-simulator.js b/cocos2d/particle/particle-simulator.js index 8caf1d90029..28ad9c4a218 100644 --- a/cocos2d/particle/particle-simulator.js +++ b/cocos2d/particle/particle-simulator.js @@ -60,7 +60,7 @@ let Particle = function () { let pool = new js.Pool(function (par) { par.pos.set(ZERO_VEC2); par.startPos.set(ZERO_VEC2); - par.color._val = ((255<<24) >>> 0); + par.color._val = 0xFF000000; par.deltaColor.r = par.deltaColor.g = par.deltaColor.b = 0; par.deltaColor.a = 255; par.size = 0; diff --git a/cocos2d/tilemap/CCTiledMap.js b/cocos2d/tilemap/CCTiledMap.js index f63feab7bcc..fcb398e11c6 100644 --- a/cocos2d/tilemap/CCTiledMap.js +++ b/cocos2d/tilemap/CCTiledMap.js @@ -153,7 +153,7 @@ let TileFlag = cc.Enum({ * @type {Number} * @static */ - FLIPPED_MASK: (~((0x80000000 | 0x40000000 | 0x20000000) >>> 0)) >>> 0 + FLIPPED_MASK: (~(0x80000000 | 0x40000000 | 0x20000000)) >>> 0 }); /* From 4a72600cba8bf9d67382fca21c7ffbac01bbbcb1 Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 16 Jan 2019 10:20:38 +0800 Subject: [PATCH 0407/1631] fix vivo oppo platform judgement on engine (#3757) --- cocos2d/core/platform/CCSys.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index 51b6f97bed6..fdcf7b6735c 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -29,8 +29,8 @@ let settingPlatform; settingPlatform = window._CCSettings ? _CCSettings.platform: undefined; } const isBaiduGame = (settingPlatform === 'baidugame' || settingPlatform === 'baidugame-subcontext'); -const isVivoGame = (settingPlatform === 'vivogame'); -const isOppoGame = (settingPlatform === 'oppogame'); +const isVivoGame = (settingPlatform === 'qgame'); +const isOppoGame = (settingPlatform === 'quickgame'); function initSys () { /** From 1e511635b255d83c45c7f89df61225cb664eda13 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 16 Jan 2019 18:03:17 +0800 Subject: [PATCH 0408/1631] fixed merge issues (#3759) * fixed merge issues * update material property --- cocos2d/core/components/CCSprite.js | 8 ++++--- cocos2d/core/mesh/CCMeshRenderer.js | 2 +- .../assemblers/sprite/2d/radial-filled.js | 8 +++++++ extensions/dragonbones/webgl-assembler.js | 23 ++++++++----------- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 2a2205e35e7..9fc53c2eee5 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -489,12 +489,11 @@ var Sprite = cc.Class({ // WebGL if (cc.game.renderType !== cc.game.RENDER_TYPE_CANVAS) { - this.markForUpdateRenderData(true); - this.markForRender(true); - let material = this.sharedMaterials[0]; // if material is not internal material, then need do nothing if (material && material!== this._graySpriteMaterial && material !== this._spriteMaterial) { + this.markForUpdateRenderData(true); + this.markForRender(true); return; } @@ -526,6 +525,9 @@ var Sprite = cc.Class({ if (this._renderData) { this._renderData.material = material; } + + this.markForUpdateRenderData(true); + this.markForRender(true); } else { this.disableRender(); diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index 08c900dea54..dffdf5bd485 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -194,7 +194,7 @@ let MeshRenderer = cc.Class({ let material = this.sharedMaterials[i]; if (material) continue; material = cc.Material.getInstantiatedMaterial(this._getDefaultMaterial(), this); - material.setProperty('texture', textures[i]); + material.setProperty('diffuseTexture', textures[i]); this.setMaterial(i, material); } } diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js index 9e8c4ae4707..d1943cb2ba2 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/2d/radial-filled.js @@ -223,6 +223,14 @@ module.exports = { packToDynamicAtlas(sprite, frame); + let fillStart = sprite._fillStart; + let fillRange = sprite._fillRange; + + if (fillRange < 0) { + fillStart += fillRange; + fillRange = -fillRange; + } + //do round fill start [0,1), include 0, exclude 1 while (fillStart >= 1.0) fillStart -= 1.0; while (fillStart < 0.0) fillStart += 1.0; diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 93c468f16c0..e9bc4835e7d 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -25,6 +25,8 @@ const Armature = require('./ArmatureDisplay'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); +const gfx = require('../../cocos2d/renderer/gfx'); +const Material = require('../../cocos2d/core/assets/material/CCMaterial'); let _boneColor = cc.color(255, 0, 0, 255); let _slotColor = cc.color(0, 0, 255, 255); @@ -56,28 +58,23 @@ function _getSlotMaterial (comp, slot, premultiAlpha) { } let key = tex.url + src + dst; - let baseMaterial = comp._material; + let baseMaterial = comp.sharedMaterials[0]; if (!baseMaterial) { return null; } let materialCache = comp._materialCache; let material = materialCache[key]; if (!material) { - var baseKey = baseMaterial._hash; - if (!materialCache[baseKey]) { - material = baseMaterial; - } else { - material = baseMaterial.clone(); - } + material = new Material(); + material.copy(baseMaterial); - material.useModel = true; - // update texture - material.texture = tex; - material.useColor = false; + material.define('_USE_MODEL', true); + material.setProperty('texture', tex); // update blend function - let pass = material._mainTech.passes[0]; + let pass = material.effect.getDefaultTechnique().passes[0]; pass.setBlend( + true, gfx.BLEND_FUNC_ADD, src, dst, gfx.BLEND_FUNC_ADD, @@ -87,7 +84,7 @@ function _getSlotMaterial (comp, slot, premultiAlpha) { material.updateHash(key); } else if (material.texture !== tex) { - material.texture = tex; + material.setProperty('texture', tex); material.updateHash(key); } return material; From ff58ffd8aaa1eda5acee6d0c7ad4685846da075d Mon Sep 17 00:00:00 2001 From: mac <1053210246@qq.com> Date: Wed, 16 Jan 2019 19:23:35 +0800 Subject: [PATCH 0409/1631] spine adapt to v211 --- extensions/spine/Skeleton.js | 10 +++++++--- extensions/spine/spine-assembler.js | 23 +++++++---------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index b2a46a6ef52..b440a1dd5f2 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -376,21 +376,25 @@ sp.Skeleton = cc.Class({ this._rootBone = null; this._listener = null; this._boundingBox = cc.rect(); - this._material = Material.getInstantiatedBuiltinMaterial('spine', this); this._materialCache = {}; this._debugRenderer = null; this._startSlotIndex = -1; this._endSlotIndex = -1; }, + onLoad() { + var material = Material.getInstantiatedBuiltinMaterial('spine', this); + this.setMaterial(0, material); + }, + // override _updateMaterial (material) { - this._super(material); + this.setMaterial(0, material); this._materialCache = {}; }, _updateUseTint () { - var cache = this._materialCache + var cache = this._materialCache; for (var mKey in cache) { var material = cache[mKey]; if (material) { diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index cfd1255d570..ce4fcf382e9 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -26,11 +26,10 @@ const Skeleton = require('./Skeleton'); const spine = require('./lib/spine'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); -const Material = require('../../cocos2d/core/assets/material/CCMaterial'); const VertexFormat = require('../../cocos2d/core/renderer/webgl/vertex-format') const VFOneColor = VertexFormat.vfmtPosUvColor; const VFTwoColor = VertexFormat.vfmtPosUvTwoColor; -import gfx from '../../cocos2d/renderer/gfx'; +const gfx = cc.gfx; let _quadTriangles = [0, 1, 2, 2, 3, 0]; let _slotColor = cc.color(0, 0, 255, 255); @@ -87,21 +86,16 @@ function _getSlotMaterial (comp, slot, tex) { } let key = tex.url + src + dst; - comp._material = comp._material || Material.getInstantiatedBuiltinMaterial('spine', comp); - let baseMaterial = comp._material; + let baseMaterial = comp.sharedMaterials[0]; + if (!baseMaterial) return null; + let materialCache = comp._materialCache; let material = materialCache[key]; if (!material) { - var baseKey = baseMaterial.getHash(); - if (!materialCache[baseKey]) { - material = baseMaterial; - } else { - material = new Material(); - material.copy(baseMaterial); - } - + material = new cc.Material(); + material.copy(baseMaterial); material.define('_USE_MODEL', true); - material.define('USE_TEXTURE', true); + material.define('USE_TINT', _useTint); // update texture material.setProperty('texture', tex); @@ -118,9 +112,6 @@ function _getSlotMaterial (comp, slot, tex) { materialCache[key] = material; } else if (material.getProperty('texture') !== tex) { - if (materialCache[material._hash]) { - delete materialCache[material._hash]; - } material.setProperty('texture', tex); material.updateHash(key); materialCache[key] = material; From 6ca07298335331ace328d77f7759a099a62ee871 Mon Sep 17 00:00:00 2001 From: mac <1053210246@qq.com> Date: Wed, 16 Jan 2019 19:36:28 +0800 Subject: [PATCH 0410/1631] Dragonbones adapt to v211 --- extensions/dragonbones/ArmatureDisplay.js | 2 +- extensions/dragonbones/webgl-assembler.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index e920221677a..bf862134ebe 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -372,7 +372,7 @@ let ArmatureDisplay = cc.Class({ // override _updateMaterial (material) { - this._super(material); + this.setMaterial(0, material); this._materialCache = {}; }, diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index e9bc4835e7d..6dca62d47b5 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -25,8 +25,8 @@ const Armature = require('./ArmatureDisplay'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); -const gfx = require('../../cocos2d/renderer/gfx'); const Material = require('../../cocos2d/core/assets/material/CCMaterial'); +const gfx = cc.gfx; let _boneColor = cc.color(255, 0, 0, 255); let _slotColor = cc.color(0, 0, 255, 255); From 276b861f558e5ed30fbb4073e948a7215838bb2b Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Wed, 16 Jan 2019 23:45:53 +0800 Subject: [PATCH 0411/1631] fix native spine and db bug (#3762) * native spine * Fix native spine bug --- cocos2d/renderer/render-data/ia-render-data.js | 3 ++- extensions/dragonbones/ArmatureDisplay.js | 1 + extensions/spine/Skeleton.js | 12 +++++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cocos2d/renderer/render-data/ia-render-data.js b/cocos2d/renderer/render-data/ia-render-data.js index 265f3f16bdc..70cfa26a905 100644 --- a/cocos2d/renderer/render-data/ia-render-data.js +++ b/cocos2d/renderer/render-data/ia-render-data.js @@ -18,4 +18,5 @@ export default class IARenderData extends BaseRenderData { } } -IARenderData.type = 'IARenderData'; \ No newline at end of file +IARenderData.type = 'IARenderData'; +cc.IARenderData = IARenderData; \ No newline at end of file diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index bf862134ebe..1d07e4ec959 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -440,6 +440,7 @@ let ArmatureDisplay = cc.Class({ let material = this.sharedMaterials[0]; if (!material) { material = Material.getInstantiatedBuiltinMaterial('sprite', this); + material.define('_USE_MODEL', true); material.define('USE_TEXTURE', true); } diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index b440a1dd5f2..863a0966ed2 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -382,11 +382,6 @@ sp.Skeleton = cc.Class({ this._endSlotIndex = -1; }, - onLoad() { - var material = Material.getInstantiatedBuiltinMaterial('spine', this); - this.setMaterial(0, material); - }, - // override _updateMaterial (material) { this.setMaterial(0, material); @@ -394,6 +389,9 @@ sp.Skeleton = cc.Class({ }, _updateUseTint () { + var baseMaterial = this.sharedMaterials[0]; + if (!baseMaterial) return; + baseMaterial.define('USE_TINT', this.useTint); var cache = this._materialCache; for (var mKey in cache) { var material = cache[mKey]; @@ -462,6 +460,10 @@ sp.Skeleton = cc.Class({ this._refreshInspector(); } + var material = Material.getInstantiatedBuiltinMaterial('spine', this); + material.define('_USE_MODEL', true); + this.setMaterial(0, material); + this._updateSkeletonData(); var children = this.node.children; From 27a71e609cfc8a24d97a9614ff1266bd18121aae Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 16 Jan 2019 23:46:35 +0800 Subject: [PATCH 0412/1631] fix particle bug with action (#3760) --- cocos2d/particle/CCParticleSystem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index db8950a9a7c..af9cb8c01d9 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -840,7 +840,7 @@ var ParticleSystem = cc.Class({ this._super(); }, - update (dt) { + lateUpdate (dt) { if (!this._simulator.finished && this._material) { this._simulator.step(dt); } From 5d91d46a10396aa218d17513e6d1977c04f02c50 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Thu, 17 Jan 2019 17:40:25 +0800 Subject: [PATCH 0413/1631] fixed run simulator (#3765) --- cocos2d/core/platform/CCAssetLibrary.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCAssetLibrary.js b/cocos2d/core/platform/CCAssetLibrary.js index b96b02ec949..6338e31d0f0 100644 --- a/cocos2d/core/platform/CCAssetLibrary.js +++ b/cocos2d/core/platform/CCAssetLibrary.js @@ -394,7 +394,12 @@ let _builtins = { function loadBuiltins (name, type, cb) { let dirname = name + 's'; let builtin = _builtins[name] = {}; - cc.loader.loadResDir(dirname, type, 'internal', () => { }, (err, assets) => { + let internalMountPath = 'internal'; + // internal path will be changed when run simulator + if (CC_PREVIEW && CC_JSB) { + internalMountPath = 'temp/internal'; + } + cc.loader.loadResDir(dirname, type, internalMountPath, () => { }, (err, assets) => { if (err) { cc.error(err); } From 652b7b33d53cc477a46f486e3e195f7a36ac1494 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 17 Jan 2019 17:40:59 +0800 Subject: [PATCH 0414/1631] Fixed RichText alignment display bug (#3758) * Fixed RichText alignment display bug * refine code * refine code --- cocos2d/core/components/CCRichText.js | 2 +- cocos2d/core/renderer/utils/label/ttf.js | 11 ++++------- cocos2d/core/utils/text-utils.js | 6 ++++++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index e2fa38f4fb6..a98bb09291a 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -769,7 +769,7 @@ let RichText = cc.Class({ if (this.maxWidth > 0) { this._labelWidth = this.maxWidth; } - this._labelHeight = this._lineCount * this.lineHeight; + this._labelHeight = (this._lineCount + textUtils.BASELINE_RATIO) * this.lineHeight; // trigger "size-changed" event this.node.setContentSize(this._labelWidth, this._labelHeight); diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 41d4a387883..86dea17a4e1 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -35,9 +35,6 @@ const packToDynamicAtlas = require('../utils').packToDynamicAtlas; const WHITE = cc.Color.WHITE; const OUTLINE_SUPPORTED = cc.js.isChildClassOf(LabelOutline, Component); -const BASELINE_RATIO = 0.25; -const MIDDLE_RATIO = (BASELINE_RATIO + 1) / 2 - BASELINE_RATIO; - let _context = null; let _canvas = null; let _texture = null; @@ -241,10 +238,10 @@ module.exports = { firstLinelabelY = lineHeight + _margin; } else if (_vAlign === macro.VerticalTextAlignment.CENTER) { - firstLinelabelY = (_canvasSize.height - drawStartY) * 0.5 + _drawFontSize * MIDDLE_RATIO; + firstLinelabelY = (_canvasSize.height - drawStartY) * 0.5 + _drawFontSize * textUtils.MIDDLE_RATIO; } else { - firstLinelabelY = _canvasSize.height - drawStartY - _drawFontSize * BASELINE_RATIO - _margin; + firstLinelabelY = _canvasSize.height - drawStartY - _drawFontSize * textUtils.BASELINE_RATIO - _margin; } return cc.v2(labelX, firstLinelabelY); @@ -305,7 +302,7 @@ module.exports = { let paragraphedStrings = _string.split('\n'); if (_overflow === Overflow.RESIZE_HEIGHT) { - _canvasSize.height = (_splitedStrings.length + BASELINE_RATIO) * this._getLineHeight() + 2 * _margin; + _canvasSize.height = (_splitedStrings.length + textUtils.BASELINE_RATIO) * this._getLineHeight() + 2 * _margin; } else if (_overflow === Overflow.NONE) { _splitedStrings = paragraphedStrings; @@ -315,7 +312,7 @@ module.exports = { let paraLength = textUtils.safeMeasureText(_context, paragraphedStrings[i]); canvasSizeX = canvasSizeX > paraLength ? canvasSizeX : paraLength; } - canvasSizeY = (_splitedStrings.length + BASELINE_RATIO) * this._getLineHeight(); + canvasSizeY = (_splitedStrings.length + textUtils.BASELINE_RATIO) * this._getLineHeight(); _canvasSize.width = parseFloat(canvasSizeX.toFixed(2)) + 2 * _margin; _canvasSize.height = parseFloat(canvasSizeY.toFixed(2)) + 2 * _margin; diff --git a/cocos2d/core/utils/text-utils.js b/cocos2d/core/utils/text-utils.js index eca99c198b7..2be0e4f8377 100644 --- a/cocos2d/core/utils/text-utils.js +++ b/cocos2d/core/utils/text-utils.js @@ -24,7 +24,13 @@ THE SOFTWARE. ****************************************************************************/ +const _BASELINE_RATIO = 0.25; + var textUtils = { + + BASELINE_RATIO: _BASELINE_RATIO, + MIDDLE_RATIO: (_BASELINE_RATIO + 1) / 2 - _BASELINE_RATIO, + label_wordRex : /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôûа-яА-ЯЁё]+|\S)/, label_symbolRex : /^[!,.:;'}\]%\?>、‘“》?。,!]/, label_lastWordRex : /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôûаíìÍÌïÁÀáàÉÈÒÓòóŐőÙÚŰúűñÑæÆœŒÃÂãÔõěščřžýáíéóúůťďňĚŠČŘŽÁÍÉÓÚŤżźśóńłę湯ŹŚÓŃŁĘĆĄ-яА-ЯЁё]+|\S)$/, From b88501798b6b2a8a647461da07cccd418413649f Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 18 Jan 2019 13:59:09 +0800 Subject: [PATCH 0415/1631] fixed shadow cast (#3766) --- cocos2d/renderer/build/chunks/packing.inc | 2 +- cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc | 4 ++-- cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cocos2d/renderer/build/chunks/packing.inc b/cocos2d/renderer/build/chunks/packing.inc index 5b1518d33b1..ba09469b54b 100644 --- a/cocos2d/renderer/build/chunks/packing.inc +++ b/cocos2d/renderer/build/chunks/packing.inc @@ -9,4 +9,4 @@ vec4 packDepthToRGBA(float depth) { float unpackRGBAToDepth(vec4 color) { return dot(color, vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 160581375.0)); -} \ No newline at end of file +} diff --git a/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc b/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc index 6c545bc702f..1ae0f04f8ed 100644 --- a/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc +++ b/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc @@ -5,10 +5,10 @@ varying float vDepth; #include -vec4 frag() { +void main () { // doing exp() here will cause float precision issue. //float depth = clamp(exp(-min(87.0, cc_depthScale * vDepth)), 0.0, 1.0); - return packDepthToRGBA(vDepth); + gl_FragColor = packDepthToRGBA(vDepth); // TODO: if support float32 * 4 color buffer? //gl_FragColor = vec4(depth, 1.0, 1.0, 1.0); } diff --git a/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc b/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc index 2f07a845ffa..2776674fbeb 100644 --- a/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc +++ b/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc @@ -11,12 +11,13 @@ varying float vDepth; #include -vec4 vert() { +void main () { vec4 position = vec4(a_position, 1); SKIN_VERTEX(position); + gl_Position = cc_lightViewProjMatrix * cc_matWorld * position; + // compute vDepth according to active camera's minDepth and maxDepth. vDepth = ((gl_Position.z + cc_minDepth) / (cc_minDepth + cc_maxDepth)) + cc_bias; - return cc_lightViewProjMatrix * cc_matWorld * position; } From 90078f2dd97a6bb8af00bf6af6261cc68b0fbf87 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Fri, 18 Jan 2019 13:59:59 +0800 Subject: [PATCH 0416/1631] Fix the label to execute onDestroy error without executing onEnable. (#3769) --- cocos2d/core/components/CCLabel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 23fbab46080..d73e5bca253 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -504,7 +504,7 @@ let Label = cc.Class({ }, onDestroy () { - this._assembler._resetAssemblerData && this._assembler._resetAssemblerData(this._assemblerData); + this._assembler && this._assembler._resetAssemblerData && this._assembler._resetAssemblerData(this._assemblerData); this._assemblerData = null; if (this._ttfTexture) { this._ttfTexture.destroy(); From b95e8deb2e8658b9d05ff25c09f18d301464dcc6 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 18 Jan 2019 14:13:55 +0800 Subject: [PATCH 0417/1631] Add JSB Skip modules --- gulp/tasks/engine.js | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index dc7b0e8c1c6..00cc69a28e0 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -46,7 +46,37 @@ var jsbSkipModules = [ '../../extensions/dragonbones/CCArmatureDisplay.js', '../../extensions/dragonbones/CCFactory.js', '../../extensions/dragonbones/CCSlot.js', - '../../extensions/dragonbones/CCTextureData.js' + '../../extensions/dragonbones/CCTextureData.js', + + // gfx + '../../cocos2d/renderer/gfx/device.js', + '../../cocos2d/renderer/gfx/enums.js', + '../../cocos2d/renderer/gfx/frame-buffer.js', + '../../cocos2d/renderer/gfx/index-buffer.js', + '../../cocos2d/renderer/gfx/index.js', + '../../cocos2d/renderer/gfx/misc.js', + '../../cocos2d/renderer/gfx/program.js', + '../../cocos2d/renderer/gfx/render-buffer.js', + '../../cocos2d/renderer/gfx/state.js', + '../../cocos2d/renderer/gfx/texture-2d.js', + '../../cocos2d/renderer/gfx/texture-cube.js', + '../../cocos2d/renderer/gfx/texture.js', + '../../cocos2d/renderer/gfx/vertex-buffer.js', + '../../cocos2d/renderer/gfx/vertex-format.js', + + // renderer + '../../cocos2d/renderer/core/base-renderer.js', + '../../cocos2d/renderer/core/effect.js', + '../../cocos2d/renderer/core/input-assembler.js', + '../../cocos2d/renderer/core/pass.js', + '../../cocos2d/renderer/core/program-lib.js', + '../../cocos2d/renderer/core/technique.js', + '../../cocos2d/renderer/core/view.js', + '../../cocos2d/renderer/renderers/forward-renderer.js', + '../../cocos2d/renderer/scene/camera.js', + '../../cocos2d/renderer/scene/light.js', + '../../cocos2d/renderer/scene/model.js', + '../../cocos2d/renderer/scene/scene.js', ]; var jsbAliasify = { replacements: { From d9c3e29cd92e7700bc3bc6fdcf4ae7a606e081db Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 18 Jan 2019 18:27:07 +0800 Subject: [PATCH 0418/1631] fixed ttf label opacity (#3770) --- cocos2d/core/renderer/utils/label/ttf.js | 4 ++-- cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js | 6 ++++-- cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js | 4 +++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 86dea17a4e1..6019341f1dc 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -255,7 +255,7 @@ module.exports = { let lineHeight = this._getLineHeight(); //use round for line join to avoid sharp intersect point _context.lineJoin = 'round'; - _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_color.a / 255})`; + _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, 1)`; //do real rendering for (let i = 0; i < _splitedStrings.length; ++i) { @@ -268,7 +268,7 @@ module.exports = { _context.save(); _context.beginPath(); _context.lineWidth = _underlineThickness; - _context.strokeStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_color.a / 255})`; + _context.strokeStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, 1)`; _context.moveTo(_drawUnderlinePos.x, _drawUnderlinePos.y); _context.lineTo(_drawUnderlinePos.x + _canvas.width, _drawUnderlinePos.y); _context.stroke(); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js index 764a64f29de..a9c22dc1ce0 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js @@ -27,7 +27,7 @@ const js = require('../../../../../platform/js'); const ttfUtls = require('../../../../utils/label/ttf'); const fillMeshVertices = require('../../utils').fillMeshVertices; -const WHITE_VAL = cc.Color.WHITE._val; +const WHITE = cc.Color.WHITE; module.exports = js.addon({ createData (comp) { @@ -41,7 +41,9 @@ module.exports = js.addon({ }, fillBuffers (comp, renderer) { - fillMeshVertices(comp.node, renderer._meshBuffer, comp._renderData, WHITE_VAL); + let node = comp.node; + WHITE._fastSetA(node.color.a); + fillMeshVertices(node, renderer._meshBuffer, comp._renderData, WHITE._val); }, _updateVerts (comp) { diff --git a/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js index 99aa385535c..6bda982b64e 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js @@ -27,10 +27,12 @@ const js = require('../../../../../platform/js'); const assembler = require('../2d/ttf'); const fillMeshVertices3D = require('../../utils').fillMeshVertices3D; -const WHITE = cc.color(255, 255, 255, 255); +const WHITE = cc.Color.WHITE; module.exports = js.addon({ fillBuffers (comp, renderer) { + let node = comp.node; + WHITE._fastSetA(node.color.a); fillMeshVertices3D(comp.node, renderer._meshBuffer3D, comp._renderData, WHITE._val); } }, assembler); From 352a94d586bc9452895a799bc95d8fbcaf8b3290 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 21 Jan 2019 15:27:29 +0800 Subject: [PATCH 0419/1631] compatible vec3 prop methods (#3746) * compatible vec3 prop methods (#3737) * complete vec3 test --- EngineErrorMap.md | 6 ++- cocos2d/core/renderer/utils/utils.js | 2 +- cocos2d/core/value-types/vec3.js | 49 +++++++++++++++++-- test/qunit/unit-es5/test-vec3.js | 70 ++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 test/qunit/unit-es5/test-vec3.js diff --git a/EngineErrorMap.md b/EngineErrorMap.md index 369240cbd7a..c4e0f55d04d 100644 --- a/EngineErrorMap.md +++ b/EngineErrorMap.md @@ -242,7 +242,11 @@ The '%s' will be removed in v2.0, please use '%s' instead. ### 1407 -cc.pool is being removed from v2.0, you are getting cc.js.Pool instead +cc.pool is being removed from v2.0, you are getting cc.js.Pool instead. + +### 1408 + +'%s' is not support in the '%s', please use '%s' instead. ### 1500 diff --git a/cocos2d/core/renderer/utils/utils.js b/cocos2d/core/renderer/utils/utils.js index 1a1b3002fb9..2287b565795 100644 --- a/cocos2d/core/renderer/utils/utils.js +++ b/cocos2d/core/renderer/utils/utils.js @@ -4,7 +4,7 @@ module.exports = { packToDynamicAtlas (comp, frame) { // TODO: Material API design and export from editor could affect the material activation process // need to update the logic here - if (frame) { + if (frame && !CC_TEST) { if (!frame._original && dynamicAtlasManager) { let packedFrame = dynamicAtlasManager.insertSpriteFrame(frame); if (packedFrame) { diff --git a/cocos2d/core/value-types/vec3.js b/cocos2d/core/value-types/vec3.js index a1cd12aed3e..14e91506a1e 100644 --- a/cocos2d/core/value-types/vec3.js +++ b/cocos2d/core/value-types/vec3.js @@ -30,7 +30,7 @@ const ValueType = require('./value-type'); const js = require('../platform/js'); const CCClass = require('../platform/CCClass'); const misc = require('../utils/misc'); -const Vec2 = require('./vec2'); +const v2Proto = require('./vec2').prototype; /** * !#en Representation of 3D vectors and points. @@ -464,7 +464,7 @@ proto.transformMat4 = function (m, out) { * @param {Vec3} vector * @return {number} from 0 to Math.PI */ -proto.angle = Vec2.angle; +proto.angle = v2Proto.angle; /** * !#en Calculates the projection of the current vector over the given vector. @@ -477,7 +477,50 @@ proto.angle = Vec2.angle; * var v2 = cc.v3(5, 5, 5); * v1.project(v2); // Vec3 {x: 20, y: 20, z: 20}; */ -proto.project = Vec2.project; +proto.project = v2Proto.project; + +// Compatible with the vec2 API + +/** + * !#en Get angle in radian between this and vector with direction.
+ * In order to compatible with the vec2 API. + * !#zh 带方向的夹角的弧度。该方法仅用做兼容 2D 计算。 + * @method signAngle + * @param {Vec3 | Vec2} vector + * @return {number} from -MathPI to Math.PI + */ +proto.signAngle = function (vector) { + cc.warnID(1408, 'vec3.signAngle', 'v2.1', 'cc.v2(selfVector).signAngle(vector)'); + let vec1 = new cc.Vec2(this.x, this.y); + let vec2 = new cc.Vec2(vector.x, vector.y); + return vec1.signAngle(vec2); +}; + +/** + * !#en rotate. In order to compatible with the vec2 API. + * !#zh 返回旋转给定弧度后的新向量。该方法仅用做兼容 2D 计算。 + * @method rotate + * @param {number} radians + * @param {Vec3} [out] - optional, the receiving vector, you can pass the same vec2 to save result to itself, if not provided, a new vec2 will be created + * @return {Vec2 | Vec3} if the 'out' value is a vec3 you will get a Vec3 return. + */ +proto.rotate = function (radians, out) { + cc.warnID(1408, 'vec3.rotate', 'v2.1', 'cc.v2(selfVector).rotate(radians, out)'); + return v2Proto.rotate.call(this, radians, out); +}; + +/** + * !#en rotate self. In order to compatible with the vec2 API. + * !#zh 按指定弧度旋转向量。该方法仅用做兼容 2D 计算。 + * @method rotateSelf + * @param {number} radians + * @return {Vec3} returns this + * @chainable + */ +proto.rotateSelf = function (radians) { + cc.warnID(1408, 'vec3.rotateSelf', 'v2.1', 'cc.v2(selfVector).rotateSelf(radians)'); + return v2Proto.rotateSelf.call(this, radians); +}; /** * !#en return a Vec3 object with x = 1, y = 1, z = 1. diff --git a/test/qunit/unit-es5/test-vec3.js b/test/qunit/unit-es5/test-vec3.js new file mode 100644 index 00000000000..12acf1238de --- /dev/null +++ b/test/qunit/unit-es5/test-vec3.js @@ -0,0 +1,70 @@ +module('Vec3'); + +var v3 = cc.v3; + +test('basic test', function () { + var vec1 = new cc.Vec3(1, 2, 3); + ok(vec1 instanceof cc.Vec3, 'is instanceof Vec3'); + strictEqual(vec1.x, 1, 'can get x'); + strictEqual(vec1.y, 2, 'can get y'); + strictEqual(vec1.z, 3, 'can get z'); + vec1.x = -1; + vec1.y = -2; + vec1.z = -3; + strictEqual(vec1.x, -1, 'can set x'); + strictEqual(vec1.y, -2, 'can set y'); + strictEqual(vec1.z, -3, 'can set z'); + var vec3 = vec1.clone(); + deepEqual(vec1, vec3, 'can clone'); +}); + +test('scale test', function () { + var vec1 = new cc.Vec3(4, 5, 6); + deepEqual(vec1.scale(v3(1, 2, 3)), v3(4, 10, 18), 'can scale'); + deepEqual(vec1, v3(4, 5, 6), 'ensure vec1 not being changed after scale'); + deepEqual(vec1.scaleSelf(v3(1, 2, 3)), v3(4, 10, 18), 'can scaleSelf'); + deepEqual(vec1, v3(4, 10, 18), 'ensure vec1 being changed after scale'); +}); + +test('misc', function(){ + var vector = v3(3, 7, 11); + var vec1 = new cc.Vec3(2, 11, -42); + strictEqual(vec1.dot(vector), -379, 'vec1 test'); + deepEqual(vec1.cross(vector), v3(415, -148, -19), 'corss test'); + strictEqual(vec1.magSqr(vector), 1889, 'magSqr test'); + + var normalizeSelf = vec1.normalizeSelf(); + var mag = Math.sqrt(vec1.x * vec1.x + vec1.y * vec1.y + vec1.z * vec1.z); + var expect = v3(vec1.x / mag, vec1.y / mag, vec1.z / mag); + deepEqual(normalizeSelf, expect, 'normalizeSelf test'); +}); + +test('compatible', function () { + var vector = v3(5, 5, 5); + var vec1 = new cc.Vec3(5, 0, 5); + var vec2 = new cc.Vec3(10, 10, 10); + + let magSqr1 = vec1.magSqr(); + let magSqr2 = vector.magSqr(); + var dot = vec1.dot(vector); + var theta = dot / (Math.sqrt(magSqr1 * magSqr2)); + theta = cc.misc.clampf(theta, -1.0, 1.0); + + deepClose(vec1.angle(vector), Math.acos(theta), 0.01, 'angle test'); + deepEqual(vec2.project(vector), v3(10, 10, 10), 'project test'); + + // Relating the vec2 angle features + vector.set(v3(12, 3, -10)); + vec1.set(v3(-2, -4, -11)); + + let radian = Math.PI / 3; + let vec3 = new cc.Vec2(12, 3); + let vec4 = new cc.Vec2(-2, -4); + + deepClose(vec1.signAngle(vector), vec4.signAngle(vec3), 0.01, 'signAngle test'); + + let result = vec4.rotate(radian); + deepEqual(vec1.rotate(radian, v3()), v3(result.x, result.y, 0), 'rotate test with a Vec3 out'); + deepEqual(vec1.rotate(radian), result, 'rotate test without out'); + deepEqual(vec1.rotateSelf(radian), v3(result.x, result.y, vec1.z), 'rotateSelf test'); +}); \ No newline at end of file From 789afe6a20e1fb9ac9681956cbe0858ceb0beba3 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 21 Jan 2019 15:39:58 +0800 Subject: [PATCH 0420/1631] fix exclude module invalid (#3775) --- gulp/tasks/engine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index 85ea099f44f..0fa9270dfa2 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -418,7 +418,7 @@ exports.excludeAllDepends = function (excludedModules) { let module = excMudules[key]; if (module.entries) { module.entries.forEach(function (file) { - let path = Path.join(__dirname, '../engine', file); + let path = Path.join(__dirname, '..', '..', file); if (excludes.indexOf(path) === -1) { excludes.push(path); } From f5b729e228e0628a49795616b073172640bc4814 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 21 Jan 2019 21:16:32 +0800 Subject: [PATCH 0421/1631] fixed the scrollView content calculate boundary position wrongly problem (#3752) --- cocos2d/core/components/CCScrollView.js | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/cocos2d/core/components/CCScrollView.js b/cocos2d/core/components/CCScrollView.js index ab963ac5274..e2a32ba4ef7 100644 --- a/cocos2d/core/components/CCScrollView.js +++ b/cocos2d/core/components/CCScrollView.js @@ -902,24 +902,19 @@ let ScrollView = cc.Class({ } let viewSize = this._view.getContentSize(); - let leftBottomPosition = this._convertToContentParentSpace(cc.v2(0, 0)); - this._leftBoundary = leftBottomPosition.x; - this._bottomBoundary = leftBottomPosition.y; + let anchorX = viewSize.width * this._view.anchorX; + let anchorY = viewSize.height * this._view.anchorY; - let topRightPosition = this._convertToContentParentSpace(cc.v2(viewSize.width, viewSize.height)); - this._rightBoundary = topRightPosition.x; - this._topBoundary = topRightPosition.y; + this._leftBoundary = -anchorX; + this._bottomBoundary = -anchorY; + + this._rightBoundary = this._leftBoundary + viewSize.width; + this._topBoundary = this._bottomBoundary + viewSize.height; this._moveContentToTopLeft(viewSize); } }, - _convertToContentParentSpace (position) { - let contentParent = this._view; - let viewPositionInWorldSpace = contentParent.convertToWorldSpace(position); - return contentParent.convertToNodeSpaceAR(viewPositionInWorldSpace); - }, - //this is for nested scrollview _hasNestedViewGroup (event, captureListeners) { if (event.eventPhase !== cc.Event.CAPTURING_PHASE) return; @@ -1524,8 +1519,6 @@ let ScrollView = cc.Class({ onDisable () { if (!CC_EDITOR) { this._unregisterEvent(); - this.node.off(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); - this.node.off(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); if (this.content) { this.content.off(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); this.content.off(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); @@ -1543,8 +1536,6 @@ let ScrollView = cc.Class({ onEnable () { if (!CC_EDITOR) { this._registerEvent(); - this.node.on(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); - this.node.on(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); if (this.content) { this.content.on(NodeEvent.SIZE_CHANGED, this._calculateBoundary, this); this.content.on(NodeEvent.SCALE_CHANGED, this._calculateBoundary, this); From c167bf4564a8512f1f9c54e406ae9ecf04c94436 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 22 Jan 2019 10:30:09 +0800 Subject: [PATCH 0422/1631] fixed load pvr (#3776) --- cocos2d/core/load-pipeline/loader.js | 5 +++-- cocos2d/core/renderer/utils/dynamic-atlas/manager.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/load-pipeline/loader.js b/cocos2d/core/load-pipeline/loader.js index 842d0e4fed5..557e0be0595 100644 --- a/cocos2d/core/load-pipeline/loader.js +++ b/cocos2d/core/load-pipeline/loader.js @@ -125,8 +125,9 @@ const PVR_HEADER_MIPMAPCOUNT = 11; const PVR_HEADER_METADATA = 12; function loadCompressedTex (item) { + let buffer = item.content instanceof ArrayBuffer ? item.content : item.content.buffer; // Get a view of the arrayBuffer that represents the DDS header. - let header = new Int32Array(item.content.buffer, 0, PVR_HEADER_LENGTH); + 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) { @@ -138,7 +139,7 @@ function loadCompressedTex (item) { let height = header[PVR_HEADER_HEIGHT]; let levels = header[PVR_HEADER_MIPMAPCOUNT]; let dataOffset = header[PVR_HEADER_METADATA] + 52; - let pvrtcData = new Uint8Array(item.content.buffer, dataOffset); + let pvrtcData = new Uint8Array(buffer, dataOffset); let pvrAsset = { _data: pvrtcData, diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js index e321b22005f..d187786cfa9 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js @@ -108,7 +108,7 @@ let dynamicAtlasManager = { !spriteFrame || spriteFrame._original) return null; let texture = spriteFrame._texture; - if (texture instanceof cc.RenderTexture) return null; + if (texture instanceof cc.RenderTexture || cc.Texture2D._isCompressed(texture)) return null; let w = texture.width, h = texture.height; if (w > _maxFrameSize || h > _maxFrameSize || w <= _minFrameSize || h <= _minFrameSize From fe5e0e8683bf07fc839c71ea1f398c164c570800 Mon Sep 17 00:00:00 2001 From: Knox Date: Wed, 23 Jan 2019 16:26:31 +0800 Subject: [PATCH 0423/1631] wx open data context no need to load builtins (#3782) --- cocos2d/core/platform/CCAssetLibrary.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/core/platform/CCAssetLibrary.js b/cocos2d/core/platform/CCAssetLibrary.js index 6338e31d0f0..7381ba4f321 100644 --- a/cocos2d/core/platform/CCAssetLibrary.js +++ b/cocos2d/core/platform/CCAssetLibrary.js @@ -414,6 +414,10 @@ function loadBuiltins (name, type, cb) { } AssetLibrary._loadBuiltins = function (cb) { + if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { + return cb && cb(); + } + loadBuiltins('effect', cc.EffectAsset, () => { loadBuiltins('material', cc.Material, cb); }); From 4144bd62b3ee06a586d0f2872d0c13bc64927f53 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Thu, 24 Jan 2019 13:54:07 +0800 Subject: [PATCH 0424/1631] fixed code conflict (#3783) --- cocos2d/renderer/gfx/device.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cocos2d/renderer/gfx/device.js b/cocos2d/renderer/gfx/device.js index 62c9df8c338..121b53a7a69 100644 --- a/cocos2d/renderer/gfx/device.js +++ b/cocos2d/renderer/gfx/device.js @@ -656,14 +656,18 @@ export default class Device { for (let i = 0; i < extensions.length; ++i) { let name = extensions[i]; - - try { - let ext = gl.getExtension(name); - if (ext) { - this._extensions[name] = ext; + let vendorPrefixes = ["", "WEBKIT_", "MOZ_"]; + + for (var j = 0; j < vendorPrefixes.length; j++) { + try { + let ext = gl.getExtension(vendorPrefixes[j] + name); + if (ext) { + this._extensions[name] = ext; + break; + } + } catch (e) { + console.error(e); } - } catch (e) { - console.error(e); } } } From b1ceb09302e5afacc671b9d98afb7052af8a6293 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 24 Jan 2019 14:19:33 +0800 Subject: [PATCH 0425/1631] compatible with open data context support webgl and canvas for 2d-tasks/issues/1044 (#3778) --- cocos2d/core/platform/CCSys.js | 12 +- cocos2d/core/renderer/index.js | 8 +- cocos2d/core/renderer/render-engine.canvas.js | 8835 ----------------- gulp/tasks/engine.js | 12 - 4 files changed, 13 insertions(+), 8854 deletions(-) delete mode 100644 cocos2d/core/renderer/render-engine.canvas.js diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index fdcf7b6735c..b53eaefea36 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -709,10 +709,18 @@ function initSys () { sys.localStorage = window.localStorage; + var _supportWebGL = _supportWebp = false; + try { + var _canvas = document.createElement("canvas"); + _supportWebGL = _canvas.getContext("webgl"); + _supportWebp = _canvas.toDataURL('image/webp').startsWith('data:image/webp'); + } + catch (err) { } + sys.capabilities = { "canvas": true, - "opengl": (sys.browserType !== sys.BROWSER_TYPE_WECHAT_GAME_SUB), - "webp": false + "opengl": !!_supportWebGL, + "webp": _supportWebp }; sys.__audioSupport = { ONLY_ONE: false, diff --git a/cocos2d/core/renderer/index.js b/cocos2d/core/renderer/index.js index 20e993a1980..881caaf31db 100644 --- a/cocos2d/core/renderer/index.js +++ b/cocos2d/core/renderer/index.js @@ -149,11 +149,9 @@ cc.renderer = module.exports = { initCanvas (canvas) { let canvasRenderer = require('./canvas'); - if (CC_TEST) { - // It's actually running with original render engine - renderEngine.Texture2D = renderEngine.canvas.Texture2D; - renderEngine.Device = renderEngine.canvas.Device; - } + // It's actually running with original render engine + renderEngine.Texture2D = renderEngine.canvas.Texture2D; + renderEngine.Device = renderEngine.canvas.Device; this.Texture2D = renderEngine.Texture2D; diff --git a/cocos2d/core/renderer/render-engine.canvas.js b/cocos2d/core/renderer/render-engine.canvas.js deleted file mode 100644 index 7cac7c404e2..00000000000 --- a/cocos2d/core/renderer/render-engine.canvas.js +++ /dev/null @@ -1,8835 +0,0 @@ - -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - render-engine v1.2.0 - 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. - ****************************************************************************/ - - -'use strict'; - -// reference: https://github.com/mziccard/node-timsort - -/** - * Default minimum size of a run. - */ -var DEFAULT_MIN_MERGE = 32; - -/** - * Minimum ordered subsequece required to do galloping. - */ -var DEFAULT_MIN_GALLOPING = 7; - -/** - * Default tmp storage length. Can increase depending on the size of the - * smallest run to merge. - */ -var DEFAULT_TMP_STORAGE_LENGTH = 256; - -/** - * Pre-computed powers of 10 for efficient lexicographic comparison of - * small integers. - */ -var POWERS_OF_TEN = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9]; - -/** - * Estimate the logarithm base 10 of a small integer. - * - * @param {number} x - The integer to estimate the logarithm of. - * @return {number} - The estimated logarithm of the integer. - */ -function log10(x) { - if (x < 1e5) { - if (x < 1e2) { - return x < 1e1 ? 0 : 1; - } - - if (x < 1e4) { - return x < 1e3 ? 2 : 3; - } - - return 4; - } - - if (x < 1e7) { - return x < 1e6 ? 5 : 6; - } - - if (x < 1e9) { - return x < 1e8 ? 7 : 8; - } - - return 9; -} - -/** - * Default alphabetical comparison of items. - * - * @param {string|object|number} a - First element to compare. - * @param {string|object|number} b - Second element to compare. - * @return {number} - A positive number if a.toString() > b.toString(), a - * negative number if .toString() < b.toString(), 0 otherwise. - */ -function alphabeticalCompare(a, b) { - if (a === b) { - return 0; - } - - if (~~a === a && ~~b === b) { - if (a === 0 || b === 0) { - return a < b ? -1 : 1; - } - - if (a < 0 || b < 0) { - if (b >= 0) { - return -1; - } - - if (a >= 0) { - return 1; - } - - a = -a; - b = -b; - } - - var al = log10(a); - var bl = log10(b); - - var t = 0; - - if (al < bl) { - a *= POWERS_OF_TEN[bl - al - 1]; - b /= 10; - t = -1; - } else if (al > bl) { - b *= POWERS_OF_TEN[al - bl - 1]; - a /= 10; - t = 1; - } - - if (a === b) { - return t; - } - - return a < b ? -1 : 1; - } - - var aStr = String(a); - var bStr = String(b); - - if (aStr === bStr) { - return 0; - } - - return aStr < bStr ? -1 : 1; -} - -/** - * Compute minimum run length for TimSort - * - * @param {number} n - The size of the array to sort. - */ -function minRunLength(n) { - var r = 0; - - while (n >= DEFAULT_MIN_MERGE) { - r |= (n & 1); - n >>= 1; - } - - return n + r; -} - -/** - * Counts the length of a monotonically ascending or strictly monotonically - * descending sequence (run) starting at array[lo] in the range [lo, hi). If - * the run is descending it is made ascending. - * - * @param {array} array - The array to reverse. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {function} compare - Item comparison function. - * @return {number} - The length of the run. - */ -function makeAscendingRun(array, lo, hi, compare) { - var runHi = lo + 1; - - if (runHi === hi) { - return 1; - } - - // Descending - if (compare(array[runHi++], array[lo]) < 0) { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { - runHi++; - } - - reverseRun(array, lo, runHi); - // Ascending - } else { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { - runHi++; - } - } - - return runHi - lo; -} - -/** - * Reverse an array in the range [lo, hi). - * - * @param {array} array - The array to reverse. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - */ -function reverseRun(array, lo, hi) { - hi--; - - while (lo < hi) { - var t = array[lo]; - array[lo++] = array[hi]; - array[hi--] = t; - } -} - -/** - * Perform the binary sort of the array in the range [lo, hi) where start is - * the first element possibly out of order. - * - * @param {array} array - The array to sort. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {number} start - First element possibly out of order. - * @param {function} compare - Item comparison function. - */ -function binaryInsertionSort(array, lo, hi, start, compare) { - if (start === lo) { - start++; - } - - for (; start < hi; start++) { - var pivot = array[start]; - - // Ranges of the array where pivot belongs - var left = lo; - var right = start; - - /* - * pivot >= array[i] for i in [lo, left) - * pivot < array[i] for i in in [right, start) - */ - while (left < right) { - var mid = (left + right) >>> 1; - - if (compare(pivot, array[mid]) < 0) { - right = mid; - } else { - left = mid + 1; - } - } - - /* - * Move elements right to make room for the pivot. If there are elements - * equal to pivot, left points to the first slot after them: this is also - * a reason for which TimSort is stable - */ - var n = start - left; - // Switch is just an optimization for small arrays - switch (n) { - case 3: - array[left + 3] = array[left + 2]; - /* falls through */ - case 2: - array[left + 2] = array[left + 1]; - /* falls through */ - case 1: - array[left + 1] = array[left]; - break; - default: - while (n > 0) { - array[left + n] = array[left + n - 1]; - n--; - } - } - - array[left] = pivot; - } -} - -/** - * Find the position at which to insert a value in a sorted range. If the range - * contains elements equal to the value the leftmost element index is returned - * (for stability). - * - * @param {number} value - Value to insert. - * @param {array} array - The array in which to insert value. - * @param {number} start - First element in the range. - * @param {number} length - Length of the range. - * @param {number} hint - The index at which to begin the search. - * @param {function} compare - Item comparison function. - * @return {number} - The index where to insert value. - */ -function gallopLeft(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) > 0) { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - lastOffset += hint; - offset += hint; - - // value <= array[start + hint] - } else { - maxOffset = hint + 1; - while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - } - - /* - * Now array[start+lastOffset] < value <= array[start+offset], so value - * belongs somewhere in the range (start + lastOffset, start + offset]. Do a - * binary search, with invariant array[start + lastOffset - 1] < value <= - * array[start + offset]. - */ - lastOffset++; - while (lastOffset < offset) { - var m = lastOffset + ((offset - lastOffset) >>> 1); - - if (compare(value, array[start + m]) > 0) { - lastOffset = m + 1; - - } else { - offset = m; - } - } - return offset; -} - -/** - * Find the position at which to insert a value in a sorted range. If the range - * contains elements equal to the value the rightmost element index is returned - * (for stability). - * - * @param {number} value - Value to insert. - * @param {array} array - The array in which to insert value. - * @param {number} start - First element in the range. - * @param {number} length - Length of the range. - * @param {number} hint - The index at which to begin the search. - * @param {function} compare - Item comparison function. - * @return {number} - The index where to insert value. - */ -function gallopRight(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) < 0) { - maxOffset = hint + 1; - - while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - - // value >= array[start + hint] - } else { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - // Make offsets relative to start - lastOffset += hint; - offset += hint; - } - - /* - * Now array[start+lastOffset] < value <= array[start+offset], so value - * belongs somewhere in the range (start + lastOffset, start + offset]. Do a - * binary search, with invariant array[start + lastOffset - 1] < value <= - * array[start + offset]. - */ - lastOffset++; - - while (lastOffset < offset) { - var m = lastOffset + ((offset - lastOffset) >>> 1); - - if (compare(value, array[start + m]) < 0) { - offset = m; - - } else { - lastOffset = m + 1; - } - } - - return offset; -} - -var TimSort = function TimSort(array, compare) { - this.array = array; - this.compare = compare; - this.minGallop = DEFAULT_MIN_GALLOPING; - this.length = array.length; - - this.tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH; - if (this.length < 2 * DEFAULT_TMP_STORAGE_LENGTH) { - this.tmpStorageLength = this.length >>> 1; - } - - this.tmp = new Array(this.tmpStorageLength); - - this.stackLength = - (this.length < 120 ? 5 : - this.length < 1542 ? 10 : - this.length < 119151 ? 19 : 40); - - this.runStart = new Array(this.stackLength); - this.runLength = new Array(this.stackLength); - this.stackSize = 0; -}; - -/** - * Push a new run on TimSort's stack. - * - * @param {number} runStart - Start index of the run in the original array. - * @param {number} runLength - Length of the run; - */ -TimSort.prototype.pushRun = function pushRun (runStart, runLength) { - this.runStart[this.stackSize] = runStart; - this.runLength[this.stackSize] = runLength; - this.stackSize += 1; -}; - -/** - * Merge runs on TimSort's stack so that the following holds for all i: - * 1) runLength[i - 3] > runLength[i - 2] + runLength[i - 1] - * 2) runLength[i - 2] > runLength[i - 1] - */ -TimSort.prototype.mergeRuns = function mergeRuns () { - var this$1 = this; - - while (this.stackSize > 1) { - var n = this$1.stackSize - 2; - - if ((n >= 1 && - this$1.runLength[n - 1] <= this$1.runLength[n] + this$1.runLength[n + 1]) || - (n >= 2 && - this$1.runLength[n - 2] <= this$1.runLength[n] + this$1.runLength[n - 1])) { - - if (this$1.runLength[n - 1] < this$1.runLength[n + 1]) { - n--; - } - - } else if (this$1.runLength[n] > this$1.runLength[n + 1]) { - break; - } - this$1.mergeAt(n); - } -}; - -/** - * Merge all runs on TimSort's stack until only one remains. - */ -TimSort.prototype.forceMergeRuns = function forceMergeRuns () { - var this$1 = this; - - while (this.stackSize > 1) { - var n = this$1.stackSize - 2; - - if (n > 0 && this$1.runLength[n - 1] < this$1.runLength[n + 1]) { - n--; - } - - this$1.mergeAt(n); - } -}; - -/** - * Merge the runs on the stack at positions i and i+1. Must be always be called - * with i=stackSize-2 or i=stackSize-3 (that is, we merge on top of the stack). - * - * @param {number} i - Index of the run to merge in TimSort's stack. - */ -TimSort.prototype.mergeAt = function mergeAt (i) { - var compare = this.compare; - var array = this.array; - - var start1 = this.runStart[i]; - var length1 = this.runLength[i]; - var start2 = this.runStart[i + 1]; - var length2 = this.runLength[i + 1]; - - this.runLength[i] = length1 + length2; - - if (i === this.stackSize - 3) { - this.runStart[i + 1] = this.runStart[i + 2]; - this.runLength[i + 1] = this.runLength[i + 2]; - } - - this.stackSize--; - - /* - * Find where the first element in the second run goes in run1. Previous - * elements in run1 are already in place - */ - var k = gallopRight(array[start2], array, start1, length1, 0, compare); - start1 += k; - length1 -= k; - - if (length1 === 0) { - return; - } - - /* - * Find where the last element in the first run goes in run2. Next elements - * in run2 are already in place - */ - length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); - - if (length2 === 0) { - return; - } - - /* - * Merge remaining runs. A tmp array with length = min(length1, length2) is - * used - */ - if (length1 <= length2) { - this.mergeLow(start1, length1, start2, length2); - - } else { - this.mergeHigh(start1, length1, start2, length2); - } -}; - -/** - * Merge two adjacent runs in a stable way. The runs must be such that the - * first element of run1 is bigger than the first element in run2 and the - * last element of run1 is greater than all the elements in run2. - * The method should be called when run1.length <= run2.length as it uses - * TimSort temporary array to store run1. Use mergeHigh if run1.length > - * run2.length. - * - * @param {number} start1 - First element in run1. - * @param {number} length1 - Length of run1. - * @param {number} start2 - First element in run2. - * @param {number} length2 - Length of run2. - */ -TimSort.prototype.mergeLow = function mergeLow (start1, length1, start2, length2) { - - var compare = this.compare; - var array = this.array; - var tmp = this.tmp; - var i = 0; - - for (i = 0; i < length1; i++) { - tmp[i] = array[start1 + i]; - } - - var cursor1 = 0; - var cursor2 = start2; - var dest = start1; - - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - return; - } - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - array[dest + length2] = tmp[cursor1]; - return; - } - - var minGallop = this.minGallop; - - while (true) { - var count1 = 0; - var count2 = 0; - var exit = false; - - do { - if (compare(array[cursor2], tmp[cursor1]) < 0) { - array[dest++] = array[cursor2++]; - count2++; - count1 = 0; - - if (--length2 === 0) { - exit = true; - break; - } - - } else { - array[dest++] = tmp[cursor1++]; - count1++; - count2 = 0; - if (--length1 === 1) { - exit = true; - break; - } - } - } while ((count1 | count2) < minGallop); - - if (exit) { - break; - } - - do { - count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); - - if (count1 !== 0) { - for (i = 0; i < count1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - - dest += count1; - cursor1 += count1; - length1 -= count1; - if (length1 <= 1) { - exit = true; - break; - } - } - - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - exit = true; - break; - } - - count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); - - if (count2 !== 0) { - for (i = 0; i < count2; i++) { - array[dest + i] = array[cursor2 + i]; - } - - dest += count2; - cursor2 += count2; - length2 -= count2; - - if (length2 === 0) { - exit = true; - break; - } - } - array[dest++] = tmp[cursor1++]; - - if (--length1 === 1) { - exit = true; - break; - } - - minGallop--; - - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (minGallop < 0) { - minGallop = 0; - } - - minGallop += 2; - } - - this.minGallop = minGallop; - - if (minGallop < 1) { - this.minGallop = 1; - } - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - array[dest + length2] = tmp[cursor1]; - - } else if (length1 === 0) { - throw new Error('mergeLow preconditions were not respected'); - - } else { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - } -}; - -/** - * Merge two adjacent runs in a stable way. The runs must be such that the - * first element of run1 is bigger than the first element in run2 and the - * last element of run1 is greater than all the elements in run2. - * The method should be called when run1.length > run2.length as it uses - * TimSort temporary array to store run2. Use mergeLow if run1.length <= - * run2.length. - * - * @param {number} start1 - First element in run1. - * @param {number} length1 - Length of run1. - * @param {number} start2 - First element in run2. - * @param {number} length2 - Length of run2. - */ -TimSort.prototype.mergeHigh = function mergeHigh (start1, length1, start2, length2) { - var compare = this.compare; - var array = this.array; - var tmp = this.tmp; - var i = 0; - - for (i = 0; i < length2; i++) { - tmp[i] = array[start2 + i]; - } - - var cursor1 = start1 + length1 - 1; - var cursor2 = length2 - 1; - var dest = start2 + length2 - 1; - var customCursor = 0; - var customDest = 0; - - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - customCursor = dest - (length2 - 1); - - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - - return; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - return; - } - - var minGallop = this.minGallop; - - while (true) { - var count1 = 0; - var count2 = 0; - var exit = false; - - do { - if (compare(tmp[cursor2], array[cursor1]) < 0) { - array[dest--] = array[cursor1--]; - count1++; - count2 = 0; - if (--length1 === 0) { - exit = true; - break; - } - - } else { - array[dest--] = tmp[cursor2--]; - count2++; - count1 = 0; - if (--length2 === 1) { - exit = true; - break; - } - } - - } while ((count1 | count2) < minGallop); - - if (exit) { - break; - } - - do { - count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); - - if (count1 !== 0) { - dest -= count1; - cursor1 -= count1; - length1 -= count1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = count1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - if (length1 === 0) { - exit = true; - break; - } - } - - array[dest--] = tmp[cursor2--]; - - if (--length2 === 1) { - exit = true; - break; - } - - count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); - - if (count2 !== 0) { - dest -= count2; - cursor2 -= count2; - length2 -= count2; - customDest = dest + 1; - customCursor = cursor2 + 1; - - for (i = 0; i < count2; i++) { - array[customDest + i] = tmp[customCursor + i]; - } - - if (length2 <= 1) { - exit = true; - break; - } - } - - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - exit = true; - break; - } - - minGallop--; - - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (minGallop < 0) { - minGallop = 0; - } - - minGallop += 2; - } - - this.minGallop = minGallop; - - if (minGallop < 1) { - this.minGallop = 1; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - - } else if (length2 === 0) { - throw new Error('mergeHigh preconditions were not respected'); - - } else { - customCursor = dest - (length2 - 1); - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - } -}; - -/** - * Sort an array in the range [lo, hi) using TimSort. - * - * @param {array} array - The array to sort. - * @param {number} lo - First element in the range (inclusive). - * @param {number} hi - Last element in the range. - * @param {function=} compare - Item comparison function. Default is alphabetical. - */ -function sort (array, lo, hi, compare) { - if (!Array.isArray(array)) { - throw new TypeError('Can only sort arrays'); - } - - /* - * Handle the case where a comparison function is not provided. We do - * lexicographic sorting - */ - - if (lo === undefined) { - lo = 0; - } - - if (hi === undefined) { - hi = array.length; - } - - if (compare === undefined) { - compare = alphabeticalCompare; - } - - var remaining = hi - lo; - - // The array is already sorted - if (remaining < 2) { - return; - } - - var runLength = 0; - // On small arrays binary sort can be used directly - if (remaining < DEFAULT_MIN_MERGE) { - runLength = makeAscendingRun(array, lo, hi, compare); - binaryInsertionSort(array, lo, hi, lo + runLength, compare); - return; - } - - var ts = new TimSort(array, compare); - - var minRun = minRunLength(remaining); - - do { - runLength = makeAscendingRun(array, lo, hi, compare); - if (runLength < minRun) { - var force = remaining; - if (force > minRun) { - force = minRun; - } - - binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); - runLength = force; - } - // Push new run and merge if necessary - ts.pushRun(lo, runLength); - ts.mergeRuns(); - - // Go find next run - remaining -= runLength; - lo += runLength; - - } while (remaining !== 0); - - // Force merging of remaining runs - ts.forceMergeRuns(); -} - -var FixedArray = function FixedArray(size) { - this._count = 0; - this._data = new Array(size); -}; - -var prototypeAccessors = { length: { configurable: true },data: { configurable: true } }; - -FixedArray.prototype._resize = function _resize (size) { - var this$1 = this; - - if (size > this._data.length) { - for (var i = this._data.length; i < size; ++i) { - this$1._data[i] = undefined; - } - } -}; - -prototypeAccessors.length.get = function () { - return this._count; -}; - -prototypeAccessors.data.get = function () { - return this._data; -}; - -FixedArray.prototype.reset = function reset () { - var this$1 = this; - - for (var i = 0; i < this._count; ++i) { - this$1._data[i] = undefined; - } - - this._count = 0; -}; - -FixedArray.prototype.push = function push (val) { - if (this._count >= this._data.length) { - this._resize(this._data.length * 2); - } - - this._data[this._count] = val; - ++this._count; -}; - -FixedArray.prototype.pop = function pop () { - --this._count; - - if (this._count < 0) { - this._count = 0; - } - - var ret = this._data[this._count]; - this._data[this._count] = undefined; - - return ret; -}; - -FixedArray.prototype.fastRemove = function fastRemove (idx) { - if (idx >= this._count) { - return; - } - - var last = this._count - 1; - this._data[idx] = this._data[last]; - this._data[last] = undefined; - this._count -= 1; -}; - -FixedArray.prototype.indexOf = function indexOf (val) { - var idx = this._data.indexOf(val); - if (idx >= this._count) { - return -1; - } - - return idx; -}; - -FixedArray.prototype.sort = function sort$1 (cmp) { - return sort(this._data, 0, this._count, cmp); -}; - -Object.defineProperties( FixedArray.prototype, prototypeAccessors ); - -var Pool = function Pool(fn, size) { - var this$1 = this; - - this._fn = fn; - this._idx = size - 1; - this._frees = new Array(size); - - for (var i = 0; i < size; ++i) { - this$1._frees[i] = fn(); - } -}; - -Pool.prototype._expand = function _expand (size) { - var this$1 = this; - - var old = this._frees; - this._frees = new Array(size); - - var len = size - old.length; - for (var i = 0; i < len; ++i) { - this$1._frees[i] = this$1._fn(); - } - - for (var i$1 = len, j = 0; i$1 < size; ++i$1, ++j) { - this$1._frees[i$1] = old[j]; - } - - this._idx += len; -}; - -Pool.prototype.alloc = function alloc () { - // create some more space (expand by 20%, minimum 1) - if (this._idx < 0) { - this._expand(Math.round(this._frees.length * 1.2) + 1); - } - - var ret = this._frees[this._idx]; - this._frees[this._idx] = null; - --this._idx; - - return ret; -}; - -Pool.prototype.free = function free (obj) { - ++this._idx; - this._frees[this._idx] = obj; -}; - -// NOTE: you must have `_prev` and `_next` field in the object returns by `fn` - -var LinkedArray = function LinkedArray(fn, size) { - this._fn = fn; - this._count = 0; - this._head = null; - this._tail = null; - - this._pool = new Pool(fn, size); -}; - -var prototypeAccessors$1 = { head: { configurable: true },tail: { configurable: true },length: { configurable: true } }; - -prototypeAccessors$1.head.get = function () { - return this._head; -}; - -prototypeAccessors$1.tail.get = function () { - return this._tail; -}; - -prototypeAccessors$1.length.get = function () { - return this._count; -}; - -LinkedArray.prototype.add = function add () { - var node = this._pool.alloc(); - - if (!this._tail) { - this._head = node; - } else { - this._tail._next = node; - node._prev = this._tail; - } - this._tail = node; - this._count += 1; - - return node; -}; - -LinkedArray.prototype.remove = function remove (node) { - if (node._prev) { - node._prev._next = node._next; - } else { - this._head = node._next; - } - - if (node._next) { - node._next._prev = node._prev; - } else { - this._tail = node._prev; - } - - node._next = null; - node._prev = null; - this._pool.free(node); - this._count -= 1; -}; - -LinkedArray.prototype.forEach = function forEach (fn, binder) { - var this$1 = this; - - var cursor = this._head; - if (!cursor) { - return; - } - - if (binder) { - fn = fn.bind(binder); - } - - var idx = 0; - var next = cursor; - - while (cursor) { - next = cursor._next; - fn(cursor, idx, this$1); - - cursor = next; - ++idx; - } -}; - -Object.defineProperties( LinkedArray.prototype, prototypeAccessors$1 ); - -var RecyclePool = function RecyclePool(fn, size) { - var this$1 = this; - - this._fn = fn; - this._count = 0; - this._data = new Array(size); - - for (var i = 0; i < size; ++i) { - this$1._data[i] = fn(); - } -}; - -var prototypeAccessors$2 = { length: { configurable: true },data: { configurable: true } }; - -prototypeAccessors$2.length.get = function () { - return this._count; -}; - -prototypeAccessors$2.data.get = function () { - return this._data; -}; - -RecyclePool.prototype.reset = function reset () { - this._count = 0; -}; - -RecyclePool.prototype.resize = function resize (size) { - var this$1 = this; - - if (size > this._data.length) { - for (var i = this._data.length; i < size; ++i) { - this$1._data[i] = this$1._fn(); - } - } -}; - -RecyclePool.prototype.add = function add () { - if (this._count >= this._data.length) { - this.resize(this._data.length * 2); - } - - return this._data[this._count++]; -}; - -RecyclePool.prototype.remove = function remove (idx) { - if (idx >= this._count) { - return; - } - - var last = this._count - 1; - var tmp = this._data[idx]; - this._data[idx] = this._data[last]; - this._data[last] = tmp; - this._count -= 1; -}; - -RecyclePool.prototype.sort = function sort$1 (cmp) { - return sort(this._data, 0, this._count, cmp); -}; - -Object.defineProperties( RecyclePool.prototype, prototypeAccessors$2 ); - -var _bufferPools = Array(8); -for (var i = 0; i < 8; ++i) { - _bufferPools[i] = []; -} - -// Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. - -/** - * BaseRenderData is a core data abstraction for renderer, this is a abstract class. - * An inherited render data type should define raw vertex datas. - * User should also define the effect, vertex count and index count. - */ -var BaseRenderData = function BaseRenderData () { - this.material = null; - this.vertexCount = 0; - this.indiceCount = 0; -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var _pool; -var _dataPool = new Pool(function () { - return { - x: 0.0, - y: 0.0, - u: 0.0, - v: 0.0, - color: 0 - }; -}, 128); - -/** - * RenderData is most widely used render data type. - * It describes raw vertex data with a fixed data layout. - * Each vertex is described by five property: x, y, u, v, color. The data layout might be extended in the future. - * Vertex data objects are managed automatically by RenderData, user only need to set the dataLength property. - * User can also define rendering index orders for the vertex list. - */ -var RenderData = (function (BaseRenderData$$1) { - function RenderData () { - BaseRenderData$$1.call(this); - this._data = []; - this._indices = []; - - this._pivotX = 0; - this._pivotY = 0; - this._width = 0; - this._height = 0; - - this.uvDirty = true; - this.vertDirty = true; - } - - if ( BaseRenderData$$1 ) RenderData.__proto__ = BaseRenderData$$1; - RenderData.prototype = Object.create( BaseRenderData$$1 && BaseRenderData$$1.prototype ); - RenderData.prototype.constructor = RenderData; - - var prototypeAccessors = { type: { configurable: true },dataLength: { configurable: true } }; - - prototypeAccessors.type.get = function () { - return RenderData.type; - }; - - prototypeAccessors.dataLength.get = function () { - return this._data.length; - }; - - prototypeAccessors.dataLength.set = function (length) { - var data = this._data; - if (data.length !== length) { - // Free extra data - for (var i = length; i < data.length; i++) { - _dataPool.free(data[i]); - } - // Alloc needed data - for (var i$1 = data.length; i$1 < length; i$1++) { - data[i$1] = _dataPool.alloc(); - } - data.length = length; - } - }; - - RenderData.prototype.updateSizeNPivot = function updateSizeNPivot (width, height, pivotX, pivotY) { - if (width !== this._width || - height !== this._height || - pivotX !== this._pivotX || - pivotY !== this._pivotY) - { - this._width = width; - this._height = height; - this._pivotX = pivotX; - this._pivotY = pivotY; - this.vertDirty = true; - } - }; - - RenderData.alloc = function alloc () { - return _pool.alloc(); - }; - - RenderData.free = function free (data) { - if (data instanceof RenderData) { - for (var i = data.length-1; i > 0; i--) { - _dataPool.free(data._data[i]); - } - data._data.length = 0; - data._indices.length = 0; - data.material = null; - data.uvDirty = true; - data.vertDirty = true; - data.vertexCount = 0; - data.indiceCount = 0; - _pool.free(data); - } - }; - - Object.defineProperties( RenderData.prototype, prototypeAccessors ); - - return RenderData; -}(BaseRenderData)); - -RenderData.type = 'RenderData'; - -_pool = new Pool(function () { - return new RenderData(); -}, 32); - -var _d2r = Math.PI / 180.0; -var _r2d = 180.0 / Math.PI; - -/** - * @property {number} EPSILON - */ -var EPSILON = 0.000001; - -/** - * Tests whether or not the arguments have approximately the same value, within an absolute - * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less - * than or equal to 1.0, and a relative tolerance is used for larger values) - * - * @param {Number} a The first number to test. - * @param {Number} b The second number to test. - * @returns {Boolean} True if the numbers are approximately equal, false otherwise. - */ -function equals(a, b) { - return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b)); -} - -/** - * Tests whether or not the arguments have approximately the same value by given maxDiff - * - * @param {Number} a The first number to test. - * @param {Number} b The second number to test. - * @param {Number} maxDiff Maximum difference. - * @returns {Boolean} True if the numbers are approximately equal, false otherwise. - */ -function approx(a, b, maxDiff) { - maxDiff = maxDiff || EPSILON; - return Math.abs(a - b) <= maxDiff; -} - -/** - * Clamps a value between a minimum float and maximum float value. - * - * @method clamp - * @param {number} val - * @param {number} min - * @param {number} max - * @return {number} - */ -function clamp(val, min, max) { - return val < min ? min : val > max ? max : val; -} - -/** - * Clamps a value between 0 and 1. - * - * @method clamp01 - * @param {number} val - * @return {number} - */ -function clamp01(val) { - return val < 0 ? 0 : val > 1 ? 1 : val; -} - -/** - * @method lerp - * @param {number} from - * @param {number} to - * @param {number} ratio - the interpolation coefficient - * @return {number} - */ -function lerp(from, to, ratio) { - return from + (to - from) * ratio; -} - -/** -* Convert Degree To Radian -* -* @param {Number} a Angle in Degrees -*/ -function toRadian(a) { - return a * _d2r; -} - -/** -* Convert Radian To Degree -* -* @param {Number} a Angle in Radian -*/ -function toDegree(a) { - return a * _r2d; -} - -/** -* @method random -*/ -var random = Math.random; - -/** - * Returns a floating-point random number between min (inclusive) and max (exclusive). - * - * @method randomRange - * @param {number} min - * @param {number} max - * @return {number} the random number - */ -function randomRange(min, max) { - return Math.random() * (max - min) + min; -} - -/** - * Returns a random integer between min (inclusive) and max (exclusive). - * - * @method randomRangeInt - * @param {number} min - * @param {number} max - * @return {number} the random integer - */ -function randomRangeInt(min, max) { - return Math.floor(randomRange(min, max)); -} - -/** - * Returns the next power of two for the value - * - * @method nextPow2 - * @param {number} val - * @return {number} the the next power of two - */ -function nextPow2(val) { - --val; - val = (val >> 1) | val; - val = (val >> 2) | val; - val = (val >> 4) | val; - val = (val >> 8) | val; - val = (val >> 16) | val; - ++val; - - return val; -} - -/** - * Bit twiddling hacks for JavaScript. - * - * Author: Mikola Lysenko - * - * Ported from Stanford bit twiddling hack library: - * http://graphics.stanford.edu/~seander/bithacks.html - */ - -// Number of bits in an integer -var INT_BITS = 32; -var INT_MAX = 0x7fffffff; -var INT_MIN = -1<<(INT_BITS-1); - -/** - * Returns -1, 0, +1 depending on sign of x - * - * @param {number} v - * @returns {number} - */ -function sign(v) { - return (v > 0) - (v < 0); -} - -/** - * Computes absolute value of integer - * - * @param {number} v - * @returns {number} - */ -function abs(v) { - var mask = v >> (INT_BITS-1); - return (v ^ mask) - mask; -} - -/** - * Computes minimum of integers x and y - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function min(x, y) { - return y ^ ((x ^ y) & -(x < y)); -} - -/** - * Computes maximum of integers x and y - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function max(x, y) { - return x ^ ((x ^ y) & -(x < y)); -} - -/** - * Checks if a number is a power of two - * - * @param {number} v - * @returns {boolean} - */ -function isPow2(v) { - return !(v & (v-1)) && (!!v); -} - -/** - * Computes log base 2 of v - * - * @param {number} v - * @returns {number} - */ -function log2(v) { - var r, shift; - r = (v > 0xFFFF) << 4; v >>>= r; - shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; - return r | (v >> 1); -} - -/** - * Computes log base 10 of v - * - * @param {number} v - * @returns {number} - */ -function log10$1(v) { - return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : - (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : - (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; -} - -/** - * Counts number of bits - * - * @param {number} v - * @returns {number} - */ -function popCount(v) { - v = v - ((v >>> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); - return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; -} - -/** - * Counts number of trailing zeros - * - * @param {number} v - * @returns {number} - */ -function countTrailingZeros(v) { - var c = 32; - v &= -v; - if (v) { c--; } - if (v & 0x0000FFFF) { c -= 16; } - if (v & 0x00FF00FF) { c -= 8; } - if (v & 0x0F0F0F0F) { c -= 4; } - if (v & 0x33333333) { c -= 2; } - if (v & 0x55555555) { c -= 1; } - return c; -} - -/** - * Rounds to next power of 2 - * - * @param {number} v - * @returns {number} - */ -function nextPow2$1(v) { - v += v === 0; - --v; - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v + 1; -} - -/** - * Rounds down to previous power of 2 - * - * @param {number} v - * @returns {number} - */ -function prevPow2(v) { - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v - (v>>>1); -} - -/** - * Computes parity of word - * - * @param {number} v - * @returns {number} - */ -function parity(v) { - v ^= v >>> 16; - v ^= v >>> 8; - v ^= v >>> 4; - v &= 0xf; - return (0x6996 >>> v) & 1; -} - -var REVERSE_TABLE = new Array(256); - -(function(tab) { - for(var i=0; i<256; ++i) { - var v = i, r = i, s = 7; - for (v >>>= 1; v; v >>>= 1) { - r <<= 1; - r |= v & 1; - --s; - } - tab[i] = (r << s) & 0xff; - } -})(REVERSE_TABLE); - -/** - * Reverse bits in a 32 bit word - * - * @param {number} v - * @returns {number} - */ -function reverse(v) { - return (REVERSE_TABLE[v & 0xff] << 24) | - (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | - (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | - REVERSE_TABLE[(v >>> 24) & 0xff]; -} - -/** - * Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes - * - * @param {number} x - * @param {number} y - * @returns {number} - */ -function interleave2(x, y) { - x &= 0xFFFF; - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y &= 0xFFFF; - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -/** - * Extracts the nth interleaved component - * - * @param {number} v - * @param {number} n - * @returns {number} - */ -function deinterleave2(v, n) { - v = (v >>> n) & 0x55555555; - v = (v | (v >>> 1)) & 0x33333333; - v = (v | (v >>> 2)) & 0x0F0F0F0F; - v = (v | (v >>> 4)) & 0x00FF00FF; - v = (v | (v >>> 16)) & 0x000FFFF; - return (v << 16) >> 16; -} - -/** - * Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes - * - * @param {number} x - * @param {number} y - * @param {number} z - * @returns {number} - */ -function interleave3(x, y, z) { - x &= 0x3FF; - x = (x | (x<<16)) & 4278190335; - x = (x | (x<<8)) & 251719695; - x = (x | (x<<4)) & 3272356035; - x = (x | (x<<2)) & 1227133513; - - y &= 0x3FF; - y = (y | (y<<16)) & 4278190335; - y = (y | (y<<8)) & 251719695; - y = (y | (y<<4)) & 3272356035; - y = (y | (y<<2)) & 1227133513; - x |= (y << 1); - - z &= 0x3FF; - z = (z | (z<<16)) & 4278190335; - z = (z | (z<<8)) & 251719695; - z = (z | (z<<4)) & 3272356035; - z = (z | (z<<2)) & 1227133513; - - return x | (z << 2); -} - -/** - * Extracts nth interleaved component of a 3-tuple - * - * @param {number} v - * @param {number} n - * @returns {number} - */ -function deinterleave3(v, n) { - v = (v >>> n) & 1227133513; - v = (v | (v>>>2)) & 3272356035; - v = (v | (v>>>4)) & 251719695; - v = (v | (v>>>8)) & 4278190335; - v = (v | (v>>>16)) & 0x3FF; - return (v<<22)>>22; -} - -/** - * Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) - * - * @param {number} v - * @returns {number} - */ -function nextCombination(v) { - var t = v | (v - 1); - return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); -} - -var bits_ = Object.freeze({ - INT_BITS: INT_BITS, - INT_MAX: INT_MAX, - INT_MIN: INT_MIN, - sign: sign, - abs: abs, - min: min, - max: max, - isPow2: isPow2, - log2: log2, - log10: log10$1, - popCount: popCount, - countTrailingZeros: countTrailingZeros, - nextPow2: nextPow2$1, - prevPow2: prevPow2, - parity: parity, - reverse: reverse, - interleave2: interleave2, - deinterleave2: deinterleave2, - interleave3: interleave3, - deinterleave3: deinterleave3, - nextCombination: nextCombination -}); - -var _tmp = new Array(2); - -var _vec2 = function _vec2(x, y) { - this.x = x; - this.y = y; -}; - -_vec2.prototype.toJSON = function toJSON () { - _tmp[0] = this.x; - _tmp[1] = this.y; - - return _tmp; -}; - -/** - * @class 2 Dimensional Vector - * @name vec2 - */ -var vec2 = {}; - -/** - * Creates a new, empty vec2 - * - * @returns {vec2} a new 2D vector - */ -vec2.create = function () { - return new _vec2(0, 0); -}; - -/** - * Creates a new vec2 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @returns {vec2} a new 2D vector - */ -vec2.new = function (x, y) { - return new _vec2(x, y); -}; - -/** - * Creates a new vec2 initialized with values from an existing vector - * - * @param {vec2} a vector to clone - * @returns {vec2} a new 2D vector - */ -vec2.clone = function (a) { - return new _vec2(a.x, a.y); -}; - -/** - * Copy the values from one vec2 to another - * - * @param {vec2} out the receiving vector - * @param {vec2} a the source vector - * @returns {vec2} out - */ -vec2.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - return out; -}; - -/** - * Set the components of a vec2 to the given values - * - * @param {vec2} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @returns {vec2} out - */ -vec2.set = function (out, x, y) { - out.x = x; - out.y = y; - return out; -}; - -/** - * Adds two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - return out; -}; - -/** - * Alias for {@link vec2.subtract} - * @function - */ -vec2.sub = vec2.subtract; - -/** - * Multiplies two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - return out; -}; - -/** - * Alias for {@link vec2.multiply} - * @function - */ -vec2.mul = vec2.multiply; - -/** - * Divides two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - return out; -}; - -/** - * Alias for {@link vec2.divide} - * @function - */ -vec2.div = vec2.divide; - -/** - * Math.ceil the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to ceil - * @returns {vec2} out - */ -vec2.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - return out; -}; - -/** - * Math.floor the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to floor - * @returns {vec2} out - */ -vec2.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - return out; -}; - -/** - * Returns the minimum of two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - return out; -}; - -/** - * Returns the maximum of two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec2} out - */ -vec2.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - return out; -}; - -/** - * Math.round the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to round - * @returns {vec2} out - */ -vec2.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - return out; -}; - -/** - * Scales a vec2 by a scalar number - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec2} out - */ -vec2.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - return out; -}; - -/** - * Adds two vec2's after scaling the second operand by a scalar value - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec2} out - */ -vec2.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} distance between a and b - */ -vec2.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y; - return Math.sqrt(x * x + y * y); -}; - -/** - * Alias for {@link vec2.distance} - * @function - */ -vec2.dist = vec2.distance; - -/** - * Calculates the squared euclidian distance between two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} squared distance between a and b - */ -vec2.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y; - return x * x + y * y; -}; - -/** - * Alias for {@link vec2.squaredDistance} - * @function - */ -vec2.sqrDist = vec2.squaredDistance; - -/** - * Calculates the length of a vec2 - * - * @param {vec2} a vector to calculate length of - * @returns {Number} length of a - */ -vec2.length = function (a) { - var x = a.x, - y = a.y; - return Math.sqrt(x * x + y * y); -}; - -/** - * Alias for {@link vec2.length} - * @function - */ -vec2.len = vec2.length; - -/** - * Calculates the squared length of a vec2 - * - * @param {vec2} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec2.squaredLength = function (a) { - var x = a.x, - y = a.y; - return x * x + y * y; -}; - -/** - * Alias for {@link vec2.squaredLength} - * @function - */ -vec2.sqrLen = vec2.squaredLength; - -/** - * Negates the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to negate - * @returns {vec2} out - */ -vec2.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - return out; -}; - -/** - * Returns the inverse of the components of a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to invert - * @returns {vec2} out - */ -vec2.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - return out; -}; - -/** - * Returns the inverse of the components of a vec2 safely - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to invert - * @returns {vec2} out - */ -vec2.inverseSafe = function (out, a) { - var x = a.x, - y = a.y; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / a.y; - } - - return out; -}; - -/** - * Normalize a vec2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a vector to normalize - * @returns {vec2} out - */ -vec2.normalize = function (out, a) { - var x = a.x, - y = a.y; - var len = x * x + y * y; - if (len > 0) { - //TODO: evaluate use of glm_invsqrt here? - len = 1 / Math.sqrt(len); - out.x = a.x * len; - out.y = a.y * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec2's - * - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {Number} dot product of a and b - */ -vec2.dot = function (a, b) { - return a.x * b.x + a.y * b.y; -}; - -/** - * Computes the cross product of two vec2's - * Note that the cross product must by definition produce a 3D vector - * - * @param {vec3} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @returns {vec3} out - */ -vec2.cross = function (out, a, b) { - var z = a.x * b.y - a.y * b.x; - out.x = out.y = 0; - out.z = z; - return out; -}; - -/** - * Performs a linear interpolation between two vec2's - * - * @param {vec2} out the receiving vector - * @param {vec2} a the first operand - * @param {vec2} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec2} out - */ -vec2.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec2} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec2} out - */ -vec2.random = function (out, scale) { - scale = scale || 1.0; - var r = random() * 2.0 * Math.PI; - out.x = Math.cos(r) * scale; - out.y = Math.sin(r) * scale; - return out; -}; - -/** - * Transforms the vec2 with a mat2 - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat2} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat2 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m02 * y; - out.y = m.m01 * x + m.m03 * y; - return out; -}; - -/** - * Transforms the vec2 with a mat23 - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat23} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat23 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m02 * y + m.m04; - out.y = m.m01 * x + m.m03 * y + m.m05; - return out; -}; - -/** - * Transforms the vec2 with a mat3 - * 3rd vector component is implicitly '1' - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat3} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat3 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m03 * y + m.m06; - out.y = m.m01 * x + m.m04 * y + m.m07; - return out; -}; - -/** - * Transforms the vec2 with a mat4 - * 3rd vector component is implicitly '0' - * 4th vector component is implicitly '1' - * - * @param {vec2} out the receiving vector - * @param {vec2} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec2} out - */ -vec2.transformMat4 = function (out, a, m) { - var x = a.x, - y = a.y; - out.x = m.m00 * x + m.m04 * y + m.m12; - out.y = m.m01 * x + m.m05 * y + m.m13; - return out; -}; - -/** - * Perform some operation over an array of vec2s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec2.forEach = (function () { - var vec = vec2.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 2; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; - } - - return a; - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec2} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec2.str = function (a) { - return ("vec2(" + (a.x) + ", " + (a.y) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec2} v - * @returns {array} - */ -vec2.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - - return out; -}; - -/** - * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===) - * - * @param {vec2} a The first vector. - * @param {vec2} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec2.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec2} a The first vector. - * @param {vec2} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec2.equals = function (a, b) { - var a0 = a.x, a1 = a.y; - var b0 = b.x, b1 = b.y; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1))); -}; - -var _tmp$1 = new Array(3); - -var _vec3 = function _vec3(x, y, z) { - this.x = x; - this.y = y; - this.z = z; -}; - -_vec3.prototype.toJSON = function toJSON () { - _tmp$1[0] = this.x; - _tmp$1[1] = this.y; - _tmp$1[2] = this.z; - - return _tmp$1; -}; - -/** - * @class 3 Dimensional Vector - * @name vec3 - */ -var vec3 = {}; - -/** - * Creates a new, empty vec3 - * - * @returns {vec3} a new 3D vector - */ -vec3.create = function () { - return new _vec3(0, 0, 0); -}; - -/** - * Creates a new vec3 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} a new 3D vector - */ -vec3.new = function (x, y, z) { - return new _vec3(x, y, z); -}; - -/** - * Creates a new vec3 initialized with values from an existing vector - * - * @param {vec3} a vector to clone - * @returns {vec3} a new 3D vector - */ -vec3.clone = function (a) { - return new _vec3(a.x, a.y, a.z); -}; - -/** - * Copy the values from one vec3 to another - * - * @param {vec3} out the receiving vector - * @param {vec3} a the source vector - * @returns {vec3} out - */ -vec3.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - out.z = a.z; - return out; -}; - -/** - * Set the components of a vec3 to the given values - * - * @param {vec3} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} out - */ -vec3.set = function (out, x, y, z) { - out.x = x; - out.y = y; - out.z = z; - return out; -}; - -/** - * Adds two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - out.z = a.z + b.z; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; - return out; -}; - -/** - * Alias for {@link vec3.subtract} - * @function - */ -vec3.sub = vec3.subtract; - -/** - * Multiplies two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - out.z = a.z * b.z; - return out; -}; - -/** - * Alias for {@link vec3.multiply} - * @function - */ -vec3.mul = vec3.multiply; - -/** - * Divides two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - out.z = a.z / b.z; - return out; -}; - -/** - * Alias for {@link vec3.divide} - * @function - */ -vec3.div = vec3.divide; - -/** - * Math.ceil the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to ceil - * @returns {vec3} out - */ -vec3.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - out.z = Math.ceil(a.z); - return out; -}; - -/** - * Math.floor the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to floor - * @returns {vec3} out - */ -vec3.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - out.z = Math.floor(a.z); - return out; -}; - -/** - * Returns the minimum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - out.z = Math.min(a.z, b.z); - return out; -}; - -/** - * Returns the maximum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - out.z = Math.max(a.z, b.z); - return out; -}; - -/** - * Math.round the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to round - * @returns {vec3} out - */ -vec3.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - out.z = Math.round(a.z); - return out; -}; - -/** - * Scales a vec3 by a scalar number - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec3} out - */ -vec3.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - out.z = a.z * b; - return out; -}; - -/** - * Adds two vec3's after scaling the second operand by a scalar value - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec3} out - */ -vec3.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - out.z = a.z + (b.z * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} distance between a and b - */ -vec3.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z; - return Math.sqrt(x * x + y * y + z * z); -}; - -/** - * Alias for {@link vec3.distance} - * @function - */ -vec3.dist = vec3.distance; - -/** - * Calculates the squared euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} squared distance between a and b - */ -vec3.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z; - return x * x + y * y + z * z; -}; - -/** - * Alias for {@link vec3.squaredDistance} - * @function - */ -vec3.sqrDist = vec3.squaredDistance; - -/** - * Calculates the length of a vec3 - * - * @param {vec3} a vector to calculate length of - * @returns {Number} length of a - */ -vec3.length = function (a) { - var x = a.x, - y = a.y, - z = a.z; - return Math.sqrt(x * x + y * y + z * z); -}; - -/** - * Alias for {@link vec3.length} - * @function - */ -vec3.len = vec3.length; - -/** - * Calculates the squared length of a vec3 - * - * @param {vec3} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec3.squaredLength = function (a) { - var x = a.x, - y = a.y, - z = a.z; - return x * x + y * y + z * z; -}; - -/** - * Alias for {@link vec3.squaredLength} - * @function - */ -vec3.sqrLen = vec3.squaredLength; - -/** - * Negates the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to negate - * @returns {vec3} out - */ -vec3.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - return out; -}; - -/** - * Returns the inverse of the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to invert - * @returns {vec3} out - */ -vec3.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - out.z = 1.0 / a.z; - return out; -}; - -/** - * Returns the inverse of the components of a vec3 safely - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to invert - * @returns {vec3} out - */ -vec3.inverseSafe = function (out, a) { - var x = a.x, - y = a.y, - z = a.z; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / y; - } - - if (Math.abs(z) < EPSILON) { - out.z = 0; - } else { - out.z = 1.0 / z; - } - - return out; -}; - -/** - * Normalize a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to normalize - * @returns {vec3} out - */ -vec3.normalize = function (out, a) { - var x = a.x, - y = a.y, - z = a.z; - - var len = x * x + y * y + z * z; - if (len > 0) { - //TODO: evaluate use of glm_invsqrt here? - len = 1 / Math.sqrt(len); - out.x = x * len; - out.y = y * len; - out.z = z * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} dot product of a and b - */ -vec3.dot = function (a, b) { - return a.x * b.x + a.y * b.y + a.z * b.z; -}; - -/** - * Computes the cross product of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -vec3.cross = function (out, a, b) { - var ax = a.x, ay = a.y, az = a.z, - bx = b.x, by = b.y, bz = b.z; - - out.x = ay * bz - az * by; - out.y = az * bx - ax * bz; - out.z = ax * by - ay * bx; - return out; -}; - -/** - * Performs a linear interpolation between two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y, - az = a.z; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - out.z = az + t * (b.z - az); - return out; -}; - -/** - * Performs a hermite interpolation with two control points - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {vec3} c the third operand - * @param {vec3} d the fourth operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.hermite = function (out, a, b, c, d, t) { - var factorTimes2 = t * t, - factor1 = factorTimes2 * (2 * t - 3) + 1, - factor2 = factorTimes2 * (t - 2) + t, - factor3 = factorTimes2 * (t - 1), - factor4 = factorTimes2 * (3 - 2 * t); - - out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; - out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; - out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; - - return out; -}; - -/** - * Performs a bezier interpolation with two control points - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {vec3} c the third operand - * @param {vec3} d the fourth operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -vec3.bezier = function (out, a, b, c, d, t) { - var inverseFactor = 1 - t, - inverseFactorTimesTwo = inverseFactor * inverseFactor, - factorTimes2 = t * t, - factor1 = inverseFactorTimesTwo * inverseFactor, - factor2 = 3 * t * inverseFactorTimesTwo, - factor3 = 3 * factorTimes2 * inverseFactor, - factor4 = factorTimes2 * t; - - out.x = a.x * factor1 + b.x * factor2 + c.x * factor3 + d.x * factor4; - out.y = a.y * factor1 + b.y * factor2 + c.y * factor3 + d.y * factor4; - out.z = a.z * factor1 + b.z * factor2 + c.z * factor3 + d.z * factor4; - - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec3} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec3} out - */ -vec3.random = function (out, scale) { - scale = scale || 1.0; - - var r = random() * 2.0 * Math.PI; - var z = (random() * 2.0) - 1.0; - var zScale = Math.sqrt(1.0 - z * z) * scale; - - out.x = Math.cos(r) * zScale; - out.y = Math.sin(r) * zScale; - out.z = z * scale; - return out; -}; - -/** - * Transforms the vec3 with a mat4. - * 4th vector component is implicitly '1' - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec3} out - */ -vec3.transformMat4 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z, - w = m.m03 * x + m.m07 * y + m.m11 * z + m.m15; - w = w || 1.0; - out.x = (m.m00 * x + m.m04 * y + m.m08 * z + m.m12) / w; - out.y = (m.m01 * x + m.m05 * y + m.m09 * z + m.m13) / w; - out.z = (m.m02 * x + m.m06 * y + m.m10 * z + m.m14) / w; - return out; -}; - -/** - * Transforms the vec3 with a mat3. - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m the 3x3 matrix to transform with - * @returns {vec3} out - */ -vec3.transformMat3 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z; - out.x = x * m.m00 + y * m.m03 + z * m.m06; - out.y = x * m.m01 + y * m.m04 + z * m.m07; - out.z = x * m.m02 + y * m.m05 + z * m.m08; - return out; -}; - -/** - * Transforms the vec3 with a quat - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec3} out - */ -vec3.transformQuat = function (out, a, q) { - // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations - - var x = a.x, y = a.y, z = a.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vec - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - - // calculate result * inverse quat - out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - return out; -}; - -/** - * Rotate a 3D vector around the x-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateX = function (out, a, b, c) { - var p = [], r = []; - // Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.x; - r.y = p.y * Math.cos(c) - p.z * Math.sin(c); - r.z = p.y * Math.sin(c) + p.z * Math.cos(c); - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Rotate a 3D vector around the y-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateY = function (out, a, b, c) { - var p = [], r = []; - //Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.z * Math.sin(c) + p.x * Math.cos(c); - r.y = p.y; - r.z = p.z * Math.cos(c) - p.x * Math.sin(c); - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Rotate a 3D vector around the z-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -vec3.rotateZ = function (out, a, b, c) { - var p = [], r = []; - //Translate point to the origin - p.x = a.x - b.x; - p.y = a.y - b.y; - p.z = a.z - b.z; - - //perform rotation - r.x = p.x * Math.cos(c) - p.y * Math.sin(c); - r.y = p.x * Math.sin(c) + p.y * Math.cos(c); - r.z = p.z; - - //translate to correct position - out.x = r.x + b.x; - out.y = r.y + b.y; - out.z = r.z + b.z; - - return out; -}; - -/** - * Perform some operation over an array of vec3s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec3.forEach = (function () { - var vec = vec3.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 3; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; vec.z = a[i + 2]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; a[i + 2] = vec.z; - } - - return a; - }; -})(); - -/** - * Get the angle between two 3D vectors - * @param {vec3} a The first operand - * @param {vec3} b The second operand - * @returns {Number} The angle in radians - */ -vec3.angle = (function () { - var tempA = vec3.create(); - var tempB = vec3.create(); - - return function (a, b) { - vec3.copy(tempA, a); - vec3.copy(tempB, b); - - vec3.normalize(tempA, tempA); - vec3.normalize(tempB, tempB); - - var cosine = vec3.dot(tempA, tempB); - - if (cosine > 1.0) { - return 0; - } - - if (cosine < -1.0) { - return Math.PI; - } - - return Math.acos(cosine); - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec3} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec3.str = function (a) { - return ("vec3(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec3} v - * @returns {array} - */ -vec3.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - out[2] = v.z; - - return out; -}; - -/** - * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec3.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y && a.z === b.z; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec3.equals = function (a, b) { - var a0 = a.x, a1 = a.y, a2 = a.z; - var b0 = b.x, b1 = b.y, b2 = b.z; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); -}; - -var _tmp$2 = new Array(4); - -var _vec4 = function _vec4(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; -}; - -_vec4.prototype.toJSON = function toJSON () { - _tmp$2[0] = this.x; - _tmp$2[1] = this.y; - _tmp$2[2] = this.z; - _tmp$2[3] = this.w; - - return _tmp$2; -}; - -/** - * @class 4 Dimensional Vector - * @name vec4 - */ -var vec4 = {}; - -/** - * Creates a new, empty vec4 - * - * @returns {vec4} a new 4D vector - */ -vec4.create = function () { - return new _vec4(0, 0, 0, 0); -}; - -/** - * Creates a new vec4 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} a new 4D vector - */ -vec4.new = function (x, y, z, w) { - return new _vec4(x, y, z, w); -}; - -/** - * Creates a new vec4 initialized with values from an existing vector - * - * @param {vec4} a vector to clone - * @returns {vec4} a new 4D vector - */ -vec4.clone = function (a) { - return new _vec4(a.x, a.y, a.z, a.w); -}; - -/** - * Copy the values from one vec4 to another - * - * @param {vec4} out the receiving vector - * @param {vec4} a the source vector - * @returns {vec4} out - */ -vec4.copy = function (out, a) { - out.x = a.x; - out.y = a.y; - out.z = a.z; - out.w = a.w; - return out; -}; - -/** - * Set the components of a vec4 to the given values - * - * @param {vec4} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} out - */ -vec4.set = function (out, x, y, z, w) { - out.x = x; - out.y = y; - out.z = z; - out.w = w; - return out; -}; - -/** - * Adds two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.add = function (out, a, b) { - out.x = a.x + b.x; - out.y = a.y + b.y; - out.z = a.z + b.z; - out.w = a.w + b.w; - return out; -}; - -/** - * Subtracts vector b from vector a - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.subtract = function (out, a, b) { - out.x = a.x - b.x; - out.y = a.y - b.y; - out.z = a.z - b.z; - out.w = a.w - b.w; - return out; -}; - -/** - * Alias for {@link vec4.subtract} - * @function - */ -vec4.sub = vec4.subtract; - -/** - * Multiplies two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.multiply = function (out, a, b) { - out.x = a.x * b.x; - out.y = a.y * b.y; - out.z = a.z * b.z; - out.w = a.w * b.w; - return out; -}; - -/** - * Alias for {@link vec4.multiply} - * @function - */ -vec4.mul = vec4.multiply; - -/** - * Divides two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.divide = function (out, a, b) { - out.x = a.x / b.x; - out.y = a.y / b.y; - out.z = a.z / b.z; - out.w = a.w / b.w; - return out; -}; - -/** - * Alias for {@link vec4.divide} - * @function - */ -vec4.div = vec4.divide; - -/** - * Math.ceil the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to ceil - * @returns {vec4} out - */ -vec4.ceil = function (out, a) { - out.x = Math.ceil(a.x); - out.y = Math.ceil(a.y); - out.z = Math.ceil(a.z); - out.w = Math.ceil(a.w); - return out; -}; - -/** - * Math.floor the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to floor - * @returns {vec4} out - */ -vec4.floor = function (out, a) { - out.x = Math.floor(a.x); - out.y = Math.floor(a.y); - out.z = Math.floor(a.z); - out.w = Math.floor(a.w); - return out; -}; - -/** - * Returns the minimum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.min = function (out, a, b) { - out.x = Math.min(a.x, b.x); - out.y = Math.min(a.y, b.y); - out.z = Math.min(a.z, b.z); - out.w = Math.min(a.w, b.w); - return out; -}; - -/** - * Returns the maximum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -vec4.max = function (out, a, b) { - out.x = Math.max(a.x, b.x); - out.y = Math.max(a.y, b.y); - out.z = Math.max(a.z, b.z); - out.w = Math.max(a.w, b.w); - return out; -}; - -/** - * Math.round the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to round - * @returns {vec4} out - */ -vec4.round = function (out, a) { - out.x = Math.round(a.x); - out.y = Math.round(a.y); - out.z = Math.round(a.z); - out.w = Math.round(a.w); - return out; -}; - -/** - * Scales a vec4 by a scalar number - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec4} out - */ -vec4.scale = function (out, a, b) { - out.x = a.x * b; - out.y = a.y * b; - out.z = a.z * b; - out.w = a.w * b; - return out; -}; - -/** - * Adds two vec4's after scaling the second operand by a scalar value - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec4} out - */ -vec4.scaleAndAdd = function (out, a, b, scale) { - out.x = a.x + (b.x * scale); - out.y = a.y + (b.y * scale); - out.z = a.z + (b.z * scale); - out.w = a.w + (b.w * scale); - return out; -}; - -/** - * Calculates the euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} distance between a and b - */ -vec4.distance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z, - w = b.w - a.w; - return Math.sqrt(x * x + y * y + z * z + w * w); -}; - -/** - * Alias for {@link vec4.distance} - * @function - */ -vec4.dist = vec4.distance; - -/** - * Calculates the squared euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} squared distance between a and b - */ -vec4.squaredDistance = function (a, b) { - var x = b.x - a.x, - y = b.y - a.y, - z = b.z - a.z, - w = b.w - a.w; - return x * x + y * y + z * z + w * w; -}; - -/** - * Alias for {@link vec4.squaredDistance} - * @function - */ -vec4.sqrDist = vec4.squaredDistance; - -/** - * Calculates the length of a vec4 - * - * @param {vec4} a vector to calculate length of - * @returns {Number} length of a - */ -vec4.length = function (a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - return Math.sqrt(x * x + y * y + z * z + w * w); -}; - -/** - * Alias for {@link vec4.length} - * @function - */ -vec4.len = vec4.length; - -/** - * Calculates the squared length of a vec4 - * - * @param {vec4} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -vec4.squaredLength = function (a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - return x * x + y * y + z * z + w * w; -}; - -/** - * Alias for {@link vec4.squaredLength} - * @function - */ -vec4.sqrLen = vec4.squaredLength; - -/** - * Negates the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to negate - * @returns {vec4} out - */ -vec4.negate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - out.w = -a.w; - return out; -}; - -/** - * Returns the inverse of the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to invert - * @returns {vec4} out - */ -vec4.inverse = function (out, a) { - out.x = 1.0 / a.x; - out.y = 1.0 / a.y; - out.z = 1.0 / a.z; - out.w = 1.0 / a.w; - return out; -}; - -/** - * Returns the inverse of the components of a vec4 safely - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to invert - * @returns {vec4} out - */ -vec4.inverseSafe = function (out, a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - - if (Math.abs(x) < EPSILON) { - out.x = 0; - } else { - out.x = 1.0 / x; - } - - if (Math.abs(y) < EPSILON) { - out.y = 0; - } else { - out.y = 1.0 / y; - } - - if (Math.abs(z) < EPSILON) { - out.z = 0; - } else { - out.z = 1.0 / z; - } - - if (Math.abs(w) < EPSILON) { - out.w = 0; - } else { - out.w = 1.0 / w; - } - - return out; -}; - -/** - * Normalize a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to normalize - * @returns {vec4} out - */ -vec4.normalize = function (out, a) { - var x = a.x, - y = a.y, - z = a.z, - w = a.w; - var len = x * x + y * y + z * z + w * w; - if (len > 0) { - len = 1 / Math.sqrt(len); - out.x = x * len; - out.y = y * len; - out.z = z * len; - out.w = w * len; - } - return out; -}; - -/** - * Calculates the dot product of two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} dot product of a and b - */ -vec4.dot = function (a, b) { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -}; - -/** - * Performs a linear interpolation between two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec4} out - */ -vec4.lerp = function (out, a, b, t) { - var ax = a.x, - ay = a.y, - az = a.z, - aw = a.w; - out.x = ax + t * (b.x - ax); - out.y = ay + t * (b.y - ay); - out.z = az + t * (b.z - az); - out.w = aw + t * (b.w - aw); - return out; -}; - -/** - * Generates a random vector with the given scale - * - * @param {vec4} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec4} out - */ -vec4.random = function (out, scale) { - scale = scale || 1.0; - - //TODO: This is a pretty awful way of doing this. Find something better. - out.x = random(); - out.y = random(); - out.z = random(); - out.w = random(); - vec4.normalize(out, out); - vec4.scale(out, out, scale); - return out; -}; - -/** - * Transforms the vec4 with a mat4. - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec4} out - */ -vec4.transformMat4 = function (out, a, m) { - var x = a.x, y = a.y, z = a.z, w = a.w; - out.x = m.m00 * x + m.m04 * y + m.m08 * z + m.m12 * w; - out.y = m.m01 * x + m.m05 * y + m.m09 * z + m.m13 * w; - out.z = m.m02 * x + m.m06 * y + m.m10 * z + m.m14 * w; - out.w = m.m03 * x + m.m07 * y + m.m11 * z + m.m15 * w; - return out; -}; - -/** - * Transforms the vec4 with a quat - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec4} out - */ -vec4.transformQuat = function (out, a, q) { - var x = a.x, y = a.y, z = a.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vec - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = -qx * x - qy * y - qz * z; - - // calculate result * inverse quat - out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; - out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; - out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; - out.w = a.w; - return out; -}; - -/** - * Perform some operation over an array of vec4s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -vec4.forEach = (function () { - var vec = vec4.create(); - - return function (a, stride, offset, count, fn, arg) { - var i, l; - if (!stride) { - stride = 4; - } - - if (!offset) { - offset = 0; - } - - if (count) { - l = Math.min((count * stride) + offset, a.length); - } else { - l = a.length; - } - - for (i = offset; i < l; i += stride) { - vec.x = a[i]; vec.y = a[i + 1]; vec.z = a[i + 2]; vec.w = a[i + 3]; - fn(vec, vec, arg); - a[i] = vec.x; a[i + 1] = vec.y; a[i + 2] = vec.z; a[i + 3] = vec.w; - } - - return a; - }; -})(); - -/** - * Returns a string representation of a vector - * - * @param {vec4} a vector to represent as a string - * @returns {String} string representation of the vector - */ -vec4.str = function (a) { - return ("vec4(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ", " + (a.w) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {vec4} v - * @returns {array} - */ -vec4.array = function (out, v) { - out[0] = v.x; - out[1] = v.y; - out[2] = v.z; - out[3] = v.w; - - return out; -}; - -/** - * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) - * - * @param {vec4} a The first vector. - * @param {vec4} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec4.exactEquals = function (a, b) { - return a.x === b.x && a.y === b.y && a.z === b.z && a.w === b.w; -}; - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec4} a The first vector. - * @param {vec4} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -vec4.equals = function (a, b) { - var a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; - var b0 = b.x, b1 = b.y, b2 = b.z, b3 = b.w; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); -}; - -var _tmp$3 = new Array(9); - -var _mat3 = function _mat3(m00, m01, m02, m03, m04, m05, m06, m07, m08) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; - this.m06 = m06; - this.m07 = m07; - this.m08 = m08; -}; - -_mat3.prototype.toJSON = function toJSON () { - _tmp$3[0] = this.m00; - _tmp$3[1] = this.m01; - _tmp$3[2] = this.m02; - _tmp$3[3] = this.m03; - _tmp$3[4] = this.m04; - _tmp$3[5] = this.m05; - _tmp$3[6] = this.m06; - _tmp$3[7] = this.m07; - _tmp$3[8] = this.m08; - - return _tmp$3; -}; - -/** - * @class 3x3 Matrix - * @name mat3 - * - * NOTE: we use column-major matrix for all matrix calculation. - * - * This may lead to some confusion when referencing OpenGL documentation, - * however, which represents out all matricies in column-major format. - * This means that while in code a matrix may be typed out as: - * - * [1, 0, 0, 0, - * 0, 1, 0, 0, - * 0, 0, 1, 0, - * x, y, z, 0] - * - * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) - * is written as: - * - * 1 0 0 x - * 0 1 0 y - * 0 0 1 z - * 0 0 0 0 - * - * Please rest assured, however, that they are the same thing! - * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the - * apparent lack of consistency between the memory layout and the documentation. - */ -var mat3 = {}; - -/** - * Creates a new identity mat3 - * - * @returns {mat3} a new 3x3 matrix - */ -mat3.create = function () { - return new _mat3( - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - ); -}; - -/** - * Create a new mat3 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m10 Component in column 1, row 0 position (index 3) - * @param {Number} m11 Component in column 1, row 1 position (index 4) - * @param {Number} m12 Component in column 1, row 2 position (index 5) - * @param {Number} m20 Component in column 2, row 0 position (index 6) - * @param {Number} m21 Component in column 2, row 1 position (index 7) - * @param {Number} m22 Component in column 2, row 2 position (index 8) - * @returns {mat3} A new mat3 - */ -mat3.new = function (m00, m01, m02, m10, m11, m12, m20, m21, m22) { - return new _mat3( - m00, m01, m02, - m10, m11, m12, - m20, m21, m22 - ); -}; - -/** - * Creates a new mat3 initialized with values from an existing matrix - * - * @param {mat3} a matrix to clone - * @returns {mat3} a new 3x3 matrix - */ -mat3.clone = function (a) { - return new _mat3( - a.m00, a.m01, a.m02, - a.m03, a.m04, a.m05, - a.m06, a.m07, a.m08 - ); -}; - -/** - * Copy the values from one mat3 to another - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - return out; -}; - -/** - * Set the components of a mat3 to the given values - * - * @param {mat3} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m10 Component in column 1, row 0 position (index 3) - * @param {Number} m11 Component in column 1, row 1 position (index 4) - * @param {Number} m12 Component in column 1, row 2 position (index 5) - * @param {Number} m20 Component in column 2, row 0 position (index 6) - * @param {Number} m21 Component in column 2, row 1 position (index 7) - * @param {Number} m22 Component in column 2, row 2 position (index 8) - * @returns {mat3} out - */ -mat3.set = function (out, m00, m01, m02, m10, m11, m12, m20, m21, m22) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m02; - out.m03 = m10; - out.m04 = m11; - out.m05 = m12; - out.m06 = m20; - out.m07 = m21; - out.m08 = m22; - return out; -}; - -/** - * Set a mat3 to the identity matrix - * - * @param {mat3} out the receiving matrix - * @returns {mat3} out - */ -mat3.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 1; - out.m05 = 0; - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Transpose the values of a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a01 = a.m01, a02 = a.m02, a12 = a.m05; - out.m01 = a.m03; - out.m02 = a.m06; - out.m03 = a01; - out.m05 = a.m07; - out.m06 = a02; - out.m07 = a12; - } else { - out.m00 = a.m00; - out.m01 = a.m03; - out.m02 = a.m06; - out.m03 = a.m01; - out.m04 = a.m04; - out.m05 = a.m07; - out.m06 = a.m02; - out.m07 = a.m05; - out.m08 = a.m08; - } - - return out; -}; - -/** - * Inverts a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.invert = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var b01 = a22 * a11 - a12 * a21; - var b11 = -a22 * a10 + a12 * a20; - var b21 = a21 * a10 - a11 * a20; - - // Calculate the determinant - var det = a00 * b01 + a01 * b11 + a02 * b21; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = b01 * det; - out.m01 = (-a22 * a01 + a02 * a21) * det; - out.m02 = (a12 * a01 - a02 * a11) * det; - out.m03 = b11 * det; - out.m04 = (a22 * a00 - a02 * a20) * det; - out.m05 = (-a12 * a00 + a02 * a10) * det; - out.m06 = b21 * det; - out.m07 = (-a21 * a00 + a01 * a20) * det; - out.m08 = (a11 * a00 - a01 * a10) * det; - return out; -}; - -/** - * Calculates the adjugate of a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -mat3.adjoint = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - out.m00 = (a11 * a22 - a12 * a21); - out.m01 = (a02 * a21 - a01 * a22); - out.m02 = (a01 * a12 - a02 * a11); - out.m03 = (a12 * a20 - a10 * a22); - out.m04 = (a00 * a22 - a02 * a20); - out.m05 = (a02 * a10 - a00 * a12); - out.m06 = (a10 * a21 - a11 * a20); - out.m07 = (a01 * a20 - a00 * a21); - out.m08 = (a00 * a11 - a01 * a10); - return out; -}; - -/** - * Calculates the determinant of a mat3 - * - * @param {mat3} a the source matrix - * @returns {Number} determinant of a - */ -mat3.determinant = function (a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); -}; - -/** - * Multiplies two mat3's - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.multiply = function (out, a, b) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var b00 = b.m00, b01 = b.m01, b02 = b.m02; - var b10 = b.m03, b11 = b.m04, b12 = b.m05; - var b20 = b.m06, b21 = b.m07, b22 = b.m08; - - out.m00 = b00 * a00 + b01 * a10 + b02 * a20; - out.m01 = b00 * a01 + b01 * a11 + b02 * a21; - out.m02 = b00 * a02 + b01 * a12 + b02 * a22; - - out.m03 = b10 * a00 + b11 * a10 + b12 * a20; - out.m04 = b10 * a01 + b11 * a11 + b12 * a21; - out.m05 = b10 * a02 + b11 * a12 + b12 * a22; - - out.m06 = b20 * a00 + b21 * a10 + b22 * a20; - out.m07 = b20 * a01 + b21 * a11 + b22 * a21; - out.m08 = b20 * a02 + b21 * a12 + b22 * a22; - return out; -}; - -/** - * Alias for {@link mat3.multiply} - * @function - */ -mat3.mul = mat3.multiply; - -/** - * Translate a mat3 by the given vector - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to translate - * @param {vec2} v vector to translate by - * @returns {mat3} out - */ -mat3.translate = function (out, a, v) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - var x = v.x, y = v.y; - - out.m00 = a00; - out.m01 = a01; - out.m02 = a02; - - out.m03 = a10; - out.m04 = a11; - out.m05 = a12; - - out.m06 = x * a00 + y * a10 + a20; - out.m07 = x * a01 + y * a11 + a21; - out.m08 = x * a02 + y * a12 + a22; - return out; -}; - -/** - * Rotates a mat3 by the given angle - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat3} out - */ -mat3.rotate = function (out, a, rad) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, - a10 = a.m03, a11 = a.m04, a12 = a.m05, - a20 = a.m06, a21 = a.m07, a22 = a.m08; - - var s = Math.sin(rad); - var c = Math.cos(rad); - - out.m00 = c * a00 + s * a10; - out.m01 = c * a01 + s * a11; - out.m02 = c * a02 + s * a12; - - out.m03 = c * a10 - s * a00; - out.m04 = c * a11 - s * a01; - out.m05 = c * a12 - s * a02; - - out.m06 = a20; - out.m07 = a21; - out.m08 = a22; - return out; -}; - -/** - * Scales the mat3 by the dimensions in the given vec2 - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to rotate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat3} out - **/ -mat3.scale = function (out, a, v) { - var x = v.x, y = v.y; - - out.m00 = x * a.m00; - out.m01 = x * a.m01; - out.m02 = x * a.m02; - - out.m03 = y * a.m03; - out.m04 = y * a.m04; - out.m05 = y * a.m05; - - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - return out; -}; - -/** - * Copies the upper-left 3x3 values into the given mat3. - * - * @param {mat3} out the receiving 3x3 matrix - * @param {mat4} a the source 4x4 matrix - * @returns {mat3} out - */ -mat3.fromMat4 = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m04; - out.m04 = a.m05; - out.m05 = a.m06; - out.m06 = a.m08; - out.m07 = a.m09; - out.m08 = a.m10; - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.translate(dest, dest, vec); - * - * @param {mat3} out mat3 receiving operation result - * @param {vec2} v Translation vector - * @returns {mat3} out - */ -mat3.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 1; - out.m05 = 0; - out.m06 = v.x; - out.m07 = v.y; - out.m08 = 1; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.rotate(dest, dest, rad); - * - * @param {mat3} out mat3 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat3} out - */ -mat3.fromRotation = function (out, rad) { - var s = Math.sin(rad), c = Math.cos(rad); - - out.m00 = c; - out.m01 = s; - out.m02 = 0; - - out.m03 = -s; - out.m04 = c; - out.m05 = 0; - - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat3.identity(dest); - * mat3.scale(dest, dest, vec); - * - * @param {mat3} out mat3 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat3} out - */ -mat3.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - - out.m03 = 0; - out.m04 = v.y; - out.m05 = 0; - - out.m06 = 0; - out.m07 = 0; - out.m08 = 1; - return out; -}; - -/** - * Copies the values from a mat2d into a mat3 - * - * @param {mat3} out the receiving matrix - * @param {mat2d} a the matrix to copy - * @returns {mat3} out - **/ -mat3.fromMat2d = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = 0; - - out.m03 = a.m02; - out.m04 = a.m03; - out.m05 = 0; - - out.m06 = a.m04; - out.m07 = a.m05; - out.m08 = 1; - return out; -}; - -/** -* Calculates a 3x3 matrix from the given quaternion -* -* @param {mat3} out mat3 receiving operation result -* @param {quat} q Quaternion to create matrix from -* -* @returns {mat3} out -*/ -mat3.fromQuat = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var yx = y * x2; - var yy = y * y2; - var zx = z * x2; - var zy = z * y2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - yy - zz; - out.m03 = yx - wz; - out.m06 = zx + wy; - - out.m01 = yx + wz; - out.m04 = 1 - xx - zz; - out.m07 = zy - wx; - - out.m02 = zx - wy; - out.m05 = zy + wx; - out.m08 = 1 - xx - yy; - - return out; -}; - -/** -* Calculates a 3x3 matrix from view direction and up direction -* -* @param {mat3} out mat3 receiving operation result -* @param {vec3} view view direction (must be normalized) -* @param {vec3} [up] up direction, default is (0,1,0) (must be normalized) -* -* @returns {mat3} out -*/ -mat3.fromViewUp = (function () { - var default_up = vec3.new(0, 1, 0); - var x = vec3.create(); - var y = vec3.create(); - - return function (out, view, up) { - if (vec3.sqrLen(view) < EPSILON * EPSILON) { - mat3.identity(out); - return out; - } - - up = up || default_up; - vec3.cross(x, up, view); - - if (vec3.sqrLen(x) < EPSILON * EPSILON) { - mat3.identity(out); - return out; - } - - vec3.cross(y, view, x); - mat3.set(out, - x.x, x.y, x.z, - y.x, y.y, y.z, - view.x, view.y, view.z - ); - - return out; - }; -})(); - -/** -* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix -* -* @param {mat3} out mat3 receiving operation result -* @param {mat4} a Mat4 to derive the normal matrix from -* -* @returns {mat3} out -*/ -mat3.normalFromMat4 = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out.m01 = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out.m02 = (a10 * b10 - a11 * b08 + a13 * b06) * det; - - out.m03 = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out.m04 = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out.m05 = (a01 * b08 - a00 * b10 - a03 * b06) * det; - - out.m06 = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out.m07 = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out.m08 = (a30 * b04 - a31 * b02 + a33 * b00) * det; - - return out; -}; - -/** - * Returns a string representation of a mat3 - * - * @param {mat3} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat3.str = function (a) { - return ("mat3(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ", " + (a.m06) + ", " + (a.m07) + ", " + (a.m08) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat3} m - * @returns {array} - */ -mat3.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - out[6] = m.m06; - out[7] = m.m07; - out[8] = m.m08; - - return out; -}; - -/** - * Returns Frobenius norm of a mat3 - * - * @param {mat3} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat3.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2))); -}; - -/** - * Adds two mat3's - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - out.m06 = a.m06 + b.m06; - out.m07 = a.m07 + b.m07; - out.m08 = a.m08 + b.m08; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @returns {mat3} out - */ -mat3.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - out.m06 = a.m06 - b.m06; - out.m07 = a.m07 - b.m07; - out.m08 = a.m08 - b.m08; - return out; -}; - -/** - * Alias for {@link mat3.subtract} - * @function - */ -mat3.sub = mat3.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat3} out the receiving matrix - * @param {mat3} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat3} out - */ -mat3.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - out.m06 = a.m06 * b; - out.m07 = a.m07 * b; - out.m08 = a.m08 * b; - return out; -}; - -/** - * Adds two mat3's after multiplying each element of the second operand by a scalar value. - * - * @param {mat3} out the receiving vector - * @param {mat3} a the first operand - * @param {mat3} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat3} out - */ -mat3.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - out.m06 = a.m06 + (b.m06 * scale); - out.m07 = a.m07 + (b.m07 * scale); - out.m08 = a.m08 + (b.m08 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat3} a The first matrix. - * @param {mat3} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat3.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && - a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05 && - a.m06 === b.m06 && a.m07 === b.m07 && a.m08 === b.m08; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat3} a The first matrix. - * @param {mat3} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat3.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, a8 = a.m08; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, b8 = b.m08; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && - Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && - Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && - Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) - ); -}; - -var _tmp$4 = new Array(4); - -var _quat = function _quat(x, y, z, w) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; -}; - -_quat.prototype.toJSON = function toJSON () { - _tmp$4[0] = this.x; - _tmp$4[1] = this.y; - _tmp$4[2] = this.z; - _tmp$4[3] = this.w; - - return _tmp$4; -}; - -/** - * @class Quaternion - * @name quat - */ -var quat = {}; - -/** - * Creates a new identity quat - * - * @returns {quat} a new quaternion - */ -quat.create = function () { - return new _quat(0, 0, 0, 1); -}; - -/** - * Creates a new quat initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {quat} a new quaternion - * @function - */ -quat.new = function (x, y, z, w) { - return new _quat(x, y, z, w); -}; - -/** - * Creates a new quat initialized with values from an existing quaternion - * - * @param {quat} a quaternion to clone - * @returns {quat} a new quaternion - * @function - */ -quat.clone = function (a) { - return new _quat(a.x, a.y, a.z, a.w); -}; - -/** - * Copy the values from one quat to another - * - * @param {quat} out the receiving quaternion - * @param {quat} a the source quaternion - * @returns {quat} out - * @function - */ -quat.copy = vec4.copy; - -/** - * Set the components of a quat to the given values - * - * @param {quat} out the receiving quaternion - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {quat} out - * @function - */ -quat.set = vec4.set; - -/** - * Set a quat to the identity quaternion - * - * @param {quat} out the receiving quaternion - * @returns {quat} out - */ -quat.identity = function (out) { - out.x = 0; - out.y = 0; - out.z = 0; - out.w = 1; - return out; -}; - -/** - * Sets a quaternion to represent the shortest rotation from one - * vector to another. - * - * Both vectors are assumed to be unit length. - * - * @param {quat} out the receiving quaternion. - * @param {vec3} a the initial vector - * @param {vec3} b the destination vector - * @returns {quat} out - */ -quat.rotationTo = (function () { - var tmpvec3 = vec3.create(); - var xUnitVec3 = vec3.new(1, 0, 0); - var yUnitVec3 = vec3.new(0, 1, 0); - - return function (out, a, b) { - var dot = vec3.dot(a, b); - if (dot < -0.999999) { - vec3.cross(tmpvec3, xUnitVec3, a); - if (vec3.length(tmpvec3) < 0.000001) { - vec3.cross(tmpvec3, yUnitVec3, a); - } - vec3.normalize(tmpvec3, tmpvec3); - quat.fromAxisAngle(out, tmpvec3, Math.PI); - return out; - } else if (dot > 0.999999) { - out.x = 0; - out.y = 0; - out.z = 0; - out.w = 1; - return out; - } else { - vec3.cross(tmpvec3, a, b); - out.x = tmpvec3.x; - out.y = tmpvec3.y; - out.z = tmpvec3.z; - out.w = 1 + dot; - return quat.normalize(out, out); - } - }; -})(); - -/** - * Gets the rotation axis and angle for a given - * quaternion. If a quaternion is created with - * fromAxisAngle, this method will return the same - * values as providied in the original parameter list - * OR functionally equivalent values. - * Example: The quaternion formed by axis [0, 0, 1] and - * angle -90 is the same as the quaternion formed by - * [0, 0, 1] and 270. This method favors the latter. - * @param {vec3} out_axis Vector receiving the axis of rotation - * @param {quat} q Quaternion to be decomposed - * @return {Number} Angle, in radians, of the rotation - */ -quat.getAxisAngle = function (out_axis, q) { - var rad = Math.acos(q.w) * 2.0; - var s = Math.sin(rad / 2.0); - if (s != 0.0) { - out_axis.x = q.x / s; - out_axis.y = q.y / s; - out_axis.z = q.z / s; - } else { - // If s is zero, return any axis (no rotation - axis does not matter) - out_axis.x = 1; - out_axis.y = 0; - out_axis.z = 0; - } - return rad; -}; - -/** - * Multiplies two quat's - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @returns {quat} out - */ -quat.multiply = function (out, a, b) { - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = b.x, by = b.y, bz = b.z, bw = b.w; - - out.x = ax * bw + aw * bx + ay * bz - az * by; - out.y = ay * bw + aw * by + az * bx - ax * bz; - out.z = az * bw + aw * bz + ax * by - ay * bx; - out.w = aw * bw - ax * bx - ay * by - az * bz; - return out; -}; - -/** - * Alias for {@link quat.multiply} - * @function - */ -quat.mul = quat.multiply; - -/** - * Scales a quat by a scalar number - * - * @param {quat} out the receiving vector - * @param {quat} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {quat} out - * @function - */ -quat.scale = vec4.scale; - -/** - * Rotates a quaternion by the given angle about the X axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateX = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw + aw * bx; - out.y = ay * bw + az * bx; - out.z = az * bw - ay * bx; - out.w = aw * bw - ax * bx; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the Y axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateY = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - by = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw - az * by; - out.y = ay * bw + aw * by; - out.z = az * bw + ax * by; - out.w = aw * bw - ay * by; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the Z axis - * - * @param {quat} out quat receiving operation result - * @param {quat} a quat to rotate - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateZ = function (out, a, rad) { - rad *= 0.5; - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bz = Math.sin(rad), bw = Math.cos(rad); - - out.x = ax * bw + ay * bz; - out.y = ay * bw - ax * bz; - out.z = az * bw + aw * bz; - out.w = aw * bw - az * bz; - return out; -}; - -/** - * Rotates a quaternion by the given angle about the axis in world space - * - * @param {quat} out quat receiving operation result - * @param {quat} rot quat to rotate - * @param {vec3} axis the axis around which to rotate in world space - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateAround = (function () { - var v3_tmp = vec3.create(); - var q_tmp = quat.create(); - - return function (out, rot, axis, rad) { - // get inv-axis (local to rot) - quat.invert(q_tmp, rot); - vec3.transformQuat(v3_tmp, axis, q_tmp); - // rotate by inv-axis - quat.fromAxisAngle(q_tmp, v3_tmp, rad); - quat.mul(out, rot, q_tmp); - - return out; - }; -})(); - -/** - * Rotates a quaternion by the given angle about the axis in local space - * - * @param {quat} out quat receiving operation result - * @param {quat} rot quat to rotate - * @param {vec3} axis the axis around which to rotate in local space - * @param {number} rad angle (in radians) to rotate - * @returns {quat} out - */ -quat.rotateAroundLocal = (function () { - var q_tmp = quat.create(); - - return function (out, rot, axis, rad) { - quat.fromAxisAngle(q_tmp, axis, rad); - quat.mul(out, rot, q_tmp); - - return out; - }; -})(); - -/** - * Calculates the W component of a quat from the X, Y, and Z components. - * Assumes that quaternion is 1 unit in length. - * Any existing W component will be ignored. - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate W component of - * @returns {quat} out - */ -quat.calculateW = function (out, a) { - var x = a.x, y = a.y, z = a.z; - - out.x = x; - out.y = y; - out.z = z; - out.w = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z)); - return out; -}; - -/** - * Calculates the dot product of two quat's - * - * @param {quat} a the first operand - * @param {quat} b the second operand - * @returns {Number} dot product of a and b - * @function - */ -quat.dot = vec4.dot; - -/** - * Performs a linear interpolation between two quat's - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {quat} out - * @function - */ -quat.lerp = vec4.lerp; - -/** - * Performs a spherical linear interpolation between two quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {quat} out - */ -quat.slerp = function (out, a, b, t) { - // benchmarks: - // http://jsperf.com/quaternion-slerp-implementations - - var ax = a.x, ay = a.y, az = a.z, aw = a.w, - bx = b.x, by = b.y, bz = b.z, bw = b.w; - - var omega, cosom, sinom, scale0, scale1; - - // calc cosine - cosom = ax * bx + ay * by + az * bz + aw * bw; - // adjust signs (if necessary) - if (cosom < 0.0) { - cosom = -cosom; - bx = - bx; - by = - by; - bz = - bz; - bw = - bw; - } - // calculate coefficients - if ((1.0 - cosom) > 0.000001) { - // standard case (slerp) - omega = Math.acos(cosom); - sinom = Math.sin(omega); - scale0 = Math.sin((1.0 - t) * omega) / sinom; - scale1 = Math.sin(t * omega) / sinom; - } else { - // "from" and "to" quaternions are very close - // ... so we can do a linear interpolation - scale0 = 1.0 - t; - scale1 = t; - } - // calculate final values - out.x = scale0 * ax + scale1 * bx; - out.y = scale0 * ay + scale1 * by; - out.z = scale0 * az + scale1 * bz; - out.w = scale0 * aw + scale1 * bw; - - return out; -}; - -/** - * Performs a spherical linear interpolation with two control points - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {quat} c the third operand - * @param {quat} d the fourth operand - * @param {Number} t interpolation amount - * @returns {quat} out - */ -quat.sqlerp = (function () { - var temp1 = quat.create(); - var temp2 = quat.create(); - - return function (out, a, b, c, d, t) { - quat.slerp(temp1, a, d, t); - quat.slerp(temp2, b, c, t); - quat.slerp(out, temp1, temp2, 2 * t * (1 - t)); - - return out; - }; -}()); - -/** - * Calculates the inverse of a quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate inverse of - * @returns {quat} out - */ -quat.invert = function (out, a) { - var a0 = a.x, a1 = a.y, a2 = a.z, a3 = a.w; - var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3; - var invDot = dot ? 1.0 / dot : 0; - - // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0 - - out.x = -a0 * invDot; - out.y = -a1 * invDot; - out.z = -a2 * invDot; - out.w = a3 * invDot; - return out; -}; - -/** - * Calculates the conjugate of a quat - * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result. - * - * @param {quat} out the receiving quaternion - * @param {quat} a quat to calculate conjugate of - * @returns {quat} out - */ -quat.conjugate = function (out, a) { - out.x = -a.x; - out.y = -a.y; - out.z = -a.z; - out.w = a.w; - return out; -}; - -/** - * Calculates the length of a quat - * - * @param {quat} a vector to calculate length of - * @returns {Number} length of a - * @function - */ -quat.length = vec4.length; - -/** - * Alias for {@link quat.length} - * @function - */ -quat.len = quat.length; - -/** - * Calculates the squared length of a quat - * - * @param {quat} a vector to calculate squared length of - * @returns {Number} squared length of a - * @function - */ -quat.squaredLength = vec4.squaredLength; - -/** - * Alias for {@link quat.squaredLength} - * @function - */ -quat.sqrLen = quat.squaredLength; - -/** - * Normalize a quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a quaternion to normalize - * @returns {quat} out - * @function - */ -quat.normalize = vec4.normalize; - -/** - * Sets the specified quaternion with values corresponding to the given - * axes. Each axis is a vec3 and is expected to be unit length and - * perpendicular to all other specified axes. - * - * @param {vec3} xAxis the vector representing the local "right" direction - * @param {vec3} yAxis the vector representing the local "up" direction - * @param {vec3} zAxis the vector representing the viewing direction - * @returns {quat} out - */ -quat.fromAxes = (function () { - var matr = mat3.create(); - - return function (out, xAxis, yAxis, zAxis) { - mat3.set( - matr, - xAxis.x, xAxis.y, xAxis.z, - yAxis.x, yAxis.y, yAxis.z, - zAxis.x, zAxis.y, zAxis.z - ); - return quat.normalize(out, quat.fromMat3(out, matr)); - }; -})(); - -/** -* Calculates a quaternion from view direction and up direction -* -* @param {quat} out mat3 receiving operation result -* @param {vec3} view view direction (must be normalized) -* @param {vec3} [up] up direction, default is (0,1,0) (must be normalized) -* -* @returns {quat} out -*/ -quat.fromViewUp = (function () { - var matr = mat3.create(); - - return function (out, view, up) { - mat3.fromViewUp(matr, view, up); - if (!matr) { - return null; - } - - return quat.normalize(out, quat.fromMat3(out, matr)); - }; -})(); - -/** - * Sets a quat from the given angle and rotation axis, - * then returns it. - * - * @param {quat} out the receiving quaternion - * @param {vec3} axis the axis around which to rotate - * @param {Number} rad the angle in radians - * @returns {quat} out - **/ -quat.fromAxisAngle = function (out, axis, rad) { - rad = rad * 0.5; - var s = Math.sin(rad); - out.x = s * axis.x; - out.y = s * axis.y; - out.z = s * axis.z; - out.w = Math.cos(rad); - return out; -}; - -/** - * Creates a quaternion from the given 3x3 rotation matrix. - * - * NOTE: The resultant quaternion is not normalized, so you should be sure - * to renormalize the quaternion yourself where necessary. - * - * @param {quat} out the receiving quaternion - * @param {mat3} m rotation matrix - * @returns {quat} out - * @function - */ -quat.fromMat3 = function (out, m) { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - - var m00 = m.m00, m01 = m.m03, m02 = m.m06, - m10 = m.m01, m11 = m.m04, m12 = m.m07, - m20 = m.m02, m21 = m.m05, m22 = m.m08; - - var trace = m00 + m11 + m22; - - if (trace > 0) { - var s = 0.5 / Math.sqrt(trace + 1.0); - - out.w = 0.25 / s; - out.x = (m21 - m12) * s; - out.y = (m02 - m20) * s; - out.z = (m10 - m01) * s; - - } else if ((m00 > m11) && (m00 > m22)) { - var s$1 = 2.0 * Math.sqrt(1.0 + m00 - m11 - m22); - - out.w = (m21 - m12) / s$1; - out.x = 0.25 * s$1; - out.y = (m01 + m10) / s$1; - out.z = (m02 + m20) / s$1; - - } else if (m11 > m22) { - var s$2 = 2.0 * Math.sqrt(1.0 + m11 - m00 - m22); - - out.w = (m02 - m20) / s$2; - out.x = (m01 + m10) / s$2; - out.y = 0.25 * s$2; - out.z = (m12 + m21) / s$2; - - } else { - var s$3 = 2.0 * Math.sqrt(1.0 + m22 - m00 - m11); - - out.w = (m10 - m01) / s$3; - out.x = (m02 + m20) / s$3; - out.y = (m12 + m21) / s$3; - out.z = 0.25 * s$3; - } - - return out; -}; - -/** - * Creates a quaternion from the given euler angle x, y, z. - * - * @param {quat} out the receiving quaternion - * @param {x} Angle to rotate around X axis in degrees. - * @param {y} Angle to rotate around Y axis in degrees. - * @param {z} Angle to rotate around Z axis in degrees. - * @returns {quat} out - * @function - */ -quat.fromEuler = function (out, x, y, z) { - var halfToRad = 0.5 * Math.PI / 180.0; - x *= halfToRad; - y *= halfToRad; - z *= halfToRad; - - var sx = Math.sin(x); - var cx = Math.cos(x); - var sy = Math.sin(y); - var cy = Math.cos(y); - var sz = Math.sin(z); - var cz = Math.cos(z); - - out.x = sx * cy * cz - cx * sy * sz; - out.y = cx * sy * cz + sx * cy * sz; - out.z = cx * cy * sz - sx * sy * cz; - out.w = cx * cy * cz + sx * sy * sz; - - return out; -}; - -/** - * Returns a string representation of a quatenion - * - * @param {quat} a vector to represent as a string - * @returns {String} string representation of the vector - */ -quat.str = function (a) { - return ("quat(" + (a.x) + ", " + (a.y) + ", " + (a.z) + ", " + (a.w) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {quat} q - * @returns {array} - */ -quat.array = function (out, q) { - out[0] = q.x; - out[1] = q.y; - out[2] = q.z; - out[3] = q.w; - - return out; -}; - -/** - * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===) - * - * @param {quat} a The first quaternion. - * @param {quat} b The second quaternion. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -quat.exactEquals = vec4.exactEquals; - -/** - * Returns whether or not the quaternions have approximately the same elements in the same position. - * - * @param {quat} a The first vector. - * @param {quat} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -quat.equals = vec4.equals; - -var _tmp$5 = new Array(4); - -var _mat2 = function _mat2(m00, m01, m02, m03) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; -}; - -_mat2.prototype.toJSON = function toJSON () { - _tmp$5[0] = this.m00; - _tmp$5[1] = this.m01; - _tmp$5[2] = this.m02; - _tmp$5[3] = this.m03; - - return _tmp$5; -}; - -/** - * @class 2x2 Matrix - * @name mat2 - */ -var mat2 = {}; - -/** - * Creates a new identity mat2 - * - * @returns {mat2} a new 2x2 matrix - */ -mat2.create = function() { - return new _mat2(1, 0, 0, 1); -}; - -/** - * Create a new mat2 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m10 Component in column 1, row 0 position (index 2) - * @param {Number} m11 Component in column 1, row 1 position (index 3) - * @returns {mat2} out A new 2x2 matrix - */ -mat2.new = function (m00, m01, m10, m11) { - return new _mat2(m00, m01, m10, m11); -}; - -/** - * Creates a new mat2 initialized with values from an existing matrix - * - * @param {mat2} a matrix to clone - * @returns {mat2} a new 2x2 matrix - */ -mat2.clone = function (a) { - return new _mat2(a.m00, a.m01, a.m02, a.m03); -}; - -/** - * Copy the values from one mat2 to another - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - return out; -}; - -/** - * Set a mat2 to the identity matrix - * - * @param {mat2} out the receiving matrix - * @returns {mat2} out - */ -mat2.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - return out; -}; - -/** - * Set the components of a mat2 to the given values - * - * @param {mat2} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m10 Component in column 1, row 0 position (index 2) - * @param {Number} m11 Component in column 1, row 1 position (index 3) - * @returns {mat2} out - */ -mat2.set = function (out, m00, m01, m10, m11) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m10; - out.m03 = m11; - return out; -}; - - -/** - * Transpose the values of a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a1 = a.m01; - out.m01 = a.m02; - out.m02 = a1; - } else { - out.m00 = a.m00; - out.m01 = a.m02; - out.m02 = a.m01; - out.m03 = a.m03; - } - - return out; -}; - -/** - * Inverts a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.invert = function (out, a) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - - // Calculate the determinant - var det = a0 * a3 - a2 * a1; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = a3 * det; - out.m01 = -a1 * det; - out.m02 = -a2 * det; - out.m03 = a0 * det; - - return out; -}; - -/** - * Calculates the adjugate of a mat2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -mat2.adjoint = function (out, a) { - // Caching this value is nessecary if out == a - var a0 = a.m00; - out.m00 = a.m03; - out.m01 = -a.m01; - out.m02 = -a.m02; - out.m03 = a0; - - return out; -}; - -/** - * Calculates the determinant of a mat2 - * - * @param {mat2} a the source matrix - * @returns {Number} determinant of a - */ -mat2.determinant = function (a) { - return a.m00 * a.m03 - a.m02 * a.m01; -}; - -/** - * Multiplies two mat2's - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.multiply = function (out, a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - out.m00 = a0 * b0 + a2 * b1; - out.m01 = a1 * b0 + a3 * b1; - out.m02 = a0 * b2 + a2 * b3; - out.m03 = a1 * b2 + a3 * b3; - return out; -}; - -/** - * Alias for {@link mat2.multiply} - * @function - */ -mat2.mul = mat2.multiply; - -/** - * Rotates a mat2 by the given angle - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat2} out - */ -mat2.rotate = function (out, a, rad) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = a0 * c + a2 * s; - out.m01 = a1 * c + a3 * s; - out.m02 = a0 * -s + a2 * c; - out.m03 = a1 * -s + a3 * c; - return out; -}; - -/** - * Scales the mat2 by the dimensions in the given vec2 - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to rotate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat2} out - **/ -mat2.scale = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - v0 = v.x, v1 = v.y; - out.m00 = a0 * v0; - out.m01 = a1 * v0; - out.m02 = a2 * v1; - out.m03 = a3 * v1; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat2.identity(dest); - * mat2.rotate(dest, dest, rad); - * - * @param {mat2} out mat2 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat2} out - */ -mat2.fromRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = c; - out.m01 = s; - out.m02 = -s; - out.m03 = c; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat2.identity(dest); - * mat2.scale(dest, dest, vec); - * - * @param {mat2} out mat2 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat2} out - */ -mat2.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - out.m03 = v.y; - return out; -}; - -/** - * Returns a string representation of a mat2 - * - * @param {mat2} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat2.str = function (a) { - return ("mat2(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat2} m - * @returns {array} - */ -mat2.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - - return out; -}; - -/** - * Returns Frobenius norm of a mat2 - * - * @param {mat2} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat2.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2))); -}; - -/** - * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix - * @param {mat2} L the lower triangular matrix - * @param {mat2} D the diagonal matrix - * @param {mat2} U the upper triangular matrix - * @param {mat2} a the input matrix to factorize - */ - -mat2.LDU = function (L, D, U, a) { - L.m02 = a.m02 / a.m00; - U.m00 = a.m00; - U.m01 = a.m01; - U.m03 = a.m03 - L.m02 * U.m01; -}; - -/** - * Adds two mat2's - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @returns {mat2} out - */ -mat2.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - return out; -}; - -/** - * Alias for {@link mat2.subtract} - * @function - */ -mat2.sub = mat2.subtract; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat2} a The first matrix. - * @param {mat2} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat2.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat2} a The first matrix. - * @param {mat2} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat2.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) - ); -}; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat2} out the receiving matrix - * @param {mat2} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat2} out - */ -mat2.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - return out; -}; - -/** - * Adds two mat2's after multiplying each element of the second operand by a scalar value. - * - * @param {mat2} out the receiving vector - * @param {mat2} a the first operand - * @param {mat2} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat2} out - */ -mat2.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - return out; -}; - -var _tmp$6 = new Array(6); - -var _mat23 = function _mat23(m00, m01, m02, m03, m04, m05) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; -}; - -_mat23.prototype.toJSON = function toJSON () { - _tmp$6[0] = this.m00; - _tmp$6[1] = this.m01; - _tmp$6[2] = this.m02; - _tmp$6[3] = this.m03; - _tmp$6[4] = this.m04; - _tmp$6[5] = this.m05; - - return _tmp$6; -}; - -/** - * @class 2x3 Matrix - * @name mat23 - * - * @description - * A mat23 contains six elements defined as: - *
- * [a, c, tx,
- *  b, d, ty]
- * 
- * This is a short form for the 3x3 matrix: - *
- * [a, c, tx,
- *  b, d, ty,
- *  0, 0, 1]
- * 
- * The last row is ignored so the array is shorter and operations are faster. - */ -var mat23 = {}; - -/** - * Creates a new identity mat23 - * - * @returns {mat23} a new 2x3 matrix - */ -mat23.create = function () { - return new _mat23( - 1, 0, - 0, 1, - 0, 0 - ); -}; - -/** - * Create a new mat23 with the given values - * - * @param {Number} a Component A (index 0) - * @param {Number} b Component B (index 1) - * @param {Number} c Component C (index 2) - * @param {Number} d Component D (index 3) - * @param {Number} tx Component TX (index 4) - * @param {Number} ty Component TY (index 5) - * @returns {mat23} A new mat23 - */ -mat23.new = function (a, b, c, d, tx, ty) { - return new _mat23( - a, b, - c, d, - tx, ty - ); -}; - -/** - * Creates a new mat23 initialized with values from an existing matrix - * - * @param {mat23} a matrix to clone - * @returns {mat23} a new 2x3 matrix - */ -mat23.clone = function (a) { - return new _mat23( - a.m00, a.m01, - a.m02, a.m03, - a.m04, a.m05 - ); -}; - -/** - * Copy the values from one mat23 to another - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the source matrix - * @returns {mat23} out - */ -mat23.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - return out; -}; - -/** - * Set a mat23 to the identity matrix - * - * @param {mat23} out the receiving matrix - * @returns {mat23} out - */ -mat23.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Set the components of a mat23 to the given values - * - * @param {mat23} out the receiving matrix - * @param {Number} a Component A (index 0) - * @param {Number} b Component B (index 1) - * @param {Number} c Component C (index 2) - * @param {Number} d Component D (index 3) - * @param {Number} tx Component TX (index 4) - * @param {Number} ty Component TY (index 5) - * @returns {mat23} out - */ -mat23.set = function (out, a, b, c, d, tx, ty) { - out.m00 = a; - out.m01 = b; - out.m02 = c; - out.m03 = d; - out.m04 = tx; - out.m05 = ty; - return out; -}; - -/** - * Inverts a mat23 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the source matrix - * @returns {mat23} out - */ -mat23.invert = function (out, a) { - var aa = a.m00, ab = a.m01, ac = a.m02, ad = a.m03, - atx = a.m04, aty = a.m05; - - var det = aa * ad - ab * ac; - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = ad * det; - out.m01 = -ab * det; - out.m02 = -ac * det; - out.m03 = aa * det; - out.m04 = (ac * aty - ad * atx) * det; - out.m05 = (ab * atx - aa * aty) * det; - return out; -}; - -/** - * Calculates the determinant of a mat23 - * - * @param {mat23} a the source matrix - * @returns {Number} determinant of a - */ -mat23.determinant = function (a) { - return a.m00 * a.m03 - a.m01 * a.m02; -}; - -/** - * Multiplies two mat23's - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.multiply = function (out, a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; - out.m00 = a0 * b0 + a2 * b1; - out.m01 = a1 * b0 + a3 * b1; - out.m02 = a0 * b2 + a2 * b3; - out.m03 = a1 * b2 + a3 * b3; - out.m04 = a0 * b4 + a2 * b5 + a4; - out.m05 = a1 * b4 + a3 * b5 + a5; - return out; -}; - -/** - * Alias for {@link mat23.multiply} - * @function - */ -mat23.mul = mat23.multiply; - -/** - * Rotates a mat23 by the given angle - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat23} out - */ -mat23.rotate = function (out, a, rad) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - s = Math.sin(rad), - c = Math.cos(rad); - out.m00 = a0 * c + a2 * s; - out.m01 = a1 * c + a3 * s; - out.m02 = a0 * -s + a2 * c; - out.m03 = a1 * -s + a3 * c; - out.m04 = a4; - out.m05 = a5; - return out; -}; - -/** - * Scales the mat23 by the dimensions in the given vec2 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to translate - * @param {vec2} v the vec2 to scale the matrix by - * @returns {mat23} out - **/ -mat23.scale = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - v0 = v.x, v1 = v.y; - out.m00 = a0 * v0; - out.m01 = a1 * v0; - out.m02 = a2 * v1; - out.m03 = a3 * v1; - out.m04 = a4; - out.m05 = a5; - return out; -}; - -/** - * Translates the mat23 by the dimensions in the given vec2 - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to translate - * @param {vec2} v the vec2 to translate the matrix by - * @returns {mat23} out - **/ -mat23.translate = function (out, a, v) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05, - v0 = v.x, v1 = v.y; - out.m00 = a0; - out.m01 = a1; - out.m02 = a2; - out.m03 = a3; - out.m04 = a0 * v0 + a2 * v1 + a4; - out.m05 = a1 * v0 + a3 * v1 + a5; - return out; -}; - -/** - * Creates a matrix from a given angle - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.rotate(dest, dest, rad); - * - * @param {mat23} out mat23 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat23} out - */ -mat23.fromRotation = function (out, rad) { - var s = Math.sin(rad), c = Math.cos(rad); - out.m00 = c; - out.m01 = s; - out.m02 = -s; - out.m03 = c; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.scale(dest, dest, vec); - * - * @param {mat23} out mat23 receiving operation result - * @param {vec2} v Scaling vector - * @returns {mat23} out - */ -mat23.fromScaling = function (out, v) { - out.m00 = v.m00; - out.m01 = 0; - out.m02 = 0; - out.m03 = v.m01; - out.m04 = 0; - out.m05 = 0; - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat23.identity(dest); - * mat23.translate(dest, dest, vec); - * - * @param {mat23} out mat23 receiving operation result - * @param {vec2} v Translation vector - * @returns {mat23} out - */ -mat23.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 1; - out.m04 = v.x; - out.m05 = v.y; - return out; -}; - -/** - * Returns a string representation of a mat23 - * - * @param {mat23} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat23.str = function (a) { - return ("mat23(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat23} m - * @returns {array} - */ -mat23.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - - return out; -}; - -/** - * Returns typed array to 16 float array - * - * @param {array} out - * @param {mat23} m - * @returns {array} - */ -mat23.array4x4 = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = 0; - out[3] = 0; - out[4] = m.m02; - out[5] = m.m03; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 1; - out[11] = 0; - out[12] = m.m04; - out[13] = m.m05; - out[14] = 0; - out[15] = 1; - - return out; -}; - -/** - * Returns Frobenius norm of a mat23 - * - * @param {mat23} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat23.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + 1)); -}; - -/** - * Adds two mat23's - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @returns {mat23} out - */ -mat23.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - return out; -}; - -/** - * Alias for {@link mat23.subtract} - * @function - */ -mat23.sub = mat23.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat23} out the receiving matrix - * @param {mat23} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat23} out - */ -mat23.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - return out; -}; - -/** - * Adds two mat23's after multiplying each element of the second operand by a scalar value. - * - * @param {mat23} out the receiving vector - * @param {mat23} a the first operand - * @param {mat23} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat23} out - */ -mat23.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat23} a The first matrix. - * @param {mat23} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat23.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && a.m04 === b.m04 && a.m05 === b.m05; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat23} a The first matrix. - * @param {mat23} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat23.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, a4 = a.m04, a5 = a.m05; - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, b4 = b.m04, b5 = b.m05; - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) - ); -}; - -var _tmp$7 = new Array(16); - -var _mat4 = function _mat4( - m00, m01, m02, m03, - m04, m05, m06, m07, - m08, m09, m10, m11, - m12, m13, m14, m15 -) { - this.m00 = m00; - this.m01 = m01; - this.m02 = m02; - this.m03 = m03; - this.m04 = m04; - this.m05 = m05; - this.m06 = m06; - this.m07 = m07; - this.m08 = m08; - this.m09 = m09; - this.m10 = m10; - this.m11 = m11; - this.m12 = m12; - this.m13 = m13; - this.m14 = m14; - this.m15 = m15; -}; - -_mat4.prototype.toJSON = function toJSON () { - _tmp$7[0] = this.m00; - _tmp$7[1] = this.m01; - _tmp$7[2] = this.m02; - _tmp$7[3] = this.m03; - _tmp$7[4] = this.m04; - _tmp$7[5] = this.m05; - _tmp$7[6] = this.m06; - _tmp$7[7] = this.m07; - _tmp$7[8] = this.m08; - _tmp$7[9] = this.m09; - _tmp$7[10] = this.m10; - _tmp$7[11] = this.m11; - _tmp$7[12] = this.m12; - _tmp$7[13] = this.m13; - _tmp$7[14] = this.m14; - _tmp$7[15] = this.m15; - - return _tmp$7; -}; - -/** - * @class 4x4 Matrix - * @name mat4 - * - * NOTE: we use column-major matrix for all matrix calculation. - * - * This may lead to some confusion when referencing OpenGL documentation, - * however, which represents out all matricies in column-major format. - * This means that while in code a matrix may be typed out as: - * - * [1, 0, 0, 0, - * 0, 1, 0, 0, - * 0, 0, 1, 0, - * x, y, z, 0] - * - * The same matrix in the [OpenGL documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml) - * is written as: - * - * 1 0 0 x - * 0 1 0 y - * 0 0 1 z - * 0 0 0 0 - * - * Please rest assured, however, that they are the same thing! - * This is not unique to glMatrix, either, as OpenGL developers have long been confused by the - * apparent lack of consistency between the memory layout and the documentation. - */ -var mat4 = {}; - -/** - * Creates a new identity mat4 - * - * @returns {mat4} a new 4x4 matrix - */ -mat4.create = function () { - return new _mat4( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ); -}; - -/** - * Create a new mat4 with the given values - * - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m03 Component in column 0, row 3 position (index 3) - * @param {Number} m10 Component in column 1, row 0 position (index 4) - * @param {Number} m11 Component in column 1, row 1 position (index 5) - * @param {Number} m12 Component in column 1, row 2 position (index 6) - * @param {Number} m13 Component in column 1, row 3 position (index 7) - * @param {Number} m20 Component in column 2, row 0 position (index 8) - * @param {Number} m21 Component in column 2, row 1 position (index 9) - * @param {Number} m22 Component in column 2, row 2 position (index 10) - * @param {Number} m23 Component in column 2, row 3 position (index 11) - * @param {Number} m30 Component in column 3, row 0 position (index 12) - * @param {Number} m31 Component in column 3, row 1 position (index 13) - * @param {Number} m32 Component in column 3, row 2 position (index 14) - * @param {Number} m33 Component in column 3, row 3 position (index 15) - * @returns {mat4} A new mat4 - */ -mat4.new = function (m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { - return new _mat4( - m00, m01, m02, m03, - m10, m11, m12, m13, - m20, m21, m22, m23, - m30, m31, m32, m33 - ); -}; - -/** - * Creates a new mat4 initialized with values from an existing matrix - * - * @param {mat4} a matrix to clone - * @returns {mat4} a new 4x4 matrix - */ -mat4.clone = function (a) { - return new _mat4( - a.m00, a.m01, a.m02, a.m03, - a.m04, a.m05, a.m06, a.m07, - a.m08, a.m09, a.m10, a.m11, - a.m12, a.m13, a.m14, a.m15 - ); -}; - -/** - * Copy the values from one mat4 to another - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.copy = function (out, a) { - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m08 = a.m08; - out.m09 = a.m09; - out.m10 = a.m10; - out.m11 = a.m11; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - return out; -}; - -/** - * Set the components of a mat4 to the given values - * - * @param {mat4} out the receiving matrix - * @param {Number} m00 Component in column 0, row 0 position (index 0) - * @param {Number} m01 Component in column 0, row 1 position (index 1) - * @param {Number} m02 Component in column 0, row 2 position (index 2) - * @param {Number} m03 Component in column 0, row 3 position (index 3) - * @param {Number} m10 Component in column 1, row 0 position (index 4) - * @param {Number} m11 Component in column 1, row 1 position (index 5) - * @param {Number} m12 Component in column 1, row 2 position (index 6) - * @param {Number} m13 Component in column 1, row 3 position (index 7) - * @param {Number} m20 Component in column 2, row 0 position (index 8) - * @param {Number} m21 Component in column 2, row 1 position (index 9) - * @param {Number} m22 Component in column 2, row 2 position (index 10) - * @param {Number} m23 Component in column 2, row 3 position (index 11) - * @param {Number} m30 Component in column 3, row 0 position (index 12) - * @param {Number} m31 Component in column 3, row 1 position (index 13) - * @param {Number} m32 Component in column 3, row 2 position (index 14) - * @param {Number} m33 Component in column 3, row 3 position (index 15) - * @returns {mat4} out - */ -mat4.set = function (out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { - out.m00 = m00; - out.m01 = m01; - out.m02 = m02; - out.m03 = m03; - out.m04 = m10; - out.m05 = m11; - out.m06 = m12; - out.m07 = m13; - out.m08 = m20; - out.m09 = m21; - out.m10 = m22; - out.m11 = m23; - out.m12 = m30; - out.m13 = m31; - out.m14 = m32; - out.m15 = m33; - return out; -}; - - -/** - * Set a mat4 to the identity matrix - * - * @param {mat4} out the receiving matrix - * @returns {mat4} out - */ -mat4.identity = function (out) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Transpose the values of a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.transpose = function (out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a01 = a.m01, a02 = a.m02, a03 = a.m03, - a12 = a.m06, a13 = a.m07, - a23 = a.m11; - - out.m01 = a.m04; - out.m02 = a.m08; - out.m03 = a.m12; - out.m04 = a01; - out.m06 = a.m09; - out.m07 = a.m13; - out.m08 = a02; - out.m09 = a12; - out.m11 = a.m14; - out.m12 = a03; - out.m13 = a13; - out.m14 = a23; - } else { - out.m00 = a.m00; - out.m01 = a.m04; - out.m02 = a.m08; - out.m03 = a.m12; - out.m04 = a.m01; - out.m05 = a.m05; - out.m06 = a.m09; - out.m07 = a.m13; - out.m08 = a.m02; - out.m09 = a.m06; - out.m10 = a.m10; - out.m11 = a.m14; - out.m12 = a.m03; - out.m13 = a.m07; - out.m14 = a.m11; - out.m15 = a.m15; - } - - return out; -}; - -/** - * Inverts a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.invert = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out.m00 = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out.m01 = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out.m02 = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out.m03 = (a22 * b04 - a21 * b05 - a23 * b03) * det; - out.m04 = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out.m05 = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out.m06 = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out.m07 = (a20 * b05 - a22 * b02 + a23 * b01) * det; - out.m08 = (a10 * b10 - a11 * b08 + a13 * b06) * det; - out.m09 = (a01 * b08 - a00 * b10 - a03 * b06) * det; - out.m10 = (a30 * b04 - a31 * b02 + a33 * b00) * det; - out.m11 = (a21 * b02 - a20 * b04 - a23 * b00) * det; - out.m12 = (a11 * b07 - a10 * b09 - a12 * b06) * det; - out.m13 = (a00 * b09 - a01 * b07 + a02 * b06) * det; - out.m14 = (a31 * b01 - a30 * b03 - a32 * b00) * det; - out.m15 = (a20 * b03 - a21 * b01 + a22 * b00) * det; - - return out; -}; - -/** - * Calculates the adjugate of a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -mat4.adjoint = function (out, a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - out.m00 = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)); - out.m01 = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)); - out.m02 = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)); - out.m03 = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)); - out.m04 = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)); - out.m05 = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)); - out.m06 = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)); - out.m07 = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)); - out.m08 = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)); - out.m09 = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)); - out.m10 = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)); - out.m11 = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)); - out.m12 = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)); - out.m13 = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)); - out.m14 = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)); - out.m15 = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)); - return out; -}; - -/** - * Calculates the determinant of a mat4 - * - * @param {mat4} a the source matrix - * @returns {Number} determinant of a - */ -mat4.determinant = function (a) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - var b00 = a00 * a11 - a01 * a10; - var b01 = a00 * a12 - a02 * a10; - var b02 = a00 * a13 - a03 * a10; - var b03 = a01 * a12 - a02 * a11; - var b04 = a01 * a13 - a03 * a11; - var b05 = a02 * a13 - a03 * a12; - var b06 = a20 * a31 - a21 * a30; - var b07 = a20 * a32 - a22 * a30; - var b08 = a20 * a33 - a23 * a30; - var b09 = a21 * a32 - a22 * a31; - var b10 = a21 * a33 - a23 * a31; - var b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; -}; - -/** - * Multiplies two mat4's explicitly - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.multiply = function (out, a, b) { - var a00 = a.m00, a01 = a.m01, a02 = a.m02, a03 = a.m03, - a10 = a.m04, a11 = a.m05, a12 = a.m06, a13 = a.m07, - a20 = a.m08, a21 = a.m09, a22 = a.m10, a23 = a.m11, - a30 = a.m12, a31 = a.m13, a32 = a.m14, a33 = a.m15; - - // Cache only the current line of the second matrix - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03; - out.m00 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m01 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m02 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m03 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m04; b1 = b.m05; b2 = b.m06; b3 = b.m07; - out.m04 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m05 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m06 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m07 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m08; b1 = b.m09; b2 = b.m10; b3 = b.m11; - out.m08 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m09 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m10 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m11 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - - b0 = b.m12; b1 = b.m13; b2 = b.m14; b3 = b.m15; - out.m12 = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; - out.m13 = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; - out.m14 = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; - out.m15 = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; - return out; -}; - -/** - * Alias for {@link mat4.multiply} - * @function - */ -mat4.mul = mat4.multiply; - -/** - * Translate a mat4 by the given vector - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to translate - * @param {vec3} v vector to translate by - * @returns {mat4} out - */ -mat4.translate = function (out, a, v) { - var x = v.x, y = v.y, z = v.z, - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23; - - if (a === out) { - out.m12 = a.m00 * x + a.m04 * y + a.m08 * z + a.m12; - out.m13 = a.m01 * x + a.m05 * y + a.m09 * z + a.m13; - out.m14 = a.m02 * x + a.m06 * y + a.m10 * z + a.m14; - out.m15 = a.m03 * x + a.m07 * y + a.m11 * z + a.m15; - } else { - a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; - a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; - a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; - - out.m00 = a00; out.m01 = a01; out.m02 = a02; out.m03 = a03; - out.m04 = a10; out.m05 = a11; out.m06 = a12; out.m07 = a13; - out.m08 = a20; out.m09 = a21; out.m10 = a22; out.m11 = a23; - - out.m12 = a00 * x + a10 * y + a20 * z + a.m12; - out.m13 = a01 * x + a11 * y + a21 * z + a.m13; - out.m14 = a02 * x + a12 * y + a22 * z + a.m14; - out.m15 = a03 * x + a13 * y + a23 * z + a.m15; - } - - return out; -}; - -/** - * Scales the mat4 by the dimensions in the given vec3 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to scale - * @param {vec3} v the vec3 to scale the matrix by - * @returns {mat4} out - **/ -mat4.scale = function (out, a, v) { - var x = v.x, y = v.y, z = v.z; - - out.m00 = a.m00 * x; - out.m01 = a.m01 * x; - out.m02 = a.m02 * x; - out.m03 = a.m03 * x; - out.m04 = a.m04 * y; - out.m05 = a.m05 * y; - out.m06 = a.m06 * y; - out.m07 = a.m07 * y; - out.m08 = a.m08 * z; - out.m09 = a.m09 * z; - out.m10 = a.m10 * z; - out.m11 = a.m11 * z; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - return out; -}; - -/** - * Rotates a mat4 by the given angle around the given axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @param {vec3} axis the axis to rotate around - * @returns {mat4} out - */ -mat4.rotate = function (out, a, rad, axis) { - var x = axis.x, y = axis.y, z = axis.z; - var s, c, t, - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23, - b00, b01, b02, - b10, b11, b12, - b20, b21, b22; - - var len = Math.sqrt(x * x + y * y + z * z); - - if (Math.abs(len) < EPSILON) { - return null; - } - - len = 1 / len; - x *= len; - y *= len; - z *= len; - - s = Math.sin(rad); - c = Math.cos(rad); - t = 1 - c; - - a00 = a.m00; a01 = a.m01; a02 = a.m02; a03 = a.m03; - a10 = a.m04; a11 = a.m05; a12 = a.m06; a13 = a.m07; - a20 = a.m08; a21 = a.m09; a22 = a.m10; a23 = a.m11; - - // Construct the elements of the rotation matrix - b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; - b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; - b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; - - // Perform rotation-specific matrix multiplication - out.m00 = a00 * b00 + a10 * b01 + a20 * b02; - out.m01 = a01 * b00 + a11 * b01 + a21 * b02; - out.m02 = a02 * b00 + a12 * b01 + a22 * b02; - out.m03 = a03 * b00 + a13 * b01 + a23 * b02; - out.m04 = a00 * b10 + a10 * b11 + a20 * b12; - out.m05 = a01 * b10 + a11 * b11 + a21 * b12; - out.m06 = a02 * b10 + a12 * b11 + a22 * b12; - out.m07 = a03 * b10 + a13 * b11 + a23 * b12; - out.m08 = a00 * b20 + a10 * b21 + a20 * b22; - out.m09 = a01 * b20 + a11 * b21 + a21 * b22; - out.m10 = a02 * b20 + a12 * b21 + a22 * b22; - out.m11 = a03 * b20 + a13 * b21 + a23 * b22; - - // If the source and destination differ, copy the unchanged last row - if (a !== out) { - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - return out; -}; - -/** - * Rotates a matrix by the given angle around the X axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateX = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a10 = a.m04, - a11 = a.m05, - a12 = a.m06, - a13 = a.m07, - a20 = a.m08, - a21 = a.m09, - a22 = a.m10, - a23 = a.m11; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out.m00 = a.m00; - out.m01 = a.m01; - out.m02 = a.m02; - out.m03 = a.m03; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m04 = a10 * c + a20 * s; - out.m05 = a11 * c + a21 * s; - out.m06 = a12 * c + a22 * s; - out.m07 = a13 * c + a23 * s; - out.m08 = a20 * c - a10 * s; - out.m09 = a21 * c - a11 * s; - out.m10 = a22 * c - a12 * s; - out.m11 = a23 * c - a13 * s; - - return out; -}; - -/** - * Rotates a matrix by the given angle around the Y axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateY = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a.m00, - a01 = a.m01, - a02 = a.m02, - a03 = a.m03, - a20 = a.m08, - a21 = a.m09, - a22 = a.m10, - a23 = a.m11; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out.m04 = a.m04; - out.m05 = a.m05; - out.m06 = a.m06; - out.m07 = a.m07; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m00 = a00 * c - a20 * s; - out.m01 = a01 * c - a21 * s; - out.m02 = a02 * c - a22 * s; - out.m03 = a03 * c - a23 * s; - out.m08 = a00 * s + a20 * c; - out.m09 = a01 * s + a21 * c; - out.m10 = a02 * s + a22 * c; - out.m11 = a03 * s + a23 * c; - - return out; -}; - -/** - * Rotates a matrix by the given angle around the Z axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.rotateZ = function (out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a.m00, - a01 = a.m01, - a02 = a.m02, - a03 = a.m03, - a10 = a.m04, - a11 = a.m05, - a12 = a.m06, - a13 = a.m07; - - // If the source and destination differ, copy the unchanged last row - if (a !== out) { - out.m08 = a.m08; - out.m09 = a.m09; - out.m10 = a.m10; - out.m11 = a.m11; - out.m12 = a.m12; - out.m13 = a.m13; - out.m14 = a.m14; - out.m15 = a.m15; - } - - // Perform axis-specific matrix multiplication - out.m00 = a00 * c + a10 * s; - out.m01 = a01 * c + a11 * s; - out.m02 = a02 * c + a12 * s; - out.m03 = a03 * c + a13 * s; - out.m04 = a10 * c - a00 * s; - out.m05 = a11 * c - a01 * s; - out.m06 = a12 * c - a02 * s; - out.m07 = a13 * c - a03 * s; - - return out; -}; - -/** - * Creates a matrix from a vector translation - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, dest, vec); - * - * @param {mat4} out mat4 receiving operation result - * @param {vec3} v Translation vector - * @returns {mat4} out - */ -mat4.fromTranslation = function (out, v) { - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a vector scaling - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.scale(dest, dest, vec); - * - * @param {mat4} out mat4 receiving operation result - * @param {vec3} v Scaling vector - * @returns {mat4} out - */ -mat4.fromScaling = function (out, v) { - out.m00 = v.x; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = v.y; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = v.z; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a given angle around a given axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotate(dest, dest, rad, axis); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @param {vec3} axis the axis to rotate around - * @returns {mat4} out - */ -mat4.fromRotation = function (out, rad, axis) { - var x = axis.x, y = axis.y, z = axis.z; - var len = Math.sqrt(x * x + y * y + z * z); - var s, c, t; - - if (Math.abs(len) < EPSILON) { - return null; - } - - len = 1 / len; - x *= len; - y *= len; - z *= len; - - s = Math.sin(rad); - c = Math.cos(rad); - t = 1 - c; - - // Perform rotation-specific matrix multiplication - out.m00 = x * x * t + c; - out.m01 = y * x * t + z * s; - out.m02 = z * x * t - y * s; - out.m03 = 0; - out.m04 = x * y * t - z * s; - out.m05 = y * y * t + c; - out.m06 = z * y * t + x * s; - out.m07 = 0; - out.m08 = x * z * t + y * s; - out.m09 = y * z * t - x * s; - out.m10 = z * z * t + c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the X axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateX(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromXRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = 1; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = c; - out.m06 = s; - out.m07 = 0; - out.m08 = 0; - out.m09 = -s; - out.m10 = c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the Y axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateY(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromYRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = c; - out.m01 = 0; - out.m02 = -s; - out.m03 = 0; - out.m04 = 0; - out.m05 = 1; - out.m06 = 0; - out.m07 = 0; - out.m08 = s; - out.m09 = 0; - out.m10 = c; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from the given angle around the Z axis - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.rotateZ(dest, dest, rad); - * - * @param {mat4} out mat4 receiving operation result - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -mat4.fromZRotation = function (out, rad) { - var s = Math.sin(rad), - c = Math.cos(rad); - - // Perform axis-specific matrix multiplication - out.m00 = c; - out.m01 = s; - out.m02 = 0; - out.m03 = 0; - out.m04 = -s; - out.m05 = c; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 1; - out.m11 = 0; - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - return out; -}; - -/** - * Creates a matrix from a quaternion rotation and vector translation - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @returns {mat4} out - */ -mat4.fromRT = function (out, q, v) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - (yy + zz); - out.m01 = xy + wz; - out.m02 = xz - wy; - out.m03 = 0; - out.m04 = xy - wz; - out.m05 = 1 - (xx + zz); - out.m06 = yz + wx; - out.m07 = 0; - out.m08 = xz + wy; - out.m09 = yz - wx; - out.m10 = 1 - (xx + yy); - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - - return out; -}; - -/** - * Returns the translation vector component of a transformation - * matrix. If a matrix is built with fromRT, - * the returned vector will be the same as the translation vector - * originally supplied. - * @param {vec3} out Vector to receive translation component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {vec3} out - */ -mat4.getTranslation = function (out, mat) { - out.x = mat.m12; - out.y = mat.m13; - out.z = mat.m14; - - return out; -}; - -/** - * Returns the scaling factor component of a transformation - * matrix. If a matrix is built with fromRTS - * with a normalized Quaternion paramter, the returned vector will be - * the same as the scaling vector - * originally supplied. - * @param {vec3} out Vector to receive scaling factor component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {vec3} out - */ -mat4.getScaling = function (out, mat) { - var m11 = mat.m00, - m12 = mat.m01, - m13 = mat.m02, - m21 = mat.m04, - m22 = mat.m05, - m23 = mat.m06, - m31 = mat.m08, - m32 = mat.m09, - m33 = mat.m10; - - out.x = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13); - out.y = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23); - out.z = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33); - - return out; -}; - -/** - * Returns a quaternion representing the rotational component - * of a transformation matrix. If a matrix is built with - * fromRT, the returned quaternion will be the - * same as the quaternion originally supplied. - * @param {quat} out Quaternion to receive the rotation component - * @param {mat4} mat Matrix to be decomposed (input) - * @return {quat} out - */ -mat4.getRotation = function (out, mat) { - // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - var trace = mat.m00 + mat.m05 + mat.m10; - var S = 0; - - if (trace > 0) { - S = Math.sqrt(trace + 1.0) * 2; - out.w = 0.25 * S; - out.x = (mat.m06 - mat.m09) / S; - out.y = (mat.m08 - mat.m02) / S; - out.z = (mat.m01 - mat.m04) / S; - } else if ((mat.m00 > mat.m05) & (mat.m00 > mat.m10)) { - S = Math.sqrt(1.0 + mat.m00 - mat.m05 - mat.m10) * 2; - out.w = (mat.m06 - mat.m09) / S; - out.x = 0.25 * S; - out.y = (mat.m01 + mat.m04) / S; - out.z = (mat.m08 + mat.m02) / S; - } else if (mat.m05 > mat.m10) { - S = Math.sqrt(1.0 + mat.m05 - mat.m00 - mat.m10) * 2; - out.w = (mat.m08 - mat.m02) / S; - out.x = (mat.m01 + mat.m04) / S; - out.y = 0.25 * S; - out.z = (mat.m06 + mat.m09) / S; - } else { - S = Math.sqrt(1.0 + mat.m10 - mat.m00 - mat.m05) * 2; - out.w = (mat.m01 - mat.m04) / S; - out.x = (mat.m08 + mat.m02) / S; - out.y = (mat.m06 + mat.m09) / S; - out.z = 0.25 * S; - } - - return out; -}; - -/** - * Creates a matrix from a quaternion rotation, vector translation and vector scale - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * mat4.scale(dest, scale) - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @param {vec3} s Scaling vector - * @returns {mat4} out - */ -mat4.fromRTS = function (out, q, v, s) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - var sx = s.x; - var sy = s.y; - var sz = s.z; - - out.m00 = (1 - (yy + zz)) * sx; - out.m01 = (xy + wz) * sx; - out.m02 = (xz - wy) * sx; - out.m03 = 0; - out.m04 = (xy - wz) * sy; - out.m05 = (1 - (xx + zz)) * sy; - out.m06 = (yz + wx) * sy; - out.m07 = 0; - out.m08 = (xz + wy) * sz; - out.m09 = (yz - wx) * sz; - out.m10 = (1 - (xx + yy)) * sz; - out.m11 = 0; - out.m12 = v.x; - out.m13 = v.y; - out.m14 = v.z; - out.m15 = 1; - - return out; -}; - -/** - * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * mat4.translate(dest, origin); - * let quatMat = mat4.create(); - * quat.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * mat4.scale(dest, scale) - * mat4.translate(dest, negativeOrigin); - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Rotation quaternion - * @param {vec3} v Translation vector - * @param {vec3} s Scaling vector - * @param {vec3} o The origin vector around which to scale and rotate - * @returns {mat4} out - */ -mat4.fromRTSOrigin = function (out, q, v, s, o) { - // Quaternion math - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var xy = x * y2; - var xz = x * z2; - var yy = y * y2; - var yz = y * z2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - var sx = s.x; - var sy = s.y; - var sz = s.z; - - var ox = o.x; - var oy = o.y; - var oz = o.z; - - out.m00 = (1 - (yy + zz)) * sx; - out.m01 = (xy + wz) * sx; - out.m02 = (xz - wy) * sx; - out.m03 = 0; - out.m04 = (xy - wz) * sy; - out.m05 = (1 - (xx + zz)) * sy; - out.m06 = (yz + wx) * sy; - out.m07 = 0; - out.m08 = (xz + wy) * sz; - out.m09 = (yz - wx) * sz; - out.m10 = (1 - (xx + yy)) * sz; - out.m11 = 0; - out.m12 = v.x + ox - (out.m00 * ox + out.m04 * oy + out.m08 * oz); - out.m13 = v.y + oy - (out.m01 * ox + out.m05 * oy + out.m09 * oz); - out.m14 = v.z + oz - (out.m02 * ox + out.m06 * oy + out.m10 * oz); - out.m15 = 1; - - return out; -}; - -/** - * Calculates a 4x4 matrix from the given quaternion - * - * @param {mat4} out mat4 receiving operation result - * @param {quat} q Quaternion to create matrix from - * - * @returns {mat4} out - */ -mat4.fromQuat = function (out, q) { - var x = q.x, y = q.y, z = q.z, w = q.w; - var x2 = x + x; - var y2 = y + y; - var z2 = z + z; - - var xx = x * x2; - var yx = y * x2; - var yy = y * y2; - var zx = z * x2; - var zy = z * y2; - var zz = z * z2; - var wx = w * x2; - var wy = w * y2; - var wz = w * z2; - - out.m00 = 1 - yy - zz; - out.m01 = yx + wz; - out.m02 = zx - wy; - out.m03 = 0; - - out.m04 = yx - wz; - out.m05 = 1 - xx - zz; - out.m06 = zy + wx; - out.m07 = 0; - - out.m08 = zx + wy; - out.m09 = zy - wx; - out.m10 = 1 - xx - yy; - out.m11 = 0; - - out.m12 = 0; - out.m13 = 0; - out.m14 = 0; - out.m15 = 1; - - return out; -}; - -/** - * Generates a frustum matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {Number} left Left bound of the frustum - * @param {Number} right Right bound of the frustum - * @param {Number} bottom Bottom bound of the frustum - * @param {Number} top Top bound of the frustum - * @param {Number} near Near bound of the frustum - * @param {Number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.frustum = function (out, left, right, bottom, top, near, far) { - var rl = 1 / (right - left); - var tb = 1 / (top - bottom); - var nf = 1 / (near - far); - - out.m00 = (near * 2) * rl; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = (near * 2) * tb; - out.m06 = 0; - out.m07 = 0; - out.m08 = (right + left) * rl; - out.m09 = (top + bottom) * tb; - out.m10 = (far + near) * nf; - out.m11 = -1; - out.m12 = 0; - out.m13 = 0; - out.m14 = (far * near * 2) * nf; - out.m15 = 0; - return out; -}; - -/** - * Generates a perspective projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} fovy Vertical field of view in radians - * @param {number} aspect Aspect ratio. typically viewport width/height - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.perspective = function (out, fovy, aspect, near, far) { - var f = 1.0 / Math.tan(fovy / 2); - var nf = 1 / (near - far); - - out.m00 = f / aspect; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = f; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = (far + near) * nf; - out.m11 = -1; - out.m12 = 0; - out.m13 = 0; - out.m14 = (2 * far * near) * nf; - out.m15 = 0; - return out; -}; - -/** - * Generates a perspective projection matrix with the given field of view. - * This is primarily useful for generating projection matrices to be used - * with the still experiemental WebVR API. - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.perspectiveFromFieldOfView = function (out, fov, near, far) { - var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0); - var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0); - var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0); - var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0); - var xScale = 2.0 / (leftTan + rightTan); - var yScale = 2.0 / (upTan + downTan); - - out.m00 = xScale; - out.m01 = 0.0; - out.m02 = 0.0; - out.m03 = 0.0; - out.m04 = 0.0; - out.m05 = yScale; - out.m06 = 0.0; - out.m07 = 0.0; - out.m08 = -((leftTan - rightTan) * xScale * 0.5); - out.m09 = ((upTan - downTan) * yScale * 0.5); - out.m10 = far / (near - far); - out.m11 = -1.0; - out.m12 = 0.0; - out.m13 = 0.0; - out.m14 = (far * near) / (near - far); - out.m15 = 0.0; - return out; -}; - -/** - * Generates a orthogonal projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} left Left bound of the frustum - * @param {number} right Right bound of the frustum - * @param {number} bottom Bottom bound of the frustum - * @param {number} top Top bound of the frustum - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -mat4.ortho = function (out, left, right, bottom, top, near, far) { - var lr = 1 / (left - right); - var bt = 1 / (bottom - top); - var nf = 1 / (near - far); - out.m00 = -2 * lr; - out.m01 = 0; - out.m02 = 0; - out.m03 = 0; - out.m04 = 0; - out.m05 = -2 * bt; - out.m06 = 0; - out.m07 = 0; - out.m08 = 0; - out.m09 = 0; - out.m10 = 2 * nf; - out.m11 = 0; - out.m12 = (left + right) * lr; - out.m13 = (top + bottom) * bt; - out.m14 = (far + near) * nf; - out.m15 = 1; - return out; -}; - -/** - * Generates a look-at matrix with the given eye position, focal point, and up axis - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {vec3} eye Position of the viewer - * @param {vec3} center Point the viewer is looking at - * @param {vec3} up vec3 pointing up - * @returns {mat4} out - */ -mat4.lookAt = function (out, eye, center, up) { - var x0, x1, x2, y0, y1, y2, z0, z1, z2, len; - var eyex = eye.x; - var eyey = eye.y; - var eyez = eye.z; - var upx = up.x; - var upy = up.y; - var upz = up.z; - var centerx = center.x; - var centery = center.y; - var centerz = center.z; - - if ( - Math.abs(eyex - centerx) < EPSILON && - Math.abs(eyey - centery) < EPSILON && - Math.abs(eyez - centerz) < EPSILON - ) { - return mat4.identity(out); - } - - z0 = eyex - centerx; - z1 = eyey - centery; - z2 = eyez - centerz; - - len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); - z0 *= len; - z1 *= len; - z2 *= len; - - x0 = upy * z2 - upz * z1; - x1 = upz * z0 - upx * z2; - x2 = upx * z1 - upy * z0; - len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); - if (!len) { - x0 = 0; - x1 = 0; - x2 = 0; - } else { - len = 1 / len; - x0 *= len; - x1 *= len; - x2 *= len; - } - - y0 = z1 * x2 - z2 * x1; - y1 = z2 * x0 - z0 * x2; - y2 = z0 * x1 - z1 * x0; - - len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); - if (!len) { - y0 = 0; - y1 = 0; - y2 = 0; - } else { - len = 1 / len; - y0 *= len; - y1 *= len; - y2 *= len; - } - - out.m00 = x0; - out.m01 = y0; - out.m02 = z0; - out.m03 = 0; - out.m04 = x1; - out.m05 = y1; - out.m06 = z1; - out.m07 = 0; - out.m08 = x2; - out.m09 = y2; - out.m10 = z2; - out.m11 = 0; - out.m12 = -(x0 * eyex + x1 * eyey + x2 * eyez); - out.m13 = -(y0 * eyex + y1 * eyey + y2 * eyez); - out.m14 = -(z0 * eyex + z1 * eyey + z2 * eyez); - out.m15 = 1; - - return out; -}; - -/** - * Returns a string representation of a mat4 - * - * @param {mat4} a matrix to represent as a string - * @returns {String} string representation of the matrix - */ -mat4.str = function (a) { - return ("mat4(" + (a.m00) + ", " + (a.m01) + ", " + (a.m02) + ", " + (a.m03) + ", " + (a.m04) + ", " + (a.m05) + ", " + (a.m06) + ", " + (a.m07) + ", " + (a.m08) + ", " + (a.m09) + ", " + (a.m10) + ", " + (a.m11) + ", " + (a.m12) + ", " + (a.m13) + ", " + (a.m14) + ", " + (a.m15) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {mat4} m - * @returns {array} - */ -mat4.array = function (out, m) { - out[0] = m.m00; - out[1] = m.m01; - out[2] = m.m02; - out[3] = m.m03; - out[4] = m.m04; - out[5] = m.m05; - out[6] = m.m06; - out[7] = m.m07; - out[8] = m.m08; - out[9] = m.m09; - out[10] = m.m10; - out[11] = m.m11; - out[12] = m.m12; - out[13] = m.m13; - out[14] = m.m14; - out[15] = m.m15; - - return out; -}; - -/** - * Returns Frobenius norm of a mat4 - * - * @param {mat4} a the matrix to calculate Frobenius norm of - * @returns {Number} Frobenius norm - */ -mat4.frob = function (a) { - return (Math.sqrt(Math.pow(a.m00, 2) + Math.pow(a.m01, 2) + Math.pow(a.m02, 2) + Math.pow(a.m03, 2) + Math.pow(a.m04, 2) + Math.pow(a.m05, 2) + Math.pow(a.m06, 2) + Math.pow(a.m07, 2) + Math.pow(a.m08, 2) + Math.pow(a.m09, 2) + Math.pow(a.m10, 2) + Math.pow(a.m11, 2) + Math.pow(a.m12, 2) + Math.pow(a.m13, 2) + Math.pow(a.m14, 2) + Math.pow(a.m15, 2))) -}; - -/** - * Adds two mat4's - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.add = function (out, a, b) { - out.m00 = a.m00 + b.m00; - out.m01 = a.m01 + b.m01; - out.m02 = a.m02 + b.m02; - out.m03 = a.m03 + b.m03; - out.m04 = a.m04 + b.m04; - out.m05 = a.m05 + b.m05; - out.m06 = a.m06 + b.m06; - out.m07 = a.m07 + b.m07; - out.m08 = a.m08 + b.m08; - out.m09 = a.m09 + b.m09; - out.m10 = a.m10 + b.m10; - out.m11 = a.m11 + b.m11; - out.m12 = a.m12 + b.m12; - out.m13 = a.m13 + b.m13; - out.m14 = a.m14 + b.m14; - out.m15 = a.m15 + b.m15; - return out; -}; - -/** - * Subtracts matrix b from matrix a - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -mat4.subtract = function (out, a, b) { - out.m00 = a.m00 - b.m00; - out.m01 = a.m01 - b.m01; - out.m02 = a.m02 - b.m02; - out.m03 = a.m03 - b.m03; - out.m04 = a.m04 - b.m04; - out.m05 = a.m05 - b.m05; - out.m06 = a.m06 - b.m06; - out.m07 = a.m07 - b.m07; - out.m08 = a.m08 - b.m08; - out.m09 = a.m09 - b.m09; - out.m10 = a.m10 - b.m10; - out.m11 = a.m11 - b.m11; - out.m12 = a.m12 - b.m12; - out.m13 = a.m13 - b.m13; - out.m14 = a.m14 - b.m14; - out.m15 = a.m15 - b.m15; - return out; -}; - -/** - * Alias for {@link mat4.subtract} - * @function - */ -mat4.sub = mat4.subtract; - -/** - * Multiply each element of the matrix by a scalar. - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to scale - * @param {Number} b amount to scale the matrix's elements by - * @returns {mat4} out - */ -mat4.multiplyScalar = function (out, a, b) { - out.m00 = a.m00 * b; - out.m01 = a.m01 * b; - out.m02 = a.m02 * b; - out.m03 = a.m03 * b; - out.m04 = a.m04 * b; - out.m05 = a.m05 * b; - out.m06 = a.m06 * b; - out.m07 = a.m07 * b; - out.m08 = a.m08 * b; - out.m09 = a.m09 * b; - out.m10 = a.m10 * b; - out.m11 = a.m11 * b; - out.m12 = a.m12 * b; - out.m13 = a.m13 * b; - out.m14 = a.m14 * b; - out.m15 = a.m15 * b; - return out; -}; - -/** - * Adds two mat4's after multiplying each element of the second operand by a scalar value. - * - * @param {mat4} out the receiving vector - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @param {Number} scale the amount to scale b's elements by before adding - * @returns {mat4} out - */ -mat4.multiplyScalarAndAdd = function (out, a, b, scale) { - out.m00 = a.m00 + (b.m00 * scale); - out.m01 = a.m01 + (b.m01 * scale); - out.m02 = a.m02 + (b.m02 * scale); - out.m03 = a.m03 + (b.m03 * scale); - out.m04 = a.m04 + (b.m04 * scale); - out.m05 = a.m05 + (b.m05 * scale); - out.m06 = a.m06 + (b.m06 * scale); - out.m07 = a.m07 + (b.m07 * scale); - out.m08 = a.m08 + (b.m08 * scale); - out.m09 = a.m09 + (b.m09 * scale); - out.m10 = a.m10 + (b.m10 * scale); - out.m11 = a.m11 + (b.m11 * scale); - out.m12 = a.m12 + (b.m12 * scale); - out.m13 = a.m13 + (b.m13 * scale); - out.m14 = a.m14 + (b.m14 * scale); - out.m15 = a.m15 + (b.m15 * scale); - return out; -}; - -/** - * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) - * - * @param {mat4} a The first matrix. - * @param {mat4} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat4.exactEquals = function (a, b) { - return a.m00 === b.m00 && a.m01 === b.m01 && a.m02 === b.m02 && a.m03 === b.m03 && - a.m04 === b.m04 && a.m05 === b.m05 && a.m06 === b.m06 && a.m07 === b.m07 && - a.m08 === b.m08 && a.m09 === b.m09 && a.m10 === b.m10 && a.m11 === b.m11 && - a.m12 === b.m12 && a.m13 === b.m13 && a.m14 === b.m14 && a.m15 === b.m15; -}; - -/** - * Returns whether or not the matrices have approximately the same elements in the same position. - * - * @param {mat4} a The first matrix. - * @param {mat4} b The second matrix. - * @returns {Boolean} True if the matrices are equal, false otherwise. - */ -mat4.equals = function (a, b) { - var a0 = a.m00, a1 = a.m01, a2 = a.m02, a3 = a.m03, - a4 = a.m04, a5 = a.m05, a6 = a.m06, a7 = a.m07, - a8 = a.m08, a9 = a.m09, a10 = a.m10, a11 = a.m11, - a12 = a.m12, a13 = a.m13, a14 = a.m14, a15 = a.m15; - - var b0 = b.m00, b1 = b.m01, b2 = b.m02, b3 = b.m03, - b4 = b.m04, b5 = b.m05, b6 = b.m06, b7 = b.m07, - b8 = b.m08, b9 = b.m09, b10 = b.m10, b11 = b.m11, - b12 = b.m12, b13 = b.m13, b14 = b.m14, b15 = b.m15; - - return ( - Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && - Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && - Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && - Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && - Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && - Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && - Math.abs(a9 - b9) <= EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && - Math.abs(a10 - b10) <= EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && - Math.abs(a11 - b11) <= EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && - Math.abs(a12 - b12) <= EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && - Math.abs(a13 - b13) <= EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && - Math.abs(a14 - b14) <= EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && - Math.abs(a15 - b15) <= EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15)) - ); -}; - -var _tmp$8 = new Array(3); - -var _color3 = function _color3(r, g, b) { - this.r = r; - this.g = g; - this.b = b; -}; - -_color3.prototype.toJSON = function toJSON () { - _tmp$8[0] = this.r; - _tmp$8[1] = this.g; - _tmp$8[2] = this.b; - - return _tmp$8; -}; - -/** - * @class Color - * @name color3 - */ -var color3 = {}; - -/** - * Creates a new color - * - * @returns {color3} a new color - */ -color3.create = function () { - return new _color3(1, 1, 1); -}; - -/** - * Creates a new color initialized with the given values - * - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @returns {color3} a new color - * @function - */ -color3.new = function (r, g, b) { - return new _color3(r, g, b); -}; - -/** - * Creates a new color initialized with values from an existing quaternion - * - * @param {color3} a color to clone - * @returns {color3} a new color - * @function - */ -color3.clone = function (a) { - return new _color3(a.r, a.g, a.b, a.a); -}; - -/** - * Copy the values from one color to another - * - * @param {color3} out the receiving color - * @param {color3} a the source color - * @returns {color3} out - * @function - */ -color3.copy = function (out, a) { - out.r = a.r; - out.g = a.g; - out.b = a.b; - return out; -}; - -/** - * Set the components of a color to the given values - * - * @param {color3} out the receiving color - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @returns {color3} out - * @function - */ -color3.set = function (out, r, g, b) { - out.r = r; - out.g = g; - out.b = b; - return out; -}; - -/** - * Set from hex - * - * @param {color3} out the receiving color - * @param {Number} hex - * @returns {color3} out - * @function - */ -color3.fromHex = function (out, hex) { - var r = ((hex >> 16)) / 255.0; - var g = ((hex >> 8) & 0xff) / 255.0; - var b = ((hex) & 0xff) / 255.0; - - out.r = r; - out.g = g; - out.b = b; - return out; -}; - -/** - * Adds two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - * @function - */ -color3.add = function (out, a, b) { - out.r = a.r + b.r; - out.g = a.g + b.g; - out.b = a.b + b.b; - return out; -}; - -/** - * Subtracts color b from color a - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - */ -color3.subtract = function (out, a, b) { - out.r = a.r - b.r; - out.g = a.g - b.g; - out.b = a.b - b.b; - return out; -}; - -/** - * Alias for {@link color3.subtract} - * @function - */ -color3.sub = color3.subtract; - -/** - * Multiplies two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - * @function - */ -color3.multiply = function (out, a, b) { - out.r = a.r * b.r; - out.g = a.g * b.g; - out.b = a.b * b.b; - return out; -}; - -/** - * Alias for {@link color3.multiply} - * @function - */ -color3.mul = color3.multiply; - -/** - * Divides two color's - * - * @param {color3} out the receiving vector - * @param {color3} a the first operand - * @param {color3} b the second operand - * @returns {color3} out - */ -color3.divide = function (out, a, b) { - out.r = a.r / b.r; - out.g = a.g / b.g; - out.b = a.b / b.b; - return out; -}; - -/** - * Alias for {@link color3.divide} - * @function - */ -color3.div = color3.divide; - - -/** - * Scales a color by a scalar number - * - * @param {color3} out the receiving vector - * @param {color3} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {color3} out - * @function - */ -color3.scale = function (out, a, b) { - out.r = a.r * b; - out.g = a.g * b; - out.b = a.b * b; - return out; -}; - -/** - * Performs a linear interpolation between two color's - * - * @param {color3} out the receiving color - * @param {color3} a the first operand - * @param {color3} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {color3} out - * @function - */ -color3.lerp = function (out, a, b, t) { - var ar = a.r, - ag = a.g, - ab = a.b; - out.r = ar + t * (b.r - ar); - out.g = ag + t * (b.g - ag); - out.b = ab + t * (b.b - ab); - return out; -}; - -/** - * Returns a string representation of a color - * - * @param {color3} a vector to represent as a string - * @returns {String} string representation of the vector - */ -color3.str = function (a) { - return ("color3(" + (a.r) + ", " + (a.g) + ", " + (a.b) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {color3} a - * @returns {array} - */ -color3.array = function (out, a) { - out[0] = a.r; - out[1] = a.g; - out[2] = a.b; - - return out; -}; - -/** - * Returns whether or not the color have exactly the same elements in the same position (when compared with ===) - * - * @param {color3} a The first color3. - * @param {color3} b The second color3. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color3.exactEquals = function (a, b) { - return a.r === b.r && a.g === b.g && a.b === b.b; -}; - -/** - * Returns whether or not the colors have approximately the same elements in the same position. - * - * @param {color3} a The first color3. - * @param {color3} b The second color3. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color3.equals = function (a, b) { - var a0 = a.r, a1 = a.g, a2 = a.b; - var b0 = b.r, b1 = b.g, b2 = b.b; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))); -}; - -/** - * Returns the hex value - * - * @param {color3} a The color - * @returns {Number} - */ -color3.hex = function (a) { - return (a.r * 255) << 16 | (a.g * 255) << 8 | (a.b * 255); -}; - -var _tmp$9 = new Array(4); - -var _color4 = function _color4(r, g, b, a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; -}; - -_color4.prototype.toJSON = function toJSON () { - _tmp$9[0] = this.r; - _tmp$9[1] = this.g; - _tmp$9[2] = this.b; - _tmp$9[3] = this.a; - - return _tmp$9; -}; - -/** - * @class Color - * @name color4 - */ -var color4 = {}; - -/** - * Creates a new color - * - * @returns {color4} a new color - */ -color4.create = function () { - return new _color4(1, 1, 1, 1); -}; - -/** - * Creates a new color initialized with the given values - * - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @param {Number} a alpha component - * @returns {color4} a new color - * @function - */ -color4.new = function (r, g, b, a) { - return new _color4(r, g, b, a); -}; - -/** - * Creates a new color initialized with values from an existing quaternion - * - * @param {color4} a color to clone - * @returns {color4} a new color - * @function - */ -color4.clone = function (a) { - return new _color4(a.r, a.g, a.b, a.a); -}; - -/** - * Copy the values from one color to another - * - * @param {color4} out the receiving color - * @param {color4} a the source color - * @returns {color4} out - * @function - */ -color4.copy = function (out, a) { - out.r = a.r; - out.g = a.g; - out.b = a.b; - out.a = a.a; - return out; -}; - -/** - * Set the components of a color to the given values - * - * @param {color4} out the receiving color - * @param {Number} r red component - * @param {Number} g green component - * @param {Number} b blue component - * @param {Number} a alpha component - * @returns {color4} out - * @function - */ -color4.set = function (out, r, g, b, a) { - out.r = r; - out.g = g; - out.b = b; - out.a = a; - return out; -}; - -/** - * Set from hex - * - * @param {color4} out the receiving color - * @param {Number} hex - * @returns {color4} out - * @function - */ -color4.fromHex = function (out, hex) { - var r = ((hex >> 24)) / 255.0; - var g = ((hex >> 16) & 0xff) / 255.0; - var b = ((hex >> 8) & 0xff) / 255.0; - var a = ((hex) & 0xff) / 255.0; - - out.r = r; - out.g = g; - out.b = b; - out.a = a; - return out; -}; - -/** - * Adds two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - * @function - */ -color4.add = function (out, a, b) { - out.r = a.r + b.r; - out.g = a.g + b.g; - out.b = a.b + b.b; - out.a = a.a + b.a; - return out; -}; - -/** - * Subtracts color b from color a - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - */ -color4.subtract = function (out, a, b) { - out.r = a.r - b.r; - out.g = a.g - b.g; - out.b = a.b - b.b; - out.a = a.a - b.a; - return out; -}; - -/** - * Alias for {@link color4.subtract} - * @function - */ -color4.sub = color4.subtract; - -/** - * Multiplies two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - * @function - */ -color4.multiply = function (out, a, b) { - out.r = a.r * b.r; - out.g = a.g * b.g; - out.b = a.b * b.b; - out.a = a.a * b.a; - return out; -}; - -/** - * Alias for {@link color4.multiply} - * @function - */ -color4.mul = color4.multiply; - -/** - * Divides two color's - * - * @param {color4} out the receiving vector - * @param {color4} a the first operand - * @param {color4} b the second operand - * @returns {color4} out - */ -color4.divide = function (out, a, b) { - out.r = a.r / b.r; - out.g = a.g / b.g; - out.b = a.b / b.b; - out.a = a.a / b.a; - return out; -}; - -/** - * Alias for {@link color4.divide} - * @function - */ -color4.div = color4.divide; - - -/** - * Scales a color by a scalar number - * - * @param {color4} out the receiving vector - * @param {color4} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {color4} out - * @function - */ -color4.scale = function (out, a, b) { - out.r = a.r * b; - out.g = a.g * b; - out.b = a.b * b; - out.a = a.a * b; - return out; -}; - -/** - * Performs a linear interpolation between two color's - * - * @param {color4} out the receiving color - * @param {color4} a the first operand - * @param {color4} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {color4} out - * @function - */ -color4.lerp = function (out, a, b, t) { - var ar = a.r, - ag = a.g, - ab = a.b, - aa = a.a; - out.r = ar + t * (b.r - ar); - out.g = ag + t * (b.g - ag); - out.b = ab + t * (b.b - ab); - out.a = aa + t * (b.a - aa); - return out; -}; - -/** - * Returns a string representation of a color - * - * @param {color4} a vector to represent as a string - * @returns {String} string representation of the vector - */ -color4.str = function (a) { - return ("color4(" + (a.r) + ", " + (a.g) + ", " + (a.b) + ", " + (a.a) + ")"); -}; - -/** - * Returns typed array - * - * @param {array} out - * @param {color4} a - * @returns {array} - */ -color4.array = function (out, a) { - out[0] = a.r; - out[1] = a.g; - out[2] = a.b; - out[3] = a.a; - - return out; -}; - -/** - * Returns whether or not the color have exactly the same elements in the same position (when compared with ===) - * - * @param {color4} a The first color4. - * @param {color4} b The second color4. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color4.exactEquals = function (a, b) { - return a.r === b.r && a.g === b.g && a.b === b.b && a.a === b.a; -}; - -/** - * Returns whether or not the colors have approximately the same elements in the same position. - * - * @param {color4} a The first color4. - * @param {color4} b The second color4. - * @returns {Boolean} True if the colors are equal, false otherwise. - */ -color4.equals = function (a, b) { - var a0 = a.r, a1 = a.g, a2 = a.b, a3 = a.a; - var b0 = b.r, b1 = b.g, b2 = b.b, b3 = b.a; - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && - Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))); -}; - -/** - * Returns the hex value - * - * @param {color4} a The color - * @returns {Number} - */ -color4.hex = function (a) { - return ((a.r * 255) << 24 | (a.g * 255) << 16 | (a.b * 255) << 8 | a.a * 255) >>> 0; -}; - -// NOTE: there is no syntax for: export {* as bits} from './lib/bits'; -var bits = bits_; - - - -var math = Object.freeze({ - bits: bits, - vec2: vec2, - vec3: vec3, - vec4: vec4, - quat: quat, - mat2: mat2, - mat23: mat23, - mat3: mat3, - mat4: mat4, - color3: color3, - color4: color4, - EPSILON: EPSILON, - equals: equals, - approx: approx, - clamp: clamp, - clamp01: clamp01, - lerp: lerp, - toRadian: toRadian, - toDegree: toDegree, - random: random, - randomRange: randomRange, - randomRangeInt: randomRangeInt, - nextPow2: nextPow2 -}); - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Device = function Device(canvasEL) { - var ctx; - - try { - ctx = canvasEL.getContext('2d'); - } catch (err) { - console.error(err); - return; - } - - // statics - this._canvas = canvasEL; - this._ctx = ctx; - this._caps = {}; // capability - this._stats = { - drawcalls: 0, - }; - - // runtime - this._vx = this._vy = this._vw = this._vh = 0; - this._sx = this._sy = this._sw = this._sh = 0; -}; - -Device.prototype._restoreTexture = function _restoreTexture (unit) { -}; - -// =============================== -// Immediate Settings -// =============================== - -/** - * @method setViewport - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device.prototype.setViewport = function setViewport (x, y, w, h) { - if ( - this._vx !== x || - this._vy !== y || - this._vw !== w || - this._vh !== h - ) { - this._vx = x; - this._vy = y; - this._vw = w; - this._vh = h; - } -}; - -/** - * @method setScissor - * @param {Number} x - * @param {Number} y - * @param {Number} w - * @param {Number} h - */ -Device.prototype.setScissor = function setScissor (x, y, w, h) { - if ( - this._sx !== x || - this._sy !== y || - this._sw !== w || - this._sh !== h - ) { - this._sx = x; - this._sy = y; - this._sw = w; - this._sh = h; - } -}; - -Device.prototype.clear = function clear (color) { - var ctx = this._ctx; - ctx.clearRect(this._vx, this._vy, this._vw, this._vh); - if (color && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { - ctx.fillStyle = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] +')'; - ctx.globalAlpha = color[3]; - ctx.fillRect(this._vx, this._vy, this._vw, this._vh); - } -}; - -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -var Texture2D = function Texture2D(device, options) { - this._device = device; - - this._width = 4; - this._height = 4; - - this._image = null; - - if (options) { - if (options.width !== undefined) { - this._width = options.width; - } - if (options.height !== undefined) { - this._height = options.height; - } - - this.updateImage(options); - } -}; - -Texture2D.prototype.update = function update (options) { - this.updateImage(options); -}; - -Texture2D.prototype.updateImage = function updateImage (options) { - if (options.images && options.images[0]) { - var image = options.images[0]; - if (image && image !== this._image) { - this._image = image; - } - } -}; - -Texture2D.prototype.destroy = function destroy () { - this._image = null; -}; - -var canvas = { - Device: Device, - Texture2D: Texture2D -}; - -// intenral -// deps -var Texture2D$2 = canvas.Texture2D; -var Device$2 = canvas.Device; -var gfx = {}; - -var renderEngine = { - // core classes - Device: Device$2, - Texture2D: Texture2D$2, - - // Canvas render support - canvas: canvas, - - // render scene - RenderData: RenderData, - - // memop - RecyclePool: RecyclePool, - Pool: Pool, - - // modules - math: math, - gfx: gfx -}; - -module.exports = renderEngine; diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index 0fa9270dfa2..aff6bc2d0e2 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -54,12 +54,6 @@ var jsbAliasify = { }, verbose: false }; -var canvasAliasify = { - replacements: { - '(.*)render-engine(.js)?': require.resolve('../../cocos2d/core/renderer/render-engine.canvas') - }, - verbose: false -}; exports.buildDebugInfos = require('./buildDebugInfos'); @@ -72,9 +66,6 @@ exports.buildCocosJs = function (sourceFile, outputFile, excludes, opt_macroFlag var opts = { sourcemaps: createMap !== false }; - if (opt_macroFlags && (opt_macroFlags.wechatgameSub || opt_macroFlags.baidugameSub)) { - opts.aliasifyConfig = canvasAliasify; - } var outDir = Path.dirname(outputFile); var outFile = Path.basename(outputFile); var bundler = createBundler(sourceFile, opts); @@ -117,9 +108,6 @@ exports.buildCocosJsMin = function (sourceFile, outputFile, excludes, opt_macroF var opts = { sourcemaps: createMap !== false }; - if (opt_macroFlags && (opt_macroFlags.wechatgameSub || opt_macroFlags.baidugameSub)) { - opts.aliasifyConfig = canvasAliasify; - } var outDir = Path.dirname(outputFile); var outFile = Path.basename(outputFile); var bundler = createBundler(sourceFile, opts); From 7e6eaa38778f9f0d200e0c0ccb42f28bd68007be Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Tue, 29 Jan 2019 17:56:59 +0800 Subject: [PATCH 0426/1631] Optimize db (#3772) * optimize db * optimize db * optimize db * optimize db * optimize db * optimize db * optimize db * optimize db * optimize db * optimize db * optimze spine --- editor/i18n/en/localization.js | 4 +- editor/i18n/zh/localization.js | 4 +- extensions/dragonbones/ArmatureCache.js | 360 +++++++++++++++ extensions/dragonbones/ArmatureDisplay.js | 435 ++++++++++++++++-- extensions/dragonbones/CCSlot.js | 72 +-- extensions/dragonbones/DragonBonesAsset.js | 5 +- .../dragonbones/DragonBonesAtlasAsset.js | 3 + extensions/dragonbones/index.js | 1 + extensions/dragonbones/webgl-assembler.js | 428 +++++++++-------- extensions/spine/Skeleton.js | 2 +- extensions/spine/spine-assembler.js | 4 - gulp/tasks/engine.js | 1 + 12 files changed, 1050 insertions(+), 269 deletions(-) create mode 100644 extensions/dragonbones/ArmatureCache.js diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 2e93ad00d10..9a3d56805dc 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -267,7 +267,9 @@ module.exports = { "animation_name": "The name of current playing animation.", "time_scale": "The time scale of this armature.", "play_times": "The play times of the default animation.\n-1 means using the value of config file\n0 means repeat for ever\n>0 means repeat times", - "debug_bones": "Indicates whether open debug bones" + "debug_bones": "Indicates whether open debug bones", + "enabled_batch": "Indicates whether enabled batch model", + "render_mode": "The render mode of current armature. \n'realtime' means realtime calculate animation data, support animation blend but low performance. \n'sharedCache' means precomputation animation data and share data with same armature, high performance and less memery. \n'privateCache' means precomputation animation data but not share data with other same armature, high performance and more memery.\nAbove two cache mode, not support nest armature, not support 'fade' related interface.", }, 'motionStreak': { 'fadeTime': "Trail fragment fade time, in seconds", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index c082c6914eb..911853b2055 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -271,7 +271,9 @@ module.exports = { "animation_name": "当前播放的动画名称", "time_scale": "当前骨骼中所有动画的时间缩放率", "play_times": "播放默认动画的循环次数\n-1 表示使用配置文件中的默认值\n0 表示无限循环\n>0 表示循环次数", - "debug_bones": "是否显示 bone 的 debug 信息" + "debug_bones": "是否显示 bone 的 debug 信息", + "enabled_batch": "是否开启合批", + "render_mode": "当前骨骼动画的渲染模式\nrealtime 表示实时计算,支持动画融合,较耗性能\nsharedCache 表示预计算且共享动画数据,性能较高,占用较少内存\nprivateCache 表示预计算但不共享动画数据,性能较高,占用较多内存\n以上两种缓存模式,不支持骨骼嵌套,不支持fade相关接口", }, 'motionStreak': { 'fadeTime': "拖尾的渐隐时间,以秒为单位", diff --git a/extensions/dragonbones/ArmatureCache.js b/extensions/dragonbones/ArmatureCache.js new file mode 100644 index 00000000000..5bbdd61920b --- /dev/null +++ b/extensions/dragonbones/ArmatureCache.js @@ -0,0 +1,360 @@ +/**************************************************************************** + Copyright (c) 2018 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. + ****************************************************************************/ +let _vertices = []; +let _indices = []; +let _vertexOffset = 0; +let _indexOffset = 0; +let _vfOffset = 0; +let _frameRate = 1 / 60; +let _preTexUrl = undefined; +let _preBlendMode = undefined; +let _segVCount = 0; +let _segICount = 0; +let _segOffset = 0; +let _colorOffset = 0; +let _preColor = undefined; +let _x, _y; + +//Cache all frames in an animation +let AnimationCache = cc.Class({ + ctor () { + this.frames = []; + this.totalTime = 0; + + this._tempSegments = undefined; + this._tempColors = undefined; + }, + + // Clear texture quote. + clear () { + for (let i = 0, n = this.frames.length; i < n; i++) { + let frame = this.frames[i]; + frame.segments.length = 0; + } + }, + + update (armature, animationName) { + let animation = armature.animation; + animation.play(animationName, 1); + let frameIdx = 0; + do { + // Solid update frame rate 1/60. + armature.advanceTime(_frameRate); + this._updateFrame(armature, frameIdx) && frameIdx++; + } while (!animation.isCompleted); + // Update frame length. + this.frames.length = frameIdx; + this.totalTime = frameIdx * _frameRate; + }, + + _updateFrame (armature, index) { + _vfOffset = 0; + _indexOffset = 0; + _vertexOffset = 0; + _preTexUrl = undefined; + _preBlendMode = undefined; + _segVCount = 0; + _segICount = 0; + _segOffset = 0; + _colorOffset = 0; + _preColor = undefined; + + this.frames[index] = this.frames[index] || { + segments : [], + colors : [], + }; + let frame = this.frames[index]; + + let segments = this._tempSegments = frame.segments; + let colors = this._tempColors = frame.colors; + this._traverseArmature(armature); + // At last must handle pre color and segment. + // Because vertex count will right at the end. + // Handle pre color. + if (_colorOffset > 0) { + colors[_colorOffset - 1].vfOffset = _vfOffset; + } + colors.length = _colorOffset; + // Handle pre segment + let preSegOffset = _segOffset - 1; + if (preSegOffset >= 0 && _segICount > 0) { + let preSegInfo = segments[preSegOffset]; + preSegInfo.indexCount = _segICount; + preSegInfo.vfCount = _segVCount * 5; + preSegInfo.vertexCount = _segVCount; + segments.length = _segOffset; + } else { + segments.length = 0; + return false; + } + + // Fill vertices + let vertices = frame.vertices || new Float32Array(_vfOffset); + let uintVert = frame.uintVert || new Uint32Array(vertices.buffer); + for (let i = 0, j = 0; i < _vfOffset;) { + vertices[i++] = _vertices[j++]; // x + vertices[i++] = _vertices[j++]; // y + vertices[i++] = _vertices[j++]; // u + vertices[i++] = _vertices[j++]; // v + uintVert[i++] = _vertices[j++]; // color + } + + // Fill indices + let indices = frame.indices || new Uint16Array(_indexOffset); + for (let i = 0; i < _indexOffset; i++) { + indices[i] = _indices[i]; + } + + frame.vertices = vertices; + frame.uintVert = uintVert; + frame.indices = indices; + return true; + }, + + _traverseArmature (armature) { + let colors = this._tempColors; + let segments = this._tempSegments; + let gVertices = _vertices; + let gIndices = _indices; + let slotVertices, slotIndices; + let slots = armature._slots, slot, slotMatrix, slotColor, colorVal; + let texture; + let preSegOffset, preSegInfo; + + for (let i = 0, l = slots.length; i < l; i++) { + slot = slots[i]; + if (!slot._visible || !slot._displayData) continue; + + slot.updateWorldMatrix(); + + if (slot.childArmature) { + this._traverseArmature(slot.childArmature); + continue; + } + + texture = slot.getTexture(); + if (!texture) continue; + + slotColor = slot._color; + + if (_preTexUrl !== texture.url || _preBlendMode !== slot._blendMode) { + _preTexUrl = texture.url; + _preBlendMode = slot._blendMode; + // handle pre + preSegOffset = _segOffset - 1; + if (preSegOffset >= 0 && _segICount > 0) { + preSegInfo = segments[preSegOffset]; + preSegInfo.indexCount = _segICount; + preSegInfo.vertexCount = _segVCount; + preSegInfo.vfCount = _segVCount * 5; + } + // handle now + segments[_segOffset++] = { + tex : texture, + blendMode : slot._blendMode, + indexCount : 0, + vertexCount : 0, + vfCount : 0 + }; + _segICount = 0; + _segVCount = 0; + } + + colorVal = ((slotColor.a<<24) >>> 0) + (slotColor.b<<16) + (slotColor.g<<8) + slotColor.r; + + if (_preColor !== colorVal) { + _preColor = colorVal; + if (_colorOffset > 0) { + colors[_colorOffset - 1].vfOffset = _vfOffset; + } + colors[_colorOffset++] = { + r : slotColor.r, + g : slotColor.g, + b : slotColor.b, + a : slotColor.a, + vfOffset : 0 + } + } + + slotVertices = slot._localVertices; + slotIndices = slot._indices; + + slotMatrix = slot._worldMatrix; + + for (let j = 0, vl = slotVertices.length; j < vl;) { + _x = slotVertices[j++]; + _y = slotVertices[j++]; + gVertices[_vfOffset++] = _x * slotMatrix.m00 + _y * slotMatrix.m04 + slotMatrix.m12; + gVertices[_vfOffset++] = _x * slotMatrix.m01 + _y * slotMatrix.m05 + slotMatrix.m13; + gVertices[_vfOffset++] = slotVertices[j++]; + gVertices[_vfOffset++] = slotVertices[j++]; + gVertices[_vfOffset++] = colorVal; + } + + for (let ii = 0, il = slotIndices.length; ii < il; ii ++) { + gIndices[_indexOffset++] = _vertexOffset + slotIndices[ii]; + } + + _vertexOffset = _vfOffset / 5; + _segICount += slotIndices.length; + _segVCount += slotVertices.length / 4; + } + }, +}); + +let ArmatureCache = cc.Class({ + ctor () { + this._animationPool = {}; + this._armatureCache = {}; + }, + + // If cache is private, cache will be destroy when dragonbones node destroy. + dispose () { + for (var key in this._armatureCache) { + var armatureInfo = this._armatureCache[key]; + if (armatureInfo) { + let armature = armatureInfo.armature; + armature && armature.dispose(); + } + } + this._armatureCache = undefined; + this._animationPool = undefined; + }, + + _removeArmature (armatureKey) { + var armatureInfo = this._armatureCache[armatureKey]; + let animationsCache = armatureInfo.animationsCache; + for (var aniKey in animationsCache) { + // Clear cache texture, and put cache into pool. + // No need to create TypedArray next time. + let animationCache = animationsCache[aniKey]; + if (!animationCache) continue; + this._animationPool[armatureKey + "#" + aniKey] = animationCache; + animationCache.clear(); + } + + let armature = armatureInfo.armature; + armature && armature.dispose(); + delete this._armatureCache[armatureKey]; + }, + + // When atlas asset be destroy, remove armature from db cache. + clearByAtlasName (atlasName) { + for (var armatureKey in this._armatureCache) { + var armatureInfo = this._armatureCache[armatureKey]; + if (armatureInfo && armatureInfo.atlasName === atlasName) { + this._removeArmature(armatureKey); + return; + } + } + }, + + // When db assets be destroy, remove armature from db cache. + clearByDBName (dbName) { + for (var armatureKey in this._armatureCache) { + var armatureInfo = this._armatureCache[armatureKey]; + if (armatureInfo && armatureInfo.dbName === dbName) { + this._removeArmature(armatureKey); + return; + } + } + }, + + getArmatureCache (armatureName, dragonbonesName, atlasName) { + let armatureKey = armatureName + "#" + dragonbonesName + "#" + atlasName; + let armatureInfo = this._armatureCache[armatureKey]; + let armature; + if (!armatureInfo) { + let factory = dragonBones.CCFactory.getInstance(); + let proxy = factory.buildArmatureDisplay(armatureName, dragonbonesName, "", atlasName); + if (!proxy || !proxy._armature) return; + armature = proxy._armature; + // If armature has child armature, can not be cache, because it's + // animation data can not be precompute. + if (!ArmatureCache.canCache(armature)) { + armature.dispose(); + return; + } + + this._armatureCache[armatureKey] = { + armature : armature, + dbName : dragonbonesName, + atlasName : atlasName, + // Cache all kinds of animation frame. + // When armature is dispose, clear all animation cache. + animationsCache : {}, + }; + } else { + armature = armatureInfo.armature; + } + return armature; + }, + + getAnimationCache (armatureName, dragonbonesName, atlasName, animationName) { + let armatureKey = armatureName + "#" + dragonbonesName + "#" + atlasName; + let armatureInfo = this._armatureCache[armatureKey]; + if (!armatureInfo) return null; + + let animationsCache = armatureInfo.animationsCache; + return animationsCache[animationName]; + }, + + updateAnimationCache (armatureName, dragonbonesName, atlasName, animationName) { + let armatureKey = armatureName + "#" + dragonbonesName + "#" + atlasName; + let armatureInfo = this._armatureCache[armatureKey]; + let armature = armatureInfo && armatureInfo.armature; + if (!armature) return null; + + let animationsCache = armatureInfo.animationsCache; + let animationCache = animationsCache[animationName]; + if (!animationCache) { + // If cache exist in pool, then just use it. + let poolKey = armatureKey + "#" + animationName; + animationCache = this._animationPool[poolKey]; + if (animationCache) { + delete this._animationPool[poolKey]; + } else { + animationCache = new AnimationCache(); + } + animationsCache[animationName] = animationCache; + } + animationCache.update(armature, animationName); + return animationCache; + } +}); + +ArmatureCache.sharedCache = new ArmatureCache(); +ArmatureCache.canCache = function (armature) { + let slots = armature._slots; + for (let i = 0, l = slots.length; i < l; i++) { + let slot = slots[i]; + if (slot.childArmature) { + return false; + } + } + return true; +}, + +module.exports = ArmatureCache; \ No newline at end of file diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 25ad040563e..0217a55f9e8 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -33,12 +33,16 @@ const Node = require('../../cocos2d/core/CCNode'); const Graphics = require('../../cocos2d/core/graphics/graphics'); const BlendFactor = require('../../cocos2d/core/platform/CCMacro').BlendFactor; +let ArmatureCache = require('./ArmatureCache'); + /** * @module dragonBones */ let DefaultArmaturesEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); +let DefaultRenderModeEnum = cc.Enum({ 'realtime': 0 }); +let RenderModeEnum = cc.Enum({ 'realtime': 0, 'sharedCache': 1, "privateCache": 2 }); function setEnumAttr (obj, propName, enumDef) { cc.Class.attr(obj, propName, { @@ -187,11 +191,13 @@ let ArmatureDisplay = cc.Class({ } } - if (this._armature) { + if (this._armature && !this.isCachedMode()) { this._factory._dragonBones.clock.remove(this._armature); } + this._refresh(); - if (this._armature) { + + if (this._armature && !this.isCachedMode()) { this._factory._dragonBones.clock.add(this._armature); } @@ -282,6 +288,24 @@ let ArmatureDisplay = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.animation_name' }, + // Record pre render mode. + _preRenderMode: 0, + // Best set the mode before set property 'dragonAsset', or will waste some cpu time. + // If set the mode in editor, then no need to worry about order problem. + renderMode: { + default: 0, + type: RenderModeEnum, + notify () { + if (this._preRenderMode !== this.renderMode) { + this._buildArmature(); + } + }, + visible: true, + animatable: false, + displayName: "Render Mode", + tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.render_mode' + }, + /** * !#en The time scale of this armature. * !#zh 当前骨骼中所有动画的时间缩放率。 @@ -338,14 +362,41 @@ let ArmatureDisplay = cc.Class({ debugBones: { default: false, notify () { - this._initDebugDraw(); + this._updateDebugDraw(); }, tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.debug_bones' }, + + /** + * !#en Enabled batch model, if skeleton is complex, do not enable batch, or will lower performance. + * !#zh 开启合批,如果渲染大量相同纹理,且结构简单的骨骼动画,开启合批可以降低drawcall,否则请不要开启,cpu消耗会上升。 + * @property {Boolean} enabledBatch + * @default false + */ + enabledBatch: { + default: false, + notify () { + this._updateBatch(); + }, + tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.enabled_batch' + }, + + // Below properties will effect when render mode is sharedCache or privateCache. + // accumulate time + _accTime: 0, + // Frame counter + _frameCount: 0, + // Play times counter + _playCount: 0, + // Frame cache + _frameCache: null, + // Cur frame + _curFrame: null, + // Playing flag + _playing: false, }, ctor () { - this._renderDatas = []; this._material = new SpriteMaterial; // Property _materialCache Use to cache material,since dragonBones may use multiple texture, // it will clone from the '_material' property,if the dragonbones only have one texture, @@ -360,16 +411,26 @@ let ArmatureDisplay = cc.Class({ onLoad () { // Adapt to old code,remove unuse child which is created by old code. // This logic can be remove after 2.2 or later. - var children = this.node.children; - for (var i = 0, n = children.length; i < n; i++) { - var child = children[i]; - var pos = child._name && child._name.search('CHILD_ARMATURE-'); + let children = this.node.children; + for (let i = 0, n = children.length; i < n; i++) { + let child = children[i]; + let pos = child._name && child._name.search('CHILD_ARMATURE-'); if (pos === 0) { child.destroy(); } } }, + _updateBatch () { + let cache = this._materialCache; + for (let mKey in cache) { + let material = cache[mKey]; + if (material) { + material.useModel = !this.enabledBatch; + } + } + }, + // override _updateMaterial (material) { this._super(material); @@ -384,36 +445,111 @@ let ArmatureDisplay = cc.Class({ if (this._inited) return; this._inited = true; + if (CC_JSB) { + this.renderMode = RenderModeEnum.realtime; + } + this._parseDragonAsset(); this._parseDragonAtlasAsset(); this._refresh(); + + let children = this.node.children; + for (let i = 0, n = children.length; i < n; i++) { + let child = children[i]; + if (child && child._name === "DEBUG_DRAW_NODE") { + child.destroy(); + } + } + this._updateDebugDraw(); + }, + + isCachedMode () { + if (CC_EDITOR) return false; + return this.renderMode !== RenderModeEnum.realtime; }, onEnable () { this._super(); - if (this._armature) { + // If render mode is cache, no need to update by dragonbones library. + if (this._armature && !this.isCachedMode()) { this._factory._dragonBones.clock.add(this._armature); } }, onDisable () { this._super(); - if (this._armature) { + // If render mode is cache, no need to update by dragonbones library. + if (this._armature && !this.isCachedMode()) { this._factory._dragonBones.clock.remove(this._armature); } }, + update (dt) { + if (!this.isCachedMode()) return; + if (!this._playing) return; + + let frames = this._frameCache.frames; + let totalTime = this._frameCache.totalTime; + let frameCount = frames.length; + + // Animation Start, the event diffrent from dragonbones inner event, + // It has no event object. + if (this._accTime == 0 && this._playCount == 0) { + this.emit(dragonBones.EventObject.START); + } + + this._accTime += dt * this.timeScale; + let frameIdx = Math.floor(this._accTime / totalTime * frameCount); + if (frameIdx >= frameCount) { + + // Animation loop complete, the event diffrent from dragonbones inner event, + // It has no event object. + this.emit(dragonBones.EventObject.LOOP_COMPLETE); + + // Animation complete the event diffrent from dragonbones inner event, + // It has no event object. + this.emit(dragonBones.EventObject.COMPLETE); + + this._playCount ++; + if (this.playTimes === -1 || (this.playTimes > 0 && this._playCount >= this.playTimes)) { + this._accTime = 0; + this._playing = false; + this._playCount = 0; + return; + } + this._accTime = 0; + frameIdx = 0; + } + + this._curFrame = frames[frameIdx]; + this._frameIdx = frameIdx; + }, + onDestroy () { this._super(); this._inited = false; - if (this._armature) { - this._armature.dispose(); - this._armature = null; + + if (!CC_EDITOR) { + if (this.renderMode === RenderModeEnum.privateCache) { + this._armatureCache.dispose(); + this._armatureCache = null; + this._armature = null; + } else if (this.renderMode === RenderModeEnum.sharedCache) { + this._armatureCache = null; + this._armature = null; + } else if (this._armature) { + this._armature.dispose(); + this._armature = null; + } + } else { + if (this._armature) { + this._armature.dispose(); + this._armature = null; + } } - this._renderDatas.length = 0; }, - _initDebugDraw () { + _updateDebugDraw () { if (this.debugBones) { if (!this._debugDraw) { let debugDrawNode = new cc.PrivateNode(); @@ -434,17 +570,60 @@ let ArmatureDisplay = cc.Class({ _buildArmature () { if (!this.dragonAsset || !this.dragonAtlasAsset || !this.armatureName) return; + // Switch Asset or Atlas or renderMode will rebuild armature. + if (this._armature) { + // dispose pre build armature + if (!CC_EDITOR) { + if (this._preRenderMode === RenderModeEnum.privateCache) { + this._armatureCache.dispose(); + } else if (this._preRenderMode === RenderModeEnum.realtime) { + this._armature.dispose(); + } + } else { + this._armature.dispose(); + } + + this._armatureCache = null; + this._armature = null; + this._displayProxy = null; + this._frameCache = null; + this._curFrame = null; + this._playing = false; + } - var atlasName = this.dragonAtlasAsset._textureAtlasData.name; - var displayProxy = this._factory.buildArmatureDisplay(this.armatureName, this.dragonAsset._dragonBonesData.name, "", atlasName); - if (!displayProxy) return; + if (!CC_EDITOR) { + if (this.renderMode === RenderModeEnum.sharedCache) { + this._armatureCache = ArmatureCache.sharedCache; + } else if (this.renderMode === RenderModeEnum.privateCache) { + this._armatureCache = new ArmatureCache; + } + } - this._displayProxy = displayProxy; - this._displayProxy._ccNode = this.node; + let atlasName = this.dragonAtlasAsset._textureAtlasData.name; + let dragonbonesName = this.dragonAsset._dragonBonesData.name; + + if (this.isCachedMode()) { + this._armature = this._armatureCache.getArmatureCache(this.armatureName, dragonbonesName, atlasName); + if (!this._armature) { + // Cache fail,swith to realtime render mode. + this.renderMode = RenderModeEnum.realtime; + } + } + + this._preRenderMode = this.renderMode; + if (CC_EDITOR || this.renderMode === RenderModeEnum.realtime) { + this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, dragonbonesName, "", atlasName); + if (!this._displayProxy) return; + this._displayProxy._ccNode = this.node; + this._armature = this._displayProxy._armature; + this._armature.animation.timeScale = this.timeScale; + } - this._armature = this._displayProxy._armature; - this._armature.animation.timeScale = this.timeScale; + if (this.renderMode !== RenderModeEnum.realtime && this.debugBones) { + console.warn("cached mode do not support debug bones"); + } + this._updateBatch(); if (this.animationName) { this.playAnimation(this.animationName, this.playTimes); } @@ -469,10 +648,19 @@ let ArmatureDisplay = cc.Class({ // update inspector this._updateArmatureEnum(); this._updateAnimEnum(); + this._updateRenderModeEnum(); Editor.Utils.refreshSelectedInspector('node', this.node.uuid); } }, + _updateRenderModeEnum: CC_EDITOR && function () { + if (this._armature && ArmatureCache.canCache(this._armature)) { + setEnumAttr(this, 'renderMode', RenderModeEnum); + } else { + setEnumAttr(this, 'renderMode', DefaultRenderModeEnum); + } + }, + // update animation list for editor _updateAnimEnum: CC_EDITOR && function () { let animEnum; @@ -501,7 +689,7 @@ let ArmatureDisplay = cc.Class({ * -1 means use the value of the config file. * 0 means play the animation for ever. * >0 means repeat times. - * !#zh + * !#zh * 播放指定的动画. * animName 指定播放动画的名称。 * playTimes 指定播放动画的次数。 @@ -514,13 +702,46 @@ let ArmatureDisplay = cc.Class({ * @return {dragonBones.AnimationState} */ playAnimation (animName, playTimes) { - if (this._armature) { - this.playTimes = (playTimes === undefined) ? -1 : playTimes; - this.animationName = animName; - return this._armature.animation.play(animName, this.playTimes); + + this.playTimes = (playTimes === undefined) ? -1 : playTimes; + this.animationName = animName; + + if (this.isCachedMode()) { + let atlasName = this.dragonAtlasAsset._textureAtlasData.name; + let dragonbonesName = this.dragonAsset._dragonBonesData.name; + let cache = this._armatureCache.getAnimationCache(this.armatureName, dragonbonesName, atlasName, animName); + if (!cache) { + cache = this._armatureCache.updateAnimationCache(this.armatureName, dragonbonesName, atlasName, animName); + } + if (cache) { + this._accTime = 0; + this._frameCount = 0; + this._playCount = 0; + this._frameCache = cache; + this._playing = true; + this._curFrame = this._frameCache.frames[0]; + } + } else { + if (this._armature) { + return this._armature.animation.play(animName, this.playTimes); + } } + }, - return null; + /** + * !#en + * Update an animation cache. + * !#zh + * 更新某个动画缓存。 + * @method updateAnimationCache + * @param {String} animName + */ + updateAnimationCache (animName) { + if (!this.isCachedMode()) return; + let atlasName = this.dragonAtlasAsset._textureAtlasData.name; + let dragonbonesName = this.dragonAsset._dragonBonesData.name; + let cache = this._armatureCache.updateAnimationCache(this.armatureName, dragonbonesName, atlasName, animName); + this._frameCache = cache || this._frameCache; }, /** @@ -532,7 +753,7 @@ let ArmatureDisplay = cc.Class({ * @returns {Array} */ getArmatureNames () { - var dragonBonesData = this.dragonAsset && this.dragonAsset._dragonBonesData; + let dragonBonesData = this.dragonAsset && this.dragonAsset._dragonBonesData; return (dragonBonesData && dragonBonesData.armatureNames) || []; }, @@ -575,6 +796,8 @@ let ArmatureDisplay = cc.Class({ addEventListener (eventType, listener, target) { if (this._displayProxy) { this._displayProxy.addDBEventListener(eventType, listener, target); + } else { + this.on(eventType, listener, target); } }, @@ -591,6 +814,8 @@ let ArmatureDisplay = cc.Class({ removeEventListener (eventType, listener, target) { if (this._displayProxy) { this._displayProxy.removeDBEventListener(eventType, listener, target); + } else { + this.off(eventType, listener, target); } }, @@ -621,4 +846,154 @@ let ArmatureDisplay = cc.Class({ }, }); -module.exports = dragonBones.ArmatureDisplay = ArmatureDisplay; +/** + * !#en + * Animation start play. + * !#zh + * 动画开始播放。 + * + * @event dragonBones.EventObject.START + * @param {String} type - A string representing the event type to listen for. + * @param {Function} callback - The callback that will be invoked when the event is dispatched. + * The callback is ignored if it is a duplicate (the callbacks are unique). + * @param {dragonBones.EventObject} [callback.event] + * @param {String} [callback.event.type] + * @param {dragonBones.Armature} [callback.event.armature] + * @param {dragonBones.AnimationState} [callback.event.animationState] + */ + +/** + * !#en + * Animation loop play complete once. + * !#zh + * 动画循环播放完成一次。 + * + * @event dragonBones.EventObject.LOOP_COMPLETE + * @param {String} type - A string representing the event type to listen for. + * @param {Function} callback - The callback that will be invoked when the event is dispatched. + * The callback is ignored if it is a duplicate (the callbacks are unique). + * @param {dragonBones.EventObject} [callback.event] + * @param {String} [callback.event.type] + * @param {dragonBones.Armature} [callback.event.armature] + * @param {dragonBones.AnimationState} [callback.event.animationState] + */ + +/** + * !#en + * Animation play complete. + * !#zh + * 动画播放完成。 + * + * @event dragonBones.EventObject.COMPLETE + * @param {String} type - A string representing the event type to listen for. + * @param {Function} callback - The callback that will be invoked when the event is dispatched. + * The callback is ignored if it is a duplicate (the callbacks are unique). + * @param {dragonBones.EventObject} [callback.event] + * @param {String} [callback.event.type] + * @param {dragonBones.Armature} [callback.event.armature] + * @param {dragonBones.AnimationState} [callback.event.animationState] + */ + +/** + * !#en + * Animation fade in start. + * !#zh + * 动画淡入开始。 + * + * @event dragonBones.EventObject.FADE_IN + * @param {String} type - A string representing the event type to listen for. + * @param {Function} callback - The callback that will be invoked when the event is dispatched. + * The callback is ignored if it is a duplicate (the callbacks are unique). + * @param {dragonBones.EventObject} [callback.event] + * @param {String} [callback.event.type] + * @param {dragonBones.Armature} [callback.event.armature] + * @param {dragonBones.AnimationState} [callback.event.animationState] + */ + +/** + * !#en + * Animation fade in complete. + * !#zh + * 动画淡入完成。 + * + * @event dragonBones.EventObject.FADE_IN_COMPLETE + * @param {String} type - A string representing the event type to listen for. + * @param {Function} callback - The callback that will be invoked when the event is dispatched. + * The callback is ignored if it is a duplicate (the callbacks are unique). + * @param {dragonBones.EventObject} [callback.event] + * @param {String} [callback.event.type] + * @param {dragonBones.Armature} [callback.event.armature] + * @param {dragonBones.AnimationState} [callback.event.animationState] + */ + +/** + * !#en + * Animation fade out start. + * !#zh + * 动画淡出开始。 + * + * @event dragonBones.EventObject.FADE_OUT + * @param {String} type - A string representing the event type to listen for. + * @param {Function} callback - The callback that will be invoked when the event is dispatched. + * The callback is ignored if it is a duplicate (the callbacks are unique). + * @param {dragonBones.EventObject} [callback.event] + * @param {String} [callback.event.type] + * @param {dragonBones.Armature} [callback.event.armature] + * @param {dragonBones.AnimationState} [callback.event.animationState] + */ + +/** + * !#en + * Animation fade out complete. + * !#zh + * 动画淡出完成。 + * + * @event dragonBones.EventObject.FADE_OUT_COMPLETE + * @param {String} type - A string representing the event type to listen for. + * @param {Function} callback - The callback that will be invoked when the event is dispatched. + * The callback is ignored if it is a duplicate (the callbacks are unique). + * @param {dragonBones.EventObject} [callback.event] + * @param {String} [callback.event.type] + * @param {dragonBones.Armature} [callback.event.armature] + * @param {dragonBones.AnimationState} [callback.event.animationState] + */ + +/** + * !#en + * Animation frame event. + * !#zh + * 动画帧事件。 + * + * @event dragonBones.EventObject.FRAME_EVENT + * @param {String} type - A string representing the event type to listen for. + * @param {Function} callback - The callback that will be invoked when the event is dispatched. + * The callback is ignored if it is a duplicate (the callbacks are unique). + * @param {dragonBones.EventObject} [callback.event] + * @param {String} [callback.event.type] + * @param {String} [callback.event.name] + * @param {dragonBones.Armature} [callback.event.armature] + * @param {dragonBones.AnimationState} [callback.event.animationState] + * @param {dragonBones.Bone} [callback.event.bone] + * @param {dragonBones.Slot} [callback.event.slot] + */ + +/** + * !#en + * Animation frame sound event. + * !#zh + * 动画帧声音事件。 + * + * @event dragonBones.EventObject.SOUND_EVENT + * @param {String} type - A string representing the event type to listen for. + * @param {Function} callback - The callback that will be invoked when the event is dispatched. + * The callback is ignored if it is a duplicate (the callbacks are unique). + * @param {dragonBones.EventObject} [callback.event] + * @param {String} [callback.event.type] + * @param {String} [callback.event.name] + * @param {dragonBones.Armature} [callback.event.armature] + * @param {dragonBones.AnimationState} [callback.event.animationState] + * @param {dragonBones.Bone} [callback.event.bone] + * @param {dragonBones.Slot} [callback.event.slot] + */ + +module.exports = dragonBones.ArmatureDisplay = ArmatureDisplay; \ No newline at end of file diff --git a/extensions/dragonbones/CCSlot.js b/extensions/dragonbones/CCSlot.js index fdb34c74397..dfd7245d298 100644 --- a/extensions/dragonbones/CCSlot.js +++ b/extensions/dragonbones/CCSlot.js @@ -24,7 +24,6 @@ ****************************************************************************/ const math = require('../../cocos2d/core/renderer/render-engine').math; -const BlendFactor = require('../../cocos2d/core/platform/CCMacro'); const BinaryOffset = dragonBones.BinaryOffset; const BoneType = dragonBones.BoneType; @@ -119,9 +118,7 @@ dragonBones.CCSlot = cc.Class({ this._indices.length = 0; let indices = this._indices, localVertices = this._localVertices; - - indices.length = 0; - localVertices.length = 0; + let indexOffset = 0, vfOffset = 0; let currentTextureData = this._textureData; @@ -162,19 +159,20 @@ dragonBones.CCSlot = cc.Class({ const uvOffset = vertexOffset + vertexCount * 2; for (let i = 0, l = vertexCount; i < l; i++) { - let x = floatArray[vertexOffset + i*2] * scale; - let y = -floatArray[vertexOffset + i*2 + 1] * scale; - - let u = (region.x + floatArray[uvOffset + i*2] * region.width) / textureAtlasWidth; - let v = (region.y + floatArray[uvOffset + i*2 + 1] * region.height) / textureAtlasHeight; + localVertices[vfOffset++] = floatArray[vertexOffset + i*2] * scale; + localVertices[vfOffset++] = -floatArray[vertexOffset + i*2 + 1] * scale; - localVertices.push({ x, y, u, v}); + localVertices[vfOffset++] = (region.x + floatArray[uvOffset + i*2] * region.width) / textureAtlasWidth; + localVertices[vfOffset++] = (region.y + floatArray[uvOffset + i*2 + 1] * region.height) / textureAtlasHeight; } for (let i = 0; i < triangleCount * 3; ++i) { - indices.push(intArray[meshData.offset + BinaryOffset.MeshVertexIndices + i]); + indices[indexOffset++] = intArray[meshData.offset + BinaryOffset.MeshVertexIndices + i]; } + localVertices.length = vfOffset; + indices.length = indexOffset; + this._pivotX = 0; this._pivotY = 0; } @@ -200,24 +198,31 @@ dragonBones.CCSlot = cc.Class({ } this._pivotY -= region.height * scale; - - for (let i = 0; i < 4; i++) { - localVertices.push({}); - } let l = region.x / textureAtlasWidth; let b = (region.y + region.height) / textureAtlasHeight; let r = (region.x + region.width) / textureAtlasWidth; let t = region.y / textureAtlasHeight; - localVertices[0].u = l; localVertices[0].v = b; - localVertices[1].u = r; localVertices[1].v = b; - localVertices[2].u = l; localVertices[2].v = t; - localVertices[3].u = r; localVertices[3].v = t; - localVertices[0].x = localVertices[2].x = 0; - localVertices[1].x = localVertices[3].x = region.width; - localVertices[0].y = localVertices[1].y = 0; - localVertices[2].y = localVertices[3].y = region.height; + localVertices[vfOffset++] = 0; // 0x + localVertices[vfOffset++] = 0; // 0y + localVertices[vfOffset++] = l; // 0u + localVertices[vfOffset++] = b; // 0v + + localVertices[vfOffset++] = region.width; // 1x + localVertices[vfOffset++] = 0; // 1y + localVertices[vfOffset++] = r; // 1u + localVertices[vfOffset++] = b; // 1v + + localVertices[vfOffset++] = 0; // 2x + localVertices[vfOffset++] = region.height;; // 2y + localVertices[vfOffset++] = l; // 2u + localVertices[vfOffset++] = t; // 2v + + localVertices[vfOffset++] = region.width; // 3x + localVertices[vfOffset++] = region.height;; // 3y + localVertices[vfOffset++] = r; // 3u + localVertices[vfOffset++] = t; // 3v indices[0] = 0; indices[1] = 1; @@ -226,6 +231,9 @@ dragonBones.CCSlot = cc.Class({ indices[4] = 3; indices[5] = 2; + localVertices.length = vfOffset; + indices.length = 6; + this._blendModeDirty = true; } }, @@ -249,9 +257,9 @@ dragonBones.CCSlot = cc.Class({ } for ( - let i = 0, iB = weight.offset + BinaryOffset.WeigthBoneIndices + weight.bones.length, iV = weightFloatOffset, iF = 0; + let i = 0, iB = weight.offset + BinaryOffset.WeigthBoneIndices + weight.bones.length, iV = weightFloatOffset, iF = 0, lvi = 0; i < vertexCount; - ++i + i++, lvi+=4 ) { const boneCount = intArray[iB++]; let xG = 0.0, yG = 0.0; @@ -276,8 +284,8 @@ dragonBones.CCSlot = cc.Class({ } } - localVertices[i].x = xG; - localVertices[i].y = -yG; + localVertices[lvi] = xG; + localVertices[lvi + 1] = -yG; } } else if (hasDeform) { @@ -293,18 +301,18 @@ dragonBones.CCSlot = cc.Class({ vertexOffset += 65536; // Fixed out of bouds bug. } - for (let i = 0, l = vertexCount; i < l; i ++) { + for (let i = 0, l = vertexCount, lvi = 0; i < l; i ++, lvi += 4) { const x = floatArray[vertexOffset + i*2] * scale + this._deformVertices[i*2]; const y = floatArray[vertexOffset + i*2 + 1] * scale + this._deformVertices[i*2 + 1]; if (isSurface) { const matrix = this._parent._getGlobalTransformMatrix(x, y); - localVertices[i].x = matrix.a * x + matrix.c * y + matrix.tx; - localVertices[i].y = -matrix.b * x + matrix.d * y + matrix.ty; + localVertices[lvi] = matrix.a * x + matrix.c * y + matrix.tx; + localVertices[lvi + 1] = -matrix.b * x + matrix.d * y + matrix.ty; } else { - localVertices[i].x = x; - localVertices[i].y = -y; + localVertices[lvi] = x; + localVertices[lvi + 1] = -y; } } } diff --git a/extensions/dragonbones/DragonBonesAsset.js b/extensions/dragonbones/DragonBonesAsset.js index fb3d3c0737a..cbb9424d248 100644 --- a/extensions/dragonbones/DragonBonesAsset.js +++ b/extensions/dragonbones/DragonBonesAsset.js @@ -27,6 +27,7 @@ /** * @module dragonBones */ +let ArmatureCache = !CC_JSB && require('./ArmatureCache').sharedCache; /** * !#en The skeleton data of dragonBones. @@ -189,7 +190,9 @@ var DragonBonesAsset = cc.Class({ var useGlobalFactory = !CC_JSB; if (useGlobalFactory && this._dragonBonesData) { var factory = dragonBones.CCFactory.getInstance(); - factory.removeDragonBonesData(this._dragonBonesData.name, true); + let name = this._dragonBonesData.name; + factory.removeDragonBonesData(name, true); + ArmatureCache.clearByDBName(name); } this._super(); }, diff --git a/extensions/dragonbones/DragonBonesAtlasAsset.js b/extensions/dragonbones/DragonBonesAtlasAsset.js index a3cbae4ac0e..c2e06aa9e03 100644 --- a/extensions/dragonbones/DragonBonesAtlasAsset.js +++ b/extensions/dragonbones/DragonBonesAtlasAsset.js @@ -27,6 +27,7 @@ /** * @module dragonBones */ +let ArmatureCache = !CC_JSB && require('./ArmatureCache').sharedCache; /** * !#en The skeleton atlas data of dragonBones. @@ -126,6 +127,8 @@ var DragonBonesAtlasAsset = cc.Class({ var name = this._textureAtlasData.name; factory.removeTextureAtlasData(name, true); factory.removeDragonBonesData(name, true); + ArmatureCache.clearByDBName(name); + ArmatureCache.clearByAtlasName(name); } this._super(); }, diff --git a/extensions/dragonbones/index.js b/extensions/dragonbones/index.js index baa5d051de1..0c80dae8ee2 100644 --- a/extensions/dragonbones/index.js +++ b/extensions/dragonbones/index.js @@ -133,6 +133,7 @@ if (_global.dragonBones !== undefined) { require('./CCSlot'); require('./CCTextureData'); require('./CCArmatureDisplay'); + require('./ArmatureCache'); } // require the component for dragonbones diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index c352845dc91..edf82dfdb1f 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -22,33 +22,36 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ - -const StencilManager = require('../../cocos2d/core/renderer/webgl/stencil-manager').sharedManager; const Armature = require('./ArmatureDisplay'); const renderEngine = require('../../cocos2d/core/renderer/render-engine'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); const gfx = renderEngine.gfx; -const SpriteMaterial = renderEngine.SpriteMaterial; -const vfmtPosUvColor = require('../../cocos2d/core/renderer/webgl/vertex-format').vfmtPosUvColor; +const math = require('../../cocos2d/core/renderer/render-engine').math; +const NEED_NONE = 0x00; +const NEED_COLOR = 0x01; +const NEED_BATCH = 0x10; +const NEED_COLOR_BATCH = 0x11; let _boneColor = cc.color(255, 0, 0, 255); let _slotColor = cc.color(0, 0, 255, 255); -const STENCIL_SEP = '@'; - -function _updateKeyWithStencilRef (key, stencilRef) { - return key.replace(/@\d+$/, STENCIL_SEP + stencilRef); -} - -function _getSlotMaterial (comp, slot, premultiAlpha) { - premultiAlpha = premultiAlpha || false; - let tex = slot.getTexture(); +let _nodeR, _nodeG, _nodeB, _nodeA, + _premultipliedAlpha, + _mustFlush, _buffer, _node, + _renderer, _comp, + _vfOffset, _indexOffset, _vertexOffset, + _vertexCount, _indexCount, + _x, _y, _c, _r, _g, _b, _a, _handleVal, + _m00, _m04, _m12, + _m01, _m05, _m13; + +function _getSlotMaterial (tex, blendMode) { if(!tex)return null; - let src, dst; - switch (slot._blendMode) { + let src, dst; + switch (blendMode) { case 1://additive - src = premultiAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; + src = _premultipliedAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; dst = cc.macro.ONE; break; case 10://multiply @@ -61,15 +64,15 @@ function _getSlotMaterial (comp, slot, premultiAlpha) { break; case 0://normal default: - src = premultiAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; + src = _premultipliedAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; dst = cc.macro.ONE_MINUS_SRC_ALPHA; break; } - let key = tex.url + src + dst + STENCIL_SEP + '0'; - comp._material = comp._material || new SpriteMaterial(); - let baseMaterial = comp._material; - let materialCache = comp._materialCache; + let key = tex.url + src + dst; + let baseMaterial = _comp._material; + if (!baseMaterial) return null; + let materialCache = _comp._materialCache; let material = materialCache[key]; if (!material) { @@ -80,7 +83,7 @@ function _getSlotMaterial (comp, slot, premultiAlpha) { material = baseMaterial.clone(); } - material.useModel = true; + material.useModel = !_comp.enabledBatch; // update texture material.texture = tex; material.useColor = false; @@ -103,225 +106,252 @@ function _getSlotMaterial (comp, slot, premultiAlpha) { return material; } -let _vertexOffset, _indiceOffset, - _nodeR, _nodeG, _nodeB, _nodeA, - _material, _currMaterial, - _dataId, _datas, _data, _newData; +function _handleColor (color) { + _r = color.r * _nodeR; + _g = color.g * _nodeG; + _b = color.b * _nodeB; + _a = color.a * _nodeA; + _c = ((_a<<24) >>> 0) + (_b<<16) + (_g<<8) + _r; +} let armatureAssembler = { - useModel: true, + updateRenderData (comp, batchData) {}, - updateRenderData (comp) { - - let armature = comp._armature; - if (!armature) { - return; - } - - _dataId = 0; - _datas = comp._renderDatas; - _data = _datas[_dataId]; - _newData = false; - if (!_data) { - _data = _datas[_dataId] = comp.requestRenderData(); - } - _data.dataLength = 0; - _material = null; - _currMaterial = null; - _vertexOffset = 0; - _indiceOffset = 0; - - let node = comp.node; - let nodeColor = node.color; - _nodeR = nodeColor.r / 255; - _nodeG = nodeColor.g / 255; - _nodeB = nodeColor.b / 255; - _nodeA = nodeColor.a / 255; - - this.traverseArmature(comp,armature); - }, - - traverseArmature (comp,armature) { + realTimeTraverse (armature, parentMat) { let slots = armature._slots; - let premultipliedAlpha = comp.premultipliedAlpha; + let vbuf, ibuf, uintbuf; + let material; + let vertices, indices; + let slotColor; + let slot; + let slotMat; + for (let i = 0, l = slots.length; i < l; i++) { - let slot = slots[i]; + slot = slots[i]; if (!slot._visible || !slot._displayData) continue; - slot.updateWorldMatrix(); + if (parentMat) { + slot._mulMat(slot._worldMatrix, parentMat, slot._matrix); + } else { + math.mat4.copy(slot._worldMatrix, slot._matrix); + } - // If slot has childArmature,then the slot has no - // vertices and indice info.It only has sub slots - // transform info,so multiply the slot's transform - // with parent transform and give the sub slots. if (slot.childArmature) { - this.traverseArmature(comp, slot.childArmature); + this.realTimeTraverse(slot.childArmature, slot._worldMatrix); continue; } - _material = _getSlotMaterial(comp, slot, premultipliedAlpha); - if (!_material) { + material = _getSlotMaterial(slot.getTexture(), slot._blendMode); + if (!material) { continue; } - // Check break - if (_currMaterial !== _material) { - if (_currMaterial) { - _newData = true; - _data.material = _currMaterial; - } - else { - // Init data material - _data.material = _material; - } - _currMaterial = _material; + if (_mustFlush || material._hash !== _renderer.material._hash) { + _mustFlush = false; + _renderer._flush(); + _renderer.node = _node; + _renderer.material = material; } - // Request new render data and new vertex content - if (_newData) { - // set old data vertex indice - _data.vertexCount = _vertexOffset; - _data.indiceCount = _indiceOffset; - // gen new data - _dataId++; - _data = _datas[_dataId]; - if (!_data) { - _data = _datas[_dataId] = comp.requestRenderData(); - } - _data.material = _currMaterial; - _data.dataLength = 0; + slotColor = slot._color; + _handleColor(slotColor); + slotMat = slot._worldMatrix; - // reset offset - _vertexOffset = 0; - _indiceOffset = 0; - } + vertices = slot._localVertices; + _vertexCount = vertices.length >> 2; + + indices = slot._indices; + _indexCount = indices.length; + + _vfOffset = _buffer.byteOffset >> 2; + _indexOffset = _buffer.indiceOffset; + _vertexOffset = _buffer.vertexOffset; + + _buffer.request(_vertexCount, _indexCount); + vbuf = _buffer._vData; + ibuf = _buffer._iData; + uintbuf = _buffer._uintVData; - let indices = slot._indices; - let indiceBuffer = _data._indices; - for (let j = 0, il = indices.length; j < il; j++) { - indiceBuffer[_indiceOffset++] = _vertexOffset + indices[j]; + _m00 = slotMat.m00; + _m04 = slotMat.m04; + _m12 = slotMat.m12; + _m01 = slotMat.m01; + _m05 = slotMat.m05; + _m13 = slotMat.m13; + + for (let vi = 0, vl = vertices.length; vi < vl;) { + _x = vertices[vi++]; + _y = vertices[vi++]; + + vbuf[_vfOffset++] = _x * _m00 + _y * _m04 + _m12; // x + vbuf[_vfOffset++] = _x * _m01 + _y * _m05 + _m13; // y + + vbuf[_vfOffset++] = vertices[vi++]; // u + vbuf[_vfOffset++] = vertices[vi++]; // v + uintbuf[_vfOffset++] = _c; // color } - let vertices = slot._localVertices; - let slotColor = slot._color; - let worldMatrix = slot._worldMatrix; - let cr = slotColor.r * _nodeR; - let cg = slotColor.g * _nodeG; - let cb = slotColor.b * _nodeB; - let ca = slotColor.a * _nodeA; - let color = ((ca<<24) >>> 0) + (cb<<16) + (cg<<8) + cr; - - let vertexBuffer = _data._data; - _data.dataLength += vertices.length; - for (let j = 0, vl = vertices.length; j < vl; j++) { - let vertex = vertices[j]; - let content = vertexBuffer[_vertexOffset++]; - content.x = vertex.x * worldMatrix.m00 + vertex.y * worldMatrix.m04 + worldMatrix.m12; - content.y = vertex.x * worldMatrix.m01 + vertex.y * worldMatrix.m05 + worldMatrix.m13; - content.u = vertex.u; - content.v = vertex.v; - content.color = color; + for (let ii = 0, il = indices.length; ii < il; ii ++) { + ibuf[_indexOffset++] = _vertexOffset + indices[ii]; } } + }, - _data.vertexCount = _vertexOffset; - _data.indiceCount = _indiceOffset; - - // Check for last data valid or not - if (_vertexOffset > 0 && _indiceOffset > 0) { - _datas.length = _dataId + 1; - } - else { - _datas.length = _dataId; + cacheTraverse (frame, parentMat) { + if (!frame) return; + + let vbuf, ibuf, uintbuf; + let material; + + let vertices = frame.vertices; + let indices = frame.indices; + let uintVert = frame.uintVert; + let segments = frame.segments; + let frameVFOffset = 0, frameIndexOffset = 0, segVFCount = 0; + if (parentMat) { + _m00 = parentMat.m00; + _m04 = parentMat.m04; + _m12 = parentMat.m12; + _m01 = parentMat.m01; + _m05 = parentMat.m05; + _m13 = parentMat.m13; } - }, - fillBuffers (comp, renderer) { + let colorOffset = 0; + let colors = frame.colors; + let nowColor = colors[colorOffset++]; + let maxVFOffset = nowColor.vfOffset; + _handleColor(nowColor); + + for (let i = 0, n = segments.length; i < n; i++) { + let segInfo = segments[i]; + material = _getSlotMaterial(segInfo.tex, segInfo.blendMode); + if (_mustFlush || material._hash !== _renderer.material._hash) { + _mustFlush = false; + _renderer._flush(); + _renderer.node = _node; + _renderer.material = material; + } - let armature = comp._armature; - if (!armature) return; + _vertexCount = segInfo.vertexCount; + _indexCount = segInfo.indexCount; - let renderDatas = comp._renderDatas; - let materialCache = comp._materialCache; + _vfOffset = _buffer.byteOffset >> 2; + _indexOffset = _buffer.indiceOffset; + _vertexOffset = _buffer.vertexOffset; - for (let index = 0, length = renderDatas.length; index < length; index++) { - let data = renderDatas[index]; + _buffer.request(_vertexCount, _indexCount); + vbuf = _buffer._vData; + ibuf = _buffer._iData; + uintbuf = _buffer._uintVData; - let key = data.material._hash; - let newKey = _updateKeyWithStencilRef(key, StencilManager.getStencilRef()); - if (key !== newKey) { - data.material = materialCache[newKey] || data.material.clone(); - data.material.updateHash(newKey); - if (!materialCache[newKey]) { - materialCache[newKey] = data.material; - } + for (let ii = _indexOffset, il = _indexOffset + _indexCount; ii < il; ii++) { + ibuf[ii] = _vertexOffset + indices[frameIndexOffset++]; } - if (data.material !== renderer.material) { - renderer._flush(); - renderer.node = comp.node; - renderer.material = data.material; + segVFCount = segInfo.vfCount; + switch (_handleVal) { + case NEED_COLOR: + case NEED_NONE: + vbuf.set(vertices.subarray(frameVFOffset, frameVFOffset + segVFCount), _vfOffset); + frameVFOffset += segVFCount; + break; + case NEED_BATCH: + case NEED_COLOR_BATCH: + for (let ii = _vfOffset, il = _vfOffset + segVFCount; ii < il;) { + _x = vertices[frameVFOffset++]; + _y = vertices[frameVFOffset++]; + vbuf[ii++] = _x * _m00 + _y * _m04 + _m12; // x + vbuf[ii++] = _x * _m01 + _y * _m05 + _m13; // y + vbuf[ii++] = vertices[frameVFOffset++]; // u + vbuf[ii++] = vertices[frameVFOffset++]; // v + uintbuf[ii++] = uintVert[frameVFOffset++]; + } + break; } - let vertexs = data._data; - let indices = data._indices; - - let buffer = renderer.getBuffer('mesh', vfmtPosUvColor), - vertexOffset = buffer.byteOffset >> 2, - vertexCount = data.vertexCount; - - let indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; - - buffer.request(vertexCount, data.indiceCount); - - // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - ibuf = buffer._iData, - uintbuf = buffer._uintVData; - - // fill vertex buffer - let vert; - for (let i = 0, l = data.dataLength; i < l; i++) { - vert = vertexs[i]; - vbuf[vertexOffset++] = vert.x; - vbuf[vertexOffset++] = vert.y; - vbuf[vertexOffset++] = vert.u; - vbuf[vertexOffset++] = vert.v; - uintbuf[vertexOffset++] = vert.color; - } + if ( !(_handleVal & NEED_COLOR) ) continue; - // index buffer - for (let i = 0, l = indices.length; i < l; i ++) { - ibuf[indiceOffset++] = vertexId + indices[i]; + // handle color + let frameColorOffset = frameVFOffset - segVFCount; + for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii+=5, frameColorOffset += 5) { + if (frameColorOffset >= maxVFOffset) { + nowColor = colors[colorOffset++]; + _handleColor(nowColor); + maxVFOffset = nowColor.vfOffset; + } + uintbuf[ii] = _c; } } + }, - if (comp.debugBones && comp._debugDraw) { - - var graphics = comp._debugDraw; - graphics.clear(); - - graphics.lineWidth = 5; - graphics.strokeColor = _boneColor; - graphics.fillColor = _slotColor; // Root bone color is same as slot color. + fillBuffers (comp, renderer) { + comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; + + // Init temp var. + _mustFlush = true; + _premultipliedAlpha = comp.premultipliedAlpha; + _node = comp.node; + _buffer = renderer._meshBuffer; + _renderer = renderer; + _comp = comp; + _handleVal = 0; + + let nodeColor = _node._color; + _nodeR = nodeColor.r / 255; + _nodeG = nodeColor.g / 255; + _nodeB = nodeColor.b / 255; + _nodeA = nodeColor.a / 255; + if (nodeColor._val !== 0xffffffff) { + _handleVal |= NEED_COLOR; + } - let bones = armature.getBones(); - for (let i = 0, l = bones.length; i < l; i++) { - let bone = bones[i]; - let boneLength = Math.max(bone.boneData.length, 5); - let startX = bone.globalTransformMatrix.tx; - let startY = -bone.globalTransformMatrix.ty; - let endX = startX + bone.globalTransformMatrix.a * boneLength; - let endY = startY - bone.globalTransformMatrix.b * boneLength; + let worldMat = undefined; + if (_comp.enabledBatch) { + worldMat = _node._worldMatrix; + _mustFlush = false; + _handleVal |= NEED_BATCH; + } - graphics.moveTo(startX, startY); - graphics.lineTo(endX, endY); - graphics.stroke(); + if (comp.isCachedMode()) { + // Traverse input assembler. + this.cacheTraverse(comp._curFrame, worldMat); + } else { + // Traverse all armature. + let armature = comp._armature; + if (!armature) return; + + this.realTimeTraverse(armature, worldMat); + + let graphics = comp._debugDraw; + if (comp.debugBones && graphics) { + graphics.clear(); + + graphics.lineWidth = 5; + graphics.strokeColor = _boneColor; + graphics.fillColor = _slotColor; // Root bone color is same as slot color. + + let bones = armature.getBones(); + for (let i = 0, l = bones.length; i < l; i++) { + let bone = bones[i]; + let boneLength = Math.max(bone.boneData.length, 5); + let startX = bone.globalTransformMatrix.tx; + let startY = -bone.globalTransformMatrix.ty; + let endX = startX + bone.globalTransformMatrix.a * boneLength; + let endY = startY - bone.globalTransformMatrix.b * boneLength; + + graphics.moveTo(startX, startY); + graphics.lineTo(endX, endY); + graphics.stroke(); + } } } - - comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; + + // Clear temp var. + _node = undefined; + _buffer = undefined; + _renderer = undefined; + _comp = undefined; } }; diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index a5660f2b0b2..f3f2af98da5 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -390,7 +390,7 @@ sp.Skeleton = cc.Class({ }, _updateUseTint () { - var cache = this._materialCache + var cache = this._materialCache; for (var mKey in cache) { var material = cache[mKey]; if (material) { diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 5d2d383a1af..25621000b3f 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -120,12 +120,8 @@ function _getSlotMaterial (comp, slot, tex) { materialCache[key] = material; } else if (material.texture !== tex) { - if (materialCache[material._hash]) { - delete materialCache[material._hash]; - } material.texture = tex; material.updateHash(key); - materialCache[key] = material; } return material; } diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index aff6bc2d0e2..ecf0b8c852b 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -43,6 +43,7 @@ var jsbSkipModules = [ // modules need to skip in jsb '../../extensions/spine/lib/spine.js', '../../extensions/dragonbones/lib/dragonBones.js', + '../../extensions/dragonbones/ArmatureCache.js', '../../extensions/dragonbones/CCArmatureDisplay.js', '../../extensions/dragonbones/CCFactory.js', '../../extensions/dragonbones/CCSlot.js', From f34c08d32adaeaa7ecb6006d111e590bcfb034cc Mon Sep 17 00:00:00 2001 From: id-ilych Date: Tue, 29 Jan 2019 12:06:33 +0200 Subject: [PATCH 0427/1631] Fix sp.Skeleton asset migration (#3771) Version 1.10 used to serialize this property as `_premultipliedAlpha` --- extensions/spine/Skeleton.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 863a0966ed2..c9cf56e9f5c 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -311,6 +311,7 @@ sp.Skeleton = cc.Class({ */ premultipliedAlpha: { default: true, + formerlySerializedAs: "_premultipliedAlpha", tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.premultipliedAlpha' }, @@ -1020,4 +1021,4 @@ sp.Skeleton = cc.Class({ }, }); -module.exports = sp.Skeleton; \ No newline at end of file +module.exports = sp.Skeleton; From f68666fa8df81510996676aae9dc35cdf62c75a0 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 29 Jan 2019 18:15:14 +0800 Subject: [PATCH 0428/1631] add polyhedron primitive (#3784) * add polyhedron primitive * refine primitive api doc * refine polyhedron --- cocos2d/core/3d/primitive/box.js | 5 +- cocos2d/core/3d/primitive/capsule.js | 5 +- cocos2d/core/3d/primitive/cylinder.js | 5 +- cocos2d/core/3d/primitive/index.js | 149 ++++++++++++++++++-- cocos2d/core/3d/primitive/plane.js | 5 +- cocos2d/core/3d/primitive/polyhedron.js | 172 +++++++++++++++++++++++ cocos2d/core/3d/primitive/quad.js | 5 +- cocos2d/core/3d/primitive/sphere.js | 5 +- cocos2d/core/3d/primitive/torus.js | 6 +- cocos2d/core/3d/primitive/utils.js | 61 ++++++++ cocos2d/core/3d/primitive/vertex-data.js | 41 ++++++ 11 files changed, 437 insertions(+), 22 deletions(-) create mode 100644 cocos2d/core/3d/primitive/polyhedron.js create mode 100644 cocos2d/core/3d/primitive/vertex-data.js diff --git a/cocos2d/core/3d/primitive/box.js b/cocos2d/core/3d/primitive/box.js index 21446fb5677..df409ddef5b 100644 --- a/cocos2d/core/3d/primitive/box.js +++ b/cocos2d/core/3d/primitive/box.js @@ -1,6 +1,7 @@ 'use strict'; import { vec3 } from '../../vmath'; +import VertexData from './vertex-data'; let temp1 = vec3.create(0, 0, 0); let temp2 = vec3.create(0, 0, 0); @@ -118,7 +119,7 @@ export default function (width = 1, height = 1, length = 1, opts = {}) { _buildPlane(3, ws, ls); // BOTTOM _buildPlane(2, ws, ls); // TOP - return { + return new VertexData( positions, normals, uvs, @@ -126,5 +127,5 @@ export default function (width = 1, height = 1, length = 1, opts = {}) { minPos, maxPos, boundingRadius - }; + ); } diff --git a/cocos2d/core/3d/primitive/capsule.js b/cocos2d/core/3d/primitive/capsule.js index 6bfb705897e..17156357abc 100644 --- a/cocos2d/core/3d/primitive/capsule.js +++ b/cocos2d/core/3d/primitive/capsule.js @@ -1,6 +1,7 @@ 'use strict'; import { vec3 } from '../../vmath'; +import VertexData from './vertex-data'; let temp1 = vec3.create(0, 0, 0); let temp2 = vec3.create(0, 0, 0); @@ -50,7 +51,7 @@ export default function (radiusTop = 0.5, radiusBottom = 0.5, height = 2, opts = generateTop(); - return { + return new VertexData( positions, normals, uvs, @@ -58,7 +59,7 @@ export default function (radiusTop = 0.5, radiusBottom = 0.5, height = 2, opts = minPos, maxPos, boundingRadius - }; + ); // ======================= // internal fucntions diff --git a/cocos2d/core/3d/primitive/cylinder.js b/cocos2d/core/3d/primitive/cylinder.js index 706df1a92d6..e14376547a7 100644 --- a/cocos2d/core/3d/primitive/cylinder.js +++ b/cocos2d/core/3d/primitive/cylinder.js @@ -1,6 +1,7 @@ 'use strict'; import { vec3 } from '../../vmath'; +import VertexData from './vertex-data'; let temp1 = vec3.create(0, 0, 0); let temp2 = vec3.create(0, 0, 0); @@ -69,7 +70,7 @@ export default function (radiusTop = 0.5, radiusBottom = 0.5, height = 2, opts = } } - return { + return new VertexData( positions, normals, uvs, @@ -77,7 +78,7 @@ export default function (radiusTop = 0.5, radiusBottom = 0.5, height = 2, opts = minPos, maxPos, boundingRadius - }; + ); // ======================= // internal fucntions diff --git a/cocos2d/core/3d/primitive/index.js b/cocos2d/core/3d/primitive/index.js index 89057242895..c7e80f5418b 100644 --- a/cocos2d/core/3d/primitive/index.js +++ b/cocos2d/core/3d/primitive/index.js @@ -7,14 +7,147 @@ import quad from './quad'; import sphere from './sphere'; import torus from './torus'; import capsule from './capsule'; +import { PolyhedronType, polyhedron } from './polyhedron'; +/** + * @class Primitive + */ cc.primitive = Object.assign({ - box: box, - cone: cone, - cylinder: cylinder, - plane: plane, - quad: quad, - sphere: sphere, - torus: torus, - capsule: capsule, + /** + * !#en Create box vertex data + * !#zh 创建长方体顶点数据 + * @method box + * @static + * @param {Number} width + * @param {Number} height + * @param {Number} length + * @param {Object} opts + * @param {Number} opts.widthSegments + * @param {Number} opts.heightSegments + * @param {Number} opts.lengthSegments + * @return Primitive.VertextData + */ + box, + /** + * !#en Create cone vertex data + * !#zh 创建圆锥体顶点数据 + * @method cone + * @static + * @param {Number} radius + * @param {Number} height + * @param {Object} opts + * @param {Number} opts.radialSegments + * @param {Number} opts.heightSegments + * @param {Boolean} opts.capped + * @param {Number} opts.arc + * @return Primitive.VertextData + */ + cone, + /** + * !#en Create cylinder vertex data + * !#zh 创建圆柱体顶点数据 + * @method cylinder + * @static + * @param {Number} radiusTop + * @param {Number} radiusBottom + * @param {Number} height + * @param {Object} opts + * @param {Number} opts.radialSegments + * @param {Number} opts.heightSegments + * @param {Boolean} opts.capped + * @param {Number} opts.arc + * @return Primitive.VertextData + */ + cylinder, + /** + * !#en Create plane vertex data + * + */ + /** + * !#en Create plane vertex data + * !#zh 创建平台顶点数据 + * @method plane + * @static + * @param {Number} width + * @param {Number} length + * @param {Object} opts + * @param {Number} opts.widthSegments + * @param {Number} opts.lengthSegments + * @return Primitive.VertextData + */ + plane, + /** + * !#en Create quad vertex data + * !#zh 创建面片顶点数据 + * @method quad + * @static + * @return Primitive.VertextData + */ + quad, + /** + * !#en Create sphere vertex data + * !#zh 创建球体顶点数据 + * @method sphere + * @static + * @param {Number} radius + * @param {Object} opts + * @param {Number} opts.segments + * @return Primitive.VertextData + */ + sphere, + /** + * !#en Create torus vertex data + * !#zh 创建圆环顶点数据 + * @method torus + * @static + * @param {Number} radius + * @param {Number} tube + * @param {Object} opts + * @param {Number} opts.radialSegments + * @param {Number} opts.tubularSegments + * @param {Number} opts.arc + * @return Primitive.VertextData + */ + torus, + /** + * !#en Create capsule vertex data + * !#zh 创建胶囊体顶点数据 + * @method capsule + * @static + * @param {Number} radiusTop + * @param {Number} radiusBottom + * @param {Number} height + * @param {Object} opts + * @param {Number} opts.sides + * @param {Number} opts.heightSegments + * @param {Boolean} opts.capped + * @param {Number} opts.arc + * @return Primitive.VertextData + */ + capsule, + /** + * !#en Create polyhedron vertex data + * !#zh 创建多面体顶点数据 + * @method polyhedron + * @static + * @param {Primitive.PolyhedronType} type + * @param {Number} Size + * @param {Object} opts + * @param {Number} opts.sizeX + * @param {Number} opts.sizeY + * @param {Number} opts.sizeZ + * @return Primitive.VertextData + */ + polyhedron, + + PolyhedronType: PolyhedronType }, utils); + +/** + * @module cc + */ + +/** + * @property primitive + * @type Primitive + */ diff --git a/cocos2d/core/3d/primitive/plane.js b/cocos2d/core/3d/primitive/plane.js index 4223f0e3c70..be1f89b959e 100644 --- a/cocos2d/core/3d/primitive/plane.js +++ b/cocos2d/core/3d/primitive/plane.js @@ -1,6 +1,7 @@ 'use strict'; import { vec3 } from '../../vmath'; +import VertexData from './vertex-data'; let temp1 = vec3.create(0, 0, 0); let temp2 = vec3.create(0, 0, 0); @@ -63,7 +64,7 @@ export default function (width = 10, length = 10, opts = {}) { } } - return { + return new VertexData( positions, normals, uvs, @@ -71,5 +72,5 @@ export default function (width = 10, length = 10, opts = {}) { minPos, maxPos, boundingRadius - }; + ); } diff --git a/cocos2d/core/3d/primitive/polyhedron.js b/cocos2d/core/3d/primitive/polyhedron.js new file mode 100644 index 00000000000..e2f43123c7f --- /dev/null +++ b/cocos2d/core/3d/primitive/polyhedron.js @@ -0,0 +1,172 @@ + +import { calcNormals } from './utils'; +import { vec3 } from '../../vmath'; +import VertexData from './vertex-data'; + +/** + * @enum Primitive.PolyhedronType + * @static + * @namespace Primitive + */ +export const PolyhedronType = cc.Enum({ + /** + * @property Tetrahedron + * @static + */ + Tetrahedron: 0, + /** + * @property Octahedron + * @static + */ + Octahedron: 1, + /** + * @property Dodecahedron + * @static + */ + Dodecahedron: 2, + /** + * @property Icosahedron + * @static + */ + Icosahedron: 3, + /** + * @property Rhombicuboctahedron + * @static + */ + Rhombicuboctahedron: 4, + /** + * @property TriangularPrism + * @static + */ + TriangularPrism: 5, + /** + * @property PentagonalPrism + * @static + */ + PentagonalPrism: 6, + /** + * @property HexagonalPrism + * @static + */ + HexagonalPrism: 7, + /** + * @property SquarePyramid + * @static + */ + SquarePyramid: 8, + /** + * @property PentagonalPyramid + * @static + */ + PentagonalPyramid: 9, + /** + * @property TriangularDipyramid + * @static + */ + TriangularDipyramid: 10, + /** + * @property PentagonalDipyramid + * @static + */ + PentagonalDipyramid: 11, + /** + * @property ElongatedSquareDipyramid + * @static + */ + ElongatedSquareDipyramid: 12, + /** + * @property ElongatedPentagonalDipyramid + * @static + */ + ElongatedPentagonalDipyramid: 13, + /** + * @property ElongatedPentagonalCupola + * @static + */ + ElongatedPentagonalCupola: 14 +}); + +// precached polyhedra data +let polyhedra = []; +polyhedra[0] = { vertex: [[0, 0, 1.732051], [1.632993, 0, -0.5773503], [-0.8164966, 1.414214, -0.5773503], [-0.8164966, -1.414214, -0.5773503]], face: [[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 2]] }; +polyhedra[1] = { vertex: [[0, 0, 1.414214], [1.414214, 0, 0], [0, 1.414214, 0], [-1.414214, 0, 0], [0, -1.414214, 0], [0, 0, -1.414214]], face: [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1], [1, 4, 5], [1, 5, 2], [2, 5, 3], [3, 5, 4]] }; +polyhedra[2] = { + vertex: [[0, 0, 1.070466], [0.7136442, 0, 0.7978784], [-0.3568221, 0.618034, 0.7978784], [-0.3568221, -0.618034, 0.7978784], [0.7978784, 0.618034, 0.3568221], [0.7978784, -0.618034, 0.3568221], [-0.9341724, 0.381966, 0.3568221], [0.1362939, 1, 0.3568221], [0.1362939, -1, 0.3568221], [-0.9341724, -0.381966, 0.3568221], [0.9341724, 0.381966, -0.3568221], [0.9341724, -0.381966, -0.3568221], [-0.7978784, 0.618034, -0.3568221], [-0.1362939, 1, -0.3568221], [-0.1362939, -1, -0.3568221], [-0.7978784, -0.618034, -0.3568221], [0.3568221, 0.618034, -0.7978784], [0.3568221, -0.618034, -0.7978784], [-0.7136442, 0, -0.7978784], [0, 0, -1.070466]], + face: [[0, 1, 4, 7, 2], [0, 2, 6, 9, 3], [0, 3, 8, 5, 1], [1, 5, 11, 10, 4], [2, 7, 13, 12, 6], [3, 9, 15, 14, 8], [4, 10, 16, 13, 7], [5, 8, 14, 17, 11], [6, 12, 18, 15, 9], [10, 11, 17, 19, 16], [12, 13, 16, 19, 18], [14, 15, 18, 19, 17]] +}; +polyhedra[3] = { + vertex: [[0, 0, 1.175571], [1.051462, 0, 0.5257311], [0.3249197, 1, 0.5257311], [-0.8506508, 0.618034, 0.5257311], [-0.8506508, -0.618034, 0.5257311], [0.3249197, -1, 0.5257311], [0.8506508, 0.618034, -0.5257311], [0.8506508, -0.618034, -0.5257311], [-0.3249197, 1, -0.5257311], [-1.051462, 0, -0.5257311], [-0.3249197, -1, -0.5257311], [0, 0, -1.175571]], + face: [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 5], [0, 5, 1], [1, 5, 7], [1, 7, 6], [1, 6, 2], [2, 6, 8], [2, 8, 3], [3, 8, 9], [3, 9, 4], [4, 9, 10], [4, 10, 5], [5, 10, 7], [6, 7, 11], [6, 11, 8], [7, 10, 11], [8, 11, 9], [9, 11, 10]] +}; +polyhedra[4] = { + vertex: [[0, 0, 1.070722], [0.7148135, 0, 0.7971752], [-0.104682, 0.7071068, 0.7971752], [-0.6841528, 0.2071068, 0.7971752], [-0.104682, -0.7071068, 0.7971752], [0.6101315, 0.7071068, 0.5236279], [1.04156, 0.2071068, 0.1367736], [0.6101315, -0.7071068, 0.5236279], [-0.3574067, 1, 0.1367736], [-0.7888348, -0.5, 0.5236279], [-0.9368776, 0.5, 0.1367736], [-0.3574067, -1, 0.1367736], [0.3574067, 1, -0.1367736], [0.9368776, -0.5, -0.1367736], [0.7888348, 0.5, -0.5236279], [0.3574067, -1, -0.1367736], [-0.6101315, 0.7071068, -0.5236279], [-1.04156, -0.2071068, -0.1367736], [-0.6101315, -0.7071068, -0.5236279], [0.104682, 0.7071068, -0.7971752], [0.6841528, -0.2071068, -0.7971752], [0.104682, -0.7071068, -0.7971752], [-0.7148135, 0, -0.7971752], [0, 0, -1.070722]], + face: [[0, 2, 3], [1, 6, 5], [4, 9, 11], [7, 15, 13], [8, 16, 10], [12, 14, 19], [17, 22, 18], [20, 21, 23], [0, 1, 5, 2], [0, 3, 9, 4], [0, 4, 7, 1], [1, 7, 13, 6], [2, 5, 12, 8], [2, 8, 10, 3], [3, 10, 17, 9], [4, 11, 15, 7], [5, 6, 14, 12], [6, 13, 20, 14], [8, 12, 19, 16], [9, 17, 18, 11], [10, 16, 22, 17], [11, 18, 21, 15], [13, 15, 21, 20], [14, 20, 23, 19], [16, 19, 23, 22], [18, 22, 23, 21]] +}; +polyhedra[5] = { vertex: [[0, 0, 1.322876], [1.309307, 0, 0.1889822], [-0.9819805, 0.8660254, 0.1889822], [0.1636634, -1.299038, 0.1889822], [0.3273268, 0.8660254, -0.9449112], [-0.8183171, -0.4330127, -0.9449112]], face: [[0, 3, 1], [2, 4, 5], [0, 1, 4, 2], [0, 2, 5, 3], [1, 3, 5, 4]] }; +polyhedra[6] = { vertex: [[0, 0, 1.159953], [1.013464, 0, 0.5642542], [-0.3501431, 0.9510565, 0.5642542], [-0.7715208, -0.6571639, 0.5642542], [0.6633206, 0.9510565, -0.03144481], [0.8682979, -0.6571639, -0.3996071], [-1.121664, 0.2938926, -0.03144481], [-0.2348831, -1.063314, -0.3996071], [0.5181548, 0.2938926, -0.9953061], [-0.5850262, -0.112257, -0.9953061]], face: [[0, 1, 4, 2], [0, 2, 6, 3], [1, 5, 8, 4], [3, 6, 9, 7], [5, 7, 9, 8], [0, 3, 7, 5, 1], [2, 4, 8, 9, 6]] }; +polyhedra[7] = { vertex: [[0, 0, 1.118034], [0.8944272, 0, 0.6708204], [-0.2236068, 0.8660254, 0.6708204], [-0.7826238, -0.4330127, 0.6708204], [0.6708204, 0.8660254, 0.2236068], [1.006231, -0.4330127, -0.2236068], [-1.006231, 0.4330127, 0.2236068], [-0.6708204, -0.8660254, -0.2236068], [0.7826238, 0.4330127, -0.6708204], [0.2236068, -0.8660254, -0.6708204], [-0.8944272, 0, -0.6708204], [0, 0, -1.118034]], face: [[0, 1, 4, 2], [0, 2, 6, 3], [1, 5, 8, 4], [3, 6, 10, 7], [5, 9, 11, 8], [7, 10, 11, 9], [0, 3, 7, 9, 5, 1], [2, 4, 8, 11, 10, 6]] }; +polyhedra[8] = { vertex: [[-0.729665, 0.670121, 0.319155], [-0.655235, -0.29213, -0.754096], [-0.093922, -0.607123, 0.537818], [0.702196, 0.595691, 0.485187], [0.776626, -0.36656, -0.588064]], face: [[1, 4, 2], [0, 1, 2], [3, 0, 2], [4, 3, 2], [4, 1, 0, 3]] }; +polyhedra[9] = { vertex: [[-0.868849, -0.100041, 0.61257], [-0.329458, 0.976099, 0.28078], [-0.26629, -0.013796, -0.477654], [-0.13392, -1.034115, 0.229829], [0.738834, 0.707117, -0.307018], [0.859683, -0.535264, -0.338508]], face: [[3, 0, 2], [5, 3, 2], [4, 5, 2], [1, 4, 2], [0, 1, 2], [0, 3, 5, 4, 1]] }; +polyhedra[10] = { vertex: [[-0.610389, 0.243975, 0.531213], [-0.187812, -0.48795, -0.664016], [-0.187812, 0.9759, -0.664016], [0.187812, -0.9759, 0.664016], [0.798201, 0.243975, 0.132803]], face: [[1, 3, 0], [3, 4, 0], [3, 1, 4], [0, 2, 1], [0, 4, 2], [2, 4, 1]] }; +polyhedra[11] = { vertex: [[-1.028778, 0.392027, -0.048786], [-0.640503, -0.646161, 0.621837], [-0.125162, -0.395663, -0.540059], [0.004683, 0.888447, -0.651988], [0.125161, 0.395663, 0.540059], [0.632925, -0.791376, 0.433102], [1.031672, 0.157063, -0.354165]], face: [[3, 2, 0], [2, 1, 0], [2, 5, 1], [0, 4, 3], [0, 1, 4], [4, 1, 5], [2, 3, 6], [3, 4, 6], [5, 2, 6], [4, 5, 6]] }; +polyhedra[12] = { vertex: [[-0.669867, 0.334933, -0.529576], [-0.669867, 0.334933, 0.529577], [-0.4043, 1.212901, 0], [-0.334933, -0.669867, -0.529576], [-0.334933, -0.669867, 0.529577], [0.334933, 0.669867, -0.529576], [0.334933, 0.669867, 0.529577], [0.4043, -1.212901, 0], [0.669867, -0.334933, -0.529576], [0.669867, -0.334933, 0.529577]], face: [[8, 9, 7], [6, 5, 2], [3, 8, 7], [5, 0, 2], [4, 3, 7], [0, 1, 2], [9, 4, 7], [1, 6, 2], [9, 8, 5, 6], [8, 3, 0, 5], [3, 4, 1, 0], [4, 9, 6, 1]] }; +polyhedra[13] = { vertex: [[-0.931836, 0.219976, -0.264632], [-0.636706, 0.318353, 0.692816], [-0.613483, -0.735083, -0.264632], [-0.326545, 0.979634, 0], [-0.318353, -0.636706, 0.692816], [-0.159176, 0.477529, -0.856368], [0.159176, -0.477529, -0.856368], [0.318353, 0.636706, 0.692816], [0.326545, -0.979634, 0], [0.613482, 0.735082, -0.264632], [0.636706, -0.318353, 0.692816], [0.931835, -0.219977, -0.264632]], face: [[11, 10, 8], [7, 9, 3], [6, 11, 8], [9, 5, 3], [2, 6, 8], [5, 0, 3], [4, 2, 8], [0, 1, 3], [10, 4, 8], [1, 7, 3], [10, 11, 9, 7], [11, 6, 5, 9], [6, 2, 0, 5], [2, 4, 1, 0], [4, 10, 7, 1]] }; +polyhedra[14] = { + vertex: [[-0.93465, 0.300459, -0.271185], [-0.838689, -0.260219, -0.516017], [-0.711319, 0.717591, 0.128359], [-0.710334, -0.156922, 0.080946], [-0.599799, 0.556003, -0.725148], [-0.503838, -0.004675, -0.969981], [-0.487004, 0.26021, 0.48049], [-0.460089, -0.750282, -0.512622], [-0.376468, 0.973135, -0.325605], [-0.331735, -0.646985, 0.084342], [-0.254001, 0.831847, 0.530001], [-0.125239, -0.494738, -0.966586], [0.029622, 0.027949, 0.730817], [0.056536, -0.982543, -0.262295], [0.08085, 1.087391, 0.076037], [0.125583, -0.532729, 0.485984], [0.262625, 0.599586, 0.780328], [0.391387, -0.726999, -0.716259], [0.513854, -0.868287, 0.139347], [0.597475, 0.85513, 0.326364], [0.641224, 0.109523, 0.783723], [0.737185, -0.451155, 0.538891], [0.848705, -0.612742, -0.314616], [0.976075, 0.365067, 0.32976], [1.072036, -0.19561, 0.084927]], + face: [[15, 18, 21], [12, 20, 16], [6, 10, 2], [3, 0, 1], [9, 7, 13], [2, 8, 4, 0], [0, 4, 5, 1], [1, 5, 11, 7], [7, 11, 17, 13], [13, 17, 22, 18], [18, 22, 24, 21], [21, 24, 23, 20], [20, 23, 19, 16], [16, 19, 14, 10], [10, 14, 8, 2], [15, 9, 13, 18], [12, 15, 21, 20], [6, 12, 16, 10], [3, 6, 2, 0], [9, 3, 1, 7], [9, 15, 12, 6, 3], [22, 17, 11, 5, 4, 8, 14, 19, 23, 24]] +}; + +export const polyhedron = function (type, size = 1, opts = {}) { + type = type && (type < 0 || type >= polyhedra.length) ? 0 : type || 0; + let sizeX = opts.sizeX || size; + let sizeY = opts.sizeY || size; + let sizeZ = opts.sizeZ || size; + let data = polyhedra[type]; + let nbfaces = data.face.length; + + let positions = []; + let indices = []; + let normals = []; + let uvs = []; + let minPos = vec3.create(Infinity, Infinity, Infinity); + let maxPos = vec3.create(-Infinity, -Infinity, -Infinity); + + for (let i = 0; i < data.vertex.length; i++) { + let x = data.vertex[i][0] * sizeX; + let y = data.vertex[i][1] * sizeY; + let z = data.vertex[i][2] * sizeZ; + + minPos.x = Math.min(minPos.x, x); + minPos.y = Math.min(minPos.y, y); + minPos.z = Math.min(minPos.z, z); + maxPos.x = Math.max(maxPos.x, x); + maxPos.y = Math.max(maxPos.y, y); + maxPos.z = Math.max(maxPos.z, z); + + positions.push(x, y, z); + uvs.push(0, 0); + } + for (let f = 0; f < nbfaces; f++) { + for (let i = 0; i < data.face[f].length - 2; i++) { + indices.push(data.face[f][0], data.face[f][i + 2], data.face[f][i + 1]); + } + } + + calcNormals(positions, indices, normals); + + let boundingRadius = Math.sqrt( + Math.pow(maxPos.x - minPos.x, 2), + Math.pow(maxPos.y - minPos.y, 2), + Math.pow(maxPos.z - minPos.z, 2) + ); + + return new VertexData( + positions, + normals, + uvs, + indices, + minPos, + maxPos, + boundingRadius + ); +}; diff --git a/cocos2d/core/3d/primitive/quad.js b/cocos2d/core/3d/primitive/quad.js index 15ae9912dc8..2e310918f85 100644 --- a/cocos2d/core/3d/primitive/quad.js +++ b/cocos2d/core/3d/primitive/quad.js @@ -1,6 +1,7 @@ 'use strict'; import { vec3 } from '../../vmath'; +import VertexData from './vertex-data'; let positions = [ -0.5, -0.5, 0, // bottom-left @@ -34,7 +35,7 @@ let maxPos = vec3.create(0.5, 0.5, 0); let boundingRadius = Math.sqrt(0.5 * 0.5 + 0.5 * 0.5); export default function () { - return { + return new VertexData( positions, indices, normals, @@ -42,5 +43,5 @@ export default function () { minPos, maxPos, boundingRadius - }; + ); } diff --git a/cocos2d/core/3d/primitive/sphere.js b/cocos2d/core/3d/primitive/sphere.js index 29730f534cd..8a12544f6b6 100644 --- a/cocos2d/core/3d/primitive/sphere.js +++ b/cocos2d/core/3d/primitive/sphere.js @@ -1,6 +1,7 @@ 'use strict'; import { vec3 } from '../../vmath'; +import VertexData from './vertex-data'; /** * @param {Number} radius @@ -55,7 +56,7 @@ export default function (radius = 0.5, opts = {}) { } } - return { + return new VertexData( positions, indices, normals, @@ -63,5 +64,5 @@ export default function (radius = 0.5, opts = {}) { minPos, maxPos, boundingRadius - }; + ); } diff --git a/cocos2d/core/3d/primitive/torus.js b/cocos2d/core/3d/primitive/torus.js index 1a827512843..b552c226ba8 100644 --- a/cocos2d/core/3d/primitive/torus.js +++ b/cocos2d/core/3d/primitive/torus.js @@ -1,6 +1,8 @@ 'use strict'; import { vec3 } from '../../vmath'; +import VertexData from './vertex-data'; + /** * @param {Number} radius * @param {Number} tube @@ -57,7 +59,7 @@ export default function (radius = 0.4, tube = 0.1, opts = {}) { } } - return { + return new VertexData( positions, normals, uvs, @@ -65,5 +67,5 @@ export default function (radius = 0.4, tube = 0.1, opts = {}) { minPos, maxPos, boundingRadius - }; + ); } diff --git a/cocos2d/core/3d/primitive/utils.js b/cocos2d/core/3d/primitive/utils.js index c0f7ffbe6ec..f45ed9880d5 100644 --- a/cocos2d/core/3d/primitive/utils.js +++ b/cocos2d/core/3d/primitive/utils.js @@ -1,3 +1,4 @@ +import { vec3 } from '../../vmath'; export function wireframe(indices) { const offsets = [[0, 1], [1, 2], [2, 0]]; @@ -63,3 +64,63 @@ export function normals(positions, normals, length = 1) { return verts; } + + +function fromArray (out, a, offset) { + out.x = a[offset]; + out.y = a[offset+1]; + out.z = a[offset+2]; +} + +export function calcNormals (positions, indices, normals) { + normals = normals || new Array(positions.length); + for (let i = 0, l = normals.length; i < l; i++) { + normals[i] = 0; + } + + let vA, vB, vC; + let pA = cc.v3(), pB = cc.v3(), pC = cc.v3(); + let cb = cc.v3(), ab = cc.v3(); + + for (let i = 0, il = indices.length; i < il; i += 3) { + + vA = indices[i + 0] * 3; + vB = indices[i + 1] * 3; + vC = indices[i + 2] * 3; + + fromArray(pA, positions, vA); + fromArray(pB, positions, vB); + fromArray(pC, positions, vC); + + vec3.sub(cb, pC, pB); + vec3.sub(ab, pA, pB); + vec3.cross(cb, cb, ab); + + normals[vA] += cb.x; + normals[vA + 1] += cb.y; + normals[vA + 2] += cb.z; + + normals[vB] += cb.x; + normals[vB + 1] += cb.y; + normals[vB + 2] += cb.z; + + normals[vC] += cb.x; + normals[vC + 1] += cb.y; + normals[vC + 2] += cb.z; + } + + let tempNormal = cc.v3(); + for (let i = 0, l = normals.length; i < l; i+=3) { + tempNormal.x = normals[i]; + tempNormal.y = normals[i+1]; + tempNormal.z = normals[i+2]; + + tempNormal.normalizeSelf(); + + normals[i] = tempNormal.x; + normals[i+1] = tempNormal.y; + normals[i+2] = tempNormal.z; + } + + return normals; +} diff --git a/cocos2d/core/3d/primitive/vertex-data.js b/cocos2d/core/3d/primitive/vertex-data.js new file mode 100644 index 00000000000..1df92324f6a --- /dev/null +++ b/cocos2d/core/3d/primitive/vertex-data.js @@ -0,0 +1,41 @@ + +/** + * @class Primitive.VertexData + * @param {[Number]} positions + * @param {[Number]} normals + * @param {[Number]} uvs + * @param {[Number]} indices + * @param {Vec3} minPos + * @param {Vec3} maxPos + * @param {Number} boundingRadius + */ +export default function VertexData (positions, normals, uvs, indices, minPos, maxPos, boundingRadius) { + /** + * @property {[Number]} positions + */ + this.positions = positions; + /** + * @property {[Number]} normals + */ + this.normals = normals; + /** + * @property {[Number]} uvs + */ + this.uvs = uvs; + /** + * @property {[Number]} indices + */ + this.indices = indices; + /** + * @property {Vec3} minPos + */ + this.minPos = minPos; + /** + * @property {Vec3} maxPos + */ + this.maxPos = maxPos; + /** + * @property {Number} boundingRadius + */ + this.boundingRadius = boundingRadius; +} From dbed4223ee1e03241bffe1f9943bbc8c77167349 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Wed, 30 Jan 2019 14:50:35 +0800 Subject: [PATCH 0429/1631] =?UTF-8?q?When=20vertex=20count=20more=20than?= =?UTF-8?q?=2065535=EF=BC=8Cswith=20other=20buffer=20(#3773)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * when vertex more than 65535,extend mesh-buffer. * fix vertex count exceed 65535,render error * optimze spine --- .../renderer/webgl/assemblers/label/bmfont.js | 13 ++- .../renderer/webgl/assemblers/label/ttf.js | 12 +-- .../webgl/assemblers/motion-streak.js | 15 ++-- .../webgl/assemblers/sprite/bar-filled.js | 12 +-- .../renderer/webgl/assemblers/sprite/mesh.js | 13 ++- .../webgl/assemblers/sprite/radial-filled.js | 16 ++-- .../webgl/assemblers/sprite/simple.js | 12 +-- .../webgl/assemblers/sprite/sliced.js | 12 +-- .../renderer/webgl/assemblers/sprite/tiled.js | 13 ++- cocos2d/core/renderer/webgl/mesh-buffer.js | 88 +++++++++++++++++-- cocos2d/core/renderer/webgl/spine-buffer.js | 8 ++ cocos2d/tilemap/tmx-layer-assembler.js | 11 ++- extensions/dragonbones/webgl-assembler.js | 24 ++--- extensions/spine/spine-assembler.js | 24 +++-- 14 files changed, 181 insertions(+), 92 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js index 4b543d3c615..98258990090 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/bmfont.js @@ -41,16 +41,15 @@ module.exports = js.addon({ a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, - indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; - + let buffer = renderer._meshBuffer; let vertexCount = renderData.vertexCount; - buffer.request(vertexCount, renderData.indiceCount); + let offsetInfo = buffer.request(vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, uintbuf = buffer._uintVData, ibuf = buffer._iData; diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index d0252c20b6b..76682a02f60 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -47,15 +47,15 @@ module.exports = js.addon({ a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, - indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; + let buffer = renderer._meshBuffer; - buffer.request(4, 6); + let offsetInfo = buffer.request(4, 6); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, uintbuf = buffer._uintVData, ibuf = buffer._iData; diff --git a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js index 4721da89370..876e5296950 100644 --- a/cocos2d/core/renderer/webgl/assemblers/motion-streak.js +++ b/cocos2d/core/renderer/webgl/assemblers/motion-streak.js @@ -195,18 +195,17 @@ var motionStreakAssembler = { data = renderData._data; let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, vertexCount = renderData.vertexCount; - let indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; - - buffer.request(vertexCount, renderData.indiceCount); + let offsetInfo = buffer.request(vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, - ibuf = buffer._iData, - uintbuf = buffer._uintVData; + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, + uintbuf = buffer._uintVData, + ibuf = buffer._iData; // vertex buffer let vert; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js index cd8d945ff99..147303dbc54 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/bar-filled.js @@ -220,15 +220,15 @@ module.exports = { a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, - indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; + let buffer = renderer._meshBuffer; - buffer.request(4, 6); + let offsetInfo = buffer.request(4, 6); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, uintbuf = buffer._uintVData; // vertex diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js index 089801e292a..ad80bf0a38c 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/mesh.js @@ -161,16 +161,15 @@ module.exports = { } // buffer - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2; - - let indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; + let buffer = renderer._meshBuffer; - buffer.request(renderData.vertexCount, renderData.indiceCount); + let offsetInfo = buffer.request(renderData.vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, uintbuf = buffer._uintVData, ibuf = buffer._iData; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js index e3915de0394..23c73892056 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/radial-filled.js @@ -330,16 +330,16 @@ module.exports = { tx = matrix.m12, ty = matrix.m13; // buffer - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, + let buffer = renderer._meshBuffer; + + let offsetInfo = buffer.request(renderData.vertexCount, renderData.indiceCount); + + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + ibuf = buffer._iData, vbuf = buffer._vData, uintbuf = buffer._uintVData; - - let ibuf = buffer._iData, - indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; - - buffer.request(renderData.vertexCount, renderData.indiceCount); let count = data.length; for (let i = 0; i < count; i++) { diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js index 86cb966862f..0ce6f39bd6d 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/simple.js @@ -49,15 +49,15 @@ module.exports = { a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, - indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; + let buffer = renderer._meshBuffer; - buffer.request(4, 6); + let offsetInfo = buffer.request(4, 6); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, uintbuf = buffer._uintVData, ibuf = buffer._iData; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js index c2c1a2635f5..35dce6d94b3 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/sliced.js @@ -99,17 +99,17 @@ module.exports = { data = renderData._data; let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, - vertexCount = renderData.vertexCount, - indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; + vertexCount = renderData.vertexCount; let uvSliced = sprite.spriteFrame.uvSliced; - buffer.request(vertexCount, renderData.indiceCount); + let offsetInfo = buffer.request(vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, uintbuf = buffer._uintVData, ibuf = buffer._iData; diff --git a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js index a4baccef6ef..99459e8c434 100644 --- a/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js +++ b/cocos2d/core/renderer/webgl/assemblers/sprite/tiled.js @@ -84,16 +84,15 @@ module.exports = { data = renderData._data; // buffer - let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2; - - let indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; + let buffer = renderer._meshBuffer; - buffer.request(renderData.vertexCount, renderData.indiceCount); + let offsetInfo = buffer.request(renderData.vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, uintbuf = buffer._uintVData, ibuf = buffer._iData; diff --git a/cocos2d/core/renderer/webgl/mesh-buffer.js b/cocos2d/core/renderer/webgl/mesh-buffer.js index 0d49d4bc915..8a764e5927b 100644 --- a/cocos2d/core/renderer/webgl/mesh-buffer.js +++ b/cocos2d/core/renderer/webgl/mesh-buffer.js @@ -14,6 +14,8 @@ let MeshBuffer = cc.Class({ this._vertexFormat = vertexFormat; this._vertexBytes = this._vertexFormat._bytes; + this._arrOffset = 0; + this._vbArr = []; this._vb = new gfx.VertexBuffer( batcher._device, vertexFormat, @@ -21,7 +23,9 @@ let MeshBuffer = cc.Class({ new ArrayBuffer(), 0 ); + this._vbArr[0] = this._vb; + this._ibArr = []; this._ib = new gfx.IndexBuffer( batcher._device, gfx.INDEX_FMT_UINT16, @@ -29,16 +33,22 @@ let MeshBuffer = cc.Class({ new ArrayBuffer(), 0 ); + this._ibArr[0] = this._ib; this._vData = null; - this._iData = null; this._uintVData = null; + this._iData = null; this._batcher = batcher; - this._initVDataCount = 256 * vertexFormat._bytes; // actually 256 * 4 * (vertexFormat._bytes / 4) + this._initVDataCount = 256 * vertexFormat._bytes;// actually 256 * 4 * (vertexFormat._bytes / 4) this._initIDataCount = 256 * 6; + this._offsetInfo = { + byteOffset : 0, + vertexOffset : 0, + indiceOffset : 0 + } this._reallocBuffer(); }, @@ -60,7 +70,51 @@ let MeshBuffer = cc.Class({ this._dirty = false; }, + checkAndSwitchBuffer (vertexCount) { + if (this.vertexOffset + vertexCount > 65535) { + this.uploadData(); + this._batcher._flush(); + let offset = ++this._arrOffset; + + this.byteStart = 0; + this.byteOffset = 0; + this.vertexStart = 0; + this.vertexOffset = 0; + this.indiceStart = 0; + this.indiceOffset = 0; + + if (offset < this._vbArr.length) { + this._vb = this._vbArr[offset]; + this._ib = this._ibArr[offset]; + } else { + + this._vb = new gfx.VertexBuffer( + this._batcher._device, + this._vertexFormat, + gfx.USAGE_DYNAMIC, + new ArrayBuffer(), + 0 + ); + this._vbArr[offset] = this._vb; + this._vb._bytes = this._vData.byteLength; + + this._ib = new gfx.IndexBuffer( + this._batcher._device, + gfx.INDEX_FMT_UINT16, + gfx.USAGE_STATIC, + new ArrayBuffer(), + 0 + ); + this._ibArr[offset] = this._ib; + this._ib._bytes = this._iData.byteLength; + } + } + }, + requestStatic (vertexCount, indiceCount) { + + this.checkAndSwitchBuffer(vertexCount); + let byteOffset = this.byteOffset + vertexCount * this._vertexBytes; let indiceOffset = this.indiceOffset + indiceCount; @@ -78,9 +132,14 @@ let MeshBuffer = cc.Class({ this._reallocBuffer(); } + let offsetInfo = this._offsetInfo; + offsetInfo.vertexOffset = this.vertexOffset; this.vertexOffset += vertexCount; + + offsetInfo.indiceOffset = this.indiceOffset; this.indiceOffset += indiceCount; - + + offsetInfo.byteOffset = this.byteOffset; this.byteOffset = byteOffset; this._dirty = true; @@ -93,6 +152,7 @@ let MeshBuffer = cc.Class({ } this.requestStatic(vertexCount, indiceCount); + return this._offsetInfo; }, _reallocBuffer () { @@ -108,6 +168,7 @@ let MeshBuffer = cc.Class({ this._vData = new Float32Array(this._initVDataCount); this._uintVData = new Uint32Array(this._vData.buffer); + let newData = new Uint8Array(this._uintVData.buffer); if (oldVData && copyOldData) { @@ -135,18 +196,35 @@ let MeshBuffer = cc.Class({ }, reset () { + this._arrOffset = 0; + this._vb = this._vbArr[0]; + this._ib = this._ibArr[0]; + this.byteStart = 0; this.byteOffset = 0; this.indiceStart = 0; this.indiceOffset = 0; this.vertexStart = 0; this.vertexOffset = 0; + this._dirty = false; }, destroy () { - this._ib.destroy(); - this._vb.destroy(); + for (let key in this._vbArr) { + let vb = this._vbArr[key]; + vb.destroy(); + } + this._vbArr = undefined; + + for (let key in this._ibArr) { + let ib = this._ibArr[key]; + ib.destroy(); + } + this._ibArr = undefined; + + this._ib = undefined; + this._vb = undefined; } }); diff --git a/cocos2d/core/renderer/webgl/spine-buffer.js b/cocos2d/core/renderer/webgl/spine-buffer.js index 15a82130750..124be253cd4 100644 --- a/cocos2d/core/renderer/webgl/spine-buffer.js +++ b/cocos2d/core/renderer/webgl/spine-buffer.js @@ -3,6 +3,9 @@ var SpineBuffer = cc.Class({ extends: require('./mesh-buffer'), requestStatic (vertexCount, indiceCount) { + + this.checkAndSwitchBuffer(vertexCount); + let byteOffset = this.byteOffset + vertexCount * this._vertexBytes; let indiceOffset = this.indiceOffset + indiceCount; @@ -19,6 +22,11 @@ var SpineBuffer = cc.Class({ this._reallocBuffer(); } + + let offsetInfo = this._offsetInfo; + offsetInfo.vertexOffset = this.vertexOffset; + offsetInfo.indiceOffset = this.indiceOffset; + offsetInfo.byteOffset = this.byteOffset; }, adjust (vertexCount, indiceCount) { diff --git a/cocos2d/tilemap/tmx-layer-assembler.js b/cocos2d/tilemap/tmx-layer-assembler.js index 6ab948cee7e..00ef3ca6130 100644 --- a/cocos2d/tilemap/tmx-layer-assembler.js +++ b/cocos2d/tilemap/tmx-layer-assembler.js @@ -63,16 +63,15 @@ let tmxAssembler = { let data = renderData._data; let buffer = renderer._meshBuffer, - vertexOffset = buffer.byteOffset >> 2, vertexCount = renderData.vertexCount; - - let indiceOffset = buffer.indiceOffset, - vertexId = buffer.vertexOffset; - buffer.request(vertexCount, renderData.indiceCount); + let offsetInfo = buffer.request(vertexCount, renderData.indiceCount); // buffer data may be realloc, need get reference after request. - let vbuf = buffer._vData, + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, ibuf = buffer._iData, uintbuf = buffer._uintVData; diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index edf82dfdb1f..5c8c08fc2f0 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -125,6 +125,7 @@ let armatureAssembler = { let slotColor; let slot; let slotMat; + let offsetInfo; for (let i = 0, l = slots.length; i < l; i++) { slot = slots[i]; @@ -162,12 +163,11 @@ let armatureAssembler = { indices = slot._indices; _indexCount = indices.length; - - _vfOffset = _buffer.byteOffset >> 2; - _indexOffset = _buffer.indiceOffset; - _vertexOffset = _buffer.vertexOffset; - - _buffer.request(_vertexCount, _indexCount); + + offsetInfo = _buffer.request(_vertexCount, _indexCount); + _indexOffset = offsetInfo.indiceOffset; + _vfOffset = offsetInfo.byteOffset >> 2; + _vertexOffset = offsetInfo.vertexOffset; vbuf = _buffer._vData; ibuf = _buffer._iData; uintbuf = _buffer._uintVData; @@ -203,6 +203,7 @@ let armatureAssembler = { let vbuf, ibuf, uintbuf; let material; + let offsetInfo; let vertices = frame.vertices; let indices = frame.indices; let uintVert = frame.uintVert; @@ -235,12 +236,11 @@ let armatureAssembler = { _vertexCount = segInfo.vertexCount; _indexCount = segInfo.indexCount; - - _vfOffset = _buffer.byteOffset >> 2; - _indexOffset = _buffer.indiceOffset; - _vertexOffset = _buffer.vertexOffset; - - _buffer.request(_vertexCount, _indexCount); + + offsetInfo = _buffer.request(_vertexCount, _indexCount); + _indexOffset = offsetInfo.indiceOffset; + _vertexOffset = offsetInfo.vertexOffset; + _vfOffset = offsetInfo.byteOffset >> 2; vbuf = _buffer._vData; ibuf = _buffer._iData; uintbuf = _buffer._uintVData; diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 25621000b3f..84bd012aa0e 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -142,6 +142,7 @@ var spineAssembler = { let vbuf = buffer._vData, ibuf = buffer._iData, uintVData = buffer._uintVData; + let offsetInfo; _tempa = slotColor.a * attachmentColor.a * skeletonColor.a * 255; _multiplier = _premultipliedAlpha? _tempa : 255; @@ -189,7 +190,10 @@ var spineAssembler = { _indexCount = clippedTriangles.length; _vertexFloatCount = clippedVertices.length / _perClipVertexSize * _perVertexSize; - buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + offsetInfo = buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + _indexOffset = offsetInfo.indiceOffset, + _vertexOffset = offsetInfo.vertexOffset, + _vertexFloatOffset = offsetInfo.byteOffset >> 2; vbuf = buffer._vData, ibuf = buffer._iData; uintVData = buffer._uintVData; @@ -229,6 +233,8 @@ var spineAssembler = { let node = comp.node; node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; + let locSkeleton = comp._skeleton; + if (!locSkeleton) return; let nodeColor = node._color; _nodeR = nodeColor.r / 255; @@ -242,7 +248,6 @@ var spineAssembler = { let vbuf; let ibuf; - let locSkeleton = comp._skeleton; let skeletonColor = locSkeleton.color; let graphics = comp._debugRenderer; let clipper = comp._clipper; @@ -250,6 +255,7 @@ var spineAssembler = { let attachment, attachmentColor, slotColor, uvs, triangles; let hasFlush = false; let isRegion, isMesh, isClip; + let offsetInfo; _premultipliedAlpha = comp.premultipliedAlpha; _multiplier = 1.0; @@ -296,10 +302,6 @@ var spineAssembler = { _vertexFloatCount = 0; _indexCount = 0; - - _indexOffset = buffer.indiceOffset, - _vertexOffset = buffer.vertexOffset, - _vertexFloatOffset = buffer.byteOffset >> 2; attachment = slot.getAttachment(); if (!attachment) continue; @@ -335,7 +337,10 @@ var spineAssembler = { _vertexFloatCount = 4 * _perVertexSize; _indexCount = 6; - buffer.request(4, 6); + offsetInfo = buffer.request(4, 6); + _indexOffset = offsetInfo.indiceOffset, + _vertexOffset = offsetInfo.vertexOffset, + _vertexFloatOffset = offsetInfo.byteOffset >> 2; vbuf = buffer._vData, ibuf = buffer._iData; uintVData = buffer._uintVData; @@ -361,7 +366,10 @@ var spineAssembler = { _vertexFloatCount = (attachment.worldVerticesLength >> 1) * _perVertexSize; _indexCount = triangles.length; - buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + offsetInfo = buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + _indexOffset = offsetInfo.indiceOffset, + _vertexOffset = offsetInfo.vertexOffset, + _vertexFloatOffset = offsetInfo.byteOffset >> 2; vbuf = buffer._vData, ibuf = buffer._iData; uintVData = buffer._uintVData; From 791765f21b5bc8c0ab1e478fdc396293fb8d761a Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Wed, 30 Jan 2019 14:51:10 +0800 Subject: [PATCH 0430/1631] Fix sp.Skeleton asset migration (#3771) (#3803) Version 1.10 used to serialize this property as `_premultipliedAlpha` --- extensions/spine/Skeleton.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index f3f2af98da5..2009a0c0b64 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -311,6 +311,7 @@ sp.Skeleton = cc.Class({ */ premultipliedAlpha: { default: true, + formerlySerializedAs: "_premultipliedAlpha", tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.premultipliedAlpha' }, @@ -1014,4 +1015,4 @@ sp.Skeleton = cc.Class({ }, }); -module.exports = sp.Skeleton; \ No newline at end of file +module.exports = sp.Skeleton; From 89394d7f724fa3375124ff31b4d994024a0bc3b1 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Wed, 30 Jan 2019 15:29:03 +0800 Subject: [PATCH 0431/1631] Fix the problem that the button display error when it is grayed out after changing the color. (#3793) * Add dynamic configuration of useColor to GraySpriteMaterial. * Change the default value of useColor. --- cocos2d/core/renderer/render-engine.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index a16d6f86d64..7d76d8010bb 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -13703,9 +13703,10 @@ var chunks = { var templates = [ { name: 'gray_sprite', - vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute mediump vec2 a_uv0;\nvarying mediump vec2 uv0;\nvoid main () {\n vec4 pos = viewProj * vec4(a_position, 1);\n gl_Position = pos;\n uv0 = a_uv0;\n}', - frag: '\n \nuniform sampler2D texture;\nvarying mediump vec2 uv0;\nuniform lowp vec4 color;\nvoid main () {\n vec4 c = color * texture2D(texture, uv0);\n float gray = 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;\n gl_FragColor = vec4(gray, gray, gray, c.a);\n}', + vert: '\n \nuniform mat4 viewProj;\nattribute vec3 a_position;\nattribute mediump vec2 a_uv0;\nvarying mediump vec2 uv0;\n#ifndef useColor\nattribute lowp vec4 a_color;\nvarying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n vec4 pos = viewProj * vec4(a_position, 1);\n gl_Position = pos;\n uv0 = a_uv0;\n #ifndef useColor\n v_fragmentColor = a_color;\n #endif\n}', + frag: '\n \nuniform sampler2D texture;\nvarying mediump vec2 uv0;\n#ifdef useColor\n uniform lowp vec4 color;\n#else\n varying lowp vec4 v_fragmentColor;\n#endif\nvoid main () {\n #ifdef useColor\n vec4 o = color;\n #else\n vec4 o = v_fragmentColor;\n #endif\n vec4 c = o * texture2D(texture, uv0);\n float gray = 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;\n gl_FragColor = vec4(gray, gray, gray, c.a);\n}', defines: [ + { name: 'useColor', } ], }, { @@ -14390,7 +14391,9 @@ var GraySpriteMaterial = (function (Material$$1) { { 'color': this._color }, - [] + [ + { name: 'useColor', value: false } + ] ); this._mainTech = mainTech; From c139c2e12f41bd05c370c974ebabee8e29ee34c5 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Wed, 30 Jan 2019 15:29:42 +0800 Subject: [PATCH 0432/1631] modify the debug info (#3802) --- EngineErrorMap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EngineErrorMap.md b/EngineErrorMap.md index 369240cbd7a..c078885c3bf 100644 --- a/EngineErrorMap.md +++ b/EngineErrorMap.md @@ -174,7 +174,7 @@ loadScene: Unknown name type to load: '%s' ### 1208 -loadScene: Failed to load scene '%s' because '%s' is already loading +loadScene: Failed to load scene '%s' because '%s' is already being loaded. ### 1209 From 29568124e3e26791f787bb2053c415fda59a2e67 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Thu, 10 Jan 2019 10:26:47 +0800 Subject: [PATCH 0433/1631] Fix bmfont error in subdomain and setting color invalid. (#3731) --- cocos2d/core/renderer/canvas/renderers/label/bmfont.js | 4 ++-- cocos2d/core/renderer/canvas/renderers/utils.js | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js index 301a950090e..fdfae6720ca 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js +++ b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js @@ -87,10 +87,10 @@ module.exports = js.addon({ // opacity ctx.globalAlpha = node.opacity / 255; - let tex = comp._texture, + let tex = comp._frame._texture, data = comp._renderData._data; - let image = tex.getHtmlElementObj(); + let image = utils.getColorizedImage(tex, node._color); for (let i = 0, l = data.length; i < l; i+=2) { let x = data[i].x; diff --git a/cocos2d/core/renderer/canvas/renderers/utils.js b/cocos2d/core/renderer/canvas/renderers/utils.js index 202add731da..427ffae0eae 100644 --- a/cocos2d/core/renderer/canvas/renderers/utils.js +++ b/cocos2d/core/renderer/canvas/renderers/utils.js @@ -27,9 +27,6 @@ const WHITE = (255<<16) + (255<<8) + 255; const MAX_CANVAS_COUNT = 32; function colorizedFrame (canvas, texture, color, sx, sy, sw, sh) { - if (cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { - return canvas; - } let image = texture._image; let ctx = canvas.getContext("2d"); From 04151c680ac1fa89551d57e6444da56319a71f9c Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Wed, 9 Jan 2019 22:53:13 +0800 Subject: [PATCH 0434/1631] fix the creator.d.ts EventListener lost prop (#3727) fix the text and label note error --- cocos2d/core/components/CCLabel.js | 2 +- cocos2d/core/components/CCRichText.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index a58301cf66b..23fbab46080 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -371,7 +371,7 @@ let Label = cc.Class({ /** * !#en Whether use system font name or not. * !#zh 是否使用系统字体。 - * @property {Boolean} isSystemFontUsed + * @property {Boolean} useSystemFont */ useSystemFont: { get () { diff --git a/cocos2d/core/components/CCRichText.js b/cocos2d/core/components/CCRichText.js index 7203e30d49d..e2fa38f4fb6 100644 --- a/cocos2d/core/components/CCRichText.js +++ b/cocos2d/core/components/CCRichText.js @@ -237,7 +237,7 @@ let RichText = cc.Class({ /** * !#en Whether use system font name or not. * !#zh 是否使用系统字体。 - * @property {Boolean} isSystemFontUsed + * @property {Boolean} useSystemFont */ _isSystemFontUsed: true, useSystemFont: { From 4ed900eae5fceb85fd2d6e0ca33b27e22ff0c407 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Sun, 3 Feb 2019 10:38:29 +0800 Subject: [PATCH 0435/1631] Add _maxPixelRatio setting to view --- cocos2d/core/platform/CCView.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index 5808f8c7f09..62c66b02716 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -151,6 +151,7 @@ var View = function () { _t._autoFullScreen = false; // The device's pixel ratio (for retina displays) _t._devicePixelRatio = 1; + _t._maxPixelRatio = 2; // Retina disabled by default _t._retinaEnabled = false; // Custom callback for resize event @@ -1083,7 +1084,7 @@ cc.ContainerStrategy = cc.Class({ // Setup pixel ratio for retina display var devicePixelRatio = view._devicePixelRatio = 1; if (view.isRetinaEnabled()) - devicePixelRatio = view._devicePixelRatio = Math.min(2, window.devicePixelRatio || 1); + devicePixelRatio = view._devicePixelRatio = Math.min(view._maxPixelRatio, window.devicePixelRatio || 1); // Setup canvas locCanvas.width = w * devicePixelRatio; locCanvas.height = h * devicePixelRatio; From ca5191a5e68dee690b9c84cf0b222b45b1a9420c Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 11 Feb 2019 10:01:27 +0800 Subject: [PATCH 0436/1631] fix set button.interactable as false before __preload && update originalScale on target scale changed (#3764) * fix set button.interactable as false before __preload * update originalScale on target scale changed && add registerNodeEvent * fix button --- cocos2d/core/components/CCButton.js | 137 +++++++++++++++++++--------- 1 file changed, 93 insertions(+), 44 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 37378899675..11dd68d6425 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -136,7 +136,7 @@ let Button = cc.Class({ // init _originalScale in __preload() this._fromScale = cc.Vec2.ZERO; this._toScale = cc.Vec2.ZERO; - this._originalScale = cc.Vec2.ZERO; + this._originalScale = null; this._sprite = null; }, @@ -388,8 +388,13 @@ let Button = cc.Class({ default: null, type: cc.Node, tooltip: CC_DEV && "i18n:COMPONENT.button.target", - notify () { - this._applyTarget(); + notify (oldValue) { + if (oldValue !== this.target) { + this._applyTarget(); + if (oldValue) { + this._unregisterNodeEvent(oldValue); + } + } } }, @@ -422,7 +427,7 @@ let Button = cc.Class({ let transition = this.transition; if (transition === Transition.COLOR && this.interactable) { this._setTargetColor(this.normalColor); - } else if (transition === Transition.SCALE) { + } else if (transition === Transition.SCALE && this._originalScale) { target.scaleX = this._originalScale.x; target.scaleY = this._originalScale.y; } @@ -443,21 +448,6 @@ let Button = cc.Class({ if (this.disabledSprite) { this.disabledSprite.ensureLoadTexture(); } - // - if (!CC_EDITOR) { - this._registerEvent(); - } else { - this.node.on('spriteframe-changed', function (comp) { - if (this.transition === Transition.SPRITE) { - this._setCurrentStateSprite(comp.spriteFrame); - } - }.bind(this)); - this.node.on('color-changed', function (color) { - if (this.transition === Transition.COLOR) { - this._setCurrentStateColor(color); - } - }.bind(this)); - } }, _getTarget () { @@ -532,18 +522,12 @@ let Button = cc.Class({ onDisable () { this._resetState(); + }, - if (!CC_EDITOR) { - this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this); - this.node.off(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this); - this.node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); - this.node.off(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this); - - this.node.off(cc.Node.EventType.MOUSE_ENTER, this._onMouseMoveIn, this); - this.node.off(cc.Node.EventType.MOUSE_LEAVE, this._onMouseMoveOut, this); - } else { - this.node.off('spriteframe-changed'); - } + onDestroy () { + let target = this._getTarget(); + this._unregisterNodeEvent(target); + this._originalScale = null; }, update (dt) { @@ -557,28 +541,81 @@ let Button = cc.Class({ ratio = this.time / this.duration; } + // clamp ratio if (ratio >= 1) { ratio = 1; - this._transitionFinished = true; } if (this.transition === Transition.COLOR) { let color = this._fromColor.lerp(this._toColor, ratio); this._setTargetColor(color); - } else if (this.transition === Transition.SCALE) { + } + // Skip if _originalScale is invalid + else if (this.transition === Transition.SCALE && this._originalScale) { target.scale = this._fromScale.lerp(this._toScale, ratio); } + if (ratio === 1) { + this._transitionFinished = true; + } + + }, + + _registerNodeEvent (node) { + if (CC_EDITOR) { + node.on('spriteframe-changed', this._onNodeSpriteFrameChanged, this); + node.on(cc.Node.EventType.COLOR_CHANGED, this._onNodeColorChanged, this); + node.on(cc.Node.EventType.SCALE_CHANGED, this._onNodeScaleChanged, this); + } + else { + node.on(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this); + node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this); + node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); + node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this); + + node.on(cc.Node.EventType.MOUSE_ENTER, this._onMouseMoveIn, this); + node.on(cc.Node.EventType.MOUSE_LEAVE, this._onMouseMoveOut, this); + } + }, + + _unregisterNodeEvent (node) { + if (CC_EDITOR) { + node.off('spriteframe-changed', this._onNodeSpriteFrameChanged, this); + node.off(cc.Node.EventType.COLOR_CHANGED, this._onNodeColorChanged, this); + node.off(cc.Node.EventType.SCALE_CHANGED, this._onNodeScaleChanged, this); + } + else { + node.off(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this); + node.off(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this); + node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); + node.off(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this); + + node.off(cc.Node.EventType.MOUSE_ENTER, this._onMouseMoveIn, this); + node.off(cc.Node.EventType.MOUSE_LEAVE, this._onMouseMoveOut, this); + } }, - _registerEvent () { - this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this); - this.node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this); - this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); - this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this); + _onNodeScaleChanged () { + let target = this._getTarget(); + // update _originalScale if target scale changed + if (this._originalScale) { + if (this.transition !== Transition.SCALE || this._transitionFinished) { + this._originalScale.x = target.scaleX; + this._originalScale.y = target.scaleY; + } + } + }, - this.node.on(cc.Node.EventType.MOUSE_ENTER, this._onMouseMoveIn, this); - this.node.on(cc.Node.EventType.MOUSE_LEAVE, this._onMouseMoveOut, this); + _onNodeSpriteFrameChanged (comp) { + if (this.transition === Transition.SPRITE) { + this._setCurrentStateSprite(comp.spriteFrame); + } + }, + + _onNodeColorChanged (color) { + if (this.transition === Transition.COLOR) { + this._setCurrentStateColor(color); + } }, _getTargetSprite (target) { @@ -592,8 +629,12 @@ let Button = cc.Class({ _applyTarget () { let target = this._getTarget(); this._sprite = this._getTargetSprite(target); + if (!this._originalScale) { + this._originalScale = cc.Vec2.ZERO; + } this._originalScale.x = target.scaleX; this._originalScale.y = target.scaleY; + this._registerNodeEvent(target); }, // touch event handler @@ -607,13 +648,12 @@ let Button = cc.Class({ _onTouchMove (event) { if (!this.interactable || !this.enabledInHierarchy || !this._pressed) return; + let target = this._getTarget(); // mobile phone will not emit _onMouseMoveOut, // so we have to do hit test when touch moving let touch = event.touch; - let hit = this.node._hitTest(touch.getLocation()); - let target = this._getTarget(); - - if (this.transition === Transition.SCALE) { + let hit = target._hitTest(touch.getLocation()); + if (this.transition === Transition.SCALE && this._originalScale) { if (hit) { this._fromScale.x = this._originalScale.x; this._fromScale.y = this._originalScale.y; @@ -642,8 +682,9 @@ let Button = cc.Class({ if (!this.interactable || !this.enabledInHierarchy) return; if (this._pressed) { + let target = this._getTarget(); cc.Component.EventHandler.emitEvents(this.clickEvents, event); - this.node.emit('click', this); + target.emit('click', this); } this._pressed = false; this._updateState(); @@ -733,6 +774,10 @@ let Button = cc.Class({ }, _zoomUp () { + // skip before __preload() + if (!this._originalScale) { + return; + } this._fromScale.x = this._originalScale.x; this._fromScale.y = this._originalScale.y; this._toScale.x = this._originalScale.x * this.zoomScale; @@ -742,6 +787,10 @@ let Button = cc.Class({ }, _zoomBack () { + // skip before __preload() + if (!this._originalScale) { + return; + } let target = this._getTarget(); this._fromScale.x = target.scaleX; this._fromScale.y = target.scaleY; From 9546fb0f9c421d190e0aba7645402156498449ea Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 12 Feb 2019 14:32:36 +0800 Subject: [PATCH 0437/1631] support etc1 texture (#3800) * support etc1 texture * change define from _USE_ETC_ to _USE_ETC1_ --- cocos2d/core/assets/CCTexture2D.js | 12 +++++-- cocos2d/core/assets/material/CCMaterial.js | 4 +++ cocos2d/core/load-pipeline/downloader.js | 2 +- cocos2d/core/load-pipeline/loader.js | 39 +++++++++++++++++++--- cocos2d/core/platform/CCMacro.js | 6 ++-- cocos2d/renderer/build/chunks/diffuse.inc | 3 ++ cocos2d/renderer/build/chunks/emissive.inc | 3 ++ 7 files changed, 59 insertions(+), 10 deletions(-) diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 5871e62eaea..9a2cd48e2f0 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -153,6 +153,13 @@ const PixelFormat = cc.Enum({ * @type {Number} */ RGBA_PVRTC_4BPPV1: gfx.TEXTURE_FMT_RGBA_PVRTC_4BPPV1, + /** + * rgb etc + * @property RGB_ETC1 + * @readonly + * @type {Number} + */ + RGB_ETC1: gfx.TEXTURE_FMT_RGB_ETC1, }); /** @@ -280,10 +287,11 @@ var Texture2D = cc.Class({ _FilterIndex: FilterIndex, // predefined most common extnames - extnames: ['.png', '.jpg', '.jpeg', '.bmp', '.webp', '.pvr', '.etc'], + extnames: ['.png', '.jpg', '.jpeg', '.bmp', '.webp', '.pvr', '.pkm'], _isCompressed (texture) { - return texture._format >= PixelFormat.RGB_PVRTC_2BPPV1 && texture._format <= PixelFormat.RGBA_PVRTC_4BPPV1; + let format = texture._format; + return (format >= PixelFormat.RGB_PVRTC_2BPPV1 && format <= PixelFormat.RGBA_PVRTC_4BPPV1) || format === PixelFormat.RGB_ETC1; } }, diff --git a/cocos2d/core/assets/material/CCMaterial.js b/cocos2d/core/assets/material/CCMaterial.js index 12b0710c773..04f10259d61 100644 --- a/cocos2d/core/assets/material/CCMaterial.js +++ b/cocos2d/core/assets/material/CCMaterial.js @@ -26,6 +26,7 @@ const Asset = require('../CCAsset'); const Texture = require('../CCTexture2D'); +const PixelFormat = Texture.PixelFormat; const EffectAsset = require('../CCEffectAsset'); import Effect from '../../../renderer/core/effect'; @@ -142,6 +143,9 @@ let Material = cc.Class({ if (this._effect) { if (val instanceof Texture) { this._effect.setProperty(name, val.getImpl()); + if (val.getPixelFormat() === PixelFormat.RGB_ETC1) { + this.define('_USE_ETC1_' + name.toUpperCase(), true); + } } else { this._effect.setProperty(name, val); diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index 379e3968612..523b4849801 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -149,7 +149,7 @@ var defaultMap = { 'webp' : downloadWebp, 'image' : downloadImage, 'pvr': downloadBinary, - 'etc': downloadBinary, + 'pkm': downloadBinary, // Audio 'mp3' : downloadAudio, diff --git a/cocos2d/core/load-pipeline/loader.js b/cocos2d/core/load-pipeline/loader.js index 557e0be0595..a04c7af2239 100644 --- a/cocos2d/core/load-pipeline/loader.js +++ b/cocos2d/core/load-pipeline/loader.js @@ -124,7 +124,7 @@ const PVR_HEADER_WIDTH = 7; const PVR_HEADER_MIPMAPCOUNT = 11; const PVR_HEADER_METADATA = 12; -function loadCompressedTex (item) { +function loadPVRTex (item) { let buffer = item.content instanceof ArrayBuffer ? item.content : item.content.buffer; // Get a view of the arrayBuffer that represents the DDS header. let header = new Int32Array(buffer, 0, PVR_HEADER_LENGTH); @@ -137,7 +137,6 @@ function loadCompressedTex (item) { // 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 levels = header[PVR_HEADER_MIPMAPCOUNT]; let dataOffset = header[PVR_HEADER_METADATA] + 52; let pvrtcData = new Uint8Array(buffer, dataOffset); @@ -152,6 +151,38 @@ function loadCompressedTex (item) { return pvrAsset; } +//===============// +// ETC constants // +//===============// +const ETC1_PKM_FORMAT_OFFSET = 6; +const ETC1_PKM_ENCODED_WIDTH_OFFSET = 8; +const ETC1_PKM_ENCODED_HEIGHT_OFFSET = 10; +const ETC1_PKM_WIDTH_OFFSET = 12; +const ETC1_PKM_HEIGHT_OFFSET = 14; +const ETC1_RGB_NO_MIPMAPS = 0; +const ETC_PKM_HEADER_SIZE = 16; + +function readBEUint16(header, offset) { + return (header[offset] << 8) | header[offset+1]; +} +function loadPKMTex(item) { + let buffer = item.content instanceof ArrayBuffer ? item.content : item.content.buffer; + let header = new Uint8Array(buffer); + if (readBEUint16(header, ETC1_PKM_FORMAT_OFFSET) !== ETC1_RGB_NO_MIPMAPS) return new Error("Invalid magic number in ETC header"); + let width = readBEUint16(header, ETC1_PKM_WIDTH_OFFSET); + let height = readBEUint16(header, ETC1_PKM_HEIGHT_OFFSET); + let encodedWidth = readBEUint16(header, ETC1_PKM_ENCODED_WIDTH_OFFSET); + let encodedHeight = readBEUint16(header, ETC1_PKM_ENCODED_HEIGHT_OFFSET); + let etcData = new Uint8Array(buffer, ETC_PKM_HEADER_SIZE); + let etcAsset = { + _data: etcData, + _compressed: true, + width: width, + height: height + }; + return etcAsset; +} + var defaultMap = { // Images 'png' : loadImage, @@ -163,8 +194,8 @@ var defaultMap = { 'tiff' : loadImage, 'webp' : loadImage, 'image' : loadImage, - 'pvr' : loadCompressedTex, - 'etc' : loadCompressedTex, + 'pvr' : loadPVRTex, + 'pkm' : loadPKMTex, // Audio 'mp3' : loadAudioAsAsset, diff --git a/cocos2d/core/platform/CCMacro.js b/cocos2d/core/platform/CCMacro.js index a2e247bf59d..8b1d4672fdd 100644 --- a/cocos2d/core/platform/CCMacro.js +++ b/cocos2d/core/platform/CCMacro.js @@ -361,9 +361,9 @@ if (cc.sys.isMobile) { if (cc.sys.os === cc.sys.OS_IOS) { SUPPORT_TEXTURE_FORMATS = ['.pvr'].concat(SUPPORT_TEXTURE_FORMATS); } - // else if (cc.sys.os === cc.sys.OS_ANDROID) { - // SUPPORT_TEXTURE_FORMATS = ['.etc'].join(SUPPORT_TEXTURE_FORMATS); - // } + else if (cc.sys.os === cc.sys.OS_ANDROID) { + SUPPORT_TEXTURE_FORMATS = ['.pkm'].concat(SUPPORT_TEXTURE_FORMATS); + } } /** diff --git a/cocos2d/renderer/build/chunks/diffuse.inc b/cocos2d/renderer/build/chunks/diffuse.inc index a9846ab0c30..4a6c1ddbeef 100644 --- a/cocos2d/renderer/build/chunks/diffuse.inc +++ b/cocos2d/renderer/build/chunks/diffuse.inc @@ -10,6 +10,9 @@ uniform vec4 diffuseColor; void MULTIPLY_DIFFUSE_TEXTRUE_COLOR (inout vec4 color, in vec2 uv) { #if USE_DIFFUSE_TEXTURE && _USE_ATTRIBUTE_UV0 vec4 diffuseTextureColor = texture2D(diffuseTexture, uv); + #if _USE_ETC1_DIFFUSETEXTURE + diffuseTextureColor.a *= texture2D(diffuseTexture, uv + vec2(0, 0.5)).r; + #endif color *= TEXEL_TO_LINEAR(diffuseTextureColor); #endif } diff --git a/cocos2d/renderer/build/chunks/emissive.inc b/cocos2d/renderer/build/chunks/emissive.inc index d0088675b94..b3c19b79f7a 100644 --- a/cocos2d/renderer/build/chunks/emissive.inc +++ b/cocos2d/renderer/build/chunks/emissive.inc @@ -13,6 +13,9 @@ void MULTIPLY_EMISSIVE_TEXTRUE_COLOR (inout vec3 color, in vec2 uv) { #if USE_EMISSIVE_TEXTURE && _USE_ATTRIBUTE_UV0 vec4 emissiveTextureColor = texture2D(emissiveTexture, uv); + #if _USE_ETC1_EMISSIVETEXTURE + emissiveTextureColor.a *= texture2D(emissiveTexture, uv + vec2(0, 0.5)).r; + #endif emissiveTextureColor = TEXEL_TO_LINEAR(emissiveTextureColor); color *= emissiveTextureColor.rgb; #endif From de46973d0b5edcff4f973186ce89752080cb6b7c Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 12 Feb 2019 14:34:02 +0800 Subject: [PATCH 0438/1631] modify the warning (#3825) --- cocos2d/core/platform/CCClassDecorator.js | 5 ++++- cocos2d/core/platform/preprocess-class.js | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/platform/CCClassDecorator.js b/cocos2d/core/platform/CCClassDecorator.js index aeaef2eb44f..8676065fef8 100644 --- a/cocos2d/core/platform/CCClassDecorator.js +++ b/cocos2d/core/platform/CCClassDecorator.js @@ -228,7 +228,10 @@ function genProperty (ctor, properties, propName, options, desc, cache) { isDefaultValueSpecified && defaultValue == null ) { - cc.warnID(3656, JS.getClassName(ctor), propName); + // Avoid excessive warning when the ts decorator format is wrong + if (typeof options !== 'function' || cc.RawAsset.isRawAssetType(options)) { + cc.warnID(3656, js.getClassName(ctor), propName); + } } } prop.default = defaultValue; diff --git a/cocos2d/core/platform/preprocess-class.js b/cocos2d/core/platform/preprocess-class.js index 2d96214d7b5..68358814b53 100644 --- a/cocos2d/core/platform/preprocess-class.js +++ b/cocos2d/core/platform/preprocess-class.js @@ -226,11 +226,16 @@ exports.getFullFormOfProperty = function (options, propname_dev, classname_dev) 'Please use the complete form.\n' + 'For example, if property is Texture2D\'s url array, the previous definition is:\n' + ' %s: [cc.Texture2D],\n' + - 'Now it should be changed to:\n' + + 'If you use JS, it should be changed to:\n' + ' %s: {\n' + ' type: cc.Texture2D, // use \'type:\' to define an array of Texture2D objects\n' + ' default: []\n' + ' },\n' + + 'If you use TS, it should be changed to:\n' + + ' %s: {\n' + + ' type: cc.Texture2D, // use \'type:\' to define an array of Texture2D objects\n' + + ' }\n' + + ' %s: cc.Texture2D[] = [];\n'+ '(This helps us to successfully refactor all RawAssets at v2.0, ' + 'sorry for the inconvenience. \uD83D\uDE30 )', propname_dev, classname_dev, propname_dev, propname_dev); @@ -257,11 +262,16 @@ exports.getFullFormOfProperty = function (options, propname_dev, classname_dev) 'Please use the complete form.\n' + 'For example, if the type is Texture2D, the previous definition is:\n' + ' %s: cc.Texture2D,\n' + - 'Now it should be changed to:\n' + + 'If you use JS, it should be changed to:\n' + ' %s: {\n' + ' type: cc.Texture2D // use \'type:\' to define Texture2D object directly\n' + ' default: null, // object\'s default value is null\n' + ' },\n' + + 'If you use TS, it should be changed to:\n' + + ' %s: {\n' + + ' type: cc.Texture2D // use \'type:\' to define Texture2D object directly\n' + + ' }\n' + + ' %s: cc.Texture2D = null;\n'+ '(This helps us to successfully refactor all RawAssets at v2.0, ' + 'sorry for the inconvenience. \uD83D\uDE30 )', propname_dev, classname_dev, propname_dev, propname_dev); From 1018570c9b44e1921686ed8670eaa034391d2b88 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 12 Feb 2019 14:35:17 +0800 Subject: [PATCH 0439/1631] Button note (#3831) * modify the button note * add the desciption to node event --- cocos2d/core/CCNode.js | 30 ++++++++++++++++++++++++++++- cocos2d/core/components/CCButton.js | 3 ++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index ecf647278b6..29dfd738cb8 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1454,7 +1454,7 @@ var Node = cc.Class({ * 鼠标或触摸事件会被系统调用 dispatchEvent 方法触发,触发的过程包含三个阶段:
* 1. 捕获阶段:派发事件给捕获目标(通过 `_getCapturingTargets` 获取),比如,节点树中注册了捕获阶段的父节点,从根节点开始派发直到目标节点。
* 2. 目标阶段:派发给目标节点的监听器。
- * 3. 冒泡阶段:派发事件给冒泡目标(通过 `_getBubblingTargets` 获取),比如,节点树中注册了冒泡阶段的父节点,从目标节点开始派发知道根节点。
+ * 3. 冒泡阶段:派发事件给冒泡目标(通过 `_getBubblingTargets` 获取),比如,节点树中注册了冒泡阶段的父节点,从目标节点开始派发直到根节点。
* 同时您可以将事件派发到父节点或者通过调用 stopPropagation 拦截它。
* 推荐使用这种方式来监听节点上的触摸或鼠标事件,请不要在节点上直接使用 cc.eventManager。
* 你也可以注册自定义事件到节点上,并通过 emit 方法触发此类事件,对于这类事件,不会发生捕获冒泡阶段,只会直接派发给注册在该节点上的监听器
@@ -3094,29 +3094,57 @@ var Node = cc.Class({ }); /** + * !#en + * The position changing event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.POSITION_CHANGED, callback, this); + * !#zh + * 位置变动监听事件, 通过 cc.node.on(cc.Node.EventType.POSITION_CHANGED, callback, this); 进行监听。 * @event position-changed * @param {Vec2} oldPos - The old position, but this parameter is only available in editor! */ /** + * !#en + * The size changing event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.SIZE_CHANGED, callback, this); + * !#zh + * 尺寸变动监听事件,通过 cc.node.on(cc.Node.EventType.SIZE_CHANGED, callback, this); 进行监听。 * @event size-changed * @param {Size} oldSize - The old size, but this parameter is only available in editor! */ /** + * !#en + * The anchor changing event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.ANCHOR_CHANGED, callback, this); + * !#zh + * 锚点变动监听事件,通过 cc.node.on(cc.Node.EventType.ANCHOR_CHANGED, callback, this); 进行监听。 * @event anchor-changed */ /** + * !#en + * The adding child event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.CHILD_ADDED, callback, this); + * !#zh + * 增加子节点监听事件,通过 cc.node.on(cc.Node.EventType.CHILD_ADDED, callback, this); 进行监听。 * @event child-added * @param {Node} child - child which have been added */ /** + * !#en + * The removing child event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.CHILD_REMOVED, callback, this); + * !#zh + * 删除子节点监听事件,通过 cc.node.on(cc.Node.EventType.CHILD_REMOVED, callback, this); 进行监听。 * @event child-removed * @param {Node} child - child which have been removed */ /** + * !#en + * The reordering child event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.CHILD_REORDER, callback, this); + * !#zh + * 自节点顺序变动监听事件,通过 cc.node.on(cc.Node.EventType.CHILD_REORDER, callback, this); 进行监听。 * @event child-reorder * @param {Node} node - node whose children have been reordered */ /** + * !#en + * The group changing event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.GROUP_CHANGED, callback, this); + * !#zh + * 节点分组变动监听事件,通过 cc.node.on(cc.Node.EventType.GROUP_CHANGED, callback, this); 进行监听。 * @event group-changed * @param {Node} node - node whose group has changed */ diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 11dd68d6425..b073d3c92d7 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -82,6 +82,7 @@ const State = cc.Enum({ * Button.EVENT_HOVER_IN
* Button.EVENT_HOVER_MOVE
* Button.EVENT_HOVER_OUT
+ * User can get the current clicked node with 'event.target' from event object which is passed as parameter in the callback function of click event. * * !#zh * 按钮组件。可以被按下,或者点击。
@@ -105,7 +106,7 @@ const State = cc.Enum({ * -cc.Node.EventType.MOUSE_LEAVE // 鼠标离开目标事件
* -cc.Node.EventType.MOUSE_UP // 鼠标松开事件
* -cc.Node.EventType.MOUSE_WHEEL // 鼠标滚轮事件
- * + * 用户可以通过获取 __点击事件__ 回调函数的参数 event 的 target 属性获取当前点击对象。 * @class Button * @extends Component * @example From a3bfccbca34ed4bb2057900d747d6d5ac5c6ef3b Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 12 Feb 2019 16:09:43 +0800 Subject: [PATCH 0440/1631] add notify object to support reset data (#3835) --- cocos2d/core/platform/CCClass.js | 2 ++ cocos2d/core/platform/preprocess-class.js | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/cocos2d/core/platform/CCClass.js b/cocos2d/core/platform/CCClass.js index a138d2f84b9..cec4acf62be 100644 --- a/cocos2d/core/platform/CCClass.js +++ b/cocos2d/core/platform/CCClass.js @@ -1187,6 +1187,8 @@ function parseAttributes (cls, attrs, className, propName, usedInGetter) { parseSimpleAttr('formerlySerializedAs', 'string'); if (CC_EDITOR) { + parseSimpleAttr('notifyFor', 'string'); + if ('animatable' in attrs && !attrs.animatable) { (attrsProto || getAttrsProto())[attrsProtoKey + 'animatable'] = false; } diff --git a/cocos2d/core/platform/preprocess-class.js b/cocos2d/core/platform/preprocess-class.js index ee15f9b2ac9..9c33041f43b 100644 --- a/cocos2d/core/platform/preprocess-class.js +++ b/cocos2d/core/platform/preprocess-class.js @@ -67,6 +67,10 @@ function parseNotify (val, propName, notify, properties) { notify.call(this, oldValue); }; + if (CC_EDITOR) { + val.notifyFor = newKey; + } + var newValue = {}; properties[newKey] = newValue; // 将不能用于get方法中的属性移动到newValue中 From 01401a8631615a6e35fad596fa58b5807a2d42d9 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Tue, 12 Feb 2019 16:55:55 +0800 Subject: [PATCH 0441/1631] modify the event note (#3836) --- cocos2d/core/CCNode.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 29dfd738cb8..06731bdae3d 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -3095,56 +3095,56 @@ var Node = cc.Class({ /** * !#en - * The position changing event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.POSITION_CHANGED, callback, this); + * The position changing event, you can listen to this event through the statement this.node.on(cc.Node.EventType.POSITION_CHANGED, callback, this); * !#zh - * 位置变动监听事件, 通过 cc.node.on(cc.Node.EventType.POSITION_CHANGED, callback, this); 进行监听。 + * 位置变动监听事件, 通过 this.node.on(cc.Node.EventType.POSITION_CHANGED, callback, this); 进行监听。 * @event position-changed * @param {Vec2} oldPos - The old position, but this parameter is only available in editor! */ /** * !#en - * The size changing event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.SIZE_CHANGED, callback, this); + * The size changing event, you can listen to this event through the statement this.node.on(cc.Node.EventType.SIZE_CHANGED, callback, this); * !#zh - * 尺寸变动监听事件,通过 cc.node.on(cc.Node.EventType.SIZE_CHANGED, callback, this); 进行监听。 + * 尺寸变动监听事件,通过 this.node.on(cc.Node.EventType.SIZE_CHANGED, callback, this); 进行监听。 * @event size-changed * @param {Size} oldSize - The old size, but this parameter is only available in editor! */ /** * !#en - * The anchor changing event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.ANCHOR_CHANGED, callback, this); + * The anchor changing event, you can listen to this event through the statement this.node.on(cc.Node.EventType.ANCHOR_CHANGED, callback, this); * !#zh - * 锚点变动监听事件,通过 cc.node.on(cc.Node.EventType.ANCHOR_CHANGED, callback, this); 进行监听。 + * 锚点变动监听事件,通过 this.node.on(cc.Node.EventType.ANCHOR_CHANGED, callback, this); 进行监听。 * @event anchor-changed */ /** * !#en - * The adding child event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.CHILD_ADDED, callback, this); + * The adding child event, you can listen to this event through the statement this.node.on(cc.Node.EventType.CHILD_ADDED, callback, this); * !#zh - * 增加子节点监听事件,通过 cc.node.on(cc.Node.EventType.CHILD_ADDED, callback, this); 进行监听。 + * 增加子节点监听事件,通过 this.node.on(cc.Node.EventType.CHILD_ADDED, callback, this); 进行监听。 * @event child-added * @param {Node} child - child which have been added */ /** * !#en - * The removing child event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.CHILD_REMOVED, callback, this); + * The removing child event, you can listen to this event through the statement this.node.on(cc.Node.EventType.CHILD_REMOVED, callback, this); * !#zh - * 删除子节点监听事件,通过 cc.node.on(cc.Node.EventType.CHILD_REMOVED, callback, this); 进行监听。 + * 删除子节点监听事件,通过 this.node.on(cc.Node.EventType.CHILD_REMOVED, callback, this); 进行监听。 * @event child-removed * @param {Node} child - child which have been removed */ /** * !#en - * The reordering child event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.CHILD_REORDER, callback, this); + * The reordering child event, you can listen to this event through the statement this.node.on(cc.Node.EventType.CHILD_REORDER, callback, this); * !#zh - * 自节点顺序变动监听事件,通过 cc.node.on(cc.Node.EventType.CHILD_REORDER, callback, this); 进行监听。 + * 子节点顺序变动监听事件,通过 this.node.on(cc.Node.EventType.CHILD_REORDER, callback, this); 进行监听。 * @event child-reorder * @param {Node} node - node whose children have been reordered */ /** * !#en - * The group changing event, you can listen to this event through the statement cc.node.on(cc.Node.EventType.GROUP_CHANGED, callback, this); + * The group changing event, you can listen to this event through the statement this.node.on(cc.Node.EventType.GROUP_CHANGED, callback, this); * !#zh - * 节点分组变动监听事件,通过 cc.node.on(cc.Node.EventType.GROUP_CHANGED, callback, this); 进行监听。 + * 节点分组变动监听事件,通过 this.node.on(cc.Node.EventType.GROUP_CHANGED, callback, this); 进行监听。 * @event group-changed * @param {Node} node - node whose group has changed */ From d60407ecf7d6ef0734d21c1561a7cd1b2fad4db9 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 14 Feb 2019 08:29:45 +0800 Subject: [PATCH 0442/1631] fix deserialization for default value of generic ValueTypes (#3843) * fix deserialization for default value of generic ValueTypes * refine --- cocos2d/core/CCGame.js | 2 +- cocos2d/core/platform/deserialize.js | 46 +++++++++++++++--------- test/qunit/unit-es5/test-deserialize.js | 40 ++++++++++++++++++++- test/qunit/unit-es5/test-serialize.js | 48 +++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 19 deletions(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 79074ea13dd..07ee3911eca 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -797,7 +797,7 @@ var game = { dynamicAtlasManager.enabled = true; } // Disable dynamicAtlasManager to fix rendering residue for transparent images on Chrome69. - if (cc.sys.browserType == cc.sys.BROWSER_TYPE_CHROME && parseFloat(cc.sys.browserVersion) >= 69.0) { + if (cc.sys.browserType === cc.sys.BROWSER_TYPE_CHROME && parseFloat(cc.sys.browserVersion) >= 69.0) { dynamicAtlasManager.enabled = false; } } diff --git a/cocos2d/core/platform/deserialize.js b/cocos2d/core/platform/deserialize.js index ec62b32a68e..26722a4b3ed 100644 --- a/cocos2d/core/platform/deserialize.js +++ b/cocos2d/core/platform/deserialize.js @@ -385,12 +385,19 @@ var _Deserializer = (function () { // } // } + // deserialize ValueType prototype._deserializeTypedObject = function (instance, serialized, klass) { if (klass === cc.Vec2) { instance.x = serialized.x || 0; instance.y = serialized.y || 0; return; } + else if (klass === cc.Vec3) { + instance.x = serialized.x || 0; + instance.y = serialized.y || 0; + instance.z = serialized.z || 0; + return; + } else if (klass === cc.Color) { instance.r = serialized.r || 0; instance.g = serialized.g || 0; @@ -405,29 +412,34 @@ var _Deserializer = (function () { return; } - var fastDefinedProps = klass.__props__; - if (!fastDefinedProps) { - fastDefinedProps = Object.keys(instance); // 遍历 instance,如果具有类型,才不会把 __type__ 也读进来 - } + var DEFAULT = Attr.DELIMETER + 'default'; + var attrs = Attr.getClassAttrs(klass); + var fastDefinedProps = klass.__props__ || + Object.keys(instance); // 遍历 instance,如果具有类型,才不会把 __type__ 也读进来 for (var i = 0; i < fastDefinedProps.length; i++) { var propName = fastDefinedProps[i]; - var prop = serialized[propName]; - if (prop !== undefined && serialized.hasOwnProperty(propName)) { - if (typeof prop !== 'object') { - instance[propName] = prop; - } - else if (prop) { - if (CC_EDITOR || CC_TEST) { - this._deserializeObjField(instance, prop, propName, this._target && instance); - } - else { - this._deserializeObjField(instance, prop, propName); - } + var value = serialized[propName]; + if (value === undefined || !serialized.hasOwnProperty(propName)) { + // not serialized, + // recover to default value in ValueType, because eliminated properties equals to + // its default value in ValueType, not default value in user class + value = CCClass.getDefault(attrs[propName + DEFAULT]); + } + + if (typeof value !== 'object') { + instance[propName] = value; + } + else if (value) { + if (CC_EDITOR || CC_TEST) { + this._deserializeObjField(instance, value, propName, this._target && instance); } else { - instance[propName] = null; + this._deserializeObjField(instance, value, propName); } } + else { + instance[propName] = null; + } } }; diff --git a/test/qunit/unit-es5/test-deserialize.js b/test/qunit/unit-es5/test-deserialize.js index e1566af8b8d..4cce1cbf69a 100644 --- a/test/qunit/unit-es5/test-deserialize.js +++ b/test/qunit/unit-es5/test-deserialize.js @@ -396,4 +396,42 @@ if (TestEditorExtends) { cc.js.unregisterClass(Asset); }); -} \ No newline at end of file + + test('eliminated default property for unknown value type', function () { + function Vec3 (x, y, z) { + this.x = x || 1; + this.y = y || 0; + this.z = z || 0; + } + cc.js.extend(Vec3, cc.ValueType); + cc.Class.fastDefine('Vector3', Vec3, { x: 1, y: 0, z: 0 }); + Vec3.prototype.clone = function () { + return new Vec3(this.x, this.y, this.z); + }; + window.Vector3 = Vec3; + + var MyAsset = cc.Class({ + name: 'MyAsset', + properties: { + scale1: new Vec3(1, 0, 0), + scale10: new Vec3(1, 99, 0), + } + }); + var asset = new MyAsset(); + asset.scale10.y = 0; + + var json = { + __type__: 'MyAsset', + scale10: { + __type__: 'Vector3', + }, + }; + + var result = cc.deserialize(json); + deepEqual(result.scale1, asset.scale1, 'should load eliminated entire property'); + deepEqual(result.scale10, asset.scale10, 'should load eliminated sub property'); + + cc.js.unregisterClass(Vec3, MyAsset); + delete window.Vector3; + }); +} diff --git a/test/qunit/unit-es5/test-serialize.js b/test/qunit/unit-es5/test-serialize.js index de860260bc6..0900feef8c3 100644 --- a/test/qunit/unit-es5/test-serialize.js +++ b/test/qunit/unit-es5/test-serialize.js @@ -528,4 +528,52 @@ cc.js.unregisterClass(MyAsset); }); + + test('eliminate default property', function () { + var MyAsset = cc.Class({ + name: 'MyAsset', + properties: { + scale0: cc.v3(0, 0, 0), + scale1: cc.v3(1, 1, 1), + scale00: cc.v3(0, 1, 0), + scale01: cc.v3(0, 0, 0), + scale10: cc.v3(1, 1, 1), + } + }); + var asset = new MyAsset(); + asset.scale00.y = 0; + asset.scale01.y = 1; + asset.scale10.y = 0; + + var expectedDefaultScaleResult = { + __type__: 'MyAsset', + scale00: { + __type__: "cc.Vec3", + }, + scale01: { + __type__: 'cc.Vec3', + y: 1, + }, + scale10: { + __type__: 'cc.Vec3', + x: 1, + z: 1, + }, + }; + + var actualDefaultScaled = JSON.parse(Editor.serialize(asset, { exporting: true, dontStripDefault: false })); + + // to read default value from ValueType instead of constructor of user class + deepEqual(actualDefaultScaled.scale00, expectedDefaultScaleResult.scale00, 'should leave a empty type declaration if equal to default value defined in ValueType'); + + // to make the deserialization for ValueTypes more unique and simplify + ok(actualDefaultScaled.scale10.x === 1 && actualDefaultScaled.scale10.z === 1, 'should serialize non-zero sub properties even if they equal to default values defined in user class'); + + ok(actualDefaultScaled.scale0 === undefined && actualDefaultScaled.scale1 === undefined, 'should eliminate entire property if equals to the default value defined in user class'); + + deepEqual(actualDefaultScaled, expectedDefaultScaleResult, 'test all serialized result'); + + cc.js.unregisterClass(MyAsset); + }); + } \ No newline at end of file From 1bb8b3074f70cccc236fea1c6a85952d435561c7 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 14 Feb 2019 18:09:23 +0800 Subject: [PATCH 0443/1631] fix mask hit ellipse bug (#3847) --- cocos2d/core/components/CCMask.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCMask.js b/cocos2d/core/components/CCMask.js index 4de028dbca0..8439da8ab0a 100644 --- a/cocos2d/core/components/CCMask.js +++ b/cocos2d/core/components/CCMask.js @@ -472,7 +472,7 @@ let Mask = cc.Class({ else if (this.type === MaskType.ELLIPSE) { let rx = w / 2, ry = h / 2; let px = testPt.x - 0.5 * w, py = testPt.y - 0.5 * h; - reult = px * px / (rx * rx) + py * py / (ry * ry) < 1; + result = px * px / (rx * rx) + py * py / (ry * ry) < 1; } if (this.inverted) { result = !result; From ac71c83b5787c2790e910f9abb1431f90e2fa0ed Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 15 Feb 2019 10:45:21 +0800 Subject: [PATCH 0444/1631] fix color toHEX bug (#3846) * fix color toHEX bug * refine code --- cocos2d/core/value-types/color.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/cocos2d/core/value-types/color.js b/cocos2d/core/value-types/color.js index 722b9f1c611..cf08a55634c 100644 --- a/cocos2d/core/value-types/color.js +++ b/cocos2d/core/value-types/color.js @@ -412,10 +412,11 @@ var Color = (function () { * color.toHEX("#rrggbb"); // "000000"; */ proto.toHEX = function ( fmt ) { - var hex = [ - (this.r | 0 ).toString(16), - (this.g | 0 ).toString(16), - (this.b | 0 ).toString(16) + let prefix = '0'; + let hex = [ + (this.r < 16 ? prefix : '') + (this.r | 0).toString(16), + (this.g < 16 ? prefix : '') + (this.g | 0).toString(16), + (this.b < 16 ? prefix : '') + (this.b | 0).toString(16), ]; var i = -1; if ( fmt === '#rgb' ) { @@ -432,13 +433,8 @@ var Color = (function () { } } } - else if ( fmt === '#rrggbbaa' ) { - hex.push((this.a | 0 ).toString(16)); - for ( i = 0; i < hex.length; ++i ) { - if ( hex[i].length === 1 ) { - hex[i] = '0' + hex[i]; - } - } + else if (fmt === '#rrggbbaa') { + hex.push((this.a < 16 ? prefix : '') + (this.a | 0).toString(16)); } return hex.join(''); }; From 5e10276777e4e1a2320ddc2f87768e182427d094 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Fri, 15 Feb 2019 13:08:12 +0800 Subject: [PATCH 0445/1631] Fix the problem of particleSystem repeatedly parsing image. (#3844) --- cocos2d/particle/CCParticleSystem.js | 40 +++++++++++++++------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index af9cb8c01d9..ee4d55757d5 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -964,27 +964,31 @@ var ParticleSystem = cc.Class({ var textureData = dict["textureImageData"]; if (textureData && textureData.length > 0) { - var buffer = codec.unzipBase64AsArray(textureData, 1); - if (!buffer) { - cc.logID(6030); - return false; - } + let tex = cc.loader.getRes(imgPath); + + if (!tex) { + var buffer = codec.unzipBase64AsArray(textureData, 1); + if (!buffer) { + cc.logID(6030); + return false; + } - var imageFormat = getImageFormatByData(buffer); - if (imageFormat !== macro.ImageFormat.TIFF && imageFormat !== macro.ImageFormat.PNG) { - cc.logID(6031); - return false; - } + var imageFormat = getImageFormatByData(buffer); + if (imageFormat !== macro.ImageFormat.TIFF && imageFormat !== macro.ImageFormat.PNG) { + cc.logID(6031); + return false; + } - var canvasObj = document.createElement("canvas"); - if(imageFormat === macro.ImageFormat.PNG){ - var myPngObj = new PNGReader(buffer); - myPngObj.render(canvasObj); - } else { - tiffReader.parseTIFF(buffer,canvasObj); + var canvasObj = document.createElement("canvas"); + if(imageFormat === macro.ImageFormat.PNG){ + var myPngObj = new PNGReader(buffer); + myPngObj.render(canvasObj); + } else { + tiffReader.parseTIFF(buffer,canvasObj); + } + tex = textureUtil.cacheImage(imgPath, canvasObj); } - - var tex = textureUtil.cacheImage(imgPath, canvasObj); + if (!tex) cc.logID(6032); // TODO: Use cc.loader to load asynchronously the SpriteFrame object, avoid using textureUtil From 1181ecf8de7eb417324cb71cdde1738bb06cd058 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Fri, 15 Feb 2019 13:50:23 +0800 Subject: [PATCH 0446/1631] Fix the flash problem when the label plays the fadeIn action. (#3837) * Fix the flash problem when the label plays the fadeIn action. * add alphaTest * Set the fillStyle of context to white. * Cancel the setting of blend factor. * Add the settings of alphaTest. * Delete updateColor in CCLabel. * Cancel alpha test. --- cocos2d/core/components/CCLabel.js | 22 ------------------- cocos2d/core/components/CCLabelOutline.js | 2 +- cocos2d/core/renderer/utils/label/ttf.js | 7 +++++- .../renderer/webgl/assemblers/label/ttf.js | 4 +--- 4 files changed, 8 insertions(+), 27 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index d73e5bca253..d3db11f20e0 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -575,10 +575,6 @@ let Label = cc.Class({ else { if (!this._ttfTexture) { this._ttfTexture = new cc.Texture2D(); - // TTF texture in web will blend with canvas or body background color - if (!CC_JSB && !CC_RUNTIME) { - this._ttfTexture.setPremultiplyAlpha(true); - } this._assemblerData = this._assembler._getAssemblerData(); this._ttfTexture.initWithElement(this._assemblerData.canvas); } @@ -612,13 +608,6 @@ let Label = cc.Class({ if (!material) { material = new SpriteMaterial(); } - // Setup blend function for premultiplied ttf label texture - if (this._frame._texture === this._ttfTexture) { - this._srcBlendFactor = cc.macro.BlendFactor.ONE; - } - else { - this._srcBlendFactor = cc.macro.BlendFactor.SRC_ALPHA; - } material.texture = this._frame._texture; // For batch rendering, do not use uniform color. material.useColor = false; @@ -628,17 +617,6 @@ let Label = cc.Class({ this.markForUpdateRenderData(true); this.markForRender(true); }, - - _updateColor () { - let font = this.font; - if (font instanceof cc.BitmapFont) { - this._super(); - } - else { - this._updateRenderData(); - this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; - } - }, _updateRenderData (force) { let renderData = this._renderData; diff --git a/cocos2d/core/components/CCLabelOutline.js b/cocos2d/core/components/CCLabelOutline.js index d846be4b955..6c80cf6ae43 100644 --- a/cocos2d/core/components/CCLabelOutline.js +++ b/cocos2d/core/components/CCLabelOutline.js @@ -98,7 +98,7 @@ let LabelOutline = cc.Class({ _updateRenderData () { let label = this.node.getComponent(cc.Label); if (label) { - label._updateRenderData(); + label._updateRenderData(true); } } diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index c431ec5f5e0..94fa0b7822c 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -51,6 +51,7 @@ let _color = null; let _fontFamily = ''; let _overflow = Overflow.NONE; let _isWrapText = false; +let _backgroundAlpha = 0.005; // outline let _isOutlined = false; @@ -244,13 +245,17 @@ module.exports = { _updateTexture (comp) { _context.clearRect(0, 0, _canvas.width, _canvas.height); + //Add a white background to avoid black edges. + //TODO: it is best to add alphaTest to filter out the background color. + _context.fillStyle = `rgba(${255}, ${255}, ${255}, ${_backgroundAlpha})`; + _context.fillRect(0, 0, _canvas.width, _canvas.height); _context.font = _fontDesc; let startPosition = this._calculateFillTextStartPosition(); let lineHeight = this._getLineHeight(); //use round for line join to avoid sharp intersect point _context.lineJoin = 'round'; - _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_color.a / 255})`; + _context.fillStyle = 'white'; let underlineStartPosition; //do real rendering diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index 76682a02f60..1d3d32ac01b 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -26,8 +26,6 @@ const js = require('../../../../platform/js'); const ttfUtls = require('../../../utils/label/ttf'); -const WHITE_VAL = cc.Color.WHITE._val; - module.exports = js.addon({ createData (comp) { let renderData = comp.requestRenderData(); @@ -42,7 +40,7 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let data = comp._renderData._data, node = comp.node, - color = WHITE_VAL, + color = node.color._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; From 524e155ef9a9b1b80512bd0bfbaad18ac87c1258 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Fri, 15 Feb 2019 13:53:43 +0800 Subject: [PATCH 0447/1631] add subpackage pipe to transform url (#3848) --- cocos2d/core/load-pipeline/downloader.js | 2 +- cocos2d/core/load-pipeline/subpackage-pipe.js | 68 +++++++++++++++++++ cocos2d/core/platform/CCAssetLibrary.js | 7 ++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 cocos2d/core/load-pipeline/subpackage-pipe.js diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index 0a157de53de..ca34ae88309 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -302,7 +302,7 @@ Downloader.prototype.loadSubpackage = function (name, completeCallback) { if (completeCallback) completeCallback(); } else { - downloadScript({url: pac.path}, function (err) { + downloadScript({url: pac.path + 'game.js'}, function (err) { if (!err) { pac.loaded = true; } diff --git a/cocos2d/core/load-pipeline/subpackage-pipe.js b/cocos2d/core/load-pipeline/subpackage-pipe.js new file mode 100644 index 00000000000..3f8d6e96977 --- /dev/null +++ b/cocos2d/core/load-pipeline/subpackage-pipe.js @@ -0,0 +1,68 @@ +/**************************************************************************** + Copyright (c) 2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 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 Pipeline = require('./pipeline'); + +const ID = 'SubPackPipe'; +const UuidRegex = /.*[/\\][0-9a-fA-F]{2}[/\\]([0-9a-fA-F-]{8,})/; + +function getUuidFromURL(url) { + var matches = url.match(UuidRegex); + if (matches) { + return matches[1]; + } + return ""; +} + +var _uuidToSubPack = Object.create(null); + +var SubPackPipe = function (subpackage) { + this.id = ID; + this.async = false; + this.pipeline = null; + for (var packName in subpackage) { + var pack = subpackage[packName]; + pack.uuids && pack.uuids.forEach(function (val) { + _uuidToSubPack[val] = pack.path; + }); + } +}; + +SubPackPipe.ID = ID; + +SubPackPipe.prototype.handle = function (item) { + item.url = this.transformURL(item.url); + return null; +}; + +SubPackPipe.prototype.transformURL = function (url) { + var uuid = getUuidFromURL(url); + if (uuid) { + var subpackage = _uuidToSubPack[uuid]; + if (subpackage) { + // only replace url of native assets + return url.replace('res/raw-assets/', subpackage + 'raw-assets/'); + } + } + return url; +}; + +Pipeline.SubPackPipe = module.exports = SubPackPipe; diff --git a/cocos2d/core/platform/CCAssetLibrary.js b/cocos2d/core/platform/CCAssetLibrary.js index dcd816203a7..d5a4f11a02b 100644 --- a/cocos2d/core/platform/CCAssetLibrary.js +++ b/cocos2d/core/platform/CCAssetLibrary.js @@ -31,6 +31,7 @@ var PackDownloader = require('../load-pipeline/pack-downloader'); var AutoReleaseUtils = require('../load-pipeline/auto-release-utils'); var decodeUuid = require('../utils/decode-uuid'); var MD5Pipe = require('../load-pipeline/md5-pipe'); +var SubPackPipe = require('../load-pipeline/subpackage-pipe'); var js = require('./js'); /** @@ -284,6 +285,12 @@ var AssetLibrary = { _rawAssetsBase = options.rawAssetsBase; + if (options.subpackages) { + var subPackPipe = new SubPackPipe(options.subpackages); + cc.loader.insertPipeAfter(cc.loader.assetLoader, subPackPipe); + cc.loader.subPackPipe = subPackPipe; + } + var md5AssetsMap = options.md5AssetsMap; if (md5AssetsMap && md5AssetsMap.import) { // decode uuid From d745da73958b02026263a156434eef7b9697048a Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Fri, 15 Feb 2019 16:05:59 +0800 Subject: [PATCH 0448/1631] add the primitive module (#3841) --- cocos2d/core/3d/primitive/index.js | 42 +++++++++--------------- cocos2d/core/3d/primitive/polyhedron.js | 4 +-- cocos2d/core/3d/primitive/vertex-data.js | 2 +- docs/apisrc.json | 1 + 4 files changed, 20 insertions(+), 29 deletions(-) diff --git a/cocos2d/core/3d/primitive/index.js b/cocos2d/core/3d/primitive/index.js index c7e80f5418b..ca1cc725d7b 100644 --- a/cocos2d/core/3d/primitive/index.js +++ b/cocos2d/core/3d/primitive/index.js @@ -10,8 +10,12 @@ import capsule from './capsule'; import { PolyhedronType, polyhedron } from './polyhedron'; /** - * @class Primitive + * 一个创建 3D 物体顶点数据的基础模块,你可以通过 "cc.primitive" 来访问这个模块。 + * @module primitive + * @submodule primitive + * @main */ + cc.primitive = Object.assign({ /** * !#en Create box vertex data @@ -25,7 +29,7 @@ cc.primitive = Object.assign({ * @param {Number} opts.widthSegments * @param {Number} opts.heightSegments * @param {Number} opts.lengthSegments - * @return Primitive.VertextData + * @return {primitive.VertextData} */ box, /** @@ -40,7 +44,7 @@ cc.primitive = Object.assign({ * @param {Number} opts.heightSegments * @param {Boolean} opts.capped * @param {Number} opts.arc - * @return Primitive.VertextData + * @return {primitive.VertextData} */ cone, /** @@ -56,13 +60,9 @@ cc.primitive = Object.assign({ * @param {Number} opts.heightSegments * @param {Boolean} opts.capped * @param {Number} opts.arc - * @return Primitive.VertextData + * @return {primitive.VertextData} */ cylinder, - /** - * !#en Create plane vertex data - * - */ /** * !#en Create plane vertex data * !#zh 创建平台顶点数据 @@ -73,7 +73,7 @@ cc.primitive = Object.assign({ * @param {Object} opts * @param {Number} opts.widthSegments * @param {Number} opts.lengthSegments - * @return Primitive.VertextData + * @return {primitive.VertextData} */ plane, /** @@ -81,7 +81,7 @@ cc.primitive = Object.assign({ * !#zh 创建面片顶点数据 * @method quad * @static - * @return Primitive.VertextData + * @return {primitive.VertextData} */ quad, /** @@ -92,7 +92,7 @@ cc.primitive = Object.assign({ * @param {Number} radius * @param {Object} opts * @param {Number} opts.segments - * @return Primitive.VertextData + * @return {primitive.VertextData} */ sphere, /** @@ -106,7 +106,7 @@ cc.primitive = Object.assign({ * @param {Number} opts.radialSegments * @param {Number} opts.tubularSegments * @param {Number} opts.arc - * @return Primitive.VertextData + * @return {primitive.VertextData} */ torus, /** @@ -122,7 +122,7 @@ cc.primitive = Object.assign({ * @param {Number} opts.heightSegments * @param {Boolean} opts.capped * @param {Number} opts.arc - * @return Primitive.VertextData + * @return {primitive.VertextData} */ capsule, /** @@ -130,24 +130,14 @@ cc.primitive = Object.assign({ * !#zh 创建多面体顶点数据 * @method polyhedron * @static - * @param {Primitive.PolyhedronType} type + * @param {primitive.PolyhedronType} type * @param {Number} Size * @param {Object} opts * @param {Number} opts.sizeX * @param {Number} opts.sizeY * @param {Number} opts.sizeZ - * @return Primitive.VertextData + * @return {primitive.VertextData} */ polyhedron, - PolyhedronType: PolyhedronType -}, utils); - -/** - * @module cc - */ - -/** - * @property primitive - * @type Primitive - */ +}, utils); \ No newline at end of file diff --git a/cocos2d/core/3d/primitive/polyhedron.js b/cocos2d/core/3d/primitive/polyhedron.js index e2f43123c7f..0850b3d6e71 100644 --- a/cocos2d/core/3d/primitive/polyhedron.js +++ b/cocos2d/core/3d/primitive/polyhedron.js @@ -4,9 +4,9 @@ import { vec3 } from '../../vmath'; import VertexData from './vertex-data'; /** - * @enum Primitive.PolyhedronType + * @enum primitive.PolyhedronType * @static - * @namespace Primitive + * @namespace primitive */ export const PolyhedronType = cc.Enum({ /** diff --git a/cocos2d/core/3d/primitive/vertex-data.js b/cocos2d/core/3d/primitive/vertex-data.js index 1df92324f6a..a01a13e4e46 100644 --- a/cocos2d/core/3d/primitive/vertex-data.js +++ b/cocos2d/core/3d/primitive/vertex-data.js @@ -1,6 +1,6 @@ /** - * @class Primitive.VertexData + * @class primitive.VertexData * @param {[Number]} positions * @param {[Number]} normals * @param {[Number]} uvs diff --git a/docs/apisrc.json b/docs/apisrc.json index f32ceb2c682..a601b562248 100644 --- a/docs/apisrc.json +++ b/docs/apisrc.json @@ -25,6 +25,7 @@ "./cocos2d/core/CCScheduler.js", "./cocos2d/core/assets/**/*", + "./cocos2d/core/3d/**/*", "./cocos2d/core/camera/CCCamera.js", From cb2e9d5da6421b987c7c00c0084728ecdc5fb189 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Fri, 15 Feb 2019 16:38:23 +0800 Subject: [PATCH 0449/1631] =?UTF-8?q?Optimize=20spine=EF=BC=8Csupport=20ca?= =?UTF-8?q?che=20mode=20and=20batch=20(#3834)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * optimze spine optimize spine optimize spine * rename enabledBatch to enableBatch,rename enum var name * Add complete var instead of paused --- editor/i18n/en/localization.js | 6 +- extensions/dragonbones/ArmatureCache.js | 108 +++-- extensions/dragonbones/ArmatureDisplay.js | 44 +- extensions/dragonbones/webgl-assembler.js | 14 +- extensions/spine/Skeleton.js | 396 +++++++++++++---- extensions/spine/lib/spine.js | 38 +- extensions/spine/skeleton-cache.js | 511 ++++++++++++++++++++++ extensions/spine/skeleton-data.js | 10 +- extensions/spine/spine-assembler.js | 332 +++++++++++--- gulp/tasks/engine.js | 1 + 10 files changed, 1237 insertions(+), 223 deletions(-) create mode 100644 extensions/spine/skeleton-cache.js diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 9a3d56805dc..bc1477cc782 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -258,7 +258,9 @@ module.exports = { "debug_slots": "Indicates whether show debug slots.", "debug_bones": "Indicates whether show debug bones.", "premultipliedAlpha": "Indicates whether to enable premultiplied alpha.", - "use_tint": "Indicates whether to use tint effect." + "use_tint": "Indicates whether to use tint effect.", + "enabled_batch": "Indicates whether enabled batch model", + "render_mode": "The render mode of current armature. \n'REALTIME' means REALTIME calculate animation data, support animation blend but low performance. \n'SHARED_CACHE' means precomputation animation data and share data with same armature, high performance and less memery. \n'PRIVATE_CACHE' means precomputation animation data but not share data with other same armature, high performance and more memery.\nAbove two cache mode, not support nest armature, not support 'fade' related interface.", }, "dragon_bones": { "dragon_bones_asset": "The json data contains the DragonBones information, drag the json file exported from DragonBones to get started.", @@ -269,7 +271,7 @@ module.exports = { "play_times": "The play times of the default animation.\n-1 means using the value of config file\n0 means repeat for ever\n>0 means repeat times", "debug_bones": "Indicates whether open debug bones", "enabled_batch": "Indicates whether enabled batch model", - "render_mode": "The render mode of current armature. \n'realtime' means realtime calculate animation data, support animation blend but low performance. \n'sharedCache' means precomputation animation data and share data with same armature, high performance and less memery. \n'privateCache' means precomputation animation data but not share data with other same armature, high performance and more memery.\nAbove two cache mode, not support nest armature, not support 'fade' related interface.", + "render_mode": "The render mode of current armature. \n'REALTIME' means REALTIME calculate animation data, support animation blend but low performance. \n'SHARED_CACHE' means precomputation animation data and share data with same armature, high performance and less memery. \n'PRIVATE_CACHE' means precomputation animation data but not share data with other same armature, high performance and more memery.\nAbove two cache mode, not support nest armature, not support 'fade' related interface.", }, 'motionStreak': { 'fadeTime': "Trail fragment fade time, in seconds", diff --git a/extensions/dragonbones/ArmatureCache.js b/extensions/dragonbones/ArmatureCache.js index 5bbdd61920b..8d6c176d8ec 100644 --- a/extensions/dragonbones/ArmatureCache.js +++ b/extensions/dragonbones/ArmatureCache.js @@ -22,19 +22,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ +const MaxCacheTime = 30; + let _vertices = []; let _indices = []; let _vertexOffset = 0; let _indexOffset = 0; let _vfOffset = 0; -let _frameRate = 1 / 60; -let _preTexUrl = undefined; -let _preBlendMode = undefined; +let _frameTime = 1 / 60; +let _preTexUrl = null; +let _preBlendMode = null; let _segVCount = 0; let _segICount = 0; let _segOffset = 0; let _colorOffset = 0; -let _preColor = undefined; +let _preColor = null; let _x, _y; //Cache all frames in an animation @@ -43,8 +45,13 @@ let AnimationCache = cc.Class({ this.frames = []; this.totalTime = 0; - this._tempSegments = undefined; - this._tempColors = undefined; + this._animationName = null; + this._tempSegments = null; + this._tempColors = null; + }, + + init (animationName) { + this._animationName = animationName; }, // Clear texture quote. @@ -55,35 +62,44 @@ let AnimationCache = cc.Class({ } }, - update (armature, animationName) { + update (armature) { + if (!this._animationName) { + cc.error("AnimationCache:update animationName is empty"); + return; + } let animation = armature.animation; - animation.play(animationName, 1); + animation.play(this._animationName, 1); let frameIdx = 0; + this.totalTime = 0; do { // Solid update frame rate 1/60. - armature.advanceTime(_frameRate); - this._updateFrame(armature, frameIdx) && frameIdx++; - } while (!animation.isCompleted); + armature.advanceTime(_frameTime); + this._updateFrame(armature, frameIdx); + frameIdx++; + this.totalTime += _frameTime; + } while (!animation.isCompleted && this.totalTime < MaxCacheTime); // Update frame length. this.frames.length = frameIdx; - this.totalTime = frameIdx * _frameRate; }, _updateFrame (armature, index) { _vfOffset = 0; _indexOffset = 0; _vertexOffset = 0; - _preTexUrl = undefined; - _preBlendMode = undefined; + _preTexUrl = null; + _preBlendMode = null; _segVCount = 0; _segICount = 0; _segOffset = 0; _colorOffset = 0; - _preColor = undefined; + _preColor = null; this.frames[index] = this.frames[index] || { segments : [], colors : [], + vertices : null, + uintVert : null, + indices : null, }; let frame = this.frames[index]; @@ -99,17 +115,21 @@ let AnimationCache = cc.Class({ colors.length = _colorOffset; // Handle pre segment let preSegOffset = _segOffset - 1; - if (preSegOffset >= 0 && _segICount > 0) { - let preSegInfo = segments[preSegOffset]; - preSegInfo.indexCount = _segICount; - preSegInfo.vfCount = _segVCount * 5; - preSegInfo.vertexCount = _segVCount; - segments.length = _segOffset; - } else { - segments.length = 0; - return false; + if (preSegOffset >= 0) { + if (_segICount > 0) { + let preSegInfo = segments[preSegOffset]; + preSegInfo.indexCount = _segICount; + preSegInfo.vfCount = _segVCount * 5; + preSegInfo.vertexCount = _segVCount; + segments.length = _segOffset; + } else { + segments.length = _segOffset - 1; + } } + // Discard all segments. + if (segments.length === 0) return; + // Fill vertices let vertices = frame.vertices || new Float32Array(_vfOffset); let uintVert = frame.uintVert || new Uint32Array(vertices.buffer); @@ -130,7 +150,6 @@ let AnimationCache = cc.Class({ frame.vertices = vertices; frame.uintVert = uintVert; frame.indices = indices; - return true; }, _traverseArmature (armature) { @@ -162,22 +181,28 @@ let AnimationCache = cc.Class({ if (_preTexUrl !== texture.url || _preBlendMode !== slot._blendMode) { _preTexUrl = texture.url; _preBlendMode = slot._blendMode; - // handle pre + // Handle pre segment. preSegOffset = _segOffset - 1; - if (preSegOffset >= 0 && _segICount > 0) { - preSegInfo = segments[preSegOffset]; - preSegInfo.indexCount = _segICount; - preSegInfo.vertexCount = _segVCount; - preSegInfo.vfCount = _segVCount * 5; + if (preSegOffset >= 0) { + if (_segICount > 0) { + preSegInfo = segments[preSegOffset]; + preSegInfo.indexCount = _segICount; + preSegInfo.vertexCount = _segVCount; + preSegInfo.vfCount = _segVCount * 5; + } else { + // Discard pre segment. + _segOffset--; + } } - // handle now - segments[_segOffset++] = { + // Handle now segment. + segments[_segOffset] = { tex : texture, blendMode : slot._blendMode, indexCount : 0, vertexCount : 0, vfCount : 0 }; + _segOffset++; _segICount = 0; _segVCount = 0; } @@ -213,8 +238,10 @@ let AnimationCache = cc.Class({ gVertices[_vfOffset++] = colorVal; } + // This place must use segment vertex count to calculate vertex offset. + // Assembler will calculate vertex offset again for different segment. for (let ii = 0, il = slotIndices.length; ii < il; ii ++) { - gIndices[_indexOffset++] = _vertexOffset + slotIndices[ii]; + gIndices[_indexOffset++] = _segVCount + slotIndices[ii]; } _vertexOffset = _vfOffset / 5; @@ -239,8 +266,8 @@ let ArmatureCache = cc.Class({ armature && armature.dispose(); } } - this._armatureCache = undefined; - this._animationPool = undefined; + this._armatureCache = null; + this._animationPool = null; }, _removeArmature (armatureKey) { @@ -326,6 +353,9 @@ let ArmatureCache = cc.Class({ let armatureInfo = this._armatureCache[armatureKey]; let armature = armatureInfo && armatureInfo.armature; if (!armature) return null; + let animation = armature.animation; + let hasAni = animation.hasAnimation(animationName); + if (!hasAni) return null; let animationsCache = armatureInfo.animationsCache; let animationCache = animationsCache[animationName]; @@ -337,10 +367,14 @@ let ArmatureCache = cc.Class({ delete this._animationPool[poolKey]; } else { animationCache = new AnimationCache(); + animationCache.init(animationName); } animationsCache[animationName] = animationCache; } - animationCache.update(armature, animationName); + animationCache.update(armature); + if (animationCache.totalTime >= MaxCacheTime) { + cc.warn("Animation cache is overflow, maybe animation's frame is infinite, please change armature render mode to REALTIME, dragonbones name is [%s], animation name is [%s]", dragonbonesName, animationName); + } return animationCache; } }); diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 0217a55f9e8..de721f74f2e 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -41,8 +41,8 @@ let ArmatureCache = require('./ArmatureCache'); let DefaultArmaturesEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); -let DefaultRenderModeEnum = cc.Enum({ 'realtime': 0 }); -let RenderModeEnum = cc.Enum({ 'realtime': 0, 'sharedCache': 1, "privateCache": 2 }); +let DefaultRenderModeEnum = cc.Enum({ 'REALTIME': 0 }); +let RenderModeEnum = cc.Enum({ 'REALTIME': 0, 'SHARED_CACHE': 1, "PRIVATE_CACHE": 2 }); function setEnumAttr (obj, propName, enumDef) { cc.Class.attr(obj, propName, { @@ -370,10 +370,10 @@ let ArmatureDisplay = cc.Class({ /** * !#en Enabled batch model, if skeleton is complex, do not enable batch, or will lower performance. * !#zh 开启合批,如果渲染大量相同纹理,且结构简单的骨骼动画,开启合批可以降低drawcall,否则请不要开启,cpu消耗会上升。 - * @property {Boolean} enabledBatch + * @property {Boolean} enableBatch * @default false */ - enabledBatch: { + enableBatch: { default: false, notify () { this._updateBatch(); @@ -381,11 +381,9 @@ let ArmatureDisplay = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.enabled_batch' }, - // Below properties will effect when render mode is sharedCache or privateCache. + // Below properties will effect when render mode is SHARED_CACHE or PRIVATE_CACHE. // accumulate time _accTime: 0, - // Frame counter - _frameCount: 0, // Play times counter _playCount: 0, // Frame cache @@ -394,6 +392,8 @@ let ArmatureDisplay = cc.Class({ _curFrame: null, // Playing flag _playing: false, + // Armature cache + _armatureCache: null, }, ctor () { @@ -426,7 +426,7 @@ let ArmatureDisplay = cc.Class({ for (let mKey in cache) { let material = cache[mKey]; if (material) { - material.useModel = !this.enabledBatch; + material.useModel = !this.enableBatch; } } }, @@ -446,7 +446,7 @@ let ArmatureDisplay = cc.Class({ this._inited = true; if (CC_JSB) { - this.renderMode = RenderModeEnum.realtime; + this.renderMode = RenderModeEnum.REALTIME; } this._parseDragonAsset(); @@ -465,7 +465,7 @@ let ArmatureDisplay = cc.Class({ isCachedMode () { if (CC_EDITOR) return false; - return this.renderMode !== RenderModeEnum.realtime; + return this.renderMode !== RenderModeEnum.REALTIME; }, onEnable () { @@ -522,7 +522,6 @@ let ArmatureDisplay = cc.Class({ } this._curFrame = frames[frameIdx]; - this._frameIdx = frameIdx; }, onDestroy () { @@ -530,11 +529,11 @@ let ArmatureDisplay = cc.Class({ this._inited = false; if (!CC_EDITOR) { - if (this.renderMode === RenderModeEnum.privateCache) { + if (this.renderMode === RenderModeEnum.PRIVATE_CACHE) { this._armatureCache.dispose(); this._armatureCache = null; this._armature = null; - } else if (this.renderMode === RenderModeEnum.sharedCache) { + } else if (this.renderMode === RenderModeEnum.SHARED_CACHE) { this._armatureCache = null; this._armature = null; } else if (this._armature) { @@ -574,9 +573,9 @@ let ArmatureDisplay = cc.Class({ if (this._armature) { // dispose pre build armature if (!CC_EDITOR) { - if (this._preRenderMode === RenderModeEnum.privateCache) { + if (this._preRenderMode === RenderModeEnum.PRIVATE_CACHE) { this._armatureCache.dispose(); - } else if (this._preRenderMode === RenderModeEnum.realtime) { + } else if (this._preRenderMode === RenderModeEnum.REALTIME) { this._armature.dispose(); } } else { @@ -592,9 +591,9 @@ let ArmatureDisplay = cc.Class({ } if (!CC_EDITOR) { - if (this.renderMode === RenderModeEnum.sharedCache) { + if (this.renderMode === RenderModeEnum.SHARED_CACHE) { this._armatureCache = ArmatureCache.sharedCache; - } else if (this.renderMode === RenderModeEnum.privateCache) { + } else if (this.renderMode === RenderModeEnum.PRIVATE_CACHE) { this._armatureCache = new ArmatureCache; } } @@ -605,13 +604,13 @@ let ArmatureDisplay = cc.Class({ if (this.isCachedMode()) { this._armature = this._armatureCache.getArmatureCache(this.armatureName, dragonbonesName, atlasName); if (!this._armature) { - // Cache fail,swith to realtime render mode. - this.renderMode = RenderModeEnum.realtime; + // Cache fail,swith to REALTIME render mode. + this.renderMode = RenderModeEnum.REALTIME; } } this._preRenderMode = this.renderMode; - if (CC_EDITOR || this.renderMode === RenderModeEnum.realtime) { + if (CC_EDITOR || this.renderMode === RenderModeEnum.REALTIME) { this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, dragonbonesName, "", atlasName); if (!this._displayProxy) return; this._displayProxy._ccNode = this.node; @@ -619,8 +618,8 @@ let ArmatureDisplay = cc.Class({ this._armature.animation.timeScale = this.timeScale; } - if (this.renderMode !== RenderModeEnum.realtime && this.debugBones) { - console.warn("cached mode do not support debug bones"); + if (this.renderMode !== RenderModeEnum.REALTIME && this.debugBones) { + cc.warn("Debug bones is invalid in cached mode"); } this._updateBatch(); @@ -715,7 +714,6 @@ let ArmatureDisplay = cc.Class({ } if (cache) { this._accTime = 0; - this._frameCount = 0; this._playCount = 0; this._frameCache = cache; this._playing = true; diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 5c8c08fc2f0..46de7b607a8 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -69,7 +69,10 @@ function _getSlotMaterial (tex, blendMode) { break; } - let key = tex.url + src + dst; + let useModel = !_comp.enableBatch; + // Add useModel flag due to if pre same db useModel but next db no useModel, + // then next db will multiply model matrix more than once. + let key = tex.url + src + dst + useModel; let baseMaterial = _comp._material; if (!baseMaterial) return null; let materialCache = _comp._materialCache; @@ -83,7 +86,7 @@ function _getSlotMaterial (tex, blendMode) { material = baseMaterial.clone(); } - material.useModel = !_comp.enabledBatch; + material.useModel = useModel; // update texture material.texture = tex; material.useColor = false; @@ -199,15 +202,16 @@ let armatureAssembler = { cacheTraverse (frame, parentMat) { if (!frame) return; + let segments = frame.segments; + if (segments.length == 0) return; let vbuf, ibuf, uintbuf; let material; - let offsetInfo; let vertices = frame.vertices; let indices = frame.indices; let uintVert = frame.uintVert; - let segments = frame.segments; + let frameVFOffset = 0, frameIndexOffset = 0, segVFCount = 0; if (parentMat) { _m00 = parentMat.m00; @@ -307,7 +311,7 @@ let armatureAssembler = { } let worldMat = undefined; - if (_comp.enabledBatch) { + if (_comp.enableBatch) { worldMat = _node._worldMatrix; _mustFlush = false; _handleVal |= NEED_BATCH; diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 2009a0c0b64..d287197eb37 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -31,11 +31,14 @@ const SpineMaterial = require('../../cocos2d/core/renderer/render-engine').Spine const Graphics = require('../../cocos2d/core/graphics/graphics'); const BlendFactor = require('../../cocos2d/core/platform/CCMacro').BlendFactor; +let SkeletonCache = require('./skeleton-cache'); + /** * @module sp */ let DefaultSkinsEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); +let RenderModeEnum = cc.Enum({ 'REALTIME': 0, 'SHARED_CACHE': 1, "PRIVATE_CACHE": 2 }); function setEnumAttr (obj, propName, enumDef) { cc.Class.attr(obj, propName, { @@ -175,8 +178,12 @@ sp.Skeleton = cc.Class({ */ animation: { get () { - var entry = this.getCurrent(0); - return (entry && entry.animation.name) || ""; + if (this.isCachedMode()) { + return this._animationName; + } else { + var entry = this.getCurrent(0); + return (entry && entry.animation.name) || ""; + } }, set (value) { this.defaultAnimation = value; @@ -275,19 +282,21 @@ sp.Skeleton = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.animation' }, - //// for inspector - //_animationList: { - // default: [], - // type: cc.String, - // serializable: false - //}, - // - //// for inspector - //_skinList: { - // default: [], - // type: cc.String, - // serializable: false - //}, + // Record pre render mode. + _preRenderMode: 0, + renderMode: { + default: 0, + type: RenderModeEnum, + notify () { + if (this._preRenderMode !== this.renderMode) { + this._updateSkeletonData(); + } + }, + visible: true, + animatable: false, + displayName: "Render Mode", + tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.render_mode' + }, /** * !#en TODO @@ -368,7 +377,43 @@ sp.Skeleton = cc.Class({ notify () { this._updateUseTint(); } - } + }, + + /** + * !#en Enabled batch model, if skeleton is complex, do not enable batch, or will lower performance. + * !#zh 开启合批,如果渲染大量相同纹理,且结构简单的骨骼动画,开启合批可以降低drawcall,否则请不要开启,cpu消耗会上升。 + * @property {Boolean} enableBatch + * @default false + */ + enableBatch: { + default: false, + notify () { + this._updateBatch(); + }, + tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.enabled_batch' + }, + + // Below properties will effect when render mode is SHARED_CACHE or PRIVATE_CACHE. + // accumulate time + _accTime: 0, + // Play times counter + _playCount: 0, + // Frame cache + _frameCache: null, + // Cur frame + _curFrame: null, + // Skeleton cache + _skeletonCache : null, + // Aimation name + _animationName : null, + // Animation queue + _animationQueue : [], + // Head animation info of + _headAniInfo : null, + // Play times + _playTimes : 0, + // Is animation complete. + _isAniComplete : true, }, // CONSTRUCTOR @@ -382,6 +427,8 @@ sp.Skeleton = cc.Class({ this._debugRenderer = null; this._startSlotIndex = -1; this._endSlotIndex = -1; + this._startEntry = {animation : {name : ""}, trackIndex : 0}; + this._endEntry = {animation : {name : ""}, trackIndex : 0}; }, // override @@ -400,6 +447,16 @@ sp.Skeleton = cc.Class({ } }, + _updateBatch () { + let cache = this._materialCache; + for (let mKey in cache) { + let material = cache[mKey]; + if (material) { + material.useModel = !this.enableBatch; + } + } + }, + /** * !#en * Sets runtime skeleton data to sp.Skeleton.
@@ -415,20 +472,31 @@ sp.Skeleton = cc.Class({ this.node.setContentSize(skeletonData.width, skeletonData.height); } - this._skeleton = new spine.Skeleton(skeletonData); - this._clipper = new spine.SkeletonClipping(); - this._rootBone = this._skeleton.getRootBone(); + if (this.isCachedMode()) { + let skeletonInfo = this._skeletonCache.getSkeletonCache(this.skeletonData._uuid, skeletonData); + this._skeleton = skeletonInfo.skeleton; + this._clipper = skeletonInfo.clipper; + this._rootBone = this._skeleton.getRootBone(); + } else { + this._skeleton = new spine.Skeleton(skeletonData); + this._clipper = new spine.SkeletonClipping(); + this._rootBone = this._skeleton.getRootBone(); + } }, /** * !#en Sets slots visible range. * !#zh 设置骨骼插槽可视范围。 - * @method setSkeletonData + * @method setSlotsRange * @param {sp.spine.SkeletonData} skeletonData */ setSlotsRange (startSlotIndex, endSlotIndex) { - this._startSlotIndex = startSlotIndex; - this._endSlotIndex = endSlotIndex; + if (this.isCachedMode()) { + console.warn("Slots visible range can not be modified in cached mode."); + } else { + this._startSlotIndex = startSlotIndex; + this._endSlotIndex = endSlotIndex; + } }, /** @@ -440,14 +508,19 @@ sp.Skeleton = cc.Class({ * @param {sp.spine.AnimationStateData} stateData */ setAnimationStateData (stateData) { - var state = new spine.AnimationState(stateData); - if (this._listener) { - if (this._state) { - this._state.removeListener(this._listener); + if (this.isCachedMode()) { + console.warn("'setAnimationStateData' interface can not be invoked in cached mode."); + } else { + var state = new spine.AnimationState(stateData); + if (this._listener) { + if (this._state) { + this._state.removeListener(this._listener); + } + state.addListener(this._listener); } - state.addListener(this._listener); + this._state = state; } - this._state = state; + }, // IMPLEMENT @@ -459,8 +532,6 @@ sp.Skeleton = cc.Class({ this._refreshInspector(); } - this._updateSkeletonData(); - var children = this.node.children; for (var i = 0, n = children.length; i < n; i++) { var child = children[i]; @@ -469,13 +540,90 @@ sp.Skeleton = cc.Class({ } } + if (CC_JSB) { + this.renderMode = RenderModeEnum.REALTIME; + } + + this._updateSkeletonData(); this._updateDebugDraw(); this._updateUseTint(); + this._updateBatch(); + }, + + /** + * !#en Whether in cached mode. + * !#zh 当前是否处于缓存模式。 + * @method isCachedMode + */ + isCachedMode () { + if (CC_EDITOR) return false; + return this.renderMode !== RenderModeEnum.REALTIME; }, update (dt) { if (CC_EDITOR) return; if (this.paused) return; + + if (this.isCachedMode()) { + + // Cache mode and has animation queue. + if (this._isAniComplete) { + if (this._animationQueue.length === 0 && !this._headAniInfo) return; + if (!this._headAniInfo) { + this._headAniInfo = this._animationQueue.shift(); + } + this._accTime += dt; + if (this._accTime > this._headAniInfo.delay) { + let aniInfo = this._headAniInfo; + this._headAniInfo = null; + this.setAnimation (0, aniInfo.animationName, aniInfo.loop); + } + return; + } + + this._updateCache(dt); + } else { + this._updateRealtime(dt); + } + }, + + _updateCache (dt) { + let frames = this._frameCache.frames; + let totalTime = this._frameCache.totalTime; + let frameCount = frames.length; + + // Animation Start, the event diffrent from dragonbones inner event, + // It has no event object. + if (this._accTime == 0 && this._playCount == 0) { + this._startEntry.animation.name = this._animationName; + this._listener && this._listener.start && this._listener.start(this._startEntry); + } + + this._accTime += dt * this.timeScale; + let frameIdx = Math.floor(this._accTime / totalTime * frameCount); + if (frameIdx >= frameCount) { + + // Animation complete, the event diffrent from dragonbones inner event, + // It has no event object. + this._endEntry.animation.name = this._animationName; + this._listener && this._listener.complete && this._listener.complete(this._endEntry); + this._listener && this._listener.end && this._listener.end(this._endEntry); + + this._playCount ++; + if (this._playTimes > 0 && this._playCount >= this._playTimes) { + this._accTime = 0; + this._playCount = 0; + this._isAniComplete = true; + return; + } + this._accTime = 0; + frameIdx = 0; + } + + this._curFrame = frames[frameIdx]; + }, + + _updateRealtime (dt) { let skeleton = this._skeleton; let state = this._state; if (skeleton) { @@ -512,6 +660,8 @@ sp.Skeleton = cc.Class({ * cc.log(bone.worldX); // return -23.12; */ updateWorldTransform () { + if (!this.isCachedMode()) return; + if (this._skeleton) { this._skeleton.updateWorldTransform(); } @@ -523,8 +673,12 @@ sp.Skeleton = cc.Class({ * @method setToSetupPose */ setToSetupPose () { - if (this._skeleton) { - this._skeleton.setToSetupPose(); + if (this.isCachedMode()) { + cc.warn("'SetToSetupPose' interface can not be invoked in cached mode."); + } else { + if (this._skeleton) { + this._skeleton.setToSetupPose(); + } } }, @@ -538,8 +692,12 @@ sp.Skeleton = cc.Class({ * @method setBonesToSetupPose */ setBonesToSetupPose () { - if (this._skeleton) { - this._skeleton.setBonesToSetupPose(); + if (this.isCachedMode()) { + cc.warn("'setBonesToSetupPose' interface can not be invoked in cached mode."); + } else { + if (this._skeleton) { + this._skeleton.setBonesToSetupPose(); + } } }, @@ -553,11 +711,29 @@ sp.Skeleton = cc.Class({ * @method setSlotsToSetupPose */ setSlotsToSetupPose () { - if (this._skeleton) { - this._skeleton.setSlotsToSetupPose(); + if (this.isCachedMode()) { + cc.warn("'setSlotsToSetupPose' interface can not be invoked in cached mode."); + } else { + if (this._skeleton) { + this._skeleton.setSlotsToSetupPose(); + } } }, + /** + * !#en + * Update an animation cache. + * !#zh + * 更新某个动画缓存。 + * @method updateAnimationCache + * @param {String} animName + */ + updateAnimationCache (animName) { + if (!this.isCachedMode()) return; + let cache = this._skeletonCache.updateAnimationCache(this.skeletonData._uuid, animName); + this._frameCache = cache || this._frameCache; + }, + /** * !#en * Finds a bone by name. @@ -614,8 +790,13 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.Skin} */ setSkin (skinName) { - if (this._skeleton) { - return this._skeleton.setSkinByName(skinName); + if (this.isCachedMode()) { + this._skeletonCache.resetSkeleton(); + this._animationName && (this.animation = this._animationName); + } else { + if (this._skeleton) { + return this._skeleton.setSkinByName(skinName); + } } return null; }, @@ -697,18 +878,39 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.TrackEntry} */ setAnimation (trackIndex, name, loop) { - if (this._skeleton) { - var animation = this._skeleton.data.findAnimation(name); - if (!animation) { - cc.logID(7509, name); - return null; + + this._playTimes = loop ? 0 : 1; + this._animationName = name; + + if (this.isCachedMode()) { + if (trackIndex !== 0) { + cc.warn("Track index can not greater than 0 in cached mode."); } - var res = this._state.setAnimationWith(trackIndex, animation, loop); - if (CC_EDITOR && !cc.engine.isPlaying) { - this._state.update(0); - this._state.apply(this._skeleton); + let cache = this._skeletonCache.getAnimationCache(this.skeletonData._uuid, name); + if (!cache) { + cache = this._skeletonCache.updateAnimationCache(this.skeletonData._uuid, name); + } + if (cache) { + this._isAniComplete = false; + this._accTime = 0; + this._playCount = 0; + this._frameCache = cache; + this._curFrame = this._frameCache.frames[0]; + } + } else { + if (this._skeleton) { + var animation = this._skeleton.data.findAnimation(name); + if (!animation) { + cc.logID(7509, name); + return null; + } + var res = this._state.setAnimationWith(trackIndex, animation, loop); + if (CC_EDITOR && !cc.engine.isPlaying) { + this._state.update(0); + this._state.apply(this._skeleton); + } + return res; } - return res; } return null; }, @@ -726,14 +928,21 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.TrackEntry} */ addAnimation (trackIndex, name, loop, delay) { - if (this._skeleton) { - delay = delay || 0; - var animation = this._skeleton.data.findAnimation(name); - if (!animation) { - cc.logID(7510, name); - return null; + if (this.isCachedMode()) { + if (trackIndex !== 0) { + cc.warn("Track index can not greater than 0 in cached mode."); + } + this._animationQueue.push({animationName : name, loop: loop, delay : delay}); + } else { + if (this._skeleton) { + delay = delay || 0; + var animation = this._skeleton.data.findAnimation(name); + if (!animation) { + cc.logID(7510, name); + return null; + } + return this._state.addAnimationWith(trackIndex, animation, loop, delay); } - return this._state.addAnimationWith(trackIndex, animation, loop, delay); } return null; }, @@ -762,8 +971,12 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.TrackEntry} */ getCurrent (trackIndex) { - if (this._state) { - return this._state.getCurrent(trackIndex); + if (this.isCachedMode()) { + console.warn("'getCurrent' interface can not be invoked in cached mode."); + } else { + if (this._state) { + return this._state.getCurrent(trackIndex); + } } return null; }, @@ -774,8 +987,12 @@ sp.Skeleton = cc.Class({ * @method clearTracks */ clearTracks () { - if (this._state) { - this._state.clearTracks(); + if (this.isCachedMode()) { + console.warn("'clearTracks' interface can not be invoked in cached mode."); + } else { + if (this._state) { + this._state.clearTracks(); + } } }, @@ -786,10 +1003,14 @@ sp.Skeleton = cc.Class({ * @param {number} trackIndex */ clearTrack (trackIndex) { - if (this._state) { - this._state.clearTrack(trackIndex); - if (CC_EDITOR && !cc.engine.isPlaying) { - this._state.update(0); + if (this.isCachedMode()) { + console.warn("'clearTrack' interface can not be invoked in cached mode."); + } else { + if (this._state) { + this._state.clearTrack(trackIndex); + if (CC_EDITOR && !cc.engine.isPlaying) { + this._state.update(0); + } } } }, @@ -970,31 +1191,49 @@ sp.Skeleton = cc.Class({ }, _updateSkeletonData () { - if (this.skeletonData/* && this.atlasFile*/) { - let data = this.skeletonData.getRuntimeData(); - if (data) { - try { - this.setSkeletonData(data); - this.setAnimationStateData(new spine.AnimationStateData(this._skeleton.data)); - if (this.defaultSkin) { - this._skeleton.setSkinByName(this.defaultSkin); - } - } - catch (e) { - cc.warn(e); - } - this.animation = this.defaultAnimation; + if (!this.skeletonData) return; + let data = this.skeletonData.getRuntimeData(); + if (!data) return; + + if (!CC_EDITOR) { + if (this.renderMode === RenderModeEnum.SHARED_CACHE) { + this._skeletonCache = SkeletonCache.sharedCache; + } else if (this.renderMode === RenderModeEnum.PRIVATE_CACHE) { + this._skeletonCache = new SkeletonCache; + } + } + + if (this.isCachedMode() && (this.debugBones || this.debugSlots)) { + cc.warn("Debug bones or slots is invalid in cached mode"); + } + + try { + this.setSkeletonData(data); + if (!this.isCachedMode()) { + this.setAnimationStateData(new spine.AnimationStateData(this._skeleton.data)); } + this.defaultSkin && this.setSkin(this.defaultSkin); + } + catch (e) { + cc.warn(e); } + + this._preRenderMode = this.renderMode; + this.animation = this.defaultAnimation; }, _refreshInspector () { // update inspector this._updateAnimEnum(); this._updateSkinEnum(); + this._updateRenderModeEnum(); Editor.Utils.refreshSelectedInspector('node', this.node.uuid); }, + _updateRenderModeEnum: CC_EDITOR && function () { + setEnumAttr(this, 'renderMode', RenderModeEnum); + }, + _updateDebugDraw: function () { if (this.debugBones || this.debugSlots) { if (!this._debugRenderer) { @@ -1008,6 +1247,9 @@ sp.Skeleton = cc.Class({ } this._debugRenderer.node.parent = this.node; + if (this.isCachedMode()) { + cc.warn("Debug bones or slots is invalid in cached mode"); + } } else if (this._debugRenderer) { this._debugRenderer.node.parent = null; diff --git a/extensions/spine/lib/spine.js b/extensions/spine/lib/spine.js index e3c07760962..fa8ba6a83dd 100644 --- a/extensions/spine/lib/spine.js +++ b/extensions/spine/lib/spine.js @@ -3887,25 +3887,39 @@ var spine; SkeletonClipping.prototype.isClipping = function () { return this.clipAttachment != null; }; - SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor, stride) { + SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor, stride, originIndexOffset, originVertOffset, originUVSOffset) { var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; var clippedTriangles = this.clippedTriangles; var polygons = this.clippingPolygons; var polygonsCount = this.clippingPolygons.length; var vertexSize = twoColor ? 12 : 8; - var index = 0; + var index = 0; + + originIndexOffset = originIndexOffset || 0; + originVertOffset = originVertOffset || 0; + originUVSOffset = originUVSOffset || 0; + clippedVertices.length = 0; clippedTriangles.length = 0; - outer: for (var i = 0; i < trianglesLength; i += 3) { - var vertexOffset = triangles[i] * stride; - var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; - var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; - vertexOffset = triangles[i + 1] * stride; - var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; - var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; - vertexOffset = triangles[i + 2] * stride; - var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; - var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + outer: for (var i = originIndexOffset, n = originIndexOffset + trianglesLength; i < n; i += 3) { + var vertexOffset = triangles[i] * stride; + var xyOffset = vertexOffset + originVertOffset; + var uvOffset = vertexOffset + originUVSOffset; + var x1 = vertices[xyOffset], y1 = vertices[xyOffset + 1]; + var u1 = uvs[uvOffset], v1 = uvs[uvOffset + 1]; + + vertexOffset = triangles[i + 1] * stride; + xyOffset = vertexOffset + originVertOffset; + uvOffset = vertexOffset + originUVSOffset; + var x2 = vertices[xyOffset], y2 = vertices[xyOffset + 1]; + var u2 = uvs[uvOffset], v2 = uvs[uvOffset + 1]; + + vertexOffset = triangles[i + 2] * stride; + xyOffset = vertexOffset + originVertOffset; + uvOffset = vertexOffset + originUVSOffset; + var x3 = vertices[xyOffset], y3 = vertices[xyOffset + 1]; + var u3 = uvs[uvOffset], v3 = uvs[uvOffset + 1]; + for (var p = 0; p < polygonsCount; p++) { var s = clippedVertices.length; if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { diff --git a/extensions/spine/skeleton-cache.js b/extensions/spine/skeleton-cache.js new file mode 100644 index 00000000000..f29afeb2d7e --- /dev/null +++ b/extensions/spine/skeleton-cache.js @@ -0,0 +1,511 @@ +/**************************************************************************** + Copyright (c) 2018 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 TrackEntryListeners = require('./track-entry-listeners'); +const spine = require('./lib/spine'); +// Permit max cache time, unit is second. +const MaxCacheTime = 30; + +let _vertices = []; +let _indices = []; +let _vertexOffset = 0; +let _indexOffset = 0; +let _vfOffset = 0; +let _frameTime = 1 / 60; +let _preTexUrl = null; +let _preBlendMode = null; +let _segVCount = 0; +let _segICount = 0; +let _segOffset = 0; +let _colorOffset = 0; +let _preFinalColor = null; +let _preDarkColor = null; +// x y u v c1 c2 +let _perVertexSize = 6; +// x y u v r1 g1 b1 a1 r2 g2 b2 a2 +let _perClipVertexSize = 12; +let _vfCount = 0, _indexCount = 0; +let _tempr, _tempg, _tempb, _tempa; +let _finalColor32, _darkColor32; +let _finalColor = new spine.Color(1, 1, 1, 1); +let _darkColor = new spine.Color(1, 1, 1, 1); +let _quadTriangles = [0, 1, 2, 2, 3, 0]; + +//Cache all frames in an animation +let AnimationCache = cc.Class({ + ctor () { + this.frames = []; + this.totalTime = 0; + this._isCompleted = false; + + this._animationName = null; + this._tempSegments = null; + this._tempColors = null; + }, + + init (animationName) { + this._animationName = animationName; + }, + + // Clear texture quote. + clear () { + for (let i = 0, n = this.frames.length; i < n; i++) { + let frame = this.frames[i]; + frame.segments.length = 0; + } + }, + + bind (listener) { + let completeHandle = function (entry) { + if (entry && entry.animation.name === this._animationName) { + this._isCompleted = true; + } + }.bind(this); + + listener.end = completeHandle; + listener.complete = completeHandle; + listener.dispose = completeHandle; + }, + + unbind (listener) { + listener.end = null; + listener.complete = null; + listener.dispose = null; + }, + + update (skeletonInfo) { + if (!this._animationName) { + cc.error("AnimationCache:update animationName is empty"); + return; + } + let skeleton = skeletonInfo.skeleton; + let clipper = skeletonInfo.clipper; + let listener = skeletonInfo.listener; + let state = skeletonInfo.state; + + let animation = skeleton.data.findAnimation(this._animationName); + state.setAnimationWith(0, animation, false); + this.bind(listener); + + let frameIdx = 0; + this._isCompleted = false; + this.totalTime = 0; + + do { + // Solid update frame rate 1/60. + skeleton.update(_frameTime); + state.update(_frameTime); + state.apply(skeleton); + skeleton.updateWorldTransform() + this._updateFrame(skeleton, clipper, frameIdx) + frameIdx++; + this.totalTime += _frameTime; + } while (!this._isCompleted && this.totalTime < MaxCacheTime); + // Update frame length. + this.frames.length = frameIdx; + + this.unbind(listener); + }, + + _updateFrame (skeleton, clipper, index) { + _vfOffset = 0; + _indexOffset = 0; + _vertexOffset = 0; + _preTexUrl = null; + _preBlendMode = null; + _segVCount = 0; + _segICount = 0; + _segOffset = 0; + _colorOffset = 0; + _preFinalColor = null; + _preDarkColor = null; + + this.frames[index] = this.frames[index] || { + segments : [], + colors : [], + vertices : null, + uintVert : null, + indices : null, + }; + let frame = this.frames[index]; + + let segments = this._tempSegments = frame.segments; + let colors = this._tempColors = frame.colors; + this._traverseSkeleton(skeleton, clipper); + if (_colorOffset > 0) { + colors[_colorOffset - 1].vfOffset = _vfOffset; + } + colors.length = _colorOffset; + // Handle pre segment. + let preSegOffset = _segOffset - 1; + if (preSegOffset >= 0) { + // Judge segment vertex count is not empty. + if (_segICount > 0) { + let preSegInfo = segments[preSegOffset]; + preSegInfo.indexCount = _segICount; + preSegInfo.vfCount = _segVCount * _perVertexSize; + preSegInfo.vertexCount = _segVCount; + segments.length = _segOffset; + } else { + // Discard pre segment. + segments.length = _segOffset - 1; + } + } + + // Segments is empty,discard all segments. + if (segments.length == 0) return; + + // Fill vertices + let vertices = frame.vertices || new Float32Array(_vfOffset); + let uintVert = frame.uintVert || new Uint32Array(vertices.buffer); + for (let i = 0, j = 0; i < _vfOffset;) { + vertices[i++] = _vertices[j++]; // x + vertices[i++] = _vertices[j++]; // y + vertices[i++] = _vertices[j++]; // u + vertices[i++] = _vertices[j++]; // v + uintVert[i++] = _vertices[j++]; // color1 + uintVert[i++] = _vertices[j++]; // color2 + } + + // Fill indices + let indices = frame.indices || new Uint16Array(_indexOffset); + for (let i = 0; i < _indexOffset; i++) { + indices[i] = _indices[i]; + } + + frame.vertices = vertices; + frame.uintVert = uintVert; + frame.indices = indices; + }, + + fillVertices (skeletonColor, attachmentColor, slotColor, clipper) { + + _tempa = slotColor.a * attachmentColor.a * skeletonColor.a * 255; + _tempr = attachmentColor.r * skeletonColor.r * 255; + _tempg = attachmentColor.g * skeletonColor.g * 255; + _tempb = attachmentColor.b * skeletonColor.b * 255; + + _finalColor.r = _tempr * slotColor.r; + _finalColor.g = _tempg * slotColor.g; + _finalColor.b = _tempb * slotColor.b; + _finalColor.a = _tempa; + + if (slot.darkColor == null) { + _darkColor.set(0.0, 0, 0, 1.0); + } else { + _darkColor.r = slot.darkColor.r * _tempr; + _darkColor.g = slot.darkColor.g * _tempg; + _darkColor.b = slot.darkColor.b * _tempb; + } + _darkColor.a = 0; + + _finalColor32 = ((_finalColor.a<<24) >>> 0) + (_finalColor.b<<16) + (_finalColor.g<<8) + _finalColor.r; + _darkColor32 = ((_darkColor.a<<24) >>> 0) + (_darkColor.b<<16) + (_darkColor.g<<8) + _darkColor.r; + + if (_preFinalColor !== _finalColor32 || _preDarkColor !== _darkColor32) { + let colors = this._tempColors; + _preFinalColor = _finalColor32; + _preDarkColor = _darkColor32; + if (_colorOffset > 0) { + colors[_colorOffset - 1].vfOffset = _vfOffset; + } + colors[_colorOffset++] = { + fr : _finalColor.r, + fg : _finalColor.g, + fb : _finalColor.b, + fa : _finalColor.a, + dr : _darkColor.r, + dg : _darkColor.g, + db : _darkColor.b, + da : _darkColor.a, + vfOffset : 0 + } + } + + if (!clipper.isClipping()) { + + for (let v = _vfOffset, n = _vfOffset + _vfCount; v < n; v += _perVertexSize) { + _vertices[v + 4] = _finalColor32; // light color + _vertices[v + 5] = _darkColor32; // dark color + } + + } else { + clipper.clipTriangles(_vertices, _vfCount, _indices, _indexCount, _vertices, _finalColor, _darkColor, true, _perVertexSize, _indexOffset, _vfOffset, _vfOffset + 2); + let clippedVertices = clipper.clippedVertices; + let clippedTriangles = clipper.clippedTriangles; + + // insure capacity + _indexCount = clippedTriangles.length; + _vfCount = clippedVertices.length / _perClipVertexSize * _perVertexSize; + + // fill indices + for (let ii = 0, jj = _indexOffset, nn = clippedTriangles.length; ii < nn;) { + _indices[jj++] = clippedTriangles[ii++]; + } + + // fill vertices contain x y u v light color dark color + for (let v = 0, n = clippedVertices.length, offset = _vfOffset; v < n; v += 12, offset += _perVertexSize) { + _vertices[offset] = clippedVertices[v]; // x + _vertices[offset + 1] = clippedVertices[v + 1]; // y + _vertices[offset + 2] = clippedVertices[v + 6]; // u + _vertices[offset + 3] = clippedVertices[v + 7]; // v + + _vertices[offset + 4] = _finalColor32; + _vertices[offset + 5] = _darkColor32; + } + } + }, + + _traverseSkeleton (skeleton, clipper) { + let segments = this._tempSegments; + let skeletonColor = skeleton.color; + let attachment, attachmentColor, slotColor, uvs, triangles; + let isRegion, isMesh, isClip; + let texture; + let preSegOffset, preSegInfo; + let blendMode; + + for (let slotIdx = 0, slotCount = skeleton.drawOrder.length; slotIdx < slotCount; slotIdx++) { + slot = skeleton.drawOrder[slotIdx]; + + _vfCount = 0; + _indexCount = 0; + + attachment = slot.getAttachment(); + if (!attachment) continue; + + isRegion = attachment instanceof spine.RegionAttachment; + isMesh = attachment instanceof spine.MeshAttachment; + isClip = attachment instanceof spine.ClippingAttachment; + + if (isClip) { + clipper.clipStart(slot, attachment); + continue; + } + + if (!isRegion && !isMesh) continue; + + texture = attachment.region.texture._texture; + if (!texture) { + continue; + } + + blendMode = slot.data.blendMode; + if (_preTexUrl !== texture.url || _preBlendMode !== blendMode) { + _preTexUrl = texture.url; + _preBlendMode = blendMode; + // Handle pre segment. + preSegOffset = _segOffset - 1; + if (preSegOffset >= 0) { + if (_segICount > 0) { + preSegInfo = segments[preSegOffset]; + preSegInfo.indexCount = _segICount; + preSegInfo.vertexCount = _segVCount; + preSegInfo.vfCount = _segVCount * _perVertexSize; + } else { + // Discard pre segment. + _segOffset--; + } + } + // Handle now segment. + segments[_segOffset] = { + tex : texture, + blendMode : blendMode, + indexCount : 0, + vertexCount : 0, + vfCount : 0 + }; + _segOffset++; + _segICount = 0; + _segVCount = 0; + } + + if (isRegion) { + + triangles = _quadTriangles; + + // insure capacity + _vfCount = 4 * _perVertexSize; + _indexCount = 6; + + // compute vertex and fill x y + attachment.computeWorldVertices(slot.bone, _vertices, _vfOffset, _perVertexSize); + } + else if (isMesh) { + + triangles = attachment.triangles; + + // insure capacity + _vfCount = (attachment.worldVerticesLength >> 1) * _perVertexSize; + _indexCount = triangles.length; + + // compute vertex and fill x y + attachment.computeWorldVertices(slot, 0, attachment.worldVerticesLength, _vertices, _vfOffset, _perVertexSize); + } + + if (_vfCount == 0 || _indexCount == 0) { + continue; + } + + // fill indices + for (let ii = 0, jj = _indexOffset, nn = triangles.length; ii < nn;) { + _indices[jj++] = triangles[ii++]; + } + + // fill u v + uvs = attachment.uvs; + for (let v = _vfOffset, n = _vfOffset + _vfCount, u = 0; v < n; v += _perVertexSize, u += 2) { + _vertices[v + 2] = uvs[u]; // u + _vertices[v + 3] = uvs[u + 1]; // v + } + + attachmentColor = attachment.color; + slotColor = slot.color; + + this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper); + + if (_indexCount > 0) { + for (let ii = _indexOffset, nn = _indexOffset + _indexCount; ii < nn; ii++) { + _indices[ii] += _segVCount; + } + _indexOffset += _indexCount; + _vfOffset += _vfCount; + _vertexOffset = _vfOffset / _perVertexSize; + _segICount += _indexCount; + _segVCount += _vfCount / _perVertexSize; + } + + clipper.clipEndWithSlot(slot); + } + + clipper.clipEnd(); + } +}); + +let SkeletonCache = cc.Class({ + ctor () { + this._animationPool = {}; + this._skeletonCache = {}; + }, + + clear () { + this._animationPool = {}; + this._skeletonCache = {}; + }, + + removeSkeleton (uuid) { + var skeletonInfo = this._skeletonCache[uuid]; + if (!skeletonInfo) return; + let animationsCache = skeletonInfo.animationsCache; + for (var aniKey in animationsCache) { + // Clear cache texture, and put cache into pool. + // No need to create TypedArray next time. + let animationCache = animationsCache[aniKey]; + if (!animationCache) continue; + this._animationPool[uuid + "#" + aniKey] = animationCache; + animationCache.clear(); + } + + delete this._skeletonCache[uuid]; + }, + + resetSkeleton (uuid) { + var skeletonInfo = this._skeletonCache[uuid]; + if (!skeletonInfo) return; + let animationsCache = skeletonInfo.animationsCache; + for (var aniKey in animationsCache) { + // Clear cache texture, and put cache into pool. + // No need to create TypedArray next time. + let animationCache = animationsCache[aniKey]; + if (!animationCache) continue; + this._animationPool[uuid + "#" + aniKey] = animationCache; + animationCache.clear(); + } + }, + + getSkeletonCache (uuid, skeletonData) { + let skeletonInfo = this._skeletonCache[uuid]; + if (!skeletonInfo) { + let skeleton = new spine.Skeleton(skeletonData); + let clipper = new spine.SkeletonClipping(); + let stateData = new spine.AnimationStateData(skeleton.data); + let state = new spine.AnimationState(stateData); + let listener = new TrackEntryListeners(); + state.addListener(listener); + + this._skeletonCache[uuid] = skeletonInfo = { + skeleton : skeleton, + clipper : clipper, + state : state, + listener : listener, + // Cache all kinds of animation frame. + // When skeleton is dispose, clear all animation cache. + animationsCache : {}, + }; + } + return skeletonInfo; + }, + + getAnimationCache (uuid, animationName) { + let skeletonInfo = this._skeletonCache[uuid]; + if (!skeletonInfo) return null; + + let animationsCache = skeletonInfo.animationsCache; + return animationsCache[animationName]; + }, + + updateAnimationCache (uuid, animationName) { + let skeletonInfo = this._skeletonCache[uuid]; + let skeleton = skeletonInfo && skeletonInfo.skeleton; + if (!skeleton) return null; + + let animation = skeleton.data.findAnimation(animationName); + if (!animation) { + return null; + } + + let animationsCache = skeletonInfo.animationsCache; + let animationCache = animationsCache[animationName]; + if (!animationCache) { + // If cache exist in pool, then just use it. + let poolKey = uuid + "#" + animationName; + animationCache = this._animationPool[poolKey]; + if (animationCache) { + delete this._animationPool[poolKey]; + } else { + animationCache = new AnimationCache(); + animationCache.init(animationName); + } + animationsCache[animationName] = animationCache; + } + animationCache.update(skeletonInfo); + if (animationCache.totalTime >= MaxCacheTime) { + cc.warn("Animation cache is overflow, maybe animation's frame is infinite, please change skeleton render mode to REALTIME, animation name is [%s]",animationName); + } + return animationCache; + } +}); + +SkeletonCache.sharedCache = new SkeletonCache(); +module.exports = SkeletonCache; \ No newline at end of file diff --git a/extensions/spine/skeleton-data.js b/extensions/spine/skeleton-data.js index 657d434ec68..ee59a9f22fa 100644 --- a/extensions/spine/skeleton-data.js +++ b/extensions/spine/skeleton-data.js @@ -26,6 +26,7 @@ /** * @module sp */ +let SkeletonCache = !CC_JSB && require('./skeleton-cache').sharedCache; /** * !#en The skeleton data of spine. @@ -246,7 +247,14 @@ var SkeletonData = cc.Class({ } return this._atlasCache = new sp.spine.TextureAtlas(this.atlasText, this._getTexture.bind(this)); - } + }, + + destroy () { + if (!CC_JSB) { + SkeletonCache.removeSkeleton(this._uuid); + } + this._super(); + }, }); sp.SkeletonData = module.exports = SkeletonData; diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 84bd012aa0e..05c178904f9 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -29,11 +29,18 @@ const renderer = require('../../cocos2d/core/renderer'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); const renderEngine = renderer.renderEngine; const gfx = renderEngine.gfx; -const SpineMaterial = renderEngine.SpineMaterial; const VertexFormat = require('../../cocos2d/core/renderer/webgl/vertex-format') const VFOneColor = VertexFormat.vfmtPosUvColor; const VFTwoColor = VertexFormat.vfmtPosUvTwoColor; +const FLAG_BATCH = 0x10; +const FLAG_TWO_COLOR = 0x01; +const NOT_BATCH_ONE_COLOR = 0x00; +const NOT_BATCH_TWO_COLOR = 0x01; +const BATCH_ONE_COLOR = 0x10; +const BATCH_TWO_COLOR = 0x11; + +let _handleVal = 0x00; let _quadTriangles = [0, 1, 2, 2, 3, 0]; let _slotColor = cc.color(0, 0, 255, 255); let _boneColor = cc.color(255, 0, 0, 255); @@ -65,10 +72,13 @@ let _vertexFloatCount = 0, _vertexFloatOffset = 0, _vertexOffset = 0, _indexCount = 0, _indexOffset = 0; let _tempr, _tempg, _tempb, _tempa; let _inRange; +let _mustFlush; +let _x, _y, _m00, _m04, _m12, _m01, _m05, _m13; +let _r, _g, _b, _a, _fr, _fg, _fb, _fa, _dr, _dg, _db, _da; -function _getSlotMaterial (comp, slot, tex) { +function _getSlotMaterial (tex, blendMode) { let src, dst; - switch (slot.data.blendMode) { + switch (blendMode) { case spine.BlendMode.Additive: src = _premultipliedAlpha ? cc.macro.ONE : cc.macro.SRC_ALPHA; dst = cc.macro.ONE; @@ -88,10 +98,12 @@ function _getSlotMaterial (comp, slot, tex) { break; } - let key = tex.url + src + dst; - comp._material = comp._material || new SpineMaterial(); - let baseMaterial = comp._material; - let materialCache = comp._materialCache; + let useModel = !_comp.enableBatch; + let key = tex.url + src + dst + _useTint + useModel; + let baseMaterial = _comp._material; + if (!baseMaterial) return null; + + let materialCache = _comp._materialCache; let material = materialCache[key]; if (!material) { @@ -102,7 +114,7 @@ function _getSlotMaterial (comp, slot, tex) { material = baseMaterial.clone(); } - material.useModel = true; + material.useModel = useModel; // Update texture. material.texture = tex; // Update tint. @@ -126,9 +138,27 @@ function _getSlotMaterial (comp, slot, tex) { return material; } +function _handleColor (color) { + // temp rgb has multiply 255, so need divide 255; + _multiplier = _premultipliedAlpha ? color.fa / 255 : 1; + _r = _nodeR * _multiplier; + _g = _nodeG * _multiplier; + _b = _nodeB * _multiplier; + + _fr = color.fr * _r; + _fg = color.fg * _g; + _fb = color.fb * _b; + _fa = color.fa * _nodeA; + _finalColor32 = ((_fa<<24) >>> 0) + (_fb<<16) + (_fg<<8) + _fr; + + _dr = color.dr * _r; + _dg = color.dg * _g; + _db = color.db * _b; + _da = _premultipliedAlpha ? 255 : 0; + _darkColor32 = ((_da<<24) >>> 0) + (_db<<16) + (_dg<<8) + _dr; +} + var spineAssembler = { - // Use model to avoid per vertex transform. - useModel: true, updateRenderData (comp, batchData) { let skeleton = comp._skeleton; @@ -137,11 +167,11 @@ var spineAssembler = { } }, - fillVertices (skeletonColor, attachmentColor, slotColor, clipper, buffer) { + fillVertices (skeletonColor, attachmentColor, slotColor, clipper) { - let vbuf = buffer._vData, - ibuf = buffer._iData, - uintVData = buffer._uintVData; + let vbuf = _buffer._vData, + ibuf = _buffer._iData, + uintVData = _buffer._uintVData; let offsetInfo; _tempa = slotColor.a * attachmentColor.a * skeletonColor.a * 255; @@ -170,11 +200,11 @@ var spineAssembler = { _darkColor32 = ((_darkColor.a<<24) >>> 0) + (_darkColor.b<<16) + (_darkColor.g<<8) + _darkColor.r; if (!_useTint) { - for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount, u = 0; v < n; v += _perVertexSize, u += 2) { + for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount; v < n; v += _perVertexSize) { uintVData[v + 4] = _finalColor32; } } else { - for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount, u = 0; v < n; v += _perVertexSize, u += 2) { + for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount; v < n; v += _perVertexSize) { uintVData[v + 4] = _finalColor32; // light color uintVData[v + 5] = _darkColor32; // dark color } @@ -190,13 +220,13 @@ var spineAssembler = { _indexCount = clippedTriangles.length; _vertexFloatCount = clippedVertices.length / _perClipVertexSize * _perVertexSize; - offsetInfo = buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + offsetInfo = _buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); _indexOffset = offsetInfo.indiceOffset, _vertexOffset = offsetInfo.vertexOffset, _vertexFloatOffset = offsetInfo.byteOffset >> 2; - vbuf = buffer._vData, - ibuf = buffer._iData; - uintVData = buffer._uintVData; + vbuf = _buffer._vData, + ibuf = _buffer._iData; + uintVData = _buffer._uintVData; // fill indices ibuf.set(clippedTriangles, _indexOffset); @@ -229,52 +259,32 @@ var spineAssembler = { } }, - fillBuffers (comp, renderer) { - - let node = comp.node; - node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; - let locSkeleton = comp._skeleton; - if (!locSkeleton) return; - - let nodeColor = node._color; - _nodeR = nodeColor.r / 255; - _nodeG = nodeColor.g / 255; - _nodeB = nodeColor.b / 255; - _nodeA = nodeColor.a / 255; - - _useTint = comp.useTint; - _vertexFormat = _useTint? VFTwoColor : VFOneColor; - let buffer = renderer.getBuffer('spine', _vertexFormat); + realTimeTraverse (worldMat) { let vbuf; let ibuf; + let locSkeleton = _comp._skeleton; let skeletonColor = locSkeleton.color; - let graphics = comp._debugRenderer; - let clipper = comp._clipper; + let graphics = _comp._debugRenderer; + let clipper = _comp._clipper; let material = null; let attachment, attachmentColor, slotColor, uvs, triangles; - let hasFlush = false; let isRegion, isMesh, isClip; let offsetInfo; - _premultipliedAlpha = comp.premultipliedAlpha; - _multiplier = 1.0; - - _slotRangeStart = comp._startSlotIndex; - _slotRangeEnd = comp._endSlotIndex; + _slotRangeStart = _comp._startSlotIndex; + _slotRangeEnd = _comp._endSlotIndex; _inRange = false; if (_slotRangeStart == -1) _inRange = true; - _debugSlots = comp.debugSlots; - _debugBones = comp.debugBones; + _debugSlots = _comp.debugSlots; + _debugBones = _comp.debugBones; if (graphics && (_debugBones || _debugSlots)) { graphics.clear(); graphics.strokeColor = _slotColor; graphics.lineWidth = 5; } - // x y u v color1 color2 or x y u v color - _perVertexSize = _useTint ? 6 : 5; // x y u v r1 g1 b1 a1 r2 g2 b2 a2 or x y u v r g b a _perClipVertexSize = _useTint ? 12 : 8; @@ -317,16 +327,16 @@ var spineAssembler = { if (!isRegion && !isMesh) continue; - material = _getSlotMaterial(comp, slot, attachment.region.texture._texture); + material = _getSlotMaterial(attachment.region.texture._texture, slot.data.blendMode); if (!material) { continue; } - - if (!hasFlush || material._hash !== renderer.material._hash) { - hasFlush = true; - renderer._flush(); - renderer.node = node; - renderer.material = material; + + if (_mustFlush || material._hash !== _renderer.material._hash) { + _mustFlush = false; + _renderer._flush(); + _renderer.node = _node; + _renderer.material = material; } if (isRegion) { @@ -337,13 +347,13 @@ var spineAssembler = { _vertexFloatCount = 4 * _perVertexSize; _indexCount = 6; - offsetInfo = buffer.request(4, 6); + offsetInfo = _buffer.request(4, 6); _indexOffset = offsetInfo.indiceOffset, _vertexOffset = offsetInfo.vertexOffset, _vertexFloatOffset = offsetInfo.byteOffset >> 2; - vbuf = buffer._vData, - ibuf = buffer._iData; - uintVData = buffer._uintVData; + vbuf = _buffer._vData, + ibuf = _buffer._iData; + uintVData = _buffer._uintVData; // compute vertex and fill x y attachment.computeWorldVertices(slot.bone, vbuf, _vertexFloatOffset, _perVertexSize); @@ -366,13 +376,13 @@ var spineAssembler = { _vertexFloatCount = (attachment.worldVerticesLength >> 1) * _perVertexSize; _indexCount = triangles.length; - offsetInfo = buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + offsetInfo = _buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); _indexOffset = offsetInfo.indiceOffset, _vertexOffset = offsetInfo.vertexOffset, _vertexFloatOffset = offsetInfo.byteOffset >> 2; - vbuf = buffer._vData, - ibuf = buffer._iData; - uintVData = buffer._uintVData; + vbuf = _buffer._vData, + ibuf = _buffer._iData; + uintVData = _buffer._uintVData; // compute vertex and fill x y attachment.computeWorldVertices(slot, 0, attachment.worldVerticesLength, vbuf, _vertexFloatOffset, _perVertexSize); @@ -395,13 +405,28 @@ var spineAssembler = { attachmentColor = attachment.color, slotColor = slot.color; - this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper, buffer); + this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper); if (_indexCount > 0) { for (let ii = _indexOffset, nn = _indexOffset + _indexCount; ii < nn; ii++) { ibuf[ii] += _vertexOffset; } - buffer.adjust(_vertexFloatCount / _perVertexSize, _indexCount); + + if (worldMat) { + _m00 = worldMat.m00; + _m04 = worldMat.m04; + _m12 = worldMat.m12; + _m01 = worldMat.m01; + _m05 = worldMat.m05; + _m13 = worldMat.m13; + for (let ii = _vertexFloatOffset, nn = _vertexFloatOffset + _vertexFloatCount; ii < nn; ii += _perVertexSize) { + _x = vbuf[ii]; + _y = vbuf[ii + 1]; + vbuf[ii] = _x * _m00 + _y * _m04 + _m12; + vbuf[ii + 1] = _x * _m01 + _y * _m05 + _m13; + } + } + _buffer.adjust(_vertexFloatCount / _perVertexSize, _indexCount); } clipper.clipEndWithSlot(slot); @@ -433,7 +458,182 @@ var spineAssembler = { } } } - + }, + + cacheTraverse (worldMat) { + + let frame = _comp._curFrame; + if (!frame) return; + + let segments = frame.segments; + if (segments.length == 0) return; + + let vbuf, ibuf, uintbuf; + let material; + let offsetInfo; + let vertices = frame.vertices; + let indices = frame.indices; + let uintVert = frame.uintVert; + + let frameVFOffset = 0, frameIndexOffset = 0, segVFCount = 0; + if (worldMat) { + _m00 = worldMat.m00; + _m04 = worldMat.m04; + _m12 = worldMat.m12; + _m01 = worldMat.m01; + _m05 = worldMat.m05; + _m13 = worldMat.m13; + } + + let colorOffset = 0; + let colors = frame.colors; + let nowColor = colors[colorOffset++]; + let maxVFOffset = nowColor.vfOffset; + _handleColor(nowColor); + + for (let i = 0, n = segments.length; i < n; i++) { + let segInfo = segments[i]; + material = _getSlotMaterial(segInfo.tex, segInfo.blendMode); + if (!material) continue; + + if (_mustFlush || material._hash !== _renderer.material._hash) { + _mustFlush = false; + _renderer._flush(); + _renderer.node = _node; + _renderer.material = material; + } + + _vertexCount = segInfo.vertexCount; + _indexCount = segInfo.indexCount; + _vertexFloatCount = _vertexCount * _perVertexSize; + + offsetInfo = _buffer.request(_vertexCount, _indexCount); + _indexOffset = offsetInfo.indiceOffset; + _vertexOffset = offsetInfo.vertexOffset; + _vfOffset = offsetInfo.byteOffset >> 2; + vbuf = _buffer._vData; + ibuf = _buffer._iData; + uintbuf = _buffer._uintVData; + + for (let ii = _indexOffset, il = _indexOffset + _indexCount; ii < il; ii++) { + ibuf[ii] = _vertexOffset + indices[frameIndexOffset++]; + } + + segVFCount = segInfo.vfCount; + + switch (_handleVal) { + case NOT_BATCH_ONE_COLOR: + for (let ii = _vfOffset, il = _vfOffset + _vertexFloatCount; ii < il;) { + vbuf[ii++] = vertices[frameVFOffset++]; // x + vbuf[ii++] = vertices[frameVFOffset++]; // y + vbuf[ii++] = vertices[frameVFOffset++]; // u + vbuf[ii++] = vertices[frameVFOffset++]; // v + uintbuf[ii++] = uintVert[frameVFOffset++]; // final color + frameVFOffset++; // jump dark color + } + break; + case NOT_BATCH_TWO_COLOR: + vbuf.set(vertices.subarray(frameVFOffset, frameVFOffset + _vertexFloatCount), _vfOffset); + frameVFOffset += _vertexFloatCount; + break; + case BATCH_ONE_COLOR: + for (let ii = _vfOffset, il = _vfOffset + _vertexFloatCount; ii < il;) { + _x = vertices[frameVFOffset++]; + _y = vertices[frameVFOffset++]; + vbuf[ii++] = _x * _m00 + _y * _m04 + _m12; // x + vbuf[ii++] = _x * _m01 + _y * _m05 + _m13; // y + vbuf[ii++] = vertices[frameVFOffset++]; // u + vbuf[ii++] = vertices[frameVFOffset++]; // v + uintbuf[ii++] = uintVert[frameVFOffset++]; // final color + frameVFOffset++; // dark color + } + break; + case BATCH_TWO_COLOR: + for (let ii = _vfOffset, il = _vfOffset + _vertexFloatCount; ii < il;) { + _x = vertices[frameVFOffset++]; + _y = vertices[frameVFOffset++]; + vbuf[ii++] = _x * _m00 + _y * _m04 + _m12; // x + vbuf[ii++] = _x * _m01 + _y * _m05 + _m13; // y + vbuf[ii++] = vertices[frameVFOffset++]; // u + vbuf[ii++] = vertices[frameVFOffset++]; // v + uintbuf[ii++] = uintVert[frameVFOffset++]; // final color + uintbuf[ii++] = uintVert[frameVFOffset++]; // dark color + } + break; + } + + _buffer.adjust(_vertexCount, _indexCount); + if ( !_needColor ) continue; + + // handle color + let frameColorOffset = frameVFOffset - segVFCount; + for (let ii = _vfOffset + 4, il = _vfOffset + 4 + _vertexFloatCount; ii < il; ii += _perVertexSize, frameColorOffset += 6) { + if (frameColorOffset >= maxVFOffset) { + nowColor = colors[colorOffset++]; + _handleColor(nowColor); + maxVFOffset = nowColor.vfOffset; + } + uintbuf[ii] = _finalColor32; + _useTint && (uintbuf[ii + 1] = _darkColor32); + } + } + }, + + fillBuffers (comp, renderer) { + + let node = comp.node; + node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA; + if (!comp._skeleton) return; + + let nodeColor = node._color; + _nodeR = nodeColor.r / 255; + _nodeG = nodeColor.g / 255; + _nodeB = nodeColor.b / 255; + _nodeA = nodeColor.a / 255; + + _useTint = comp.useTint; + _vertexFormat = _useTint? VFTwoColor : VFOneColor; + // x y u v color1 color2 or x y u v color + _perVertexSize = _useTint ? 6 : 5; + + _node = comp.node; + _buffer = renderer.getBuffer('spine', _vertexFormat); + _renderer = renderer; + _comp = comp; + + _mustFlush = true; + _premultipliedAlpha = comp.premultipliedAlpha; + _multiplier = 1.0; + _handleVal = 0x00; + _needColor = false; + + if (nodeColor._val !== 0xffffffff || _premultipliedAlpha) { + _needColor = true; + } + + if (_useTint) { + _handleVal |= FLAG_TWO_COLOR; + } + + let worldMat = undefined; + if (_comp.enableBatch) { + worldMat = _node._worldMatrix; + _mustFlush = false; + _handleVal |= FLAG_BATCH; + } + + if (comp.isCachedMode()) { + // Traverse input assembler. + this.cacheTraverse(worldMat); + } else { + this.realTimeTraverse(worldMat); + } + + // Clear temp var. + _node = undefined; + _buffer = undefined; + _renderer = undefined; + _comp = undefined; } }; diff --git a/gulp/tasks/engine.js b/gulp/tasks/engine.js index ecf0b8c852b..401f65d7df0 100644 --- a/gulp/tasks/engine.js +++ b/gulp/tasks/engine.js @@ -41,6 +41,7 @@ const Optimizejs = require('gulp-optimize-js'); var jsbSkipModules = [ // modules need to skip in jsb + '../../extensions/spine/skeleton-cache.js', '../../extensions/spine/lib/spine.js', '../../extensions/dragonbones/lib/dragonBones.js', '../../extensions/dragonbones/ArmatureCache.js', From b526af8e3a26b51b0130d163e8c7f8f5c2e73271 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Fri, 15 Feb 2019 16:50:58 +0800 Subject: [PATCH 0450/1631] add cc.tween (#3660) * add cc.animate * add animate.clone * refine animate.add * rename process to progress * change animate to tween * change Tween.add to Tween.then * refine tween * refine code * refine api comment * mark cc.Easing deprecated * refine tween comment --- cocos2d/actions/index.js | 3 +- cocos2d/actions/tween.js | 397 ++++++++++++++++++++++++++ cocos2d/animation/animation-curves.js | 4 +- cocos2d/animation/easing.js | 52 ++-- cocos2d/deprecated.js | 4 + test/qunit/unit-es5/test-animation.js | 2 +- 6 files changed, 432 insertions(+), 30 deletions(-) create mode 100644 cocos2d/actions/tween.js diff --git a/cocos2d/actions/index.js b/cocos2d/actions/index.js index e556fa5680f..606b22d126c 100644 --- a/cocos2d/actions/index.js +++ b/cocos2d/actions/index.js @@ -28,4 +28,5 @@ require('./CCAction'); require('./CCActionInterval'); require('./CCActionInstant'); require('./CCActionEase'); -require('./CCActionCatmullRom'); \ No newline at end of file +require('./CCActionCatmullRom'); +require('./tween'); diff --git a/cocos2d/actions/tween.js b/cocos2d/actions/tween.js new file mode 100644 index 00000000000..92b021af555 --- /dev/null +++ b/cocos2d/actions/tween.js @@ -0,0 +1,397 @@ + +let TweenAction = cc.Class({ + name: 'TweenAction', + extends: cc.ActionInterval, + + ctor (duration, props, opts) { + this._opts = opts = opts || Object.create(null); + this._props = Object.create(null); + + // global easing or progress used for this action + opts.progress = opts.progress || this.progress; + if (opts.easing && typeof opts.easing === 'string') { + opts.easing = cc.easing[opts.easing]; + } + + for (let name in props) { + let value = props[name]; + + // property may have custom easing or progress function + let easing, progress; + if (value.value && (value.easing || value.progress)) { + easing = typeof value.easing === 'string' ? cc.easing[value.easing] : value.easing; + progress = value.progress; + value = value.value; + } + + let isNumber = typeof value === 'number'; + if (!isNumber && (!value.lerp || (!value.add && !value.mul) || !value.clone)) { + cc.warn(`Can not animate ${name} property, because it do not have [lerp, (add|mul), clone] function.`); + continue; + } + + let prop = Object.create(null); + prop.value = value; + prop.easing = easing; + prop.progress = progress; + this._props[name] = prop; + } + + this._originProps = props; + this.initWithDuration(duration); + }, + + clone () { + var action = new TweenAction(this._duration, this._originProps, this._opts); + this._cloneDecoration(action); + return action; + }, + + startWithTarget (target) { + cc.ActionInterval.prototype.startWithTarget.call(this, target); + + let relative = !!this._opts.relative; + let props = this._props; + for (let name in props) { + let value = target[name]; + let prop = props[name]; + + if (typeof value === 'number') { + prop.start = value; + prop.current = value; + prop.end = relative ? value + prop.value : prop.value; + } + else { + prop.start = value.clone(); + prop.current = value.clone(); + prop.end = relative ? (value.add || value.mul).call(value, prop.value) : prop.value; + } + } + }, + + update (t) { + let opts = this._opts; + let easingTime = t; + if (opts.easing) easingTime = opts.easing(t); + + let target = this.target; + if (!target) return; + + let props = this._props; + let progress = this._opts.progress; + for (let name in props) { + let prop = props[name]; + let time = prop.easing ? prop.easing(t) : easingTime; + let current = prop.current = (prop.progress || progress)(prop.start, prop.end, prop.current, time); + target[name] = current; + } + }, + + progress (start, end, current, t) { + if (typeof start === 'number') { + current = start + (end - start) * t; + } + else { + start.lerp(end, t, current); + } + return current; + } +}); + + + +/** + * !#en + * Tween provide a simple and flexible way to create action. + * Tween's api is more flexible than cc.Action: + * - Support creating an action sequence in chained api, + * - Support animate any objects' any properties, not limited to node's properties. + * By contrast, cc.Action needs to create a new action class to support new node property. + * - Support working with cc.Action, + * - Support easing and progress function, + * !#zh + * Tween 提供了一个简单灵活的方法来创建 action。 + * 相对于 Cocos 传统的 cc.Action,cc.Tween 在创建动画上要灵活非常多: + * - 支持以链式结构的方式创建一个动画序列。 + * - 支持对任意对象的任意属性进行缓动,不再局限于节点上的属性,而 cc.Action 添加一个属性的支持时还需要添加一个新的 action 类型。 + * - 支持与 cc.Action 混用 + * - 支持设置 easing 或者 progress 函数 + * @class Tween + * @example + * cc.tween(node) + * .to(1, {scale: 2, position: cc.v3(100, 100, 100)}) + * .call(() => { console.log('This is a callback'); }) + * .by(1, {scale: 3, position: cc.v3(200, 200, 200)}, {easing: 'sineOutIn'}) + * .run(cc.find('Canvas/cocos')); + */ +function Tween (target) { + this._actions = []; + this._finalAction = null; + this._target = target; +} + +/** + * !#en + * Insert an action or tween to this sequence + * !#zh + * 插入一个 action 或者 tween 到队列中 + * @method then + * @param {Action|Tween} other + */ +Tween.prototype.then = function (other) { + if (other instanceof cc.Action) { + this._actions.push(other.clone()); + } + else { + let actions = other._actions; + for (let i = 0; i < actions.length; i++) { + this._actions.push(actions[i].clone()); + } + } + return this; +}; + +/** + * !#en + * Set tween target + * !#zh + * 设置 tween 的 target + * @method target + */ +Tween.prototype.target = function (target) { + this._target = target; + return this; +}; + +/** + * !#en + * Start this tween + * !#zh + * 运行当前 tween + * @method start + */ +Tween.prototype.start = function () { + if (!this._target) { + cc.warn('Please set target to tween first'); + return this; + } + if (!this._finalAction) { + this._finalAction = this._get(); + } + cc.director.getActionManager().addAction(this._finalAction, this._target, false); + return this; +}; + +/** + * !#en + * Stop this tween + * !#zh + * 停止当前 tween + * @method stop + */ +Tween.prototype.stop = function () { + if (this._finalAction) { + cc.director.getActionManager().removeAction(this._finalAction); + } + return this; +}; + + + +/** + * !#en + * Clone a tween + * !#zh + * 克隆当前 tween + * @method clone + * @param {Object} [target] + */ +Tween.prototype.clone = function (target) { + let action = this._get(); + return cc.tween(target).then(action.clone()); +}; + +/** + * !#en + * Get an union action from current sequence + * !#zh + * 从当前队列中获取一个整合的 action + */ +Tween.prototype._get = function () { + let actions = this._actions; + + if (actions.length === 1) { + actions = actions[0]; + } + else { + actions = Tween.sequence(actions); + } + + return actions; +}; + + +let actions = { + /** + * !#en + * Add an action which calculate with absolute value + * !#zh + * 添加一个对属性进行绝对值计算的 action + * @method to + * @param {Number} duration + * @param {Object} props - {scale: 2, position: cc.v3(100, 100, 100)} + * @param {Object} opts + * @param {Function} opts.progress + * @param {Function|String} opts.easing + */ + to (duration, props, opts) { + opts = opts || Object.create(null); + opts.relative = false; + return new TweenAction(duration, props, opts); + }, + + /** + * !#en + * Add an action which calculate with relative value + * !#zh + * 添加一个对属性进行相对值计算的 action + * @method by + * @param {Number} duration + * @param {Object} props - {scale: 2, position: cc.v3(100, 100, 100)} + * @param {Object} opts + * @param {Function} opts.progress + * @param {Function|String} opts.easing + */ + by (duration, props, opts) { + opts = opts || Object.create(null); + opts.relative = true; + return new TweenAction(duration, props, opts); + }, + + /** + * !#en + * Add an delay action + * !#zh + * 添加一个延时 action + * @method delay + * @param {Number} duration + */ + delay: cc.delayTime, + /** + * !#en + * Add an callback action + * !#zh + * 添加一个回调 action + * @method call + * @param {Function} callback + */ + call: cc.callFunc, + /** + * !#en + * Add an hide action + * !#zh + * 添加一个隐藏 action + * @method hide + */ + hide: cc.hide, + /** + * !#en + * Add an show action + * !#zh + * 添加一个显示 action + * @method show + */ + show: cc.show, + /** + * !#en + * Add an removeSelf action + * !#zh + * 添加一个移除自己 action + * @method removeSelf + */ + removeSelf: cc.removeSelf, + /** + * !#en + * Add an sequence action + * !#zh + * 添加一个队列 action + * @method sequence + * @param {[Action]} actions + */ + sequence: cc.sequence, +}; + +// these action should integrate before actions to a sequence action as their parameters +let otherActions = { + /** + * !#en + * Add an repeat action. + * This action will integrate before actions to a sequence action as their parameters. + * !#zh + * 添加一个重复 action,这个 action 会将之前的 action 整合成一个 sequence action 作为他的参数。 + * @method repeat + * @param {Number} repeatTimes + */ + repeat: cc.repeat, + /** + * !#en + * Add an repeat forever action + * This action will integrate before actions to a sequence action as their parameters. + * !#zh + * 添加一个永久重复 action,这个 action 会将之前的 action 整合成一个 sequence action 作为他的参数。 + * @method repeatForever + */ + repeatForever: cc.repeatForever, + /** + * !#en + * Add an reverse time action. + * This action will integrate before actions to a sequence action as their parameters. + * !#zh + * 添加一个倒置时间 action,这个 action 会将之前的 action 整合成一个 sequence action 作为他的参数。 + * @method reverseTime + */ + reverseTime: cc.reverseTime, +}; + +let keys = Object.keys(actions); +for (let i = 0; i < keys.length; i++) { + let key = keys[i]; + Tween.prototype[key] = function () { + let action = actions[key].apply(actions, arguments); + this._actions.push(action); + this._finalAction = null; + return this; + }; +} + +keys = Object.keys(otherActions); +for (let i = 0; i < keys.length; i++) { + let key = keys[i]; + Tween.prototype[key] = function () { + let args = []; + for (let l = arguments.length, i = 0; i < l; i++) { + args[i] = arguments[i]; + } + + let action = arguments[0]; + if (!(action instanceof cc.Action)) { + action = this._get(); + } + action = otherActions[key].apply(otherActions, [action].concat(args)); + this._actions.length = 0; + this._actions.push(action); + this._finalAction = null; + return this; + }; +} + +/** + * @method tween + * @param {Object} [target] - the target to animate + * @return {Tween} + */ +cc.tween = function (target) { + return new Tween(target); +}; + +cc.Tween = Tween; diff --git a/cocos2d/animation/animation-curves.js b/cocos2d/animation/animation-curves.js index 9f461d038c8..052c9e297d0 100644 --- a/cocos2d/animation/animation-curves.js +++ b/cocos2d/animation/animation-curves.js @@ -33,11 +33,11 @@ var WrappedInfo = require('./types').WrappedInfo; /** * Compute a new ratio by curve type * @param {Number} ratio - The origin ratio - * @param {Array|String} type - If it's Array, then ratio will be computed with bezierByTime. If it's string, then ratio will be computed with cc.Easing function + * @param {Array|String} type - If it's Array, then ratio will be computed with bezierByTime. If it's string, then ratio will be computed with cc.easing function */ function computeRatioByType (ratio, type) { if (typeof type === 'string') { - var func = cc.Easing[type]; + var func = cc.easing[type]; if (func) { ratio = func(ratio); } diff --git a/cocos2d/animation/easing.js b/cocos2d/animation/easing.js index 923f6487922..9a1e3dc733f 100644 --- a/cocos2d/animation/easing.js +++ b/cocos2d/animation/easing.js @@ -23,12 +23,12 @@ THE SOFTWARE. ****************************************************************************/ -var Easing = { +var easing = { constant: function () { return 0; }, linear: function (k) { return k; }, // quad - // Easing equation function for a quadratic (t^2) + // easing equation function for a quadratic (t^2) // @param t: Current time (in frames or seconds). // @return: The correct value. @@ -42,7 +42,7 @@ var Easing = { }, // cubic - // Easing equation function for a cubic (t^3) + // easing equation function for a cubic (t^3) // @param t: Current time (in frames or seconds). // @return: The correct value. @@ -56,7 +56,7 @@ var Easing = { }, // quart - // Easing equation function for a quartic (t^4) + // easing equation function for a quartic (t^4) // @param t: Current time (in frames or seconds). // @return: The correct value. @@ -70,7 +70,7 @@ var Easing = { }, // quint - // Easing equation function for a quintic (t^5) + // easing equation function for a quintic (t^5) // @param t: Current time (in frames or seconds). // @return: The correct value. @@ -84,7 +84,7 @@ var Easing = { }, // sine - // Easing equation function for a sinusoidal (sin(t)) + // easing equation function for a sinusoidal (sin(t)) // @param t: Current time (in frames or seconds). // @return: The correct value. @@ -93,7 +93,7 @@ var Easing = { sineInOut: function (k) { return 0.5 * ( 1 - Math.cos(Math.PI * k) ); }, // expo - // Easing equation function for an exponential (2^t) + // easing equation function for an exponential (2^t) // param t: Current time (in frames or seconds). // return: The correct value. @@ -113,7 +113,7 @@ var Easing = { }, // circ - // Easing equation function for a circular (sqrt(1-t^2)) + // easing equation function for a circular (sqrt(1-t^2)) // @param t: Current time (in frames or seconds). // @return: The correct value. @@ -127,7 +127,7 @@ var Easing = { }, // elastic - // Easing equation function for an elastic (exponentially decaying sine wave) + // easing equation function for an elastic (exponentially decaying sine wave) // @param t: Current time (in frames or seconds). // @return: The correct value. // recommand value: elastic (t) @@ -189,7 +189,7 @@ var Easing = { }, // back - // Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) + // easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) // @param t: Current time (in frames or seconds). // @return: The correct value. @@ -210,7 +210,7 @@ var Easing = { }, // bounce - // Easing equation function for a bounce (exponentially decaying parabolic bounce) + // easing equation function for a bounce (exponentially decaying parabolic bounce) // @param t: Current time (in frames or seconds). // @return: The correct value. @@ -262,22 +262,22 @@ function _makeOutIn (fnIn, fnOut) { return fnIn(2 * k - 1) / 2 + 0.5; }; } -Easing.quadOutIn = _makeOutIn(Easing.quadIn, Easing.quadOut); -Easing.cubicOutIn = _makeOutIn(Easing.cubicIn, Easing.cubicOut); -Easing.quartOutIn = _makeOutIn(Easing.quartIn, Easing.quartOut); -Easing.quintOutIn = _makeOutIn(Easing.quintIn, Easing.quintOut); -Easing.sineOutIn = _makeOutIn(Easing.sineIn, Easing.sineOut); -Easing.expoOutIn = _makeOutIn(Easing.expoIn, Easing.expoOut); -Easing.circOutIn = _makeOutIn(Easing.circIn, Easing.circOut); -Easing.backOutIn = _makeOutIn(Easing.backIn, Easing.backOut); -Easing.backOutIn = _makeOutIn(Easing.backIn, Easing.backOut); -Easing.bounceIn = function (k) { return 1 - Easing.bounceOut(1 - k); }; -Easing.bounceInOut = function (k) { +easing.quadOutIn = _makeOutIn(easing.quadIn, easing.quadOut); +easing.cubicOutIn = _makeOutIn(easing.cubicIn, easing.cubicOut); +easing.quartOutIn = _makeOutIn(easing.quartIn, easing.quartOut); +easing.quintOutIn = _makeOutIn(easing.quintIn, easing.quintOut); +easing.sineOutIn = _makeOutIn(easing.sineIn, easing.sineOut); +easing.expoOutIn = _makeOutIn(easing.expoIn, easing.expoOut); +easing.circOutIn = _makeOutIn(easing.circIn, easing.circOut); +easing.backOutIn = _makeOutIn(easing.backIn, easing.backOut); +easing.backOutIn = _makeOutIn(easing.backIn, easing.backOut); +easing.bounceIn = function (k) { return 1 - easing.bounceOut(1 - k); }; +easing.bounceInOut = function (k) { if (k < 0.5) { - return Easing.bounceIn(k * 2) * 0.5; + return easing.bounceIn(k * 2) * 0.5; } - return Easing.bounceOut(k * 2 - 1) * 0.5 + 0.5; + return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5; }; -Easing.bounceOutIn = _makeOutIn(Easing.bounceIn, Easing.bounceOut); +easing.bounceOutIn = _makeOutIn(easing.bounceIn, easing.bounceOut); -cc.Easing = module.exports = Easing; +cc.easing = module.exports = easing; diff --git a/cocos2d/deprecated.js b/cocos2d/deprecated.js index b78ac4bd48d..f6ee77cb89b 100644 --- a/cocos2d/deprecated.js +++ b/cocos2d/deprecated.js @@ -580,6 +580,10 @@ if (CC_DEBUG) { cc.warnID(1400, 'cc.KEY', 'cc.macro.KEY'); return cc.macro.KEY; }); + js.get(cc, 'Easing', function () { + cc.warnID(1400, 'cc.Easing', 'cc.easing'); + return cc.easing; + }); // cc.pool js.get(cc, 'pool', function () { diff --git a/test/qunit/unit-es5/test-animation.js b/test/qunit/unit-es5/test-animation.js index b22a239d70e..14f05e9a7c2 100644 --- a/test/qunit/unit-es5/test-animation.js +++ b/test/qunit/unit-es5/test-animation.js @@ -30,7 +30,7 @@ test('curve types', function () { state.update(0); state.update(0.2); - strictEqual(entity.x, cc.Easing.cubicInOut(0.2) * 100, 'should wrap time by cc.Easing.cubicInOut'); + strictEqual(entity.x, cc.easing.cubicInOut(0.2) * 100, 'should wrap time by cc.easing.cubicInOut'); state.update(1.2); close(entity.x, bezierByTime([0, 0.5, 0.5, 1], 0.4) * 100 + 100, 0.0001, 'should wrap time by bezierByTime'); From 163104d1cff2f4d96b58d69635be64efae95ddae Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 15 Feb 2019 16:57:49 +0800 Subject: [PATCH 0451/1631] check button._originalScale validity && distinguish target and node events (#3851) * Revert "fix set button.interactable as false before __preload && update originalScale on target scale changed (#3764)" This reverts commit ca5191a5e68dee690b9c84cf0b222b45b1a9420c. * fix set button._original.interactable as false before * distinguish target events and node events in button * remove button scale tips --- cocos2d/core/components/CCButton.js | 144 ++++++++++++++-------------- editor/i18n/en/localization.js | 2 +- editor/i18n/zh/localization.js | 2 +- 3 files changed, 76 insertions(+), 72 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index b073d3c92d7..de644281242 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -297,9 +297,7 @@ let Button = cc.Class({ /** * !#en When user press the button, the button will zoom to a scale. * The final scale of the button equals (button original scale * zoomScale) - * Setting zoomScale less than 1 is not adviced, which could fire the touchCancel event if the touch point is out of touch area after scaling. * !#zh 当用户点击按钮后,按钮会缩放到一个值,这个值等于 Button 原始 scale * zoomScale - * 不建议 zoomScale 的值小于 1, 否则缩放后如果触摸点在触摸区域外, 则会触发 touchCancel 事件。 * @property {Number} zoomScale */ zoomScale: { @@ -390,11 +388,9 @@ let Button = cc.Class({ type: cc.Node, tooltip: CC_DEV && "i18n:COMPONENT.button.target", notify (oldValue) { - if (oldValue !== this.target) { - this._applyTarget(); - if (oldValue) { - this._unregisterNodeEvent(oldValue); - } + this._applyTarget(); + if (this.target !== oldValue) { + this._unregisterTargetEvent(oldValue); } } }, @@ -428,7 +424,8 @@ let Button = cc.Class({ let transition = this.transition; if (transition === Transition.COLOR && this.interactable) { this._setTargetColor(this.normalColor); - } else if (transition === Transition.SCALE && this._originalScale) { + } + else if (transition === Transition.SCALE && this._originalScale) { target.scaleX = this._originalScale.x; target.scaleY = this._originalScale.y; } @@ -449,13 +446,48 @@ let Button = cc.Class({ if (this.disabledSprite) { this.disabledSprite.ensureLoadTexture(); } + + if (!CC_EDITOR) { + this._registerNodeEvent(); + } + }, + + onDisable () { + this._resetState(); + + if (!CC_EDITOR) { + this._unregisterNodeEvent(); + } }, _getTarget () { return this.target ? this.target : this.node; }, - _setTargetColor(color) { + _onTargetSpriteFrameChanged (comp) { + if (this.transition === Transition.SPRITE) { + this._setCurrentStateSprite(comp.spriteFrame); + } + }, + + _onTargetColorChanged (color) { + if (this.transition === Transition.COLOR) { + this._setCurrentStateColor(color); + } + }, + + _onTargetScaleChanged () { + let target = this._getTarget(); + // update _originalScale if target scale changed + if (this._originalScale) { + if (this.transition !== Transition.SCALE || this._transitionFinished) { + this._originalScale.x = target.scaleX; + this._originalScale.y = target.scaleY; + } + } + }, + + _setTargetColor (color) { let target = this._getTarget(); target.color = color; target.opacity = color.a; @@ -521,16 +553,6 @@ let Button = cc.Class({ } }, - onDisable () { - this._resetState(); - }, - - onDestroy () { - let target = this._getTarget(); - this._unregisterNodeEvent(target); - this._originalScale = null; - }, - update (dt) { let target = this._getTarget(); if (this._transitionFinished) return; @@ -562,61 +584,40 @@ let Button = cc.Class({ }, - _registerNodeEvent (node) { - if (CC_EDITOR) { - node.on('spriteframe-changed', this._onNodeSpriteFrameChanged, this); - node.on(cc.Node.EventType.COLOR_CHANGED, this._onNodeColorChanged, this); - node.on(cc.Node.EventType.SCALE_CHANGED, this._onNodeScaleChanged, this); - } - else { - node.on(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this); - node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this); - node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); - node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this); - - node.on(cc.Node.EventType.MOUSE_ENTER, this._onMouseMoveIn, this); - node.on(cc.Node.EventType.MOUSE_LEAVE, this._onMouseMoveOut, this); - } - }, + _registerNodeEvent () { + this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this); + this.node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this); + this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); + this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this); - _unregisterNodeEvent (node) { - if (CC_EDITOR) { - node.off('spriteframe-changed', this._onNodeSpriteFrameChanged, this); - node.off(cc.Node.EventType.COLOR_CHANGED, this._onNodeColorChanged, this); - node.off(cc.Node.EventType.SCALE_CHANGED, this._onNodeScaleChanged, this); - } - else { - node.off(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this); - node.off(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this); - node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); - node.off(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this); - - node.off(cc.Node.EventType.MOUSE_ENTER, this._onMouseMoveIn, this); - node.off(cc.Node.EventType.MOUSE_LEAVE, this._onMouseMoveOut, this); - } + this.node.on(cc.Node.EventType.MOUSE_ENTER, this._onMouseMoveIn, this); + this.node.on(cc.Node.EventType.MOUSE_LEAVE, this._onMouseMoveOut, this); }, - _onNodeScaleChanged () { - let target = this._getTarget(); - // update _originalScale if target scale changed - if (this._originalScale) { - if (this.transition !== Transition.SCALE || this._transitionFinished) { - this._originalScale.x = target.scaleX; - this._originalScale.y = target.scaleY; - } - } + _unregisterNodeEvent () { + this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this); + this.node.off(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this); + this.node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); + this.node.off(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this); + + this.node.off(cc.Node.EventType.MOUSE_ENTER, this._onMouseMoveIn, this); + this.node.off(cc.Node.EventType.MOUSE_LEAVE, this._onMouseMoveOut, this); }, - _onNodeSpriteFrameChanged (comp) { - if (this.transition === Transition.SPRITE) { - this._setCurrentStateSprite(comp.spriteFrame); + _registerTargetEvent (target) { + if (CC_EDITOR) { + target.on('spriteframe-changed', this._onTargetSpriteFrameChanged, this); + target.on(cc.Node.EventType.COLOR_CHANGED, this._onTargetColorChanged, this); } + target.on(cc.Node.EventType.SCALE_CHANGED, this._onTargetScaleChanged, this); }, - _onNodeColorChanged (color) { - if (this.transition === Transition.COLOR) { - this._setCurrentStateColor(color); + _unregisterTargetEvent (target) { + if (CC_EDITOR) { + target.off('spriteframe-changed', this._onTargetSpriteFrameChanged, this); + target.off(cc.Node.EventType.COLOR_CHANGED, this._onTargetColorChanged, this); } + target.off(cc.Node.EventType.SCALE_CHANGED, this._onTargetScaleChanged, this); }, _getTargetSprite (target) { @@ -635,7 +636,8 @@ let Button = cc.Class({ } this._originalScale.x = target.scaleX; this._originalScale.y = target.scaleY; - this._registerNodeEvent(target); + + this._registerTargetEvent(target); }, // touch event handler @@ -649,11 +651,12 @@ let Button = cc.Class({ _onTouchMove (event) { if (!this.interactable || !this.enabledInHierarchy || !this._pressed) return; - let target = this._getTarget(); // mobile phone will not emit _onMouseMoveOut, // so we have to do hit test when touch moving let touch = event.touch; - let hit = target._hitTest(touch.getLocation()); + let hit = this.node._hitTest(touch.getLocation()); + let target = this._getTarget(); + if (this.transition === Transition.SCALE && this._originalScale) { if (hit) { this._fromScale.x = this._originalScale.x; @@ -683,9 +686,8 @@ let Button = cc.Class({ if (!this.interactable || !this.enabledInHierarchy) return; if (this._pressed) { - let target = this._getTarget(); cc.Component.EventHandler.emitEvents(this.clickEvents, event); - target.emit('click', this); + this.node.emit('click', this); } this._pressed = false; this._updateState(); @@ -779,6 +781,7 @@ let Button = cc.Class({ if (!this._originalScale) { return; } + this._fromScale.x = this._originalScale.x; this._fromScale.y = this._originalScale.y; this._toScale.x = this._originalScale.x * this.zoomScale; @@ -792,6 +795,7 @@ let Button = cc.Class({ if (!this._originalScale) { return; } + let target = this._getTarget(); this._fromScale.x = target.scaleX; this._fromScale.y = target.scaleY; diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index bc1477cc782..bc4fdf71a45 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -72,7 +72,7 @@ module.exports = { "hover_color": "Button color when the mouse hovers over it", "disabled_color": "Button color when disabled", "duration": "How long until the button color/scale transitions to a new color?", - "zoom_scale": "When user press the button, the button will zoom to a scale.The final scale of the button equals (button original scale * zoomScale). Setting zoomScale less than 1 is not adviced, which could fire the touchCancel event if the touch point is out of touch area after scaling.", + "zoom_scale": "When user press the button, the button will zoom to a scale.The final scale of the button equals (button original scale * zoomScale).", "auto_gray_effect": "When this flag is true, Button target sprite will turn gray when interactable is false.", "normal_sprite": "The Sprite that is used when the button is in a normal sate.", "pressed_sprite": "The Sprite that is used when the button is in a pressed sate.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 911853b2055..967a35ca4c6 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -75,7 +75,7 @@ module.exports = { 'hover_color': '悬停状态的按钮背景颜色', 'disabled_color': '禁用状态的按钮背景颜色', 'duration': '按钮颜色变化或者缩放变化的过渡时间', - 'zoom_scale': '当用户点击按钮后,按钮会缩放到一个值,这个值等于 Button 原始 scale * zoomScale。不建议 zoomScale 的值小于 1, 否则缩放后如果触摸点在触摸区域外, 则会触发 touchCancel 事件', + 'zoom_scale': '当用户点击按钮后,按钮会缩放到一个值,这个值等于 Button 原始 scale * zoomScale。', 'auto_gray_effect': "如果这个标记为 true,当 button 的 interactable 属性为 false 的时候,会使用内置 shader 让 button 的 target 节点的 sprite 组件变灰", 'normal_sprite': '普通状态的按钮背景图资源', 'pressed_sprite': '按下状态的按钮背景图资源', From f83f89b03038f0df4160359a1db3fb2aaed386ab Mon Sep 17 00:00:00 2001 From: id-ilych Date: Mon, 18 Feb 2019 04:31:24 +0200 Subject: [PATCH 0452/1631] Fix: Spine blinks after instantiation (#3820) * Fix: Spine blinks after instantiation If prefab containing spine animation is instantiated from `update` of some other component then it will be rendered in 'setup' pos. I've experienced problem and verified fix using CocosCreator 2.0.7 but I see no relevant diffs with current state of the fille. My understanding is that in described case newly created animation will be rendered before `update` on `sp.Skeleton`. Not sure about changes to skeleton data beside instantiation though. Is my understanding correct and problem should be fixed like that? * Update fix according to input from @sunnylanwanjun * Remove unnecessary editor-specific code --- extensions/spine/Skeleton.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index d287197eb37..9deb4b2bdab 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -905,10 +905,7 @@ sp.Skeleton = cc.Class({ return null; } var res = this._state.setAnimationWith(trackIndex, animation, loop); - if (CC_EDITOR && !cc.engine.isPlaying) { - this._state.update(0); - this._state.apply(this._skeleton); - } + this._state.apply(this._skeleton); return res; } } From a56a89090847efa0debf730f1ad503f24b858148 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Mon, 18 Feb 2019 14:10:10 +0800 Subject: [PATCH 0453/1631] Fix native example cases spine and dragonbones not render bug (#3855) * Add setRenderMode API * Modify pre render mode default value --- extensions/dragonbones/ArmatureDisplay.js | 63 +++++++++++++++++------ extensions/spine/Skeleton.js | 45 ++++++++++++---- 2 files changed, 81 insertions(+), 27 deletions(-) diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index de721f74f2e..e79300d866a 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -78,6 +78,10 @@ let ArmatureDisplay = cc.Class({ //help: 'app://docs/html/components/dragonbones.html', // TODO help document of dragonBones }, + statics: { + RenderMode: RenderModeEnum, + }, + properties: { _factory: { default: null, @@ -289,17 +293,15 @@ let ArmatureDisplay = cc.Class({ }, // Record pre render mode. - _preRenderMode: 0, - // Best set the mode before set property 'dragonAsset', or will waste some cpu time. - // If set the mode in editor, then no need to worry about order problem. - renderMode: { + _preRenderMode: -1, + _renderMode: RenderModeEnum.REALTIME, + _defaultRenderMode: { default: 0, type: RenderModeEnum, notify () { - if (this._preRenderMode !== this.renderMode) { - this._buildArmature(); - } + this.setRenderMode(this._defaultRenderMode); }, + editorOnly: true, visible: true, animatable: false, displayName: "Render Mode", @@ -446,7 +448,7 @@ let ArmatureDisplay = cc.Class({ this._inited = true; if (CC_JSB) { - this.renderMode = RenderModeEnum.REALTIME; + this._renderMode = RenderModeEnum.REALTIME; } this._parseDragonAsset(); @@ -463,9 +465,35 @@ let ArmatureDisplay = cc.Class({ this._updateDebugDraw(); }, + /** + * !#en + * It's best to set render mode before set property 'dragonAsset', or will waste some cpu time. + * If set the mode in editor, then no need to worry about order problem. + * !#zh + * 若想切换渲染模式,最好在设置'dragonAsset'之前,先设置好渲染模式,否则有运行时开销。 + * 若在编辑中设置渲染模式,则无需担心设置次序的问题。 + * + * @method setRenderMode + * @param {RenderMode} renderMode + * * @example + * armatureDisplay.setRenderMode(dragonBones.ArmatureDisplay.RenderMode.SHARED_CACHE); + */ + setRenderMode (renderMode) { + if (CC_JSB) return; + if (this._preRenderMode !== renderMode) { + this._renderMode = renderMode; + this._buildArmature(); + } + }, + + /** + * !#en Whether in cached mode. + * !#zh 当前是否处于缓存模式。 + * @method isCachedMode + */ isCachedMode () { if (CC_EDITOR) return false; - return this.renderMode !== RenderModeEnum.REALTIME; + return this._renderMode !== RenderModeEnum.REALTIME; }, onEnable () { @@ -529,11 +557,11 @@ let ArmatureDisplay = cc.Class({ this._inited = false; if (!CC_EDITOR) { - if (this.renderMode === RenderModeEnum.PRIVATE_CACHE) { + if (this._renderMode === RenderModeEnum.PRIVATE_CACHE) { this._armatureCache.dispose(); this._armatureCache = null; this._armature = null; - } else if (this.renderMode === RenderModeEnum.SHARED_CACHE) { + } else if (this._renderMode === RenderModeEnum.SHARED_CACHE) { this._armatureCache = null; this._armature = null; } else if (this._armature) { @@ -588,12 +616,13 @@ let ArmatureDisplay = cc.Class({ this._frameCache = null; this._curFrame = null; this._playing = false; + this._preRenderMode = null; } if (!CC_EDITOR) { - if (this.renderMode === RenderModeEnum.SHARED_CACHE) { + if (this._renderMode === RenderModeEnum.SHARED_CACHE) { this._armatureCache = ArmatureCache.sharedCache; - } else if (this.renderMode === RenderModeEnum.PRIVATE_CACHE) { + } else if (this._renderMode === RenderModeEnum.PRIVATE_CACHE) { this._armatureCache = new ArmatureCache; } } @@ -605,12 +634,12 @@ let ArmatureDisplay = cc.Class({ this._armature = this._armatureCache.getArmatureCache(this.armatureName, dragonbonesName, atlasName); if (!this._armature) { // Cache fail,swith to REALTIME render mode. - this.renderMode = RenderModeEnum.REALTIME; + this._renderMode = RenderModeEnum.REALTIME; } } - this._preRenderMode = this.renderMode; - if (CC_EDITOR || this.renderMode === RenderModeEnum.REALTIME) { + this._preRenderMode = this._renderMode; + if (CC_EDITOR || this._renderMode === RenderModeEnum.REALTIME) { this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, dragonbonesName, "", atlasName); if (!this._displayProxy) return; this._displayProxy._ccNode = this.node; @@ -618,7 +647,7 @@ let ArmatureDisplay = cc.Class({ this._armature.animation.timeScale = this.timeScale; } - if (this.renderMode !== RenderModeEnum.REALTIME && this.debugBones) { + if (this._renderMode !== RenderModeEnum.REALTIME && this.debugBones) { cc.warn("Debug bones is invalid in cached mode"); } diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 9deb4b2bdab..7aa6eb7af67 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -73,6 +73,10 @@ sp.Skeleton = cc.Class({ //playOnFocus: true }, + statics: { + RenderMode: RenderModeEnum, + }, + properties: { /** * !#en The skeletal animation is paused? @@ -283,15 +287,15 @@ sp.Skeleton = cc.Class({ }, // Record pre render mode. - _preRenderMode: 0, - renderMode: { + _preRenderMode: -1, + _renderMode: RenderModeEnum.REALTIME, + _defaultRenderMode: { default: 0, type: RenderModeEnum, notify () { - if (this._preRenderMode !== this.renderMode) { - this._updateSkeletonData(); - } + this.setRenderMode(this._defaultRenderMode); }, + editorOnly: true, visible: true, animatable: false, displayName: "Render Mode", @@ -541,7 +545,7 @@ sp.Skeleton = cc.Class({ } if (CC_JSB) { - this.renderMode = RenderModeEnum.REALTIME; + this._renderMode = RenderModeEnum.REALTIME; } this._updateSkeletonData(); @@ -550,6 +554,27 @@ sp.Skeleton = cc.Class({ this._updateBatch(); }, + /** + * !#en + * It's best to set render mode before set property 'dragonAsset', or will waste some cpu time. + * If set the mode in editor, then no need to worry about order problem. + * !#zh + * 若想切换渲染模式,最好在设置'dragonAsset'之前,先设置好渲染模式,否则有运行时开销。 + * 若在编辑中设置渲染模式,则无需担心设置次序的问题。 + * + * @method setRenderMode + * @param {RenderMode} renderMode + * * @example + * armatureDisplay.setRenderMode(sp.Skeleton.RenderMode.SHARED_CACHE); + */ + setRenderMode (renderMode) { + if (CC_JSB) return; + if (this._preRenderMode !== renderMode) { + this._renderMode = renderMode; + this._updateSkeletonData(); + } + }, + /** * !#en Whether in cached mode. * !#zh 当前是否处于缓存模式。 @@ -557,7 +582,7 @@ sp.Skeleton = cc.Class({ */ isCachedMode () { if (CC_EDITOR) return false; - return this.renderMode !== RenderModeEnum.REALTIME; + return this._renderMode !== RenderModeEnum.REALTIME; }, update (dt) { @@ -1193,9 +1218,9 @@ sp.Skeleton = cc.Class({ if (!data) return; if (!CC_EDITOR) { - if (this.renderMode === RenderModeEnum.SHARED_CACHE) { + if (this._renderMode === RenderModeEnum.SHARED_CACHE) { this._skeletonCache = SkeletonCache.sharedCache; - } else if (this.renderMode === RenderModeEnum.PRIVATE_CACHE) { + } else if (this._renderMode === RenderModeEnum.PRIVATE_CACHE) { this._skeletonCache = new SkeletonCache; } } @@ -1215,7 +1240,7 @@ sp.Skeleton = cc.Class({ cc.warn(e); } - this._preRenderMode = this.renderMode; + this._preRenderMode = this._renderMode; this.animation = this.defaultAnimation; }, From 58483bf4e03dab3ccc39d6b646b03465b8d20291 Mon Sep 17 00:00:00 2001 From: Knox Date: Mon, 18 Feb 2019 15:29:26 +0800 Subject: [PATCH 0454/1631] Improve the use of imported particle system data (#3857) --- cocos2d/particle/CCParticleSystem.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index ee4d55757d5..cd189734cce 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -1010,7 +1010,13 @@ var ParticleSystem = cc.Class({ this.lifeVar = parseFloat(dict["particleLifespanVariance"] || 0); // emission Rate - this.emissionRate = Math.min(this.totalParticles / this.life, Number.MAX_VALUE); + var _tempEmissionRate = dict["emissionRate"]; + if (_tempEmissionRate) { + this.emissionRate = _tempEmissionRate; + } + else { + this.emissionRate = Math.min(this.totalParticles / this.life, Number.MAX_VALUE); + } // duration this.duration = parseFloat(dict["duration"] || 0); From 683f290b4f1d4cfe97ed2f80e12d2448b33c9148 Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 19 Feb 2019 11:14:00 +0800 Subject: [PATCH 0455/1631] improve full screen api, adjust editboxImpl (#3840) * implement WebEditBoxImpl, inherit from EditBoxImplBase sdf * improve full screen api, adjust editboxImpl * adjust on editbox and screen --- cocos2d/core/components/editbox/CCEditBox.js | 226 +++--- .../core/components/editbox/CCEditBoxImpl.js | 702 ------------------ .../components/editbox/EditBoxImplBase.js | 79 ++ .../core/components/editbox/WebEditBoxImpl.js | 594 +++++++++++++++ cocos2d/core/platform/CCScreen.js | 76 +- cocos2d/core/platform/CCView.js | 1 + editor/i18n/en/localization.js | 1 - editor/i18n/zh/localization.js | 1 - 8 files changed, 846 insertions(+), 834 deletions(-) delete mode 100644 cocos2d/core/components/editbox/CCEditBoxImpl.js create mode 100644 cocos2d/core/components/editbox/EditBoxImplBase.js create mode 100644 cocos2d/core/components/editbox/WebEditBoxImpl.js diff --git a/cocos2d/core/components/editbox/CCEditBox.js b/cocos2d/core/components/editbox/CCEditBox.js index 7a675442bd6..5adc2cfbbb1 100644 --- a/cocos2d/core/components/editbox/CCEditBox.js +++ b/cocos2d/core/components/editbox/CCEditBox.js @@ -25,7 +25,7 @@ ****************************************************************************/ const macro = require('../../platform/CCMacro'); -const EditBoxImpl = require('../editbox/CCEditBoxImpl'); +const EditBoxImplBase = require('./EditBoxImplBase'); const Label = require('../CCLabel'); const Types = require('./types'); const InputMode = Types.InputMode; @@ -79,9 +79,7 @@ let EditBox = cc.Class({ } this._string = value; - if (this._impl) { - this._updateString(value); - } + this._updateString(value); } }, @@ -114,11 +112,12 @@ let EditBox = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.editbox.returnType', displayName: 'KeyboardReturnType', type: KeyboardReturnType, - notify () { - if (this._impl) { - this._impl.returnType = this.returnType; - } - } + }, + + // To be removed in the future + _N$returnType: { + default: undefined, + type: cc.Float, }, /** @@ -132,10 +131,7 @@ let EditBox = cc.Class({ default: InputFlag.DEFAULT, type: InputFlag, notify () { - if (this._impl) { - this._impl.setInputFlag(this.inputFlag); - this._updateString(this._string); - } + this._updateString(this._string); } }, /** @@ -151,11 +147,12 @@ let EditBox = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.editbox.input_mode', default: InputMode.ANY, type: InputMode, - notify () { - if (this._impl) { - this._impl.setInputMode(this.inputMode); - } - } + }, + + // To be removed in the future + _N$inputMode: { + default: undefined, + type: cc.Float, }, /** @@ -170,9 +167,6 @@ let EditBox = cc.Class({ if (this._textLabel) { this._textLabel.fontSize = this.fontSize; } - if (this._impl) { - this._impl.setFontSize(this.fontSize); - } } }, @@ -204,9 +198,6 @@ let EditBox = cc.Class({ this._textLabel.node.opacity = this.fontColor.a; this._textLabel.node.color = this.fontColor; } - if (this._impl) { - this._impl.setFontColor(this.fontColor); - } } }, @@ -222,9 +213,6 @@ let EditBox = cc.Class({ if (this._placeholderLabel) { this._placeholderLabel.string = this.placeholder; } - if (this._impl) { - this._impl.setPlaceholderText(this.placeholder); - } } }, @@ -272,25 +260,21 @@ let EditBox = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.editbox.max_length', default: 20, notify () { - if (this._impl) { - this._impl.setMaxLength(this.maxLength); - } + } }, /** * !#en The input is always visible and be on top of the game view (only useful on Web). - * !zh 输入框总是可见,并且永远在游戏视图的上面(这个属性只有在 Web 上面修改有意义) - * Note: only available on Web at the moment. + * !zh 输入框总是可见,并且永远在游戏视图的上面(这个属性只有在 Web 上面修改有意义),这个属性已经在 v2.0.9 中废弃。 + * Note: only available on Web at the moment, this property has been deprecated since v2.0.9 * @property {Boolean} stayOnTop */ stayOnTop: { tooltip: CC_DEV && 'i18n:COMPONENT.editbox.stay_on_top', default: false, notify () { - if (this._impl) { - this._updateStayOnTop(); - } + cc.warn('editBox.stayOnTop is removed since v2.1.'); } }, @@ -357,43 +341,38 @@ let EditBox = cc.Class({ }, statics: { - _EditBoxImpl: EditBoxImpl, + _ImplClass: EditBoxImplBase, // implemented on different platform adapter KeyboardReturnType: KeyboardReturnType, InputFlag: InputFlag, InputMode: InputMode }, _init () { + if (CC_EDITOR) { + this._upgradeComp(); + } + this._createBackgroundSprite(); this._createLabels(); - this.node.on(cc.Node.EventType.SIZE_CHANGED, this._resizeChildNodes, this); - - let impl = this._impl = new EditBoxImpl(); - - impl.setDelegate(this); - impl.setNode(this.node); - impl.setInputMode(this.inputMode); - impl.setMaxLength(this.maxLength); - impl.setInputFlag(this.inputFlag); - impl.setReturnType(this.returnType); - impl.setTabIndex(this.tabIndex); - impl.setFontColor(this.fontColor); - impl.setFontSize(this.fontSize); - impl.setPlaceholderText(this.placeholder); - - this._updateStayOnTop(); + this._isLabelVisible = true; + this.node.on(cc.Node.EventType.SIZE_CHANGED, this._syncSize, this); + + let impl = this._impl = new EditBox._ImplClass(); + impl.init(this); + this._updateString(this.string); this._syncSize(); }, - _updateStayOnTop () { - if (this.stayOnTop) { - this._hideLabels(); + _upgradeComp () { + if (this._N$returnType !== undefined) { + this.returnType = this._N$returnType; + this._N$returnType = undefined; } - else { - this._showLabels(); + if (this._N$inputMode !== undefined) { + this.inputMode = this._N$inputMode; + this._N$inputMode = undefined; } - this._impl.stayOnTop(this.stayOnTop); }, _syncSize () { @@ -403,7 +382,9 @@ let EditBox = cc.Class({ this._background.node.setContentSize(size); this._updateLabelPosition(size); - this._impl.setSize(size.width, size.height); + if (this._impl) { + this._impl.setSize(size.width, size.height); + } }, _updateLabelPosition (size) { @@ -416,7 +397,6 @@ let EditBox = cc.Class({ textLabel.node.setContentSize(size.width - LEFT_PADDING, size.height); placeholderLabel.node.setContentSize(size.width - LEFT_PADDING, size.height); - placeholderLabel.lineHeight = size.height; placeholderLabel.node.setPosition(offx + LEFT_PADDING, offy + size.height); textLabel.node.setPosition(offx + LEFT_PADDING, offy + size.height); @@ -495,36 +475,25 @@ let EditBox = cc.Class({ } }, - _resizeChildNodes () { - let textLabelNode = this._textLabel.node, - placeholderLabelNode = this._placeholderLabel.node, - backgroundNode = this._background.node; - - textLabelNode.x = -this.node.width/2; - textLabelNode.y = this.node.height/2; - textLabelNode.width = this.node.width; - textLabelNode.height = this.node.height; - - placeholderLabelNode.x = -this.node.width/2; - placeholderLabelNode.y = this.node.height/2; - placeholderLabelNode.width = this.node.width; - placeholderLabelNode.height = this.node.height; - - backgroundNode.width = this.node.width; - backgroundNode.height = this.node.height; - }, - _showLabels () { - let displayText = this._textLabel.string; - this._textLabel.node.active = displayText !== ''; - this._placeholderLabel.node.active = displayText === ''; + this._isLabelVisible = true; + this._updateLabels(); }, _hideLabels () { + this._isLabelVisible = false; this._textLabel.node.active = false; this._placeholderLabel.node.active = false; }, + _updateLabels () { + if (this._isLabelVisible) { + let displayText = this._textLabel.string; + this._textLabel.node.active = displayText !== ''; + this._placeholderLabel.node.active = displayText === ''; + } + }, + _updateString (text) { let textLabel = this._textLabel; // Not inited yet @@ -538,10 +507,8 @@ let EditBox = cc.Class({ } textLabel.string = displayText; - this._impl.setString(text); - if (!this._impl._editing && !this.stayOnTop) { - this._showLabels(); - } + + this._updateLabels(); }, _updateLabelStringStyle (text, ignorePassword) { @@ -568,15 +535,11 @@ let EditBox = cc.Class({ }, editBoxEditingDidBegan () { - this._hideLabels(); cc.Component.EventHandler.emitEvents(this.editingDidBegan, this); this.node.emit('editing-did-began', this); }, editBoxEditingDidEnded () { - if (!this.stayOnTop) { - this._showLabels(); - } cc.Component.EventHandler.emitEvents(this.editingDidEnded, this); this.node.emit('editing-did-ended', this); }, @@ -593,22 +556,31 @@ let EditBox = cc.Class({ this.node.emit('editing-return', this); }, - onDestroy () { - this._impl.clear(); - }, - onEnable () { - this._impl && this._impl.onEnable(); + if (!CC_EDITOR) { + this._registerEvent(); + } + if (this._impl) { + this._impl.enable(); + } }, onDisable () { - this._impl && this._impl.onDisable(); + if (!CC_EDITOR) { + this._unregisterEvent(); + } + if (this._impl) { + this._impl.disable(); + } }, - __preload () { - if (!CC_EDITOR) { - this._registerEvent(); + onDestroy () { + if (this._impl) { + this._impl.clear(); } + }, + + __preload () { this._init(); }, @@ -617,50 +589,72 @@ let EditBox = cc.Class({ this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); }, + _unregisterEvent () { + this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this); + this.node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this); + }, + _onTouchBegan (event) { - if (this._impl) { - this._impl._onTouchBegan(event.touch); - } event.stopPropagation(); }, _onTouchCancel (event) { - if (this._impl) { - this._impl._onTouchCancel(); - } event.stopPropagation(); }, _onTouchEnded (event) { if (this._impl) { - this._impl._onTouchEnded(); + this._impl.beginEditing(); } event.stopPropagation(); }, /** - * !#en Let the EditBox get focus - * !#zh 让当前 EditBox 获得焦点 + * !#en Let the EditBox get focus, this method has been deprecated since v2.0.8, please use focus() instead. Call blur() in turn. + * !#zh 让当前 EditBox 获得焦点, 这个方法已经在 v2.0.8 中废弃,请使用 focus(). 相反的请使用 blur() * @method setFocus */ setFocus () { - if(this._impl) { - this._impl.setFocus(); + cc.warnID(1400, 'setFocus()', 'focus()'); + if (this._impl) { + this._impl.setFocus(true); + } + }, + + /** + * !#en Let the EditBox get focus + * !#zh 让当前 EditBox 获得焦点 + * @method focus + */ + focus () { + if (this._impl) { + this._impl.setFocus(true); + } + }, + + /** + * !#en Let the EditBox lose focus + * !#zh 让当前 EditBox 失去焦点 + * @method blur + */ + blur () { + if (this._impl) { + this._impl.setFocus(false); } }, /** * !#en Determine whether EditBox is getting focus or not. * !#zh 判断 EditBox 是否获得了焦点 - * Note: only available on Web at the moment. * @method isFocused */ isFocused () { - let isFocused = false; if (this._impl) { - isFocused = this._impl.isFocused(); + return this._impl.isFocused(); + } + else { + return false; } - return isFocused; }, update () { @@ -673,6 +667,10 @@ let EditBox = cc.Class({ cc.EditBox = module.exports = EditBox; +if (cc.sys.isBrowser) { + require('./WebEditBoxImpl'); +} + /** * !#en * Note: This event is emitted from the node to which the component belongs. diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js deleted file mode 100644 index 7a71ef00eb2..00000000000 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ /dev/null @@ -1,702 +0,0 @@ -/**************************************************************************** - Copyright (c) 2011-2012 cocos2d-x.org - Copyright (c) 2012 James Chen - Copyright (c) 2013-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 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 utils = require('../../platform/utils'); -const macro = require('../../platform/CCMacro'); -const Types = require('./types'); -const InputMode = Types.InputMode; -const InputFlag = Types.InputFlag; -const KeyboardReturnType = Types.KeyboardReturnType; - -// https://segmentfault.com/q/1010000002914610 -let SCROLLY = 40; -let LEFT_PADDING = 2; -let DELAY_TIME = 400; -let FOCUS_DELAY_UC = 400; -let FOCUS_DELAY_FIREFOX = 0; - -let math = cc.vmath; -let _worldMat = math.mat4.create(); -let _cameraMat = math.mat4.create(); -let _vec3 = cc.v3(); - -let _currentEditBoxImpl = null; - -// polyfill -let polyfill = { - zoomInvalid: false -}; - -if (cc.sys.OS_ANDROID === cc.sys.os && - (cc.sys.browserType === cc.sys.BROWSER_TYPE_SOUGOU || - cc.sys.browserType === cc.sys.BROWSER_TYPE_360)) { - polyfill.zoomInvalid = true; -} - -function getKeyboardReturnType (type) { - switch (type) { - case KeyboardReturnType.DEFAULT: - case KeyboardReturnType.DONE: - return 'done'; - case KeyboardReturnType.SEND: - return 'send'; - case KeyboardReturnType.SEARCH: - return 'search'; - case KeyboardReturnType.GO: - return 'go'; - case KeyboardReturnType.NEXT: - return 'next'; - } - return 'done'; -} - -let EditBoxImpl = cc.Class({ - ctor () { - this._delegate = null; - this._inputMode = -1; - this._inputFlag = -1; - this._returnType = KeyboardReturnType.DEFAULT; - this._maxLength = 50; - this._text = ''; - this._placeholderText = ''; - this._alwaysOnTop = false; - this._size = cc.size(); - this._node = null; - this._editing = false; - - this.__eventListeners = {}; - this.__fullscreen = false; - this.__autoResize = false; - this.__rotateScreen = false; - this.__orientationChanged = null; - - // matrix cache - this._m00 = 0; - this._m01 = 0; - this._m04 = 0; - this._m05 = 0; - this._m12 = 0; - this._m13 = 0; - this._w = 0; - this._h = 0; - }, - - onEnable () { - if (!this._edTxt) { - return; - } - if (this._alwaysOnTop) { - this._edTxt.style.display = ''; - } - else { - this._edTxt.style.display = 'none'; - } - }, - - onDisable () { - if (!this._edTxt) { - return; - } - this._edTxt.style.display = 'none'; - }, - - setTabIndex (index) { - if (this._edTxt) { - this._edTxt.tabIndex = index; - } - }, - - setFocus () { - this._beginEditing(); - }, - - isFocused() { - if (this._edTxt) { - return document.activeElement === this._edTxt; - } - cc.warnID(4700); - return false; - }, - - stayOnTop (flag) { - if(this._alwaysOnTop === flag || !this._edTxt) return; - - this._alwaysOnTop = flag; - - if (flag) { - this._edTxt.style.display = ''; - } else { - this._edTxt.style.display = 'none'; - } - }, - - setMaxLength (maxLength) { - if (!isNaN(maxLength)) { - if(maxLength < 0) { - //we can't set Number.MAX_VALUE to input's maxLength property - //so we use a magic number here, it should works at most use cases. - maxLength = 65535; - } - this._maxLength = maxLength; - this._edTxt && (this._edTxt.maxLength = maxLength); - } - }, - - setString (text) { - this._text = text; - this._edTxt && (this._edTxt.value = text); - }, - - getString () { - return this._text; - }, - - setPlaceholderText (text) { - this._placeholderText = text; - }, - - getPlaceholderText () { - return this._placeholderText; - }, - - setDelegate (delegate) { - this._delegate = delegate; - }, - - setInputMode (inputMode) { - if (this._inputMode === inputMode) return; - - this._inputMode = inputMode; - this.createInput(); - - this._updateDomInputType(); - this._updateSize(this._size.width, this._size.height); - }, - - setInputFlag (inputFlag) { - if (this._inputFlag === inputFlag) return; - - this._inputFlag = inputFlag; - this._updateDomInputType(); - - let textTransform = 'none'; - - if (inputFlag === InputFlag.INITIAL_CAPS_ALL_CHARACTERS) { - textTransform = 'uppercase'; - } - else if (inputFlag === InputFlag.INITIAL_CAPS_WORD) { - textTransform = 'capitalize'; - } - - if (this._edTxt) { - this._edTxt.style.textTransform = textTransform; - this._edTxt.value = this._text; - } - }, - - setReturnType (returnType) { - this._returnType = returnType; - this._updateDomInputType(); - }, - - setFontSize (fontSize) { - this._edFontSize = fontSize || this._edFontSize; - this._edTxt && (this._edTxt.style.fontSize = this._edFontSize + 'px'); - }, - - setFontColor (color) { - this._textColor = color; - this._edTxt && (this._edTxt.style.color = color.toCSS('rgba')); - }, - - setSize (width, height) { - this._size.width = width; - this._size.height = height; - this._updateSize(width, height); - }, - - setNode (node) { - this._node = node; - }, - - update () { - // TODO: find better way to update matrix - // if (this._editing) { - this._updateMatrix(); - // } - }, - - clear () { - this._node = null; - this.setDelegate(null); - this.removeDom(); - this.removeOrientationchangeEvent(); - }, - - _onTouchBegan (touch) { - - }, - - _onTouchEnded () { - this._beginEditing(); - }, - - _beginEditing () { - if (cc.sys.isMobile && !this._editing) { - // Pre adaptation add orientationchange event - this.addOrientationchangeEvent(); - } - - if (this._edTxt) { - this._edTxt.style.display = ''; - - let self = this; - function startFocus () { - self._edTxt.focus(); - } - - if (cc.sys.browserType === cc.sys.BROWSER_TYPE_UC) { - setTimeout(startFocus, FOCUS_DELAY_UC); - } - else if (cc.sys.browserType === cc.sys.BROWSER_TYPE_FIREFOX) { - setTimeout(startFocus, FOCUS_DELAY_FIREFOX); - } - else { - startFocus(); - } - } - - this._editing = true; - }, - - _endEditing () { - let self = this; - let hideDomInputAndShowLabel = function () { - if (!self._alwaysOnTop && self._edTxt) { - self._edTxt.style.display = 'none'; - } - if (self._delegate && self._delegate.editBoxEditingDidEnded) { - self._delegate.editBoxEditingDidEnded(); - } - }; - if (this._editing) { - if (cc.sys.isMobile) { - // Delay end editing adaptation to ensure virtual keyboard is disapeared - setTimeout(function () { - self._endEditingOnMobile(); - hideDomInputAndShowLabel(); - }, DELAY_TIME); - } - else { - hideDomInputAndShowLabel(); - } - } - this._editing = false; - }, - - _updateDomInputType () { - let inputMode = this._inputMode; - let edTxt = this._edTxt; - if (!edTxt) return; - - if (this._inputFlag === InputFlag.PASSWORD) { - edTxt.type = 'password'; - return; - } - - let type = edTxt.type; - if (inputMode === InputMode.EMAIL_ADDR) { - type = 'email'; - } else if(inputMode === InputMode.NUMERIC || inputMode === InputMode.DECIMAL) { - type = 'number'; - } else if(inputMode === InputMode.PHONE_NUMBER) { - type = 'number'; - edTxt.pattern = '[0-9]*'; - } else if(inputMode === InputMode.URL) { - type = 'url'; - } else { - type = 'text'; - - if (this._returnType === KeyboardReturnType.SEARCH) { - type = 'search'; - } - } - - edTxt.type = type; - }, - - _updateSize (newWidth, newHeight) { - let edTxt = this._edTxt; - if (!edTxt) return; - - edTxt.style.width = newWidth + 'px'; - edTxt.style.height = newHeight + 'px'; - }, - - _updateMatrix () { - if (!this._edTxt) return; - - let node = this._node; - node.getWorldMatrix(_worldMat); - - // check whether need to update - if (this._m00 === _worldMat.m00 && this._m01 === _worldMat.m01 && - this._m04 === _worldMat.m04 && this._m05 === _worldMat.m05 && - this._m12 === _worldMat.m12 && this._m13 === _worldMat.m13 && - this._w === node._contentSize.width && this._h === node._contentSize.height) { - return; - } - - // update matrix cache - this._m00 = _worldMat.m00; - this._m01 = _worldMat.m01; - this._m04 = _worldMat.m04; - this._m05 = _worldMat.m05; - this._m12 = _worldMat.m12; - this._m13 = _worldMat.m13; - this._w = node._contentSize.width; - this._h = node._contentSize.height; - - let scaleX = cc.view._scaleX, scaleY = cc.view._scaleY, - viewport = cc.view._viewportRect, - dpr = cc.view._devicePixelRatio; - - _vec3.x = -node._anchorPoint.x * this._w; - _vec3.y = -node._anchorPoint.y * this._h; - - math.mat4.translate(_worldMat, _worldMat, _vec3); - - // can't find camera in editor - if (CC_EDITOR) { - _cameraMat = _worldMat; - } - else { - let camera = cc.Camera.findCamera(node); - camera.getWorldToCameraMatrix(_cameraMat); - math.mat4.mul(_cameraMat, _cameraMat, _worldMat); - } - - - scaleX /= dpr; - scaleY /= dpr; - - let container = cc.game.container; - let a = _cameraMat.m00 * scaleX, b = _cameraMat.m01, c = _cameraMat.m04, d = _cameraMat.m05 * scaleY; - - let offsetX = container && container.style.paddingLeft && parseInt(container.style.paddingLeft); - offsetX += viewport.x / dpr; - let offsetY = container && container.style.paddingBottom && parseInt(container.style.paddingBottom); - offsetY += viewport.y / dpr; - let tx = _cameraMat.m12 * scaleX + offsetX, ty = _cameraMat.m13 * scaleY + offsetY; - - if (polyfill.zoomInvalid) { - this._updateSize(this._size.width * a, this._size.height * d); - a = 1; - d = 1; - } - - let matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")"; - this._edTxt.style['transform'] = matrix; - this._edTxt.style['-webkit-transform'] = matrix; - this._edTxt.style['transform-origin'] = '0px 100% 0px'; - this._edTxt.style['-webkit-transform-origin'] = '0px 100% 0px'; - }, - - _adjustEditBoxPosition () { - this._node.getWorldMatrix(_worldMat); - let y = _worldMat.m13; - let windowHeight = cc.visibleRect.height; - let windowWidth = cc.visibleRect.width; - let factor = 0.5; - if (windowWidth > windowHeight) { - factor = 0.7; - } - setTimeout(function() { - if (window.scrollY < SCROLLY && y < windowHeight * factor) { - let scrollOffset = windowHeight * factor - y - window.scrollY; - if (scrollOffset < 35) scrollOffset = 35; - if (scrollOffset > 320) scrollOffset = 320; - window.scrollTo(0, scrollOffset); - } - }, DELAY_TIME); - } -}); - -let _p = EditBoxImpl.prototype; - -_p.createInput = function() { - if (this._inputMode === InputMode.ANY) { - this._createDomTextArea(); - } - else { - this._createDomInput(); - } -}; - -// Called before editbox focus to register cc.view status -_p._beginEditingOnMobile = function () { - // add orientationchange event - this.addOrientationchangeEvent(); - - if (cc.view.isAutoFullScreenEnabled()) { - this.__fullscreen = true; - cc.view.enableAutoFullScreen(false); - cc.screen.exitFullScreen(); - } else { - this.__fullscreen = false; - } - this.__autoResize = cc.view._resizeWithBrowserSize; - cc.view.resizeWithBrowserSize(false); - _currentEditBoxImpl = this; -}; - -// Called after keyboard disappeared to readapte the game view -_p._endEditingOnMobile = function () { - if (this.__rotateScreen) { - cc.game.container.style['-webkit-transform'] = 'rotate(90deg)'; - cc.game.container.style.transform = 'rotate(90deg)'; - - let view = cc.view; - let width = view._originalDesignResolutionSize.width; - let height = view._originalDesignResolutionSize.height; - if (width > 0) { - view.setDesignResolutionSize(width, height, view._resolutionPolicy); - } - this.__rotateScreen = false; - } - - // remove orientationchange event - this.removeOrientationchangeEvent(); - - if(this.__fullscreen) { - cc.view.enableAutoFullScreen(true); - } - - // In case focus on editBox A from editBox B - // A disable resizeWithBrowserSize - // whilte B enable resizeWithBrowserSize - // Only _currentEditBoxImpl can enable resizeWithBrowserSize - if (this.__autoResize && _currentEditBoxImpl === this) { - cc.view.resizeWithBrowserSize(true); - } -}; - -function _inputValueHandle (input, editBoxImpl) { - if (input.value.length > editBoxImpl._maxLength) { - input.value = input.value.slice(0, editBoxImpl._maxLength); - } - if (editBoxImpl._delegate && editBoxImpl._delegate.editBoxTextChanged) { - if (editBoxImpl._text !== input.value) { - editBoxImpl._text = input.value; - editBoxImpl._delegate.editBoxTextChanged(editBoxImpl._text); - } - } -} - -function registerInputEventListener (tmpEdTxt, editBoxImpl, isTextarea) { - let inputLock = false; - let blurWhenComposition = false; - let cbs = editBoxImpl.__eventListeners; - cbs.compositionstart = function () { - inputLock = true; - }; - tmpEdTxt.addEventListener('compositionstart', cbs.compositionstart); - - cbs.compositionend = function () { - inputLock = false; - if (blurWhenComposition) { - // restore input value when composition not complete and blur input - this.value = editBoxImpl._text; - blurWhenComposition = false; - } - _inputValueHandle(this, editBoxImpl); - }; - tmpEdTxt.addEventListener('compositionend', cbs.compositionend); - - cbs.input = function () { - if (inputLock) { - return; - } - _inputValueHandle(this, editBoxImpl); - }; - tmpEdTxt.addEventListener('input', cbs.input); - - cbs.focus = function () { - this.style.fontSize = editBoxImpl._edFontSize + 'px'; - this.style.color = editBoxImpl._textColor.toCSS('rgba'); - // When stayOnTop, input will swallow touch event - if (editBoxImpl._alwaysOnTop) { - editBoxImpl._editing = true; - } - - if (cc.sys.isMobile) { - editBoxImpl._beginEditingOnMobile(); - } - - if (editBoxImpl._delegate && editBoxImpl._delegate.editBoxEditingDidBegan) { - editBoxImpl._delegate.editBoxEditingDidBegan(); - } - - }; - tmpEdTxt.addEventListener('focus', cbs.focus); - - cbs.keypress = function (e) { - if (e.keyCode === macro.KEY.enter) { - e.stopPropagation(); - - if (editBoxImpl._delegate && editBoxImpl._delegate.editBoxEditingReturn) { - editBoxImpl._delegate.editBoxEditingReturn(); - } - if (!isTextarea) { - editBoxImpl._text = this.value; - editBoxImpl._endEditing(); - cc.game.canvas.focus(); - } - } - }; - tmpEdTxt.addEventListener('keypress', cbs.keypress); - - cbs.blur = function () { - if (inputLock) { - blurWhenComposition = true; - } - else { - editBoxImpl._text = this.value; - } - editBoxImpl._endEditing(); - }; - tmpEdTxt.addEventListener('blur', cbs.blur); - - editBoxImpl._addDomToGameContainer(); -} - -_p._createDomInput = function () { - this.removeDom(); - - let tmpEdTxt = this._edTxt = document.createElement('input'); - tmpEdTxt.type = 'text'; - tmpEdTxt.style.fontSize = this._edFontSize + 'px'; - tmpEdTxt.style.color = '#000000'; - tmpEdTxt.style.border = 0; - tmpEdTxt.style.background = 'transparent'; - tmpEdTxt.style.width = '100%'; - tmpEdTxt.style.height = '100%'; - tmpEdTxt.style.active = 0; - tmpEdTxt.style.outline = 'medium'; - tmpEdTxt.style.padding = '0'; - tmpEdTxt.style.textTransform = 'uppercase'; - tmpEdTxt.style.display = 'none'; - tmpEdTxt.style.position = "absolute"; - tmpEdTxt.style.bottom = "0px"; - tmpEdTxt.style.left = LEFT_PADDING + "px"; - tmpEdTxt.style['-moz-appearance'] = 'textfield'; - tmpEdTxt.style.className = "cocosEditBox"; - tmpEdTxt.style.fontFamily = 'Arial'; - - registerInputEventListener(tmpEdTxt, this); - - return tmpEdTxt; -}; - -_p._createDomTextArea = function () { - this.removeDom(); - - let tmpEdTxt = this._edTxt = document.createElement('textarea'); - tmpEdTxt.type = 'text'; - tmpEdTxt.style.fontSize = this._edFontSize + 'px'; - tmpEdTxt.style.color = '#000000'; - tmpEdTxt.style.border = 0; - tmpEdTxt.style.background = 'transparent'; - tmpEdTxt.style.width = '100%'; - tmpEdTxt.style.height = '100%'; - tmpEdTxt.style.active = 0; - tmpEdTxt.style.outline = 'medium'; - tmpEdTxt.style.padding = '0'; - tmpEdTxt.style.resize = 'none'; - tmpEdTxt.style.textTransform = 'uppercase'; - tmpEdTxt.style.overflow_y = 'scroll'; - tmpEdTxt.style.display = 'none'; - tmpEdTxt.style.position = "absolute"; - tmpEdTxt.style.bottom = "0px"; - tmpEdTxt.style.left = LEFT_PADDING + "px"; - tmpEdTxt.style.className = "cocosEditBox"; - tmpEdTxt.style.fontFamily = 'Arial'; - - registerInputEventListener(tmpEdTxt, this, true); - - return tmpEdTxt; -}; - -_p._addDomToGameContainer = function () { - cc.game.container.appendChild(this._edTxt); -}; - -_p.removeDom = function () { - let edTxt = this._edTxt; - if (edTxt) { - // Remove listeners - let cbs = this.__eventListeners; - edTxt.removeEventListener('compositionstart', cbs.compositionstart); - edTxt.removeEventListener('compositionend', cbs.compositionend); - edTxt.removeEventListener('input', cbs.input); - edTxt.removeEventListener('focus', cbs.focus); - edTxt.removeEventListener('keypress', cbs.keypress); - edTxt.removeEventListener('blur', cbs.blur); - cbs.compositionstart = null; - cbs.compositionend = null; - cbs.input = null; - cbs.focus = null; - cbs.keypress = null; - cbs.blur = null; - - let hasChild = utils.contains(cc.game.container, edTxt); - if (hasChild) { - cc.game.container.removeChild(edTxt); - } - } - this._edTxt = null; -}; - -_p.addOrientationchangeEvent = function () { - let self = this; - if (!self.__orientationChanged) { - self.__orientationChanged = function () { - self._adjustEditBoxPosition(); - }; - } - window.addEventListener('orientationchange', self.__orientationChanged); -}; - -_p.removeOrientationchangeEvent = function () { - if (this.__orientationChanged) { - window.removeEventListener('orientationchange', this.__orientationChanged); - this.__orientationChanged = null; - } -}; - -module.exports = EditBoxImpl; diff --git a/cocos2d/core/components/editbox/EditBoxImplBase.js b/cocos2d/core/components/editbox/EditBoxImplBase.js new file mode 100644 index 00000000000..cdba19c67b2 --- /dev/null +++ b/cocos2d/core/components/editbox/EditBoxImplBase.js @@ -0,0 +1,79 @@ +/**************************************************************************** + Copyright (c) 2011-2012 cocos2d-x.org + Copyright (c) 2012 James Chen + Copyright (c) 2013-2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 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. + ****************************************************************************/ + +let EditBoxImplBase = cc.Class({ + ctor () { + this._delegate = null; + }, + + init (delegate) { + + }, + + enable () { + + }, + + disable () { + + }, + + clear () { + + }, + + update () { + + }, + + setTabIndex (index) { + // Only support on Web platform + }, + + setSize (width, height) { + // Only support on Web platform + }, + + setFocus (value) { + + }, + + isFocused () { + + }, + + beginEditing () { + + }, + + endEditing () { + + }, +}); + +module.exports = EditBoxImplBase; diff --git a/cocos2d/core/components/editbox/WebEditBoxImpl.js b/cocos2d/core/components/editbox/WebEditBoxImpl.js new file mode 100644 index 00000000000..11d8c0ec2c0 --- /dev/null +++ b/cocos2d/core/components/editbox/WebEditBoxImpl.js @@ -0,0 +1,594 @@ +/**************************************************************************** + Copyright (c) 2013-2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 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 utils = require('../../platform/utils'); +const macro = require('../../platform/CCMacro'); +const Types = require('./types'); + +const EditBox = cc.EditBox; +const js = cc.js; +const InputMode = Types.InputMode; +const InputFlag = Types.InputFlag; +const KeyboardReturnType = Types.KeyboardReturnType; +const math = cc.vmath; + +// polyfill +let polyfill = { + zoomInvalid: false +}; + +if (cc.sys.OS_ANDROID === cc.sys.os && + (cc.sys.browserType === cc.sys.BROWSER_TYPE_SOUGOU || + cc.sys.browserType === cc.sys.BROWSER_TYPE_360)) { + polyfill.zoomInvalid = true; +} + +// https://segmentfault.com/q/1010000002914610 +const DELAY_TIME = 800; +const SCROLLY = 100; +const LEFT_PADDING = 2; + + // private static property + let _domCount = 0; + let _vec3 = cc.v3(); + let _currentEditBoxImpl = null; + + +// on mobile +let _fullscreen = false; +let _autoResize = false; + + // This is an adapter for EditBoxImpl on web platform. + // For more adapters on other platforms, please inherit from EditBoxImplBase and implement the interface. +function WebEditBoxImpl () { + this._domId = ++_domCount; + this._elem = null; + this._isTextArea = false; + this._editing = false; + + // matrix + this._worldMat = math.mat4.create(); + this._cameraMat = math.mat4.create(); + // matrix cache + this._m00 = 0; + this._m01 = 0; + this._m04 = 0; + this._m05 = 0; + this._m12 = 0; + this._m13 = 0; + this._w = 0; + this._h = 0; + + // inputType cache + this._inputMode = null; + this._inputFlag = null; + this._returnType = null; + + // event listeners + this._eventListeners = {}; +} + +js.extend(WebEditBoxImpl, EditBox._ImplClass); +EditBox._ImplClass = WebEditBoxImpl; + +Object.assign(WebEditBoxImpl.prototype, { + // ================================= + // implement EditBoxImplBase interface + init (delegate) { + if (!delegate) { + return; + } + + this._delegate = delegate; + + if (delegate.inputMode === InputMode.ANY) { + this._createTextArea(); + } + else { + this._createInput(); + } + this.setTabIndex(delegate.tabIndex); + this._disableDom(); // enable dom when EditBox.onEnable is called + this._initStyleSheet(); + this._registerEventListeners(); + this._addDomToGameContainer(); + + _fullscreen = cc.view.isAutoFullScreenEnabled(); + _autoResize = cc.view._resizeWithBrowserSize; + }, + + enable () { + this._enableDom(); + + if (!CC_EDITOR) { + this._delegate._unregisterEvent(); // not support touch events on web platform + } + }, + + disable () { + this._disableDom(); + }, + + clear () { + this._removeEventListeners(); + this._removeDomFromGameContainer(); + }, + + update () { + this._updateMatrix(); + }, + + setTabIndex (index) { + this._elem.tabIndex = index; + }, + + setSize (width, height) { + let elem = this._elem; + elem.style.width = width + 'px'; + elem.style.height = height + 'px'; + }, + + setFocus (value) { + if (value) { + this._elem.focus(); + } + else { + this._elem.blur(); + } + }, + + isFocused () { + return this._editing; + }, + + beginEditing () { + this._editing = true; + _currentEditBoxImpl = this; + this._showDom(); + this._delegate.editBoxEditingDidBegan(); + }, + + endEditing () { + this._editing = false; + _currentEditBoxImpl = null; + this._hideDom(); + this._delegate.editBoxEditingDidEnded(); + }, + + // ========================================================================== + // implement dom input + _createInput () { + this._isTextArea = false; + this._elem = document.createElement('input'); + }, + + _createTextArea () { + this._isTextArea = true; + this._elem = document.createElement('textarea'); + }, + + _addDomToGameContainer () { + cc.game.container.appendChild(this._elem); + }, + + _removeDomFromGameContainer () { + let hasChild = utils.contains(cc.game.container, this._elem); + if (hasChild) { + cc.game.container.removeChild(this._elem); + } + + delete this._elem; + }, + + _enableDom () { + this._elem.style.disaplay = ''; + }, + + _disableDom () { + this._elem.style.disaplay = 'none'; + }, + + _showDom () { + this._updateMaxLength(); + this._updateInputType(); + this._updateStyleSheet(); + + this._elem.style.opacity = 1; + this._delegate._hideLabels(); + + if (cc.sys.isMobile) { + this._showDomOnMobile(); + } + }, + + _hideDom () { + let elem = this._elem; + + elem.style.opacity = 0; + this._delegate._showLabels(); + + if (cc.sys.isMobile) { + this._hideDomOnMobile(); + } + }, + + _showDomOnMobile () { + if (cc.sys.os !== cc.sys.OS_ANDROID) { + return; + } + + if (_fullscreen) { + cc.view.enableAutoFullScreen(false); + cc.screen.exitFullScreen(); + } + if (_autoResize) { + cc.view.resizeWithBrowserSize(false); + } + + this._adjustWindowScroll(); + }, + + _hideDomOnMobile () { + if (cc.sys.os !== cc.sys.OS_ANDROID) { + return; + } + + if (_fullscreen) { + cc.view.enableAutoFullScreen(true); + } + if (_autoResize) { + cc.view.resizeWithBrowserSize(true); + } + + this._scrollBackWindow(); + }, + + // adjust view to editBox + _adjustWindowScroll () { + let self = this; + setTimeout(function() { + if (window.scrollY < SCROLLY) { + self._elem.scrollIntoView({block: "start", inline: "nearest", behavior: "smooth"}); + } + }, DELAY_TIME); + }, + + _scrollBackWindow () { + setTimeout(function () { + window.scrollTo(0, 0); + }, DELAY_TIME); + }, + + _updateMatrix () { + let node = this._delegate.node; + node.getWorldMatrix(this._worldMat); + let worldMat = this._worldMat; + + // check whether need to update + if (this._m00 === worldMat.m00 && this._m01 === worldMat.m01 && + this._m04 === worldMat.m04 && this._m05 === worldMat.m05 && + this._m12 === worldMat.m12 && this._m13 === worldMat.m13 && + this._w === node._contentSize.width && this._h === node._contentSize.height) { + return; + } + + // update matrix cache + this._m00 = worldMat.m00; + this._m01 = worldMat.m01; + this._m04 = worldMat.m04; + this._m05 = worldMat.m05; + this._m12 = worldMat.m12; + this._m13 = worldMat.m13; + this._w = node._contentSize.width; + this._h = node._contentSize.height; + + let scaleX = cc.view._scaleX, scaleY = cc.view._scaleY, + viewport = cc.view._viewportRect, + dpr = cc.view._devicePixelRatio; + + _vec3.x = -node._anchorPoint.x * this._w; + _vec3.y = -node._anchorPoint.y * this._h; + + math.mat4.translate(worldMat, worldMat, _vec3); + + // can't find camera in editor + let cameraMat; + if (CC_EDITOR) { + cameraMat = this._cameraMat = worldMat; + } + else { + let camera = cc.Camera.findCamera(node); + camera.getWorldToCameraMatrix(this._cameraMat); + cameraMat = this._cameraMat; + math.mat4.mul(cameraMat, cameraMat, worldMat); + } + + + scaleX /= dpr; + scaleY /= dpr; + + let container = cc.game.container; + let a = cameraMat.m00 * scaleX, b = cameraMat.m01, c = cameraMat.m04, d = cameraMat.m05 * scaleY; + + let offsetX = container && container.style.paddingLeft && parseInt(container.style.paddingLeft); + offsetX += viewport.x / dpr; + let offsetY = container && container.style.paddingBottom && parseInt(container.style.paddingBottom); + offsetY += viewport.y / dpr; + let tx = cameraMat.m12 * scaleX + offsetX, ty = cameraMat.m13 * scaleY + offsetY; + + if (polyfill.zoomInvalid) { + this.setSize(node.width * a, node.height * d); + a = 1; + d = 1; + } + + let elem = this._elem; + let matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")"; + elem.style['transform'] = matrix; + elem.style['-webkit-transform'] = matrix; + elem.style['transform-origin'] = '0px 100% 0px'; + elem.style['-webkit-transform-origin'] = '0px 100% 0px'; + }, + + // =========================================== + // input type and max length + _updateInputType () { + let delegate = this._delegate, + inputMode = delegate.inputMode, + inputFlag = delegate.inputFlag, + returnType = delegate.returnType, + elem = this._elem; + + // whether need to update + if (this._inputMode === inputMode && + this._inputFlag === inputFlag && + this._returnType === returnType) { + return; + } + + // update cache + this._inputMode = inputMode; + this._inputFlag = inputFlag; + this._returnType = returnType; + + // FIX ME: TextArea actually dose not support password type. + if (this._isTextArea) { + // input flag + let textTransform = 'none'; + if (inputFlag === InputFlag.INITIAL_CAPS_ALL_CHARACTERS) { + textTransform = 'uppercase'; + } + else if (inputFlag === InputFlag.INITIAL_CAPS_WORD) { + textTransform = 'capitalize'; + } + elem.style.textTransform = textTransform; + return; + } + + // begin to updateInputType + if (inputFlag === InputFlag.PASSWORD) { + elem.type = 'password'; + return; + } + + // input mode + let type = elem.type; + if (inputMode === InputMode.EMAIL_ADDR) { + type = 'email'; + } else if(inputMode === InputMode.NUMERIC || inputMode === InputMode.DECIMAL) { + type = 'number'; + } else if(inputMode === InputMode.PHONE_NUMBER) { + type = 'number'; + elem.pattern = '[0-9]*'; + } else if(inputMode === InputMode.URL) { + type = 'url'; + } else { + type = 'text'; + + if (returnType === KeyboardReturnType.SEARCH) { + type = 'search'; + } + } + elem.type = type; + + // input flag + let textTransform = 'none'; + if (inputFlag === InputFlag.INITIAL_CAPS_ALL_CHARACTERS) { + textTransform = 'uppercase'; + } + else if (inputFlag === InputFlag.INITIAL_CAPS_WORD) { + textTransform = 'capitalize'; + } + elem.style.textTransform = textTransform; + }, + + _updateMaxLength () { + let maxLength = this._delegate.maxLength; + if(maxLength < 0) { + //we can't set Number.MAX_VALUE to input's maxLength property + //so we use a magic number here, it should works at most use cases. + maxLength = 65535; + } + this._elem.maxLength = maxLength; + }, + + // =========================================== + // style sheet + _initStyleSheet () { + let elem = this._elem; + elem.style.opacity = 0; + elem.style.border = 0; + elem.style.background = 'transparent'; + elem.style.width = '100%'; + elem.style.height = '100%'; + elem.style.active = 0; + elem.style.outline = 'medium'; + elem.style.padding = '0'; + elem.style.textTransform = 'uppercase'; + elem.style.position = "absolute"; + elem.style.bottom = "0px"; + elem.style.left = LEFT_PADDING + "px"; + elem.style.className = "cocosEditBox"; + + if (!this._isTextArea) { + elem.type = 'text'; + elem.style['-moz-appearance'] = 'textfield'; + } + else { + elem.style.resize = 'none'; + elem.style.overflow_y = 'scroll'; + } + }, + + _updateStyleSheet () { + let delegate = this._delegate, + elem = this._elem; + + elem.value = delegate.string; + elem.placeholder = delegate.placeholder; + + // TODO: handle update cache + // update after issue solved: https://github.com/cocos-creator/2d-tasks/issues/372 + this._updateTextLabel(delegate._textLabel); + this._updatePlaceholderLabel(delegate._placeholderLabel); + }, + + _updateTextLabel (textLabel) { + if (!textLabel) { + return; + } + let elem = this._elem; + + // font size + elem.style.fontSize = `${textLabel.fontSize}px`; + + // font color + elem.style.color = textLabel.node.color.toCSS('rgba'); + + // TODO: update after issue solved: https://github.com/cocos-creator/2d-tasks/issues/372 + // update color, font-family, text-align, line-height ... + }, + + _updatePlaceholderLabel (placeholderLabel) { + if (!placeholderLabel) { + return; + } + let elem = this._elem; + + // TODO: update after issue solved: https://github.com/cocos-creator/2d-tasks/issues/372 + }, + + // =========================================== + // handle event listeners + _registerEventListeners () { + let impl = this, + elem = this._elem, + inputLock = false, + cbs = this._eventListeners; + + cbs.compositionStart = function () { + inputLock = true; + }; + + cbs.compositionEnd = function () { + inputLock = false; + impl._delegate.editBoxTextChanged(elem.value); + }; + + cbs.onInput = function () { + if (inputLock) { + return; + } + impl._delegate.editBoxTextChanged(elem.value); + }; + + cbs.onFocus = function () { + impl.beginEditing() + }; + + // There are 2 ways to focus on the input element: + // Click the input element, or call input.focus(). + // Both need to adjust window scroll. + cbs.onClick = function (e) { + // In case operation sequence: click input, hide keyboard, then click again. + if (impl._editing) { + if (cc.sys.isMobile) { + impl._adjustWindowScroll(); + } + } + // If has last focused input, should call lastInput.blur() explicitly. + else if (_currentEditBoxImpl && _currentEditBoxImpl !== impl) { + _currentEditBoxImpl._elem.blur(); + } + }; + + cbs.onKeypress = function (e) { + if (e.keyCode === macro.KEY.enter) { + e.stopPropagation(); + impl._delegate.editBoxEditingReturn(); + + if (!impl._isTextArea) { + elem.blur(); // hide keyboard and call endEditing() + } + } + }; + + cbs.onBlur = function () { + impl.endEditing(); + }; + + + elem.addEventListener('compositionstart', cbs.compositionStart); + elem.addEventListener('compositionend', cbs.compositionEnd); + elem.addEventListener('input', cbs.onInput); + elem.addEventListener('focus', cbs.onFocus); + elem.addEventListener('keypress', cbs.onKeypress); + elem.addEventListener('blur', cbs.onBlur); + elem.addEventListener('touchstart', cbs.onClick); + }, + + _removeEventListeners () { + let elem = this._elem, + cbs = this._eventListeners; + + elem.removeEventListener('compositionstart', cbs.compositionStart); + elem.removeEventListener('compositionend', cbs.compositionEnd); + elem.removeEventListener('input', cbs.onInput); + elem.removeEventListener('focus', cbs.onFocus); + elem.removeEventListener('keypress', cbs.onKeypress); + elem.removeEventListener('blur', cbs.onBlur); + elem.removeEventListener('touchstart', cbs.onClick); + + cbs.compositionStart = null; + cbs.compositionEnd = null; + cbs.onInput = null; + cbs.onFocus = null; + cbs.onKeypress = null; + cbs.onBlur = null; + cbs.onClick = null; + }, +}); + diff --git a/cocos2d/core/platform/CCScreen.js b/cocos2d/core/platform/CCScreen.js index 610c9ee71d9..f02291406b7 100644 --- a/cocos2d/core/platform/CCScreen.js +++ b/cocos2d/core/platform/CCScreen.js @@ -34,6 +34,8 @@ cc.screen = /** @lends cc.screen# */{ _supportsFullScreen: false, // the pre fullscreenchange function _preOnFullScreenChange: null, + _preOnFullScreenError: null, + _preOnTouch: null, _touchEvent: "", _fn: null, // Function mapping for cross browser support @@ -43,35 +45,40 @@ cc.screen = /** @lends cc.screen# */{ 'exitFullscreen', 'fullscreenchange', 'fullscreenEnabled', - 'fullscreenElement' + 'fullscreenElement', + 'fullscreenerror', ], [ 'requestFullScreen', 'exitFullScreen', 'fullScreenchange', 'fullScreenEnabled', - 'fullScreenElement' + 'fullScreenElement', + 'fullscreenerror', ], [ 'webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitIsFullScreen', - 'webkitCurrentFullScreenElement' + 'webkitCurrentFullScreenElement', + 'webkitfullscreenerror', ], [ 'mozRequestFullScreen', 'mozCancelFullScreen', 'mozfullscreenchange', 'mozFullScreen', - 'mozFullScreenElement' + 'mozFullScreenElement', + 'mozfullscreenerror', ], [ 'msRequestFullscreen', 'msExitFullscreen', 'MSFullscreenChange', 'msFullscreenEnabled', - 'msFullscreenElement' + 'msFullscreenElement', + 'msfullscreenerror', ] ], @@ -93,7 +100,11 @@ cc.screen = /** @lends cc.screen# */{ } this._supportsFullScreen = (this._fn.requestFullscreen !== undefined); - this._touchEvent = ('ontouchstart' in window) ? 'touchstart' : 'mousedown'; + + // Bug fix only for v2.1, don't merge into v2.0 + // In v2.0, screen touchend events conflict with editBox touchend events if it's not stayOnTop. + // While in v2.1, editBox always keep stayOnTop and it doesn't support touchend events. + this._touchEvent = ('ontouchend' in window) ? 'touchend' : 'mousedown'; }, /** @@ -143,7 +154,7 @@ cc.screen = /** @lends cc.screen# */{ document.addEventListener(eventName, onFullScreenChange, false); } - return element[this._fn.requestFullscreen](); + element[this._fn.requestFullscreen](); }, /** @@ -172,15 +183,48 @@ cc.screen = /** @lends cc.screen# */{ */ autoFullScreen: function (element, onFullScreenChange) { element = element || document.body; - var touchTarget = cc.game.canvas || element; - var theScreen = this; - // Function bind will be too complicated here because we need the callback function's reference to remove the listener - function callback() { - touchTarget.removeEventListener(theScreen._touchEvent, callback); - theScreen.requestFullScreen(element, onFullScreenChange); - } + + this._ensureFullScreen(element, onFullScreenChange); this.requestFullScreen(element, onFullScreenChange); - touchTarget.addEventListener(this._touchEvent, callback); - } + }, + + disableAutoFullScreen (element) { + let touchTarget = cc.game.canvas || element; + let touchEventName = this._touchEvent; + if (this._preOnTouch) { + touchTarget.removeEventListener(touchEventName, this._preOnTouch); + this._preOnTouch = null; + } + }, + + // Register touch event if request full screen failed + _ensureFullScreen (element, onFullScreenChange) { + let self = this; + let touchTarget = cc.game.canvas || element; + let fullScreenErrorEventName = this._fn.fullscreenerror; + let touchEventName = this._touchEvent; + + function onFullScreenError () { + self._preOnFullScreenError = null; + + // handle touch event listener + function onTouch() { + self._preOnTouch = null; + self.requestFullScreen(element, onFullScreenChange); + } + if (self._preOnTouch) { + touchTarget.removeEventListener(touchEventName, self._preOnTouch); + } + self._preOnTouch = onTouch; + touchTarget.addEventListener(touchEventName, self._preOnTouch, { once: true }); + } + + // handle full screen error + if (this._preOnFullScreenError) { + element.removeEventListener(fullScreenErrorEventName, this._preOnFullScreenError); + } + this._preOnFullScreenError = onFullScreenError; + element.addEventListener(fullScreenErrorEventName, onFullScreenError, { once: true }); + }, }; cc.screen.init(); diff --git a/cocos2d/core/platform/CCView.js b/cocos2d/core/platform/CCView.js index fe2766c452a..95fdfa03e8d 100644 --- a/cocos2d/core/platform/CCView.js +++ b/cocos2d/core/platform/CCView.js @@ -528,6 +528,7 @@ cc.js.mixin(View.prototype, { } else { this._autoFullScreen = false; + cc.screen.disableAutoFullScreen(cc.game.frame); } }, diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index c509fce03fa..ac637d3cf8b 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -216,7 +216,6 @@ module.exports = { "input_mode": "Specify the input mode: multiline or single line.", "font_size": "The font size of input label.", "line_height": "The line height of input label.", - "stay_on_top": "Set to true and the input is always visible and be on top of the game view", "tab_index": "Set the tabIndex of the DOM input element, only useful on Web.", "font_color": "The font color of input label.", "placeholder": "The content string of placeholder.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index d56a61617c2..5a22641eaf0 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -221,7 +221,6 @@ module.exports = { "font_size": "输入框文本的字体大小", "line_height": "输入框文本的行高", "font_color": "输入框文本的颜色", - "stay_on_top": "设置为 True 则输入框总是可见,并且永远在游戏视图的上面", "tab_index": "修改 DOM 输入元素的 tabIndex,这个属性只有在 Web 上面修改有意义。", "placeholder": "输入框占位符的文本内容", "placeholder_font_size": "输入框占位符的字体大小", From fb15801d7d4e8154a4ff7d34e125a4aa0ab4841b Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Tue, 19 Feb 2019 15:00:44 +0800 Subject: [PATCH 0456/1631] fix gl clear throw error when clear flag is 0 (#3869) --- cocos2d/renderer/gfx/device.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cocos2d/renderer/gfx/device.js b/cocos2d/renderer/gfx/device.js index 121b53a7a69..cef71fd0b85 100644 --- a/cocos2d/renderer/gfx/device.js +++ b/cocos2d/renderer/gfx/device.js @@ -859,6 +859,9 @@ export default class Device { * @param {Number} opts.stencil */ clear(opts) { + if (opts.color === undefined && opts.depth === undefined && opts.stencil === undefined) { + return; + } const gl = this._gl; let flags = 0; From 02da74ce37dc09939aacf56eac819707f1f05d7b Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Tue, 19 Feb 2019 15:07:42 +0800 Subject: [PATCH 0457/1631] fix gl clear throw error when clear flag is 0 (#3868) * fix gl clear throw error when clear flag is 0 * fix gl clear throw error when clear flag is 0 --- cocos2d/core/renderer/render-engine.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 7d76d8010bb..13261f2a379 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -9749,6 +9749,10 @@ Device.prototype.setScissor = function setScissor (x, y, w, h) { * @param {Number} opts.stencil */ Device.prototype.clear = function clear (opts) { + if (opts.color === undefined && opts.depth === undefined && opts.stencil === undefined) { + return; + } + var gl = this._gl; var flags = 0; From a385dc87baf16df4e023087cc977a595a09a8346 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 19 Feb 2019 15:28:50 +0800 Subject: [PATCH 0458/1631] 2.x support 1.x particle system texture (#3866) --- cocos2d/particle/CCParticleSystem.js | 46 +++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index cd189734cce..dfd7985bff0 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -243,6 +243,14 @@ var properties = { tooltip: CC_DEV && 'i18n:COMPONENT.particle_system.spriteFrame' }, + + // just used to read data from 1.x + _texture: { + default: null, + type: cc.Texture2D, + editorOnly: true, + }, + /** * !#en Texture of Particle System, readonly, please use spriteFrame to setup new texture。 * !#zh 粒子贴图,只读属性,请使用 spriteFrame 属性来替换贴图。 @@ -711,7 +719,6 @@ var ParticleSystem = cc.Class({ ctor: function () { this._previewTimer = null; this._focused = false; - this._texture = null; this._simulator = new ParticleSimulator(this); @@ -791,7 +798,44 @@ var ParticleSystem = cc.Class({ // LIFE-CYCLE METHODS + // just used to read data from 1.x + _convertTextureToSpriteFrame: CC_EDITOR && function () { + if (this._spriteFrame) { + return; + } + let texture = this.texture; + if (!texture || !texture._uuid) { + return; + } + + let _this = this; + Editor.assetdb.queryMetaInfoByUuid(texture._uuid, function (err, metaInfo) { + if (err) return Editor.error(err); + let meta = JSON.parse(metaInfo.json); + if (meta.type === 'raw') { + const NodeUtils = Editor.require('app://editor/page/scene-utils/utils/node'); + let nodePath = NodeUtils.getNodePath(_this.node); + return Editor.warn(`The texture ${metaInfo.assetUrl} used by particle ${nodePath} does not contain any SpriteFrame, please set the texture type to Sprite and reassign the SpriteFrame to the particle component.`); + } + else { + let Url = require('fire-url'); + let name = Url.basenameNoExt(metaInfo.assetPath); + let uuid = meta.subMetas[name].uuid; + cc.AssetLibrary.loadAsset(uuid, function (err, sp) { + if (err) return Editor.error(err); + _this._texture = null; + _this.spriteFrame = sp; + }); + } + }); + }, + __preload: function () { + + if (CC_EDITOR) { + this._convertTextureToSpriteFrame(); + } + if (this._file) { if (this._custom) { var missCustomTexture = !this._texture; From e972f612309262dd7f30fced512c50510b61cdba Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 19 Feb 2019 16:05:17 +0800 Subject: [PATCH 0459/1631] add max value to label font size (#3871) * add max value to label font size * update font size max value to 512 --- cocos2d/core/components/CCLabel.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index d3db11f20e0..e7bd86d6284 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -249,6 +249,7 @@ let Label = cc.Class({ this._fontSize = value; this._updateRenderData(); }, + range: [0, 512], tooltip: CC_DEV && 'i18n:COMPONENT.label.font_size', }, From 62bc2c721caaad5b59b154b560f3d4d2a1c84373 Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 19 Feb 2019 17:18:19 +0800 Subject: [PATCH 0460/1631] fix video player event only fire once for 2d-tasks/issues/1075 (#3873) --- cocos2d/videoplayer/video-player-impl.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 57bbacb873f..4a5027ed3f9 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -34,7 +34,7 @@ const READY_STATE = { HAVE_CURRENT_DATA: 2, HAVE_FUTURE_DATA: 3, HAVE_ENOUGH_DATA: 4 -} +}; let _mat4_temp = math.mat4.create(); @@ -168,6 +168,8 @@ let VideoPlayerImpl = cc.Class({ video.className = "cocosVideo"; video.setAttribute('preload', 'auto'); video.setAttribute('webkit-playsinline', ''); + // This x5-playsinline tag must be added, otherwise the play, pause events will only fire once, in the qq browser. + video.setAttribute("x5-playsinline", ''); video.setAttribute('playsinline', ''); this._video = video; From 201e4e00ec0e34c67a588b79fde152d10a810ced Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Wed, 20 Feb 2019 17:48:44 +0800 Subject: [PATCH 0461/1631] Add RenderMode TS support (#3879) Add spine assembler var define --- extensions/dragonbones/ArmatureDisplay.js | 61 ++++++++++++++++------- extensions/spine/Skeleton.js | 43 ++++++++++++---- extensions/spine/skeleton-cache.js | 5 +- extensions/spine/spine-assembler.js | 14 +++--- 4 files changed, 87 insertions(+), 36 deletions(-) diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index e79300d866a..df303ddb5ba 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -41,8 +41,33 @@ let ArmatureCache = require('./ArmatureCache'); let DefaultArmaturesEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); -let DefaultRenderModeEnum = cc.Enum({ 'REALTIME': 0 }); -let RenderModeEnum = cc.Enum({ 'REALTIME': 0, 'SHARED_CACHE': 1, "PRIVATE_CACHE": 2 }); +let DefaultRenderMode = cc.Enum({ 'REALTIME': 0 }); + +/** + * !#en Enum for render mode type. + * !#zh Dragonbones渲染类型 + * @enum ArmatureDisplay.RenderMode + */ +let RenderMode = cc.Enum({ + /** + * !#en The realtime mode. + * !#zh 实时计算模式。 + * @property {Number} REALTIME + */ + REALTIME: 0, + /** + * !#en The shared cache mode. + * !#zh 共享缓存模式。 + * @property {Number} SHARED_CACHE + */ + SHARED_CACHE: 1, + /** + * !#en The private cache mode. + * !#zh 私有缓存模式。 + * @property {Number} PRIVATE_CACHE + */ + PRIVATE_CACHE: 2 +}); function setEnumAttr (obj, propName, enumDef) { cc.Class.attr(obj, propName, { @@ -79,7 +104,7 @@ let ArmatureDisplay = cc.Class({ }, statics: { - RenderMode: RenderModeEnum, + RenderMode: RenderMode, }, properties: { @@ -294,10 +319,10 @@ let ArmatureDisplay = cc.Class({ // Record pre render mode. _preRenderMode: -1, - _renderMode: RenderModeEnum.REALTIME, + _renderMode: RenderMode.REALTIME, _defaultRenderMode: { default: 0, - type: RenderModeEnum, + type: RenderMode, notify () { this.setRenderMode(this._defaultRenderMode); }, @@ -448,7 +473,7 @@ let ArmatureDisplay = cc.Class({ this._inited = true; if (CC_JSB) { - this._renderMode = RenderModeEnum.REALTIME; + this._renderMode = RenderMode.REALTIME; } this._parseDragonAsset(); @@ -493,7 +518,7 @@ let ArmatureDisplay = cc.Class({ */ isCachedMode () { if (CC_EDITOR) return false; - return this._renderMode !== RenderModeEnum.REALTIME; + return this._renderMode !== RenderMode.REALTIME; }, onEnable () { @@ -557,11 +582,11 @@ let ArmatureDisplay = cc.Class({ this._inited = false; if (!CC_EDITOR) { - if (this._renderMode === RenderModeEnum.PRIVATE_CACHE) { + if (this._renderMode === RenderMode.PRIVATE_CACHE) { this._armatureCache.dispose(); this._armatureCache = null; this._armature = null; - } else if (this._renderMode === RenderModeEnum.SHARED_CACHE) { + } else if (this._renderMode === RenderMode.SHARED_CACHE) { this._armatureCache = null; this._armature = null; } else if (this._armature) { @@ -601,9 +626,9 @@ let ArmatureDisplay = cc.Class({ if (this._armature) { // dispose pre build armature if (!CC_EDITOR) { - if (this._preRenderMode === RenderModeEnum.PRIVATE_CACHE) { + if (this._preRenderMode === RenderMode.PRIVATE_CACHE) { this._armatureCache.dispose(); - } else if (this._preRenderMode === RenderModeEnum.REALTIME) { + } else if (this._preRenderMode === RenderMode.REALTIME) { this._armature.dispose(); } } else { @@ -620,9 +645,9 @@ let ArmatureDisplay = cc.Class({ } if (!CC_EDITOR) { - if (this._renderMode === RenderModeEnum.SHARED_CACHE) { + if (this._renderMode === RenderMode.SHARED_CACHE) { this._armatureCache = ArmatureCache.sharedCache; - } else if (this._renderMode === RenderModeEnum.PRIVATE_CACHE) { + } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { this._armatureCache = new ArmatureCache; } } @@ -634,12 +659,12 @@ let ArmatureDisplay = cc.Class({ this._armature = this._armatureCache.getArmatureCache(this.armatureName, dragonbonesName, atlasName); if (!this._armature) { // Cache fail,swith to REALTIME render mode. - this._renderMode = RenderModeEnum.REALTIME; + this._renderMode = RenderMode.REALTIME; } } this._preRenderMode = this._renderMode; - if (CC_EDITOR || this._renderMode === RenderModeEnum.REALTIME) { + if (CC_EDITOR || this._renderMode === RenderMode.REALTIME) { this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, dragonbonesName, "", atlasName); if (!this._displayProxy) return; this._displayProxy._ccNode = this.node; @@ -647,7 +672,7 @@ let ArmatureDisplay = cc.Class({ this._armature.animation.timeScale = this.timeScale; } - if (this._renderMode !== RenderModeEnum.REALTIME && this.debugBones) { + if (this._renderMode !== RenderMode.REALTIME && this.debugBones) { cc.warn("Debug bones is invalid in cached mode"); } @@ -683,9 +708,9 @@ let ArmatureDisplay = cc.Class({ _updateRenderModeEnum: CC_EDITOR && function () { if (this._armature && ArmatureCache.canCache(this._armature)) { - setEnumAttr(this, 'renderMode', RenderModeEnum); + setEnumAttr(this, 'renderMode', RenderMode); } else { - setEnumAttr(this, 'renderMode', DefaultRenderModeEnum); + setEnumAttr(this, 'renderMode', DefaultRenderMode); } }, diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 7aa6eb7af67..eafa9475327 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -38,7 +38,32 @@ let SkeletonCache = require('./skeleton-cache'); */ let DefaultSkinsEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); -let RenderModeEnum = cc.Enum({ 'REALTIME': 0, 'SHARED_CACHE': 1, "PRIVATE_CACHE": 2 }); + +/** + * !#en Enum for render mode type. + * !#zh Spine渲染类型 + * @enum Skeleton.RenderMode + */ +let RenderMode = cc.Enum({ + /** + * !#en The realtime mode. + * !#zh 实时计算模式。 + * @property {Number} REALTIME + */ + REALTIME: 0, + /** + * !#en The shared cache mode. + * !#zh 共享缓存模式。 + * @property {Number} SHARED_CACHE + */ + SHARED_CACHE: 1, + /** + * !#en The private cache mode. + * !#zh 私有缓存模式。 + * @property {Number} PRIVATE_CACHE + */ + PRIVATE_CACHE: 2 +}); function setEnumAttr (obj, propName, enumDef) { cc.Class.attr(obj, propName, { @@ -74,7 +99,7 @@ sp.Skeleton = cc.Class({ }, statics: { - RenderMode: RenderModeEnum, + RenderMode: RenderMode, }, properties: { @@ -288,10 +313,10 @@ sp.Skeleton = cc.Class({ // Record pre render mode. _preRenderMode: -1, - _renderMode: RenderModeEnum.REALTIME, + _renderMode: RenderMode.REALTIME, _defaultRenderMode: { default: 0, - type: RenderModeEnum, + type: RenderMode, notify () { this.setRenderMode(this._defaultRenderMode); }, @@ -545,7 +570,7 @@ sp.Skeleton = cc.Class({ } if (CC_JSB) { - this._renderMode = RenderModeEnum.REALTIME; + this._renderMode = RenderMode.REALTIME; } this._updateSkeletonData(); @@ -582,7 +607,7 @@ sp.Skeleton = cc.Class({ */ isCachedMode () { if (CC_EDITOR) return false; - return this._renderMode !== RenderModeEnum.REALTIME; + return this._renderMode !== RenderMode.REALTIME; }, update (dt) { @@ -1218,9 +1243,9 @@ sp.Skeleton = cc.Class({ if (!data) return; if (!CC_EDITOR) { - if (this._renderMode === RenderModeEnum.SHARED_CACHE) { + if (this._renderMode === RenderMode.SHARED_CACHE) { this._skeletonCache = SkeletonCache.sharedCache; - } else if (this._renderMode === RenderModeEnum.PRIVATE_CACHE) { + } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { this._skeletonCache = new SkeletonCache; } } @@ -1253,7 +1278,7 @@ sp.Skeleton = cc.Class({ }, _updateRenderModeEnum: CC_EDITOR && function () { - setEnumAttr(this, 'renderMode', RenderModeEnum); + setEnumAttr(this, 'renderMode', RenderMode); }, _updateDebugDraw: function () { diff --git a/extensions/spine/skeleton-cache.js b/extensions/spine/skeleton-cache.js index f29afeb2d7e..44ee0d61fe7 100644 --- a/extensions/spine/skeleton-cache.js +++ b/extensions/spine/skeleton-cache.js @@ -199,7 +199,7 @@ let AnimationCache = cc.Class({ frame.indices = indices; }, - fillVertices (skeletonColor, attachmentColor, slotColor, clipper) { + fillVertices (skeletonColor, attachmentColor, slotColor, clipper, slot) { _tempa = slotColor.a * attachmentColor.a * skeletonColor.a * 255; _tempr = attachmentColor.r * skeletonColor.r * 255; @@ -285,6 +285,7 @@ let AnimationCache = cc.Class({ let texture; let preSegOffset, preSegInfo; let blendMode; + let slot; for (let slotIdx = 0, slotCount = skeleton.drawOrder.length; slotIdx < slotCount; slotIdx++) { slot = skeleton.drawOrder[slotIdx]; @@ -383,7 +384,7 @@ let AnimationCache = cc.Class({ attachmentColor = attachment.color; slotColor = slot.color; - this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper); + this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper, slot); if (_indexCount > 0) { for (let ii = _indexOffset, nn = _indexOffset + _indexCount; ii < nn; ii++) { diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 05c178904f9..d2e60bfc99c 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -68,13 +68,14 @@ let _finalColor32, _darkColor32; let _vertexFormat; let _perVertexSize; let _perClipVertexSize; -let _vertexFloatCount = 0, _vertexFloatOffset = 0, _vertexOffset = 0, - _indexCount = 0, _indexOffset = 0; +let _vertexFloatCount = 0, _vertexCount = 0, _vertexFloatOffset = 0, _vertexOffset = 0, + _indexCount = 0, _indexOffset = 0, _vfOffset = 0; let _tempr, _tempg, _tempb, _tempa; let _inRange; let _mustFlush; let _x, _y, _m00, _m04, _m12, _m01, _m05, _m13; -let _r, _g, _b, _a, _fr, _fg, _fb, _fa, _dr, _dg, _db, _da; +let _r, _g, _b, _fr, _fg, _fb, _fa, _dr, _dg, _db, _da; +let _comp, _buffer, _renderer, _node, _needColor; function _getSlotMaterial (tex, blendMode) { let src, dst; @@ -167,7 +168,7 @@ var spineAssembler = { } }, - fillVertices (skeletonColor, attachmentColor, slotColor, clipper) { + fillVertices (skeletonColor, attachmentColor, slotColor, clipper, slot) { let vbuf = _buffer._vData, ibuf = _buffer._iData, @@ -271,6 +272,7 @@ var spineAssembler = { let attachment, attachmentColor, slotColor, uvs, triangles; let isRegion, isMesh, isClip; let offsetInfo; + let slot; _slotRangeStart = _comp._startSlotIndex; _slotRangeEnd = _comp._endSlotIndex; @@ -353,7 +355,6 @@ var spineAssembler = { _vertexFloatOffset = offsetInfo.byteOffset >> 2; vbuf = _buffer._vData, ibuf = _buffer._iData; - uintVData = _buffer._uintVData; // compute vertex and fill x y attachment.computeWorldVertices(slot.bone, vbuf, _vertexFloatOffset, _perVertexSize); @@ -382,7 +383,6 @@ var spineAssembler = { _vertexFloatOffset = offsetInfo.byteOffset >> 2; vbuf = _buffer._vData, ibuf = _buffer._iData; - uintVData = _buffer._uintVData; // compute vertex and fill x y attachment.computeWorldVertices(slot, 0, attachment.worldVerticesLength, vbuf, _vertexFloatOffset, _perVertexSize); @@ -405,7 +405,7 @@ var spineAssembler = { attachmentColor = attachment.color, slotColor = slot.color; - this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper); + this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper, slot); if (_indexCount > 0) { for (let ii = _indexOffset, nn = _indexOffset + _indexCount; ii < nn; ii++) { From 5ce56c7b12e46ca04fff56fdcc5ded6fa2fd7a72 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 21 Feb 2019 00:30:42 +0800 Subject: [PATCH 0462/1631] rename 2.5D to 3D (#3884) --- cocos2d/core/CCNode.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index a0518df7c4e..b69ab9e2638 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -756,8 +756,8 @@ let NodeDefines = { }, /** - * !#en The rotation as Euler angles in degrees, used in 2.5D project. - * !#zh 该节点的欧拉角度,用于 2.5D 项目。 + * !#en The rotation as Euler angles in degrees, used in 3D project. + * !#zh 该节点的欧拉角度,用于 3D 项目。 * @property eulerAngles * @type {Vec3} */ From 95d2366256213de81e531a152524986883eafb2e Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Thu, 21 Feb 2019 09:51:19 +0800 Subject: [PATCH 0463/1631] Add RenderMode TS support (#3879) (#3881) Add spine assembler var define --- extensions/dragonbones/ArmatureDisplay.js | 61 ++++++++++++++++------- extensions/spine/Skeleton.js | 43 ++++++++++++---- extensions/spine/skeleton-cache.js | 5 +- extensions/spine/spine-assembler.js | 42 ++++++++-------- 4 files changed, 102 insertions(+), 49 deletions(-) diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 30a86d7e615..9ce7a63636f 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -41,8 +41,33 @@ let ArmatureCache = require('./ArmatureCache'); let DefaultArmaturesEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); -let DefaultRenderModeEnum = cc.Enum({ 'REALTIME': 0 }); -let RenderModeEnum = cc.Enum({ 'REALTIME': 0, 'SHARED_CACHE': 1, "PRIVATE_CACHE": 2 }); +let DefaultRenderMode = cc.Enum({ 'REALTIME': 0 }); + +/** + * !#en Enum for render mode type. + * !#zh Dragonbones渲染类型 + * @enum ArmatureDisplay.RenderMode + */ +let RenderMode = cc.Enum({ + /** + * !#en The realtime mode. + * !#zh 实时计算模式。 + * @property {Number} REALTIME + */ + REALTIME: 0, + /** + * !#en The shared cache mode. + * !#zh 共享缓存模式。 + * @property {Number} SHARED_CACHE + */ + SHARED_CACHE: 1, + /** + * !#en The private cache mode. + * !#zh 私有缓存模式。 + * @property {Number} PRIVATE_CACHE + */ + PRIVATE_CACHE: 2 +}); function setEnumAttr (obj, propName, enumDef) { cc.Class.attr(obj, propName, { @@ -79,7 +104,7 @@ let ArmatureDisplay = cc.Class({ }, statics: { - RenderMode: RenderModeEnum, + RenderMode: RenderMode, }, properties: { @@ -295,10 +320,10 @@ let ArmatureDisplay = cc.Class({ // Record pre render mode. _preRenderMode: -1, - _renderMode: RenderModeEnum.REALTIME, + _renderMode: RenderMode.REALTIME, _defaultRenderMode: { default: 0, - type: RenderModeEnum, + type: RenderMode, notify () { this.setRenderMode(this._defaultRenderMode); }, @@ -449,7 +474,7 @@ let ArmatureDisplay = cc.Class({ this._inited = true; if (CC_JSB) { - this._renderMode = RenderModeEnum.REALTIME; + this._renderMode = RenderMode.REALTIME; } this._parseDragonAsset(); @@ -496,7 +521,7 @@ let ArmatureDisplay = cc.Class({ */ isCachedMode () { if (CC_EDITOR) return false; - return this._renderMode !== RenderModeEnum.REALTIME; + return this._renderMode !== RenderMode.REALTIME; }, onEnable () { @@ -560,11 +585,11 @@ let ArmatureDisplay = cc.Class({ this._inited = false; if (!CC_EDITOR) { - if (this._renderMode === RenderModeEnum.PRIVATE_CACHE) { + if (this._renderMode === RenderMode.PRIVATE_CACHE) { this._armatureCache.dispose(); this._armatureCache = null; this._armature = null; - } else if (this._renderMode === RenderModeEnum.SHARED_CACHE) { + } else if (this._renderMode === RenderMode.SHARED_CACHE) { this._armatureCache = null; this._armature = null; } else if (this._armature) { @@ -627,9 +652,9 @@ let ArmatureDisplay = cc.Class({ if (this._armature) { // dispose pre build armature if (!CC_EDITOR) { - if (this._preRenderMode === RenderModeEnum.PRIVATE_CACHE) { + if (this._preRenderMode === RenderMode.PRIVATE_CACHE) { this._armatureCache.dispose(); - } else if (this._preRenderMode === RenderModeEnum.REALTIME) { + } else if (this._preRenderMode === RenderMode.REALTIME) { this._armature.dispose(); } } else { @@ -646,9 +671,9 @@ let ArmatureDisplay = cc.Class({ } if (!CC_EDITOR) { - if (this._renderMode === RenderModeEnum.SHARED_CACHE) { + if (this._renderMode === RenderMode.SHARED_CACHE) { this._armatureCache = ArmatureCache.sharedCache; - } else if (this._renderMode === RenderModeEnum.PRIVATE_CACHE) { + } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { this._armatureCache = new ArmatureCache; } } @@ -660,12 +685,12 @@ let ArmatureDisplay = cc.Class({ this._armature = this._armatureCache.getArmatureCache(this.armatureName, dragonbonesName, atlasName); if (!this._armature) { // Cache fail,swith to REALTIME render mode. - this._renderMode = RenderModeEnum.REALTIME; + this._renderMode = RenderMode.REALTIME; } } this._preRenderMode = this._renderMode; - if (CC_EDITOR || this._renderMode === RenderModeEnum.REALTIME) { + if (CC_EDITOR || this._renderMode === RenderMode.REALTIME) { this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, dragonbonesName, "", atlasName); if (!this._displayProxy) return; this._displayProxy._ccNode = this.node; @@ -673,7 +698,7 @@ let ArmatureDisplay = cc.Class({ this._armature.animation.timeScale = this.timeScale; } - if (this._renderMode !== RenderModeEnum.REALTIME && this.debugBones) { + if (this._renderMode !== RenderMode.REALTIME && this.debugBones) { cc.warn("Debug bones is invalid in cached mode"); } @@ -709,9 +734,9 @@ let ArmatureDisplay = cc.Class({ _updateRenderModeEnum: CC_EDITOR && function () { if (this._armature && ArmatureCache.canCache(this._armature)) { - setEnumAttr(this, 'renderMode', RenderModeEnum); + setEnumAttr(this, 'renderMode', RenderMode); } else { - setEnumAttr(this, 'renderMode', DefaultRenderModeEnum); + setEnumAttr(this, 'renderMode', DefaultRenderMode); } }, diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 9dfa8c1baa4..d16affb6fd4 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -38,7 +38,32 @@ let SkeletonCache = require('./skeleton-cache'); */ let DefaultSkinsEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); -let RenderModeEnum = cc.Enum({ 'REALTIME': 0, 'SHARED_CACHE': 1, "PRIVATE_CACHE": 2 }); + +/** + * !#en Enum for render mode type. + * !#zh Spine渲染类型 + * @enum Skeleton.RenderMode + */ +let RenderMode = cc.Enum({ + /** + * !#en The realtime mode. + * !#zh 实时计算模式。 + * @property {Number} REALTIME + */ + REALTIME: 0, + /** + * !#en The shared cache mode. + * !#zh 共享缓存模式。 + * @property {Number} SHARED_CACHE + */ + SHARED_CACHE: 1, + /** + * !#en The private cache mode. + * !#zh 私有缓存模式。 + * @property {Number} PRIVATE_CACHE + */ + PRIVATE_CACHE: 2 +}); function setEnumAttr (obj, propName, enumDef) { cc.Class.attr(obj, propName, { @@ -74,7 +99,7 @@ sp.Skeleton = cc.Class({ }, statics: { - RenderMode: RenderModeEnum, + RenderMode: RenderMode, }, properties: { @@ -288,10 +313,10 @@ sp.Skeleton = cc.Class({ // Record pre render mode. _preRenderMode: -1, - _renderMode: RenderModeEnum.REALTIME, + _renderMode: RenderMode.REALTIME, _defaultRenderMode: { default: 0, - type: RenderModeEnum, + type: RenderMode, notify () { this.setRenderMode(this._defaultRenderMode); }, @@ -544,7 +569,7 @@ sp.Skeleton = cc.Class({ } if (CC_JSB) { - this._renderMode = RenderModeEnum.REALTIME; + this._renderMode = RenderMode.REALTIME; } var material = Material.getInstantiatedBuiltinMaterial('spine', this); @@ -585,7 +610,7 @@ sp.Skeleton = cc.Class({ */ isCachedMode () { if (CC_EDITOR) return false; - return this._renderMode !== RenderModeEnum.REALTIME; + return this._renderMode !== RenderMode.REALTIME; }, update (dt) { @@ -1221,9 +1246,9 @@ sp.Skeleton = cc.Class({ if (!data) return; if (!CC_EDITOR) { - if (this._renderMode === RenderModeEnum.SHARED_CACHE) { + if (this._renderMode === RenderMode.SHARED_CACHE) { this._skeletonCache = SkeletonCache.sharedCache; - } else if (this._renderMode === RenderModeEnum.PRIVATE_CACHE) { + } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { this._skeletonCache = new SkeletonCache; } } @@ -1256,7 +1281,7 @@ sp.Skeleton = cc.Class({ }, _updateRenderModeEnum: CC_EDITOR && function () { - setEnumAttr(this, 'renderMode', RenderModeEnum); + setEnumAttr(this, 'renderMode', RenderMode); }, _updateDebugDraw: function () { diff --git a/extensions/spine/skeleton-cache.js b/extensions/spine/skeleton-cache.js index f29afeb2d7e..44ee0d61fe7 100644 --- a/extensions/spine/skeleton-cache.js +++ b/extensions/spine/skeleton-cache.js @@ -199,7 +199,7 @@ let AnimationCache = cc.Class({ frame.indices = indices; }, - fillVertices (skeletonColor, attachmentColor, slotColor, clipper) { + fillVertices (skeletonColor, attachmentColor, slotColor, clipper, slot) { _tempa = slotColor.a * attachmentColor.a * skeletonColor.a * 255; _tempr = attachmentColor.r * skeletonColor.r * 255; @@ -285,6 +285,7 @@ let AnimationCache = cc.Class({ let texture; let preSegOffset, preSegInfo; let blendMode; + let slot; for (let slotIdx = 0, slotCount = skeleton.drawOrder.length; slotIdx < slotCount; slotIdx++) { slot = skeleton.drawOrder[slotIdx]; @@ -383,7 +384,7 @@ let AnimationCache = cc.Class({ attachmentColor = attachment.color; slotColor = slot.color; - this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper); + this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper, slot); if (_indexCount > 0) { for (let ii = _indexOffset, nn = _indexOffset + _indexCount; ii < nn; ii++) { diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 1501e0ab5e8..827f9f4373d 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -66,14 +66,15 @@ let _finalColor32, _darkColor32; let _vertexFormat; let _perVertexSize; let _perClipVertexSize; -let _vertexFloatCount = 0, _vertexFloatOffset = 0, _vertexOffset = 0, - _indexCount = 0, _indexOffset = 0, _vertexCount = 0, _vfOffset = 0; + +let _vertexFloatCount = 0, _vertexCount = 0, _vertexFloatOffset = 0, _vertexOffset = 0, + _indexCount = 0, _indexOffset = 0, _vfOffset = 0; let _tempr, _tempg, _tempb, _tempa; let _inRange; let _mustFlush; let _x, _y, _m00, _m04, _m12, _m01, _m05, _m13; let _r, _g, _b, _fr, _fg, _fb, _fa, _dr, _dg, _db, _da; -let _comp, _node, _buffer, _renderer, _needColor, _slot; +let _comp, _buffer, _renderer, _node, _needColor; function _getSlotMaterial (tex, blendMode) { let src, dst; @@ -159,7 +160,7 @@ var spineAssembler = { } }, - fillVertices (skeletonColor, attachmentColor, slotColor, clipper) { + fillVertices (skeletonColor, attachmentColor, slotColor, clipper, slot) { let vbuf = _buffer._vData, ibuf = _buffer._iData, @@ -177,12 +178,12 @@ var spineAssembler = { _finalColor.b = _tempb * slotColor.b; _finalColor.a = _tempa * _nodeA; - if (_slot.darkColor == null) { + if (slot.darkColor == null) { _darkColor.set(0.0, 0, 0, 1.0); } else { - _darkColor.r = _slot.darkColor.r * _tempr; - _darkColor.g = _slot.darkColor.g * _tempg; - _darkColor.b = _slot.darkColor.b * _tempb; + _darkColor.r = slot.darkColor.r * _tempr; + _darkColor.g = slot.darkColor.g * _tempg; + _darkColor.b = slot.darkColor.b * _tempb; } _darkColor.a = _premultipliedAlpha ? 255 : 0; @@ -263,6 +264,7 @@ var spineAssembler = { let attachment, attachmentColor, slotColor, uvs, triangles; let isRegion, isMesh, isClip; let offsetInfo; + let slot; _slotRangeStart = _comp._startSlotIndex; _slotRangeEnd = _comp._endSlotIndex; @@ -287,25 +289,25 @@ var spineAssembler = { _indexOffset = 0; for (let slotIdx = 0, slotCount = locSkeleton.drawOrder.length; slotIdx < slotCount; slotIdx++) { - _slot = locSkeleton.drawOrder[slotIdx]; + slot = locSkeleton.drawOrder[slotIdx]; - if (_slotRangeStart >= 0 && _slotRangeStart == _slot.data.index) { + if (_slotRangeStart >= 0 && _slotRangeStart == slot.data.index) { _inRange = true; } if (!_inRange) { - clipper.clipEndWithSlot(_slot); + clipper.clipEndWithSlot(slot); continue; } - if (_slotRangeEnd >= 0 && _slotRangeEnd == _slot.data.index) { + if (_slotRangeEnd >= 0 && _slotRangeEnd == slot.data.index) { _inRange = false; } _vertexFloatCount = 0; _indexCount = 0; - attachment = _slot.getAttachment(); + attachment = slot.getAttachment(); if (!attachment) continue; isRegion = attachment instanceof spine.RegionAttachment; @@ -313,13 +315,13 @@ var spineAssembler = { isClip = attachment instanceof spine.ClippingAttachment; if (isClip) { - clipper.clipStart(_slot, attachment); + clipper.clipStart(slot, attachment); continue; } if (!isRegion && !isMesh) continue; - material = _getSlotMaterial(attachment.region.texture._texture, _slot.data.blendMode); + material = _getSlotMaterial(attachment.region.texture._texture, slot.data.blendMode); if (!material) { continue; } @@ -347,7 +349,7 @@ var spineAssembler = { ibuf = _buffer._iData; // compute vertex and fill x y - attachment.computeWorldVertices(_slot.bone, vbuf, _vertexFloatOffset, _perVertexSize); + attachment.computeWorldVertices(slot.bone, vbuf, _vertexFloatOffset, _perVertexSize); // draw debug slots if enabled graphics if (graphics && _debugSlots) { @@ -375,7 +377,7 @@ var spineAssembler = { ibuf = _buffer._iData; // compute vertex and fill x y - attachment.computeWorldVertices(_slot, 0, attachment.worldVerticesLength, vbuf, _vertexFloatOffset, _perVertexSize); + attachment.computeWorldVertices(slot, 0, attachment.worldVerticesLength, vbuf, _vertexFloatOffset, _perVertexSize); } if (_vertexFloatCount == 0 || _indexCount == 0) { @@ -393,9 +395,9 @@ var spineAssembler = { } attachmentColor = attachment.color, - slotColor = _slot.color; + slotColor = slot.color; - this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper); + this.fillVertices(skeletonColor, attachmentColor, slotColor, clipper, slot); if (_indexCount > 0) { for (let ii = _indexOffset, nn = _indexOffset + _indexCount; ii < nn; ii++) { @@ -419,7 +421,7 @@ var spineAssembler = { _buffer.adjust(_vertexFloatCount / _perVertexSize, _indexCount); } - clipper.clipEndWithSlot(_slot); + clipper.clipEndWithSlot(slot); } clipper.clipEnd(); From 93ec1d3644971b6a7637be1824670cf880f4523b Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 21 Feb 2019 11:03:55 +0800 Subject: [PATCH 0464/1631] fix unit test for sprite (#3870) --- .../renderer/canvas/renderers/sprite/index.js | 7 ++++- test/qunit/unit-es5/test-spriteRenderer.js | 30 ++++++++++++------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/index.js b/cocos2d/core/renderer/canvas/renderers/sprite/index.js index 4ffa73820f7..3df28b1d657 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/index.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/index.js @@ -30,6 +30,11 @@ let simple = require('./simple'); let sliced = require('./sliced'); let tiled = require('./tiled'); +if (CC_TEST) { + // 2.x not support test with the canvas simple, in order to test in local test construct. + cc._Test._spriteWebGLAssembler = require('../../../webgl/assemblers/sprite/index.js'); +} + module.exports = { getAssembler: function (sprite) { switch (sprite.type) { @@ -52,4 +57,4 @@ module.exports = { createData (sprite) { return sprite._assembler.createData(sprite); } -}; \ No newline at end of file +}; diff --git a/test/qunit/unit-es5/test-spriteRenderer.js b/test/qunit/unit-es5/test-spriteRenderer.js index b39de423b70..96e215b378e 100644 --- a/test/qunit/unit-es5/test-spriteRenderer.js +++ b/test/qunit/unit-es5/test-spriteRenderer.js @@ -1,6 +1,13 @@ largeModule('Sprite'); +var originalAssembler = cc.Sprite._assembler; +var originalCalDynamicAtlas = cc.Sprite.prototype._calDynamicAtlas; + test('basic test', function () { + // + cc.Sprite._assembler = cc._Test._spriteWebGLAssembler; + cc.Sprite.prototype._calDynamicAtlas = function () {}; + var url = assetDir + '/button.png'; var node = new cc.Node(); @@ -143,8 +150,8 @@ if (!isPhantomJS) { var vertices = sprite._renderData._data; var uvs = sprite._spriteFrame.uvSliced; - strictEqual(uvs.length == 16, true, 'have 16 uvs'); - strictEqual(vertices.length == 20, true, 'have 20 vertices'); + strictEqual(uvs.length === 16, true, 'have 16 uvs'); + strictEqual(vertices.length === 20, true, 'have 20 vertices'); strictEqual(vertices[4].x, 0, 'x0 test success'); strictEqual(vertices[4].y, 0, 'y0 test success'); strictEqual(vertices[9].x, 5, 'x1 test success'); @@ -190,8 +197,9 @@ if (!isPhantomJS) { sprite._assembler.updateRenderData(sprite); var vertices = sprite._renderData._data; + var uvs = sprite._spriteFrame.uv; - strictEqual(vertices.length == 8, true, 'have 8 vertices'); + strictEqual(vertices.length === 8, true, 'have 8 vertices'); strictEqual(vertices[0].x, 0, 'x0 test success'); strictEqual(vertices[1].x, 40, 'x1 test success'); strictEqual(vertices[2].x, 80, 'x2 test success'); @@ -200,14 +208,10 @@ if (!isPhantomJS) { strictEqual(vertices[1].y, 60, 'y1 test success'); strictEqual(vertices[2].y, 100, 'y2 test success'); // - deepClose(vertices[0].u, 10 / 100, 0.01, 'full quad u0 test success'); - deepClose(vertices[0].v, 70 / 100, 0.01, 'full quad v0 test success'); - deepClose(vertices[3].u, 50 / 100, 0.01, 'full quad u1 test success'); - deepClose(vertices[3].v, 10 / 100, 0.01, 'full quad v1 test success'); - deepClose(vertices[4].u, 10 / 100, 0.01, 'part quad u0 test success'); - deepClose(vertices[4].v, 70 / 100, 0.01, 'part quad v0 test success'); - deepClose(vertices[7].u, 30 / 100, 0.01, 'part quad u1 test success'); - deepClose(vertices[7].v, 30 / 100, 0.01, 'part quad v1 test success'); + deepClose(uvs[0], 10 / 100, 0.01, 'full quad u0 test success'); + deepClose(uvs[1], 70 / 100, 0.01, 'full quad v0 test success'); + deepClose(uvs[6], 50 / 100, 0.01, 'full quad u1 test success'); + deepClose(uvs[7], 10 / 100, 0.01, 'full quad v1 test success'); }; if (spriteFrame.textureLoaded()) { testCallBack(); @@ -364,6 +368,10 @@ if (!isPhantomJS) { deepClose(vertices[4].y, p1.y, 0.01, 'p1 test success'); deepClose(vertices[5].x, p2.x, 0.01, 'p2 test success'); deepClose(vertices[5].y, p2.y, 0.01, 'p2 test success'); + + // + cc.Sprite._assembler = originalAssembler; + cc.Sprite.prototype._calDynamicAtlas = originalCalDynamicAtlas; }; if (spriteFrame.textureLoaded()) { testCallBack(); From da65368082707fa64eaa331c5c48127e23f54ec8 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 21 Feb 2019 11:06:52 +0800 Subject: [PATCH 0465/1631] Fix 1.x to 2.x particle custom data is invalid bug (#3885) --- cocos2d/particle/CCParticleSystem.js | 188 ++++++++++++++++++++++----- 1 file changed, 157 insertions(+), 31 deletions(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index dfd7985bff0..d93f5866fdf 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -341,35 +341,55 @@ var properties = { * @property {Number} totalParticles * @default 150 */ - totalParticles: 150, + totalParticles: { + default: 150, + type: cc.Float, + formerlySerializedAs: '_totalParticles' + }, /** * !#en How many seconds the emitter wil run. -1 means 'forever'. * !#zh 发射器生存时间,单位秒,-1表示持续发射。 * @property {Number} duration * @default ParticleSystem.DURATION_INFINITY */ - duration: -1, + duration: { + default: -1, + type: cc.Float, + formerlySerializedAs: '_duration' + }, /** * !#en Emission rate of the particles. * !#zh 每秒发射的粒子数目。 * @property {Number} emissionRate * @default 10 */ - emissionRate: 10, + emissionRate: { + default: 10, + type: cc.Float, + formerlySerializedAs: '_emissionRate' + }, /** * !#en Life of each particle setter. * !#zh 粒子的运行时间。 * @property {Number} life * @default 1 */ - life: 1, + life: { + default: 1, + type: cc.Float, + formerlySerializedAs: '_life' + }, /** * !#en Variation of life. * !#zh 粒子的运行时间变化范围。 * @property {Number} lifeVar * @default 0 */ - lifeVar: 0, + lifeVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_lifeVar' + }, /** * !#en Start color of each particle. @@ -454,70 +474,110 @@ var properties = { * @property {Number} angle * @default 90 */ - angle: 90, + angle: { + default: 90, + type: cc.Float, + formerlySerializedAs: '_angle' + }, /** * !#en Variation of angle of each particle setter. * !#zh 粒子角度变化范围。 * @property {Number} angleVar * @default 20 */ - angleVar: 20, + angleVar: { + default: 20, + type: cc.Float, + formerlySerializedAs: '_angleVar' + }, /** * !#en Start size in pixels of each particle. * !#zh 粒子的初始大小。 * @property {Number} startSize * @default 50 */ - startSize: 50, + startSize: { + default: 50, + type: cc.Float, + formerlySerializedAs: '_startSize' + }, /** * !#en Variation of start size in pixels. * !#zh 粒子初始大小的变化范围。 * @property {Number} startSizeVar * @default 0 */ - startSizeVar: 0, + startSizeVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_startSizeVar' + }, /** * !#en End size in pixels of each particle. * !#zh 粒子结束时的大小。 * @property {Number} endSize * @default 0 */ - endSize: 0, + endSize: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_endSize' + }, /** * !#en Variation of end size in pixels. * !#zh 粒子结束大小的变化范围。 * @property {Number} endSizeVar * @default 0 */ - endSizeVar: 0, + endSizeVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_endSizeVar' + }, /** * !#en Start angle of each particle. * !#zh 粒子开始自旋角度。 * @property {Number} startSpin * @default 0 */ - startSpin: 0, + startSpin: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_startSpin' + }, /** * !#en Variation of start angle. * !#zh 粒子开始自旋角度变化范围。 * @property {Number} startSpinVar * @default 0 */ - startSpinVar: 0, + startSpinVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_startSpinVar' + }, /** * !#en End angle of each particle. * !#zh 粒子结束自旋角度。 * @property {Number} endSpin * @default 0 */ - endSpin: 0, + endSpin: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_endSpin' + }, /** * !#en Variation of end angle. * !#zh 粒子结束自旋角度变化范围。 * @property {Number} endSpinVar * @default 0 */ - endSpinVar: 0, + endSpinVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_endSpinVar' + }, /** * !#en Source position of the emitter. @@ -525,7 +585,11 @@ var properties = { * @property {Vec2} sourcePos * @default cc.Vec2.ZERO */ - sourcePos: cc.v2(0, 0), + sourcePos: { + default: cc.Vec2.ZERO, + type: cc.Vec2, + formerlySerializedAs: '_sourcePos' + }, /** * !#en Variation of source position. @@ -533,7 +597,11 @@ var properties = { * @property {Vec2} posVar * @default cc.Vec2.ZERO */ - posVar: cc.v2(0, 0), + posVar: { + default: cc.Vec2.ZERO, + type: cc.Vec2, + formerlySerializedAs: '_posVar' + }, /** * !#en Particles movement type. @@ -565,49 +633,77 @@ var properties = { * @property {Vec2} gravity * @default cc.Vec2.ZERO */ - gravity: cc.v2(0, 0), + gravity: { + default: cc.Vec2.ZERO, + type: cc.Vec2, + formerlySerializedAs: '_gravity' + }, /** * !#en Speed of the emitter. * !#zh 速度。 * @property {Number} speed * @default 180 */ - speed: 180, + speed: { + default: 180, + type: cc.Float, + formerlySerializedAs: '_speed' + }, /** * !#en Variation of the speed. * !#zh 速度变化范围。 * @property {Number} speedVar * @default 50 */ - speedVar: 50, + speedVar: { + default: 50, + type: cc.Float, + formerlySerializedAs: '_speedVar' + }, /** * !#en Tangential acceleration of each particle. Only available in 'Gravity' mode. * !#zh 每个粒子的切向加速度,即垂直于重力方向的加速度,只有在重力模式下可用。 * @property {Number} tangentialAccel * @default 80 */ - tangentialAccel: 80, + tangentialAccel: { + default: 80, + type: cc.Float, + formerlySerializedAs: '_tangentialAccel' + }, /** * !#en Variation of the tangential acceleration. * !#zh 每个粒子的切向加速度变化范围。 * @property {Number} tangentialAccelVar * @default 0 */ - tangentialAccelVar: 0, + tangentialAccelVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_tangentialAccelVar' + }, /** * !#en Acceleration of each particle. Only available in 'Gravity' mode. * !#zh 粒子径向加速度,即平行于重力方向的加速度,只有在重力模式下可用。 * @property {Number} radialAccel * @default 0 */ - radialAccel: 0, + radialAccel: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_radialAccel' + }, /** * !#en Variation of the radial acceleration. * !#zh 粒子径向加速度变化范围。 * @property {Number} radialAccelVar * @default 0 */ - radialAccelVar: 0, + radialAccelVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_radialAccelVar' + }, /** * !#en Indicate whether the rotation of each particle equals to its direction. Only available in 'Gravity' mode. @@ -615,7 +711,11 @@ var properties = { * @property {Boolean} rotationIsDir * @default false */ - rotationIsDir: false, + rotationIsDir: { + default: false, + type: cc.Boolean, + formerlySerializedAs: '_rotationIsDir' + }, // RADIUS MODE @@ -625,42 +725,68 @@ var properties = { * @property {Number} startRadius * @default 0 */ - startRadius: 0, + startRadius: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_startRadius' + }, /** * !#en Variation of the starting radius. * !#zh 初始半径变化范围。 * @property {Number} startRadiusVar * @default 0 */ - startRadiusVar: 0, + startRadiusVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_startRadiusVar' + }, /** * !#en Ending radius of the particles. Only available in 'Radius' mode. * !#zh 结束半径,只有在半径模式下可用。 * @property {Number} endRadius * @default 0 */ - endRadius: 0, + endRadius: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_endRadius' + }, /** * !#en Variation of the ending radius. * !#zh 结束半径变化范围。 * @property {Number} endRadiusVar * @default 0 */ - endRadiusVar: 0, + endRadiusVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_endRadiusVar' + }, /** * !#en Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode. * !#zh 粒子每秒围绕起始点的旋转角度,只有在半径模式下可用。 * @property {Number} rotatePerS * @default 0 */ - rotatePerS: 0, + rotatePerS: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_rotatePerS' + }, /** * !#en Variation of the degress to rotate a particle around the source pos per second. * !#zh 粒子每秒围绕起始点的旋转角度变化范围。 * @property {Number} rotatePerSVar * @default 0 */ - rotatePerSVar: 0 + rotatePerSVar: { + default: 0, + type: cc.Float, + formerlySerializedAs: '_rotatePerSVar' + } + + }; /** From 3722a925397faed0060382efdc8ed3f427c8fd12 Mon Sep 17 00:00:00 2001 From: Knox Date: Thu, 21 Feb 2019 17:51:57 +0800 Subject: [PATCH 0466/1631] Improve particle definition data code (#3892) --- cocos2d/particle/CCParticleSystem.js | 32 ---------------------------- 1 file changed, 32 deletions(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index d93f5866fdf..5928f9454fc 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -343,7 +343,6 @@ var properties = { */ totalParticles: { default: 150, - type: cc.Float, formerlySerializedAs: '_totalParticles' }, /** @@ -354,7 +353,6 @@ var properties = { */ duration: { default: -1, - type: cc.Float, formerlySerializedAs: '_duration' }, /** @@ -365,7 +363,6 @@ var properties = { */ emissionRate: { default: 10, - type: cc.Float, formerlySerializedAs: '_emissionRate' }, /** @@ -376,7 +373,6 @@ var properties = { */ life: { default: 1, - type: cc.Float, formerlySerializedAs: '_life' }, /** @@ -387,7 +383,6 @@ var properties = { */ lifeVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_lifeVar' }, @@ -476,7 +471,6 @@ var properties = { */ angle: { default: 90, - type: cc.Float, formerlySerializedAs: '_angle' }, /** @@ -487,7 +481,6 @@ var properties = { */ angleVar: { default: 20, - type: cc.Float, formerlySerializedAs: '_angleVar' }, /** @@ -498,7 +491,6 @@ var properties = { */ startSize: { default: 50, - type: cc.Float, formerlySerializedAs: '_startSize' }, /** @@ -509,7 +501,6 @@ var properties = { */ startSizeVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_startSizeVar' }, /** @@ -520,7 +511,6 @@ var properties = { */ endSize: { default: 0, - type: cc.Float, formerlySerializedAs: '_endSize' }, /** @@ -531,7 +521,6 @@ var properties = { */ endSizeVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_endSizeVar' }, /** @@ -542,7 +531,6 @@ var properties = { */ startSpin: { default: 0, - type: cc.Float, formerlySerializedAs: '_startSpin' }, /** @@ -553,7 +541,6 @@ var properties = { */ startSpinVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_startSpinVar' }, /** @@ -564,7 +551,6 @@ var properties = { */ endSpin: { default: 0, - type: cc.Float, formerlySerializedAs: '_endSpin' }, /** @@ -575,7 +561,6 @@ var properties = { */ endSpinVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_endSpinVar' }, @@ -587,7 +572,6 @@ var properties = { */ sourcePos: { default: cc.Vec2.ZERO, - type: cc.Vec2, formerlySerializedAs: '_sourcePos' }, @@ -599,7 +583,6 @@ var properties = { */ posVar: { default: cc.Vec2.ZERO, - type: cc.Vec2, formerlySerializedAs: '_posVar' }, @@ -635,7 +618,6 @@ var properties = { */ gravity: { default: cc.Vec2.ZERO, - type: cc.Vec2, formerlySerializedAs: '_gravity' }, /** @@ -646,7 +628,6 @@ var properties = { */ speed: { default: 180, - type: cc.Float, formerlySerializedAs: '_speed' }, /** @@ -657,7 +638,6 @@ var properties = { */ speedVar: { default: 50, - type: cc.Float, formerlySerializedAs: '_speedVar' }, /** @@ -668,7 +648,6 @@ var properties = { */ tangentialAccel: { default: 80, - type: cc.Float, formerlySerializedAs: '_tangentialAccel' }, /** @@ -679,7 +658,6 @@ var properties = { */ tangentialAccelVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_tangentialAccelVar' }, /** @@ -690,7 +668,6 @@ var properties = { */ radialAccel: { default: 0, - type: cc.Float, formerlySerializedAs: '_radialAccel' }, /** @@ -701,7 +678,6 @@ var properties = { */ radialAccelVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_radialAccelVar' }, @@ -713,7 +689,6 @@ var properties = { */ rotationIsDir: { default: false, - type: cc.Boolean, formerlySerializedAs: '_rotationIsDir' }, @@ -727,7 +702,6 @@ var properties = { */ startRadius: { default: 0, - type: cc.Float, formerlySerializedAs: '_startRadius' }, /** @@ -738,7 +712,6 @@ var properties = { */ startRadiusVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_startRadiusVar' }, /** @@ -749,7 +722,6 @@ var properties = { */ endRadius: { default: 0, - type: cc.Float, formerlySerializedAs: '_endRadius' }, /** @@ -760,7 +732,6 @@ var properties = { */ endRadiusVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_endRadiusVar' }, /** @@ -771,7 +742,6 @@ var properties = { */ rotatePerS: { default: 0, - type: cc.Float, formerlySerializedAs: '_rotatePerS' }, /** @@ -782,11 +752,9 @@ var properties = { */ rotatePerSVar: { default: 0, - type: cc.Float, formerlySerializedAs: '_rotatePerSVar' } - }; /** From ca3ec6fcb649c68c84853442a4ca995d2bf92c63 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 22 Feb 2019 14:58:05 +0800 Subject: [PATCH 0467/1631] fix event failed to reorder after modifying zIndex for 2d-tasks/issues/1130 (#3895) --- cocos2d/core/CCNode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 06731bdae3d..4f2d7b3b1ea 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1123,7 +1123,7 @@ var Node = cc.Class({ this._localZOrder = (this._localZOrder & 0x0000ffff) | (value << 16); if (this._parent) { - this._parent._delaySort(); + this._onSiblingIndexChanged(); } } } From ec4f4e53f0de7c5e21d7716fa17992c044250e6b Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Sat, 23 Feb 2019 10:02:12 +0800 Subject: [PATCH 0468/1631] fixed node scale issue (#3826) * node._scale default value should be cc.v3(1,1,1) * fixed node.scale.z can not set to zero --- cocos2d/core/3d/polyfill-3d.js | 2 +- cocos2d/core/CCNode.js | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/3d/polyfill-3d.js b/cocos2d/core/3d/polyfill-3d.js index 24fcaa5544e..425c09b468c 100644 --- a/cocos2d/core/3d/polyfill-3d.js +++ b/cocos2d/core/3d/polyfill-3d.js @@ -122,7 +122,7 @@ function setPosition (newPosOrX, y, z) { function setScale (x, y, z) { if (x && typeof x !== 'number') { y = x.y; - z = x.z || 1; + z = x.z === undefined ? 1 : x.z; x = x.x; } else if (x !== undefined && y === undefined) { diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 9abd76b1e88..9386ca127c7 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -552,7 +552,7 @@ let NodeDefines = { _contentSize: cc.Size, _anchorPoint: cc.v2(0.5, 0.5), _position: cc.Vec3, - _scale: cc.Vec3, + _scale: cc.v3(1, 1, 1), _quat: cc.Quat, _skewX: 0.0, _skewY: 0.0, @@ -565,7 +565,6 @@ let NodeDefines = { serializable: false }, - _is3DNode: false, // internal properties @@ -1160,11 +1159,6 @@ let NodeDefines = { // Mouse event listener this._mouseListener = null; - // default scale - this._scale.x = 1; - this._scale.y = 1; - this._scale.z = 1; - this._matrix = mathPools.mat4.get(); this._worldMatrix = mathPools.mat4.get(); this._localMatDirty = LocalDirtyFlag.ALL; From 222166dff1510948b4c44526002b22bcc72abc22 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Sat, 23 Feb 2019 12:49:20 +0800 Subject: [PATCH 0469/1631] Move BlendFunctionFactors to Sprite and ParticleSystem only (#3900) --- cocos2d/core/components/CCRenderComponent.js | 68 ------------------- cocos2d/core/components/CCSprite.js | 70 ++++++++++++++++++++ cocos2d/particle/CCParticleSystem.js | 70 ++++++++++++++++++++ extensions/dragonbones/ArmatureDisplay.js | 39 ----------- extensions/spine/Skeleton.js | 39 ----------- 5 files changed, 140 insertions(+), 146 deletions(-) diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index 6106a3b59d2..65b6e34db6b 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -26,9 +26,7 @@ const Component = require('./CCComponent'); const renderEngine = require('../renderer/render-engine'); const RenderFlow = require('../renderer/render-flow'); -const BlendFactor = require('../platform/CCMacro').BlendFactor; const RenderData = renderEngine.RenderData; -const gfx = renderEngine.gfx; /** * !#en @@ -49,52 +47,6 @@ let RenderComponent = cc.Class({ }, properties: { - _srcBlendFactor: BlendFactor.SRC_ALPHA, - _dstBlendFactor: BlendFactor.ONE_MINUS_SRC_ALPHA, - - /** - * !#en specify the source Blend Factor, this will generate a custom material object, please pay attention to the memory cost. - * !#zh 指定原图的混合模式,这会克隆一个新的材质对象,注意这带来的开销 - * @property srcBlendFactor - * @type {macro.BlendFactor} - * @example - * sprite.srcBlendFactor = cc.macro.BlendFactor.ONE; - */ - srcBlendFactor: { - get: function() { - return this._srcBlendFactor; - }, - set: function(value) { - if (this._srcBlendFactor === value) return; - this._srcBlendFactor = value; - this._updateBlendFunc(true); - }, - animatable: false, - type:BlendFactor, - tooltip: CC_DEV && 'i18n:COMPONENT.sprite.src_blend_factor' - }, - - /** - * !#en specify the destination Blend Factor. - * !#zh 指定目标的混合模式 - * @property dstBlendFactor - * @type {macro.BlendFactor} - * @example - * sprite.dstBlendFactor = cc.macro.BlendFactor.ONE; - */ - dstBlendFactor: { - get: function() { - return this._dstBlendFactor; - }, - set: function(value) { - if (this._dstBlendFactor === value) return; - this._dstBlendFactor = value; - this._updateBlendFunc(true); - }, - animatable: false, - type: BlendFactor, - tooltip: CC_DEV && 'i18n:COMPONENT.sprite.dst_blend_factor' - }, }, ctor () { @@ -199,28 +151,8 @@ let RenderComponent = cc.Class({ _updateMaterial (material) { this._material = material; - - this._updateBlendFunc(); material.updateHash(); }, - - _updateBlendFunc: function (updateHash) { - if (!this._material) { - return; - } - - var pass = this._material._mainTech.passes[0]; - pass.setBlend( - gfx.BLEND_FUNC_ADD, - this._srcBlendFactor, this._dstBlendFactor, - gfx.BLEND_FUNC_ADD, - this._srcBlendFactor, this._dstBlendFactor - ); - - if (updateHash) { - this._material.updateHash(); - } - }, }); RenderComponent._assembler = null; RenderComponent._postAssembler = null; diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index e2e0a9a2be9..4de19b049dd 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -29,9 +29,11 @@ const NodeEvent = require('../CCNode').EventType; const RenderComponent = require('./CCRenderComponent'); const RenderFlow = require('../renderer/render-flow'); const renderEngine = require('../renderer/render-engine'); +const gfx = renderEngine.gfx; const SpriteMaterial = renderEngine.SpriteMaterial; const GraySpriteMaterial = renderEngine.GraySpriteMaterial; const dynamicAtlasManager = require('../renderer/utils/dynamic-atlas/manager'); +const BlendFactor = require('../platform/CCMacro').BlendFactor; /** * !#en Enum for sprite type. @@ -191,6 +193,53 @@ var Sprite = cc.Class({ animatable: false }, + _srcBlendFactor: BlendFactor.SRC_ALPHA, + _dstBlendFactor: BlendFactor.ONE_MINUS_SRC_ALPHA, + + /** + * !#en specify the source Blend Factor, this will generate a custom material object, please pay attention to the memory cost. + * !#zh 指定原图的混合模式,这会克隆一个新的材质对象,注意这带来的开销 + * @property srcBlendFactor + * @type {macro.BlendFactor} + * @example + * sprite.srcBlendFactor = cc.macro.BlendFactor.ONE; + */ + srcBlendFactor: { + get: function() { + return this._srcBlendFactor; + }, + set: function(value) { + if (this._srcBlendFactor === value) return; + this._srcBlendFactor = value; + this._updateBlendFunc(true); + }, + animatable: false, + type:BlendFactor, + tooltip: CC_DEV && 'i18n:COMPONENT.sprite.src_blend_factor' + }, + + /** + * !#en specify the destination Blend Factor. + * !#zh 指定目标的混合模式 + * @property dstBlendFactor + * @type {macro.BlendFactor} + * @example + * sprite.dstBlendFactor = cc.macro.BlendFactor.ONE; + */ + dstBlendFactor: { + get: function() { + return this._dstBlendFactor; + }, + set: function(value) { + if (this._dstBlendFactor === value) return; + this._dstBlendFactor = value; + this._updateBlendFunc(true); + }, + animatable: false, + type: BlendFactor, + tooltip: CC_DEV && 'i18n:COMPONENT.sprite.dst_blend_factor' + }, + /** * !#en The sprite frame of the sprite. * !#zh 精灵的精灵帧 @@ -531,6 +580,27 @@ var Sprite = cc.Class({ } }, + _updateMaterial (material) { + this._material = material; + this._updateBlendFunc(); + material.updateHash(); + }, + + _updateBlendFunc: function (updateHash) { + if (this._material) { + var pass = this._material._mainTech.passes[0]; + pass.setBlend( + gfx.BLEND_FUNC_ADD, + this._srcBlendFactor, this._dstBlendFactor, + gfx.BLEND_FUNC_ADD, + this._srcBlendFactor, this._dstBlendFactor + ); + if (updateHash) { + this._material.updateHash(); + } + } + }, + _applyAtlas: CC_EDITOR && function (spriteFrame) { // Set atlas if (spriteFrame && spriteFrame._atlasUuid) { diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 5928f9454fc..a1baeeaf18b 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -34,6 +34,8 @@ const textureUtil = require('../core/utils/texture-util'); const renderEngine = require('../core/renderer/render-engine'); const RenderFlow = require('../core/renderer/render-flow'); const ParticleSimulator = require('./particle-simulator'); +const gfx = renderEngine.gfx; +const BlendFactor = macro.BlendFactor; function getImageFormatByData (imgData) { // if it is a png file buffer. @@ -274,6 +276,53 @@ var properties = { animatable: false }, + _srcBlendFactor: BlendFactor.SRC_ALPHA, + _dstBlendFactor: BlendFactor.ONE_MINUS_SRC_ALPHA, + + /** + * !#en specify the source Blend Factor, this will generate a custom material object, please pay attention to the memory cost. + * !#zh 指定原图的混合模式,这会克隆一个新的材质对象,注意这带来的开销 + * @property srcBlendFactor + * @type {macro.BlendFactor} + * @example + * sprite.srcBlendFactor = cc.macro.BlendFactor.ONE; + */ + srcBlendFactor: { + get: function() { + return this._srcBlendFactor; + }, + set: function(value) { + if (this._srcBlendFactor === value) return; + this._srcBlendFactor = value; + this._updateBlendFunc(true); + }, + animatable: false, + type:BlendFactor, + tooltip: CC_DEV && 'i18n:COMPONENT.sprite.src_blend_factor' + }, + + /** + * !#en specify the destination Blend Factor. + * !#zh 指定目标的混合模式 + * @property dstBlendFactor + * @type {macro.BlendFactor} + * @example + * sprite.dstBlendFactor = cc.macro.BlendFactor.ONE; + */ + dstBlendFactor: { + get: function() { + return this._dstBlendFactor; + }, + set: function(value) { + if (this._dstBlendFactor === value) return; + this._dstBlendFactor = value; + this._updateBlendFunc(true); + }, + animatable: false, + type: BlendFactor, + tooltip: CC_DEV && 'i18n:COMPONENT.sprite.dst_blend_factor' + }, + /** * !#en Current quantity of particles that are being simulated. * !#zh 当前播放的粒子数量。 @@ -1281,6 +1330,27 @@ var ParticleSystem = cc.Class({ } }, + _updateMaterial (material) { + this._material = material; + this._updateBlendFunc(); + material.updateHash(); + }, + + _updateBlendFunc: function (updateHash) { + if (this._material) { + var pass = this._material._mainTech.passes[0]; + pass.setBlend( + gfx.BLEND_FUNC_ADD, + this._srcBlendFactor, this._dstBlendFactor, + gfx.BLEND_FUNC_ADD, + this._srcBlendFactor, this._dstBlendFactor + ); + if (updateHash) { + this._material.updateHash(); + } + } + }, + _activateMaterial: function () { if (!this._material) { this._material = new renderEngine.SpriteMaterial(); diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index df303ddb5ba..63366b26098 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -31,7 +31,6 @@ let EventTarget = require('../../cocos2d/core/event/event-target'); const Node = require('../../cocos2d/core/CCNode'); const Graphics = require('../../cocos2d/core/graphics/graphics'); -const BlendFactor = require('../../cocos2d/core/platform/CCMacro').BlendFactor; let ArmatureCache = require('./ArmatureCache'); @@ -114,44 +113,6 @@ let ArmatureDisplay = cc.Class({ serializable: false, }, - /** - * !#en don't try to get or set srcBlendFactor,it doesn't affect,if you want to change dragonbones blend mode,please set it in dragonbones editor directly. - * !#zh 不要试图去获取或者设置 srcBlendFactor,没有意义,如果你想设置 dragonbones 的 blendMode,直接在 dragonbones 编辑器中设置即可。 - * @property srcBlendFactor - * @type {macro.BlendFactor} - */ - srcBlendFactor: { - get: function() { - return this._srcBlendFactor; - }, - set: function(value) { - // shield set _srcBlendFactor - }, - animatable: false, - type:BlendFactor, - override: true, - visible: false - }, - - /** - * !#en don't try to get or set dstBlendFactor,it doesn't affect,if you want to change dragonbones blend mode,please set it in dragonbones editor directly. - * !#zh 不要试图去获取或者设置 dstBlendFactor,没有意义,如果想设置 dragonbones 的 blendMode,直接在 dragonbones 编辑器中设置即可。 - * @property dstBlendFactor - * @type {macro.BlendFactor} - */ - dstBlendFactor: { - get: function() { - return this._dstBlendFactor; - }, - set: function(value) { - // shield set _dstBlendFactor - }, - animatable: false, - type: BlendFactor, - override: true, - visible: false - }, - /** * !#en * The DragonBones data contains the armatures information (bind pose bones, slots, draw order, diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index eafa9475327..31e8db7ba4e 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -29,7 +29,6 @@ const RenderComponent = require('../../cocos2d/core/components/CCRenderComponent const spine = require('./lib/spine'); const SpineMaterial = require('../../cocos2d/core/renderer/render-engine').SpineMaterial; const Graphics = require('../../cocos2d/core/graphics/graphics'); -const BlendFactor = require('../../cocos2d/core/platform/CCMacro').BlendFactor; let SkeletonCache = require('./skeleton-cache'); @@ -116,44 +115,6 @@ sp.Skeleton = cc.Class({ visible: false }, - /** - * !#en don't try to get or set srcBlendFactor,it doesn't affect,if you want to change spine blend mode,please set it in spine editor directly. - * !#zh 不要试图去获取或者设置 srcBlendFactor,没有意义,如果你想设置 spine 的 blendMode,直接在 spine 编辑器中设置即可。 - * @property srcBlendFactor - * @type {macro.BlendFactor} - */ - srcBlendFactor: { - get: function() { - return this._srcBlendFactor; - }, - set: function(value) { - // shield set _srcBlendFactor - }, - animatable: false, - type:BlendFactor, - override: true, - visible: false - }, - - /** - * !#en don't try to get or set dstBlendFactor,it doesn't affect,if you want to change spine blend mode,please set it in spine editor directly. - * !#zh 不要试图去获取或者设置 dstBlendFactor,没有意义,如果想设置 spine 的 blendMode,直接在 spine 编辑器中设置即可。 - * @property dstBlendFactor - * @type {macro.BlendFactor} - */ - dstBlendFactor: { - get: function() { - return this._dstBlendFactor; - }, - set: function(value) { - // shield set _dstBlendFactor - }, - animatable: false, - type: BlendFactor, - override: true, - visible: false - }, - /** * !#en * The skeleton data contains the skeleton information (bind pose bones, slots, draw order, From eb4229bb5fe2de3e73e5bf8c9325c8e4c2e9f394 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Sat, 23 Feb 2019 13:01:54 +0800 Subject: [PATCH 0470/1631] change API:loadSubpackage to load index.js (#3899) --- cocos2d/core/load-pipeline/downloader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index ca34ae88309..d95f5cc4d26 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -302,7 +302,7 @@ Downloader.prototype.loadSubpackage = function (name, completeCallback) { if (completeCallback) completeCallback(); } else { - downloadScript({url: pac.path + 'game.js'}, function (err) { + downloadScript({url: pac.path + 'index.js'}, function (err) { if (!err) { pac.loaded = true; } From 44c53282bbc48ebc2954950a20cbbed71fcfba33 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 25 Feb 2019 12:42:30 +0800 Subject: [PATCH 0471/1631] extract shader extensions to first line (#3858) * extract shader extensions to first line * default declare highp precision in effect * refine code * refine uniform color precision definition --- cocos2d/renderer/build/chunks/alpha-test.inc | 1 + cocos2d/renderer/build/chunks/cc-global.inc | 2 + cocos2d/renderer/build/chunks/cc-local.inc | 1 + .../build/chunks/common-attribute.inc | 1 + cocos2d/renderer/build/chunks/diffuse.inc | 3 +- cocos2d/renderer/build/chunks/emissive.inc | 3 +- .../renderer/build/chunks/lights-phong.inc | 1 + cocos2d/renderer/build/chunks/normal.inc | 7 ++- .../renderer/build/chunks/shader/phong-fs.inc | 5 +-- .../renderer/build/chunks/shader/phong-vs.inc | 3 ++ .../build/chunks/shader/shadow-depth-fs.inc | 2 + .../build/chunks/shader/shadow-depth-vs.inc | 2 + .../renderer/build/chunks/shader/unlit-fs.inc | 2 + .../renderer/build/chunks/shader/unlit-vs.inc | 2 + cocos2d/renderer/build/chunks/specular.inc | 3 +- cocos2d/renderer/build/shdc-lib.js | 44 ++++++++++++++----- cocos2d/renderer/core/base-renderer.js | 2 +- cocos2d/renderer/core/program-lib.js | 19 +++----- 18 files changed, 69 insertions(+), 34 deletions(-) diff --git a/cocos2d/renderer/build/chunks/alpha-test.inc b/cocos2d/renderer/build/chunks/alpha-test.inc index 4956eb182df..ba47c0cf049 100644 --- a/cocos2d/renderer/build/chunks/alpha-test.inc +++ b/cocos2d/renderer/build/chunks/alpha-test.inc @@ -1,3 +1,4 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. #if USE_ALPHA_TEST uniform float alphaThreshold; diff --git a/cocos2d/renderer/build/chunks/cc-global.inc b/cocos2d/renderer/build/chunks/cc-global.inc index ca6d0356669..fa76b9adcfb 100644 --- a/cocos2d/renderer/build/chunks/cc-global.inc +++ b/cocos2d/renderer/build/chunks/cc-global.inc @@ -1,3 +1,5 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + // transforms // uniform mat4 cc_matProj; // uniform mat4 cc_matProjInv; diff --git a/cocos2d/renderer/build/chunks/cc-local.inc b/cocos2d/renderer/build/chunks/cc-local.inc index 9f00ac83ebb..367c45c92da 100644 --- a/cocos2d/renderer/build/chunks/cc-local.inc +++ b/cocos2d/renderer/build/chunks/cc-local.inc @@ -1,3 +1,4 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. // transforms uniform mat4 cc_matWorld; diff --git a/cocos2d/renderer/build/chunks/common-attribute.inc b/cocos2d/renderer/build/chunks/common-attribute.inc index c949e3bc30f..83ee140514e 100644 --- a/cocos2d/renderer/build/chunks/common-attribute.inc +++ b/cocos2d/renderer/build/chunks/common-attribute.inc @@ -1,3 +1,4 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. #ifndef USE_DIFFUSE_TEXTURE #ifndef USE_EMISSIVE_TEXTURE diff --git a/cocos2d/renderer/build/chunks/diffuse.inc b/cocos2d/renderer/build/chunks/diffuse.inc index 4a6c1ddbeef..c7a2e1bd25c 100644 --- a/cocos2d/renderer/build/chunks/diffuse.inc +++ b/cocos2d/renderer/build/chunks/diffuse.inc @@ -1,6 +1,7 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. #property #color4 -uniform vec4 diffuseColor; +uniform lowp vec4 diffuseColor; #if USE_DIFFUSE_TEXTURE #property diff --git a/cocos2d/renderer/build/chunks/emissive.inc b/cocos2d/renderer/build/chunks/emissive.inc index b3c19b79f7a..9f7edd4a07b 100644 --- a/cocos2d/renderer/build/chunks/emissive.inc +++ b/cocos2d/renderer/build/chunks/emissive.inc @@ -1,7 +1,8 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. #if USE_EMISSIVE #property #color3 - uniform vec3 emissiveColor; + uniform lowp vec3 emissiveColor; #if USE_EMISSIVE_TEXTURE #property diff --git a/cocos2d/renderer/build/chunks/lights-phong.inc b/cocos2d/renderer/build/chunks/lights-phong.inc index 4e2c9140cbf..e615222ef63 100644 --- a/cocos2d/renderer/build/chunks/lights-phong.inc +++ b/cocos2d/renderer/build/chunks/lights-phong.inc @@ -1,3 +1,4 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. #include diff --git a/cocos2d/renderer/build/chunks/normal.inc b/cocos2d/renderer/build/chunks/normal.inc index bceea3d454c..d44b1422d76 100644 --- a/cocos2d/renderer/build/chunks/normal.inc +++ b/cocos2d/renderer/build/chunks/normal.inc @@ -1,5 +1,8 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +#if USE_NORMAL_TEXTURE && GL_OES_standard_derivatives + #extension GL_OES_standard_derivatives : enable -#if USE_NORMAL_TEXTURE #property uniform sampler2D normalTexture; @@ -21,7 +24,7 @@ void CALC_NORMAL (inout vec3 normal, in vec3 worldPos, in vec3 worldNormal) { normal = normalize(worldNormal); - #if USE_NORMAL_TEXTURE + #if USE_NORMAL_TEXTURE && GL_OES_standard_derivatives normal = getNormal(worldPos, normal); #endif } diff --git a/cocos2d/renderer/build/chunks/shader/phong-fs.inc b/cocos2d/renderer/build/chunks/shader/phong-fs.inc index 75f59e4145a..f4b41cf0e45 100644 --- a/cocos2d/renderer/build/chunks/shader/phong-fs.inc +++ b/cocos2d/renderer/build/chunks/shader/phong-fs.inc @@ -1,7 +1,6 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -#if USE_NORMAL_TEXTURE -#extension GL_OES_standard_derivatives : enable -#endif +precision highp float; #include #include diff --git a/cocos2d/renderer/build/chunks/shader/phong-vs.inc b/cocos2d/renderer/build/chunks/shader/phong-vs.inc index db47f924065..f0425ceed3c 100644 --- a/cocos2d/renderer/build/chunks/shader/phong-vs.inc +++ b/cocos2d/renderer/build/chunks/shader/phong-vs.inc @@ -1,3 +1,6 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + +precision highp float; #include #include diff --git a/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc b/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc index 1ae0f04f8ed..ad0c1e0adc7 100644 --- a/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc +++ b/cocos2d/renderer/build/chunks/shader/shadow-depth-fs.inc @@ -1,5 +1,7 @@ // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +precision highp float; + uniform float cc_depthScale; varying float vDepth; diff --git a/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc b/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc index 2776674fbeb..3b7c4bae328 100644 --- a/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc +++ b/cocos2d/renderer/build/chunks/shader/shadow-depth-vs.inc @@ -1,5 +1,7 @@ // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +precision highp float; + attribute vec3 a_position; uniform mat4 cc_matWorld; diff --git a/cocos2d/renderer/build/chunks/shader/unlit-fs.inc b/cocos2d/renderer/build/chunks/shader/unlit-fs.inc index ff9f864a9cf..a94bc062db7 100644 --- a/cocos2d/renderer/build/chunks/shader/unlit-fs.inc +++ b/cocos2d/renderer/build/chunks/shader/unlit-fs.inc @@ -1,5 +1,7 @@ // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +precision highp float; + #include #include #include diff --git a/cocos2d/renderer/build/chunks/shader/unlit-vs.inc b/cocos2d/renderer/build/chunks/shader/unlit-vs.inc index 65dab7aa4cd..8a1d298351f 100644 --- a/cocos2d/renderer/build/chunks/shader/unlit-vs.inc +++ b/cocos2d/renderer/build/chunks/shader/unlit-vs.inc @@ -1,5 +1,7 @@ // Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +precision highp float; + #include #include diff --git a/cocos2d/renderer/build/chunks/specular.inc b/cocos2d/renderer/build/chunks/specular.inc index 94056b156fa..b0f24f1dcca 100644 --- a/cocos2d/renderer/build/chunks/specular.inc +++ b/cocos2d/renderer/build/chunks/specular.inc @@ -1,7 +1,8 @@ +// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. #if USE_SPECULAR #property #color3 - uniform vec3 specularColor; + uniform lowp vec3 specularColor; #if USE_SPECULAR_TEXTURE #property diff --git a/cocos2d/renderer/build/shdc-lib.js b/cocos2d/renderer/build/shdc-lib.js index 9df850eceb9..3b2ef54f385 100644 --- a/cocos2d/renderer/build/shdc-lib.js +++ b/cocos2d/renderer/build/shdc-lib.js @@ -22,7 +22,8 @@ let builtins = /^(_|cc_)\w+$/; const vertHeader = '#define _IS_VERT_SHADER 1\n'; const fragHeader = '#define _IS_FRAG_SHADER 1\n'; -let ignoreDefines = {}; +// if #define a value, then program should not redefine this value +let definesInShader = {}; function convertType(t) { let tp = mappings.typeParams[t.toUpperCase()]; return tp === undefined ? t : tp; } @@ -38,14 +39,15 @@ function unwindIncludes(str, chunks) { } function glslStrip(code, cache) { - // strip tag lines + // strip tag and extension lines let result = ''; let codes = code.split('\n'); - for (let i = 1; i <= codes.length; i++) { - if (cache.tagLines.indexOf(i) === -1) { - result += codes[i-1] + '\n'; + for (let i = 0; i < codes.length; i++) { + if (cache.tagLines.indexOf(i+1) === -1) { + result += codes[i] + '\n'; } } + // strip comment let tokens = tokenizer(result); @@ -63,6 +65,24 @@ function glslStrip(code, cache) { return result; } +function glslExtractExtensions (code) { + let extensions = []; + let result = ''; + let codes = code.split('\n'); + for (let i = 0; i < codes.length; i++) { + if (codes[i].indexOf('#extension') === -1) { + result += codes[i] + '\n'; + } + else { + extensions.push(codes[i]); + } + } + + result = extensions.join('\n') + '\n' + result; + + return result; +} + /** * say we are parsing this program: * ``` @@ -99,7 +119,7 @@ function extractDefines(tokens, defines, cache) { for (let i = 0; i < tokens.length; ) { let t = tokens[i], str = t.data, id, df; if (str.startsWith('#define')) { - ignoreDefines[str.split(whitespaces)[1]] = true; + definesInShader[str.split(whitespaces)[1]] = true; i++; continue; } if (t.type !== 'preprocessor' || str.startsWith('#extension')) { i++; continue; } @@ -134,7 +154,7 @@ function extractDefines(tokens, defines, cache) { str.splice(1).some(s => { id = s.match(ident); if (id) { // is identifier - if (ignoreDefines[id[0]]) return; + if (definesInShader[id[0]] || id[0].startsWith('GL_')) return; let d = curDefs.reduce((acc, val) => acc.concat(val), defs.slice()); df = defines.find(d => d.name === id[0]); if (df) { if (d.length < df.defines.length) df.defines = d; } @@ -161,10 +181,8 @@ function extractParams(tokens, cache, uniforms, attributes, extensions) { let defines = getDefs(t.line), param = {}; if (dest === uniforms && builtins.test(tokens[i+4].data)) continue; if (dest === extensions) { - if (defines.length !== 1) console.warn('extensions must be under controll of exactly 1 define'); - param.name = extensionRE.exec(str.split(whitespaces)[1])[1]; - param.define = defines[0]; - dest.push(param); + let name = extensionRE.exec(str.split(whitespaces)[1])[1]; + if (dest.indexOf(name) === -1) dest.push(name); continue; } else { // uniforms and attributes let offset = precision.exec(tokens[i+2].data) ? 4 : 2; @@ -319,6 +337,7 @@ let buildShader = function(vertName, fragName, cache) { vert = wrapEntry(vert, vertName, vEntry, ast, true); } catch (e) { Editor.error(`parse ${vertName} failed: ${e}`); } vert = glslStrip(vert, defCache); + vert = glslExtractExtensions(vert); defCache = { lines: [], tagLines: [] }; frag = fragHeader + frag; @@ -332,6 +351,7 @@ let buildShader = function(vertName, fragName, cache) { frag = wrapEntry(frag, fragName, fEntry, ast); } catch (e) { Editor.error(`parse ${fragName} failed: ${e}`); } frag = glslStrip(frag, defCache); + frag = glslExtractExtensions(frag); return { vert, frag, defines, uniforms, attributes, extensions }; }; @@ -432,7 +452,7 @@ let addChunksCache = function(chunksDir) { }; let buildEffect = function (name, content) { - ignoreDefines = {}; + definesInShader = {}; let { effect, templates } = parseEffect(content); effect = buildEffectJSON(effect); effect.name = name; Object.assign(templates, chunksCache); diff --git a/cocos2d/renderer/core/base-renderer.js b/cocos2d/renderer/core/base-renderer.js index be4a249bf7c..75f276605a1 100644 --- a/cocos2d/renderer/core/base-renderer.js +++ b/cocos2d/renderer/core/base-renderer.js @@ -574,7 +574,7 @@ export default class Base { device.setPrimitiveType(ia._primitiveType); // set program - let program = programLib.getProgram(pass._programName, defines, null, effect._name); + let program = programLib.getProgram(pass._programName, defines, effect._name); device.setProgram(program); // cull mode diff --git a/cocos2d/renderer/core/program-lib.js b/cocos2d/renderer/core/program-lib.js index 2fecddebc4c..334e8ff139f 100644 --- a/cocos2d/renderer/core/program-lib.js +++ b/cocos2d/renderer/core/program-lib.js @@ -4,15 +4,13 @@ import gfx from '../gfx'; let _shdID = 0; -function _generateDefines(device, defs, deps) { +function _generateDefines(defs) { let defines = []; for (let def in defs) { let result = defs[def] ? 1 : 0; - // fallback if extension dependency not supported - if (deps && deps[def] && !device.ext(deps[def])) result = 0; defines.push(`#define ${def} ${result}`); } - return defines.join('\n'); + return defines.join('\n') + '\n'; } function _replaceMacroNums(string, defs) { @@ -55,7 +53,6 @@ export default class ProgramLib { */ constructor(device, templates = [], chunks = {}) { this._device = device; - this._precision = `precision highp float;\n`; // register templates this._templates = {}; @@ -88,12 +85,12 @@ export default class ProgramLib { * ], * attributes: [{ name: 'a_position', type: 'vec3' }], * uniforms: [{ name: 'color', type: 'vec4' }], - * extensions: [{ name: 'GL_OES_standard_derivatives', defines: ['USE_NORMAL_TEXTURE'] }], + * extensions: ['GL_OES_standard_derivatives'], * }; * programLib.define(program); */ define(prog) { - let name = prog.name, vert = prog.vert, frag = prog.frag, defines = prog.defines; + let { name, vert, frag, defines, extensions } = prog; if (this._templates[name]) { console.warn(`Failed to define shader ${name}: already exists.`); return; @@ -129,9 +126,6 @@ export default class ProgramLib { def._offset = offset; } - vert = this._precision + vert; - frag = this._precision + frag; - // store it this._templates[name] = { id, @@ -181,10 +175,9 @@ export default class ProgramLib { /** * @param {string} name * @param {Object} defines - * @param {Object} extensions * @param {String} errPrefix */ - getProgram(name, defines, extensions, errPrefix) { + getProgram(name, defines, errPrefix) { let key = this.getKey(name, defines); let program = this._cache[key]; if (program) { @@ -193,7 +186,7 @@ export default class ProgramLib { // get template let tmpl = this._templates[name]; - let customDef = _generateDefines(this._device, defines, extensions) + '\n'; + let customDef = _generateDefines(defines); let vert = _replaceMacroNums(tmpl.vert, defines); vert = customDef + _unrollLoops(vert); let frag = _replaceMacroNums(tmpl.frag, defines); From 323ac9cee260a1647ba53ea11d1683e4594fa5da Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Mon, 25 Feb 2019 12:50:47 +0800 Subject: [PATCH 0472/1631] mark component.enabled as animatable (#3898) --- cocos2d/core/components/CCComponent.js | 3 ++- cocos2d/core/platform/CCClass.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/components/CCComponent.js b/cocos2d/core/components/CCComponent.js index 2496ecb5593..135e208d3b8 100644 --- a/cocos2d/core/components/CCComponent.js +++ b/cocos2d/core/components/CCComponent.js @@ -176,7 +176,8 @@ var Component = cc.Class({ } } }, - visible: false + visible: false, + animatable: true }, /** diff --git a/cocos2d/core/platform/CCClass.js b/cocos2d/core/platform/CCClass.js index cec4acf62be..f5063e75505 100644 --- a/cocos2d/core/platform/CCClass.js +++ b/cocos2d/core/platform/CCClass.js @@ -1189,8 +1189,8 @@ function parseAttributes (cls, attrs, className, propName, usedInGetter) { if (CC_EDITOR) { parseSimpleAttr('notifyFor', 'string'); - if ('animatable' in attrs && !attrs.animatable) { - (attrsProto || getAttrsProto())[attrsProtoKey + 'animatable'] = false; + if ('animatable' in attrs) { + (attrsProto || getAttrsProto())[attrsProtoKey + 'animatable'] = !!attrs.animatable; } } From 51a036a80afd3cb7f950ff668a528e194dc92d8c Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 25 Feb 2019 13:10:55 +0800 Subject: [PATCH 0473/1631] ban JIT support on baidugame (#3903) --- gulp/util/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gulp/util/utils.js b/gulp/util/utils.js index ad6dcc7f403..d308cd44984 100644 --- a/gulp/util/utils.js +++ b/gulp/util/utils.js @@ -1,6 +1,6 @@ const PLATFORM_MACROS = ['CC_EDITOR', 'CC_PREVIEW', 'CC_BUILD', 'CC_TEST']; -const FLAGS = ['jsb', 'runtime', 'wechatgame', 'wechatgameSub','baidugame', 'baidugameSub', 'qqplay', 'debug', 'nativeRenderer']; +const FLAGS = ['jsb', 'runtime', 'wechatgame', 'wechatgameSub','baidugame', 'qqplay', 'debug', 'nativeRenderer']; // generate macros for uglify's global_defs // available platforms: 'editor' | 'preview' | 'build' | 'test' @@ -36,7 +36,7 @@ exports.getMacros = function (platform, flags) { // debug macros res['CC_DEV'] = res['CC_EDITOR'] || res['CC_PREVIEW'] || res['CC_TEST']; res['CC_DEBUG'] = res['CC_DEBUG'] || res['CC_DEV']; - res['CC_SUPPORT_JIT'] = !(res['CC_WECHATGAME'] || res['CC_QQPLAY'] || res['CC_RUNTIME']); + res['CC_SUPPORT_JIT'] = !(res['CC_BAIDUGAME'] || res['CC_WECHATGAME'] || res['CC_QQPLAY'] || res['CC_RUNTIME']); return res; }; From cdc1f80528a8d34e590a664fec880dff504eba9e Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 25 Feb 2019 20:22:14 +0800 Subject: [PATCH 0474/1631] Support custom data format for mesh and skeleton animation clip (#3850) * update * optimize skeleton animation * refine code * remove unused code * support import custom mesh/skeleton data * add RTSAnimCurve * remove RTSAnimCurve * refine code * fixed test * refine creating animation-curve * refine code * refine code --- cocos2d/animation/animation-animator.js | 214 ++++++------- cocos2d/animation/animation-curves.js | 79 ++--- cocos2d/animation/motion-path-helper.js | 41 ++- cocos2d/core/3d/CCModel.js | 336 --------------------- cocos2d/core/3d/CCModelMeshResource.js | 80 ----- cocos2d/core/3d/CCSkeleton.js | 83 +++-- cocos2d/core/3d/CCSkeletonAnimation.js | 15 +- cocos2d/core/3d/CCSkeletonAnimationClip.js | 98 +++--- cocos2d/core/3d/index.js | 1 - cocos2d/core/assets/CCBufferAsset.js | 3 + cocos2d/core/mesh/CCMesh.js | 65 +++- cocos2d/core/mesh/CCMeshRenderer.js | 4 - cocos2d/core/mesh/CCMeshResource.js | 34 --- cocos2d/core/mesh/mesh-data.js | 126 ++++++++ test/qunit/unit-es5/test-animation.js | 56 +--- 15 files changed, 467 insertions(+), 768 deletions(-) delete mode 100644 cocos2d/core/3d/CCModelMeshResource.js delete mode 100644 cocos2d/core/mesh/CCMeshResource.js create mode 100644 cocos2d/core/mesh/mesh-data.js diff --git a/cocos2d/animation/animation-animator.js b/cocos2d/animation/animation-animator.js index 77ebe24d837..15f3c8a9a82 100644 --- a/cocos2d/animation/animation-animator.js +++ b/cocos2d/animation/animation-animator.js @@ -23,15 +23,12 @@ THE SOFTWARE. ****************************************************************************/ -var js = cc.js; -var Playable = require('./playable'); -var DynamicAnimCurve = require('./animation-curves').DynamicAnimCurve; -var quickFindIndex = require('./animation-curves').quickFindIndex; -var sampleMotionPaths = require('./motion-path-helper').sampleMotionPaths; -var EventAnimCurve = require('./animation-curves').EventAnimCurve; -var EventInfo = require('./animation-curves').EventInfo; -var WrapModeMask = require('./types').WrapModeMask; -var binarySearch = require('../core/utils/binary-search').binarySearchEpsilon; +const js = cc.js; +const Playable = require('./playable'); +const { DynamicAnimCurve, EventAnimCurve, EventInfo, quickFindIndex } = require('./animation-curves'); +const sampleMotionPaths = require('./motion-path-helper').sampleMotionPaths; +const WrapModeMask = require('./types').WrapModeMask; +const binarySearch = require('../core/utils/binary-search').binarySearchEpsilon; // The actual animator for Animation Component @@ -43,7 +40,7 @@ function AnimationAnimator (target, animation) { this._anims = new js.array.MutableForwardIterator([]); } js.extend(AnimationAnimator, Playable); -var p = AnimationAnimator.prototype; +let p = AnimationAnimator.prototype; p.playState = function (state, startTime) { if (!state.clip) { @@ -65,10 +62,10 @@ p.playState = function (state, startTime) { }; p.stopStatesExcept = function (state) { - var iterator = this._anims; - var array = iterator.array; + let iterator = this._anims; + let array = iterator.array; for (iterator.i = 0; iterator.i < array.length; ++iterator.i) { - var anim = array[iterator.i]; + let anim = array[iterator.i]; if (anim === state) { continue; } @@ -78,7 +75,7 @@ p.stopStatesExcept = function (state) { }; p.addAnimation = function (anim) { - var index = this._anims.array.indexOf(anim); + let index = this._anims.array.indexOf(anim); if (index === -1) { this._anims.push(anim); } @@ -87,7 +84,7 @@ p.addAnimation = function (anim) { }; p.removeAnimation = function (anim) { - var index = this._anims.array.indexOf(anim); + let index = this._anims.array.indexOf(anim); if (index >= 0) { this._anims.fastRemoveAt(index); @@ -103,10 +100,10 @@ p.removeAnimation = function (anim) { }; p.sample = function () { - var iterator = this._anims; - var array = iterator.array; + let iterator = this._anims; + let array = iterator.array; for (iterator.i = 0; iterator.i < array.length; ++iterator.i) { - var anim = array[iterator.i]; + let anim = array[iterator.i]; anim.sample(); } }; @@ -143,9 +140,9 @@ p.setStateTime = function (state, time) { else { time = state; - var array = this._anims.array; - for (var i = 0; i < array.length; ++i) { - var anim = array[i]; + let array = this._anims.array; + for (let i = 0; i < array.length; ++i) { + let anim = array[i]; anim.setTime(time); anim.sample(); } @@ -153,18 +150,18 @@ p.setStateTime = function (state, time) { }; p.onStop = function () { - var iterator = this._anims; - var array = iterator.array; + let iterator = this._anims; + let array = iterator.array; for (iterator.i = 0; iterator.i < array.length; ++iterator.i) { - var anim = array[iterator.i]; + let anim = array[iterator.i]; anim.stop(); } }; p.onPause = function () { - var array = this._anims.array; - for (var i = 0; i < array.length; ++i) { - var anim = array[i]; + let array = this._anims.array; + for (let i = 0; i < array.length; ++i) { + let anim = array[i]; anim.pause(); // need to unbind animator to anim, or it maybe cannot be gc. @@ -173,9 +170,9 @@ p.onPause = function () { }; p.onResume = function () { - var array = this._anims.array; - for (var i = 0; i < array.length; ++i) { - var anim = array[i]; + let array = this._anims.array; + for (let i = 0; i < array.length; ++i) { + let anim = array[i]; // rebind animator to anim anim.animator = this; @@ -191,18 +188,18 @@ p._reloadClip = function (state) { // 这个方法应该是 SampledAnimCurve 才能用 function createBatchedProperty (propPath, firstDotIndex, mainValue, animValue) { mainValue = mainValue.clone(); - var nextValue = mainValue; - var leftIndex = firstDotIndex + 1; - var rightIndex = propPath.indexOf('.', leftIndex); + let nextValue = mainValue; + let leftIndex = firstDotIndex + 1; + let rightIndex = propPath.indexOf('.', leftIndex); // scan property path while (rightIndex !== -1) { - var nextName = propPath.slice(leftIndex, rightIndex); + let nextName = propPath.slice(leftIndex, rightIndex); nextValue = nextValue[nextName]; leftIndex = rightIndex + 1; rightIndex = propPath.indexOf('.', leftIndex); } - var lastPropName = propPath.slice(leftIndex); + let lastPropName = propPath.slice(leftIndex); nextValue[lastPropName] = animValue; return mainValue; @@ -212,18 +209,11 @@ if (CC_TEST) { cc._Test.createBatchedProperty = createBatchedProperty; } -function splitPropPath (propPath) { - var array = propPath.split('.'); - array.shift(); - //array = array.filter(function (item) { return !!item; }); - return array.length > 0 ? array : null; -} - function initClipData (root, state) { - var clip = state.clip; + let clip = state.clip; - var curves = state.curves; + let curves = state.curves; curves.length = 0; state.duration = Number.parseFloat(clip.duration); @@ -240,73 +230,30 @@ function initClipData (root, state) { // create curves - function checkMotionPath(motionPath) { - if (!Array.isArray(motionPath)) return false; - - for (let i = 0, l = motionPath.length; i < l; i++) { - var controls = motionPath[i]; - - if (!Array.isArray(controls) || controls.length !== 6) return false; - } - - return true; - } - function createPropCurve (target, propPath, keyframes) { - var isMotionPathProp = (target instanceof cc.Node) - && (propPath === 'position') - && (keyframes[0] && Array.isArray(keyframes[0].value)); - var motionPaths = []; - - var curve = new DynamicAnimCurve(); + let motionPaths = []; + let isMotionPathProp = target instanceof cc.Node && propPath === 'position'; + + let curve = new DynamicAnimCurve(); // 缓存目标对象,所以 Component 必须一开始都创建好并且不能运行时动态替换…… curve.target = target; - - var propName, propValue; - var dotIndex = propPath.indexOf('.'); - var hasSubProp = dotIndex !== -1; - if (hasSubProp) { - propName = propPath.slice(0, dotIndex); - propValue = target[propName]; - - // if (!(propValue instanceof cc.ValueType)) { - // cc.error('Only support sub animation property which is type cc.ValueType'); - // continue; - // } - } - else { - propName = propPath; - } - - curve.prop = propName; - - curve.subProps = splitPropPath(propPath); + curve.prop = propPath; // for each keyframes for (let i = 0, l = keyframes.length; i < l; i++) { - var keyframe = keyframes[i]; - var ratio = keyframe.frame / state.duration; + let keyframe = keyframes[i]; + let ratio = keyframe.frame / state.duration; curve.ratios.push(ratio); if (isMotionPathProp) { - var motionPath = keyframe.motionPath; - - if (motionPath && !checkMotionPath(motionPath)) { - cc.errorID(3904, target.name, propPath, i); - motionPath = null; - } - - motionPaths.push(motionPath); + motionPaths.push(keyframe.motionPath); } - var curveValue = keyframe.value; - //if (hasSubProp) { - // curveValue = createBatchedProperty(propPath, dotIndex, propValue, curveValue); - //} + let curveValue = keyframe.value; curve.values.push(curveValue); - var curveTypes = keyframe.curve; + let curveTypes = keyframe.curve; if (curveTypes) { if (typeof curveTypes === 'string') { curve.types.push(curveTypes); @@ -325,16 +272,16 @@ function initClipData (root, state) { } curve.types.push(DynamicAnimCurve.Linear); } - + if (isMotionPathProp) { - sampleMotionPaths(motionPaths, curve, clip.duration, clip.sample); + sampleMotionPaths(motionPaths, curve, clip.duration, clip.sample, target); } // if every piece of ratios are the same, we can use the quick function to find frame index. - var ratios = curve.ratios; - var currRatioDif, lastRatioDif; - var canOptimize = true; - var EPSILON = 1e-6; + let ratios = curve.ratios; + let currRatioDif, lastRatioDif; + let canOptimize = true; + let EPSILON = 1e-6; for (let i = 1, l = ratios.length; i < l; i++) { currRatioDif = ratios[i] - ratios[i-1]; if (i === 1) { @@ -347,35 +294,52 @@ function initClipData (root, state) { } curve._findFrameIndex = canOptimize ? quickFindIndex : binarySearch; + + // find the lerp function + let firstValue = curve.values[0]; + if (!curve._lerp && firstValue !== undefined) { + if (typeof firstValue === 'number') { + curve._lerp = DynamicAnimCurve.prototype._lerpNumber; + } + else if (firstValue instanceof cc.Quat) { + curve._lerp = DynamicAnimCurve.prototype._lerpQuat; + } + else if (firstValue instanceof cc.Vec2 || firstValue instanceof cc.Vec3) { + curve._lerp = DynamicAnimCurve.prototype._lerpVector; + } + else if (firstValue.lerp) { + curve._lerp = DynamicAnimCurve.prototype._lerpObject; + } + } return curve; } function createTargetCurves (target, curveData) { - var propsData = curveData.props; - var compsData = curveData.comps; + let propsData = curveData.props; + let compsData = curveData.comps; if (propsData) { - for (var propPath in propsData) { - var data = propsData[propPath]; - var curve = createPropCurve(target, propPath, data); + for (let propPath in propsData) { + let data = propsData[propPath]; + let curve = createPropCurve(target, propPath, data); curves.push(curve); } } if (compsData) { - for (var compName in compsData) { - var comp = target.getComponent(compName); + for (let compName in compsData) { + let comp = target.getComponent(compName); if (!comp) { continue; } - var compData = compsData[compName]; - for (var propPath in compData) { - var data = compData[propPath]; - var curve = createPropCurve(comp, propPath, data); + let compData = compsData[compName]; + for (let propPath in compData) { + let data = compData[propPath]; + let curve = createPropCurve(comp, propPath, data); curves.push(curve); } @@ -385,28 +349,28 @@ function initClipData (root, state) { // property curves - var curveData = clip.curveData; - var childrenCurveDatas = curveData.paths; + let curveData = clip.curveData; + let childrenCurveDatas = curveData.paths; createTargetCurves(root, curveData); - for (var namePath in childrenCurveDatas) { - var target = cc.find(namePath, root); + for (let namePath in childrenCurveDatas) { + let target = cc.find(namePath, root); if (!target) { continue; } - var childCurveDatas = childrenCurveDatas[namePath]; + let childCurveDatas = childrenCurveDatas[namePath]; createTargetCurves(target, childCurveDatas); } // events curve - var events = clip.events; + let events = clip.events; if (!CC_EDITOR && events) { - var curve; + let curve; for (let i = 0, l = events.length; i < l; i++) { if (!curve) { @@ -415,11 +379,11 @@ function initClipData (root, state) { curves.push(curve); } - var eventData = events[i]; - var ratio = eventData.frame / state.duration; + let eventData = events[i]; + let ratio = eventData.frame / state.duration; - var eventInfo; - var index = binarySearch(curve.ratios, ratio); + let eventInfo; + let index = binarySearch(curve.ratios, ratio); if (index >= 0) { eventInfo = curve.events[index]; } diff --git a/cocos2d/animation/animation-curves.js b/cocos2d/animation/animation-curves.js index 052c9e297d0..b277c380617 100644 --- a/cocos2d/animation/animation-curves.js +++ b/cocos2d/animation/animation-curves.js @@ -24,11 +24,11 @@ ****************************************************************************/ -var bezierByTime = require('./bezier').bezierByTime; +const bezierByTime = require('./bezier').bezierByTime; -var binarySearch = require('../core/utils/binary-search').binarySearchEpsilon; -var WrapModeMask = require('./types').WrapModeMask; -var WrappedInfo = require('./types').WrappedInfo; +const binarySearch = require('../core/utils/binary-search').binarySearchEpsilon; +const WrapModeMask = require('./types').WrapModeMask; +const WrappedInfo = require('./types').WrappedInfo; /** * Compute a new ratio by curve type @@ -143,14 +143,34 @@ var DynamicAnimCurve = cc.Class({ // - [x, x, x, x]: Four control points for bezier // - null: linear types: [], - - // @property {string[]} subProps - The path of sub property being animated. - subProps: null }, _findFrameIndex: binarySearch, + _lerp: undefined, - sample: function (time, ratio, state) { + _lerpNumber (from, to, t) { + return from + (to - from) * t; + }, + + _lerpObject (from, to, t) { + return from.lerp(to, t); + }, + + _lerpQuat: (function () { + let out = cc.quat(); + return function (from, to, t) { + return from.lerp(to, t, out); + }; + })(), + + _lerpVector: (function () { + let out = cc.v3(); + return function (from, to, t) { + return from.lerp(to, t, out); + }; + })(), + + sample (time, ratio, state) { var values = this.values; var ratios = this.ratios; var frameCount = ratios.length; @@ -175,10 +195,7 @@ var DynamicAnimCurve = cc.Class({ else { var fromVal = values[index - 1]; - var isNumber = typeof fromVal === 'number'; - var canLerp = fromVal && fromVal.lerp; - - if (!isNumber && !canLerp) { + if (!this._lerp) { value = fromVal; } else { @@ -194,13 +211,7 @@ var DynamicAnimCurve = cc.Class({ // calculate value var toVal = values[index]; - // lerp - if (isNumber) { - value = fromVal + (toVal - fromVal) * ratioBetweenFrames; - } - else if (canLerp) { - value = fromVal.lerp(toVal, ratioBetweenFrames); - } + value = this._lerp(fromVal, toVal, ratioBetweenFrames); } } } @@ -208,35 +219,6 @@ var DynamicAnimCurve = cc.Class({ value = values[index]; } - var subProps = this.subProps; - if (subProps) { - // create batched value dynamically - var mainProp = this.target[this.prop]; - var subProp = mainProp; - - for (var i = 0; i < subProps.length - 1; i++) { - var subPropName = subProps[i]; - if (subProp) { - subProp = subProp[subPropName]; - } - else { - return; - } - } - - var propName = subProps[subProps.length - 1]; - - if (subProp) { - subProp[propName] = value; - } - else { - return; - } - - value = mainProp; - } - - // apply value this.target[this.prop] = value; } }); @@ -247,7 +229,6 @@ DynamicAnimCurve.Bezier = function (controlPoints) { }; - /** * Event information, * @class EventInfo diff --git a/cocos2d/animation/motion-path-helper.js b/cocos2d/animation/motion-path-helper.js index a9e5b814531..6f88d8155e5 100644 --- a/cocos2d/animation/motion-path-helper.js +++ b/cocos2d/animation/motion-path-helper.js @@ -216,7 +216,19 @@ Bezier.prototype.getUtoTmapping = function ( u, distance ) { }; -function sampleMotionPaths (motionPaths, data, duration, fps) { +function checkMotionPath(motionPath) { + if (!Array.isArray(motionPath)) return false; + + for (let i = 0, l = motionPath.length; i < l; i++) { + let controls = motionPath[i]; + + if (!Array.isArray(controls) || controls.length !== 6) return false; + } + + return true; +} + +function sampleMotionPaths (motionPaths, data, duration, fps, target) { function createControlPoints(array) { if (array instanceof cc.Vec2) { @@ -241,18 +253,35 @@ function sampleMotionPaths (motionPaths, data, duration, fps) { }; } - var values = data.values; + let values = data.values = data.values.map(function (value) { + if (Array.isArray(value)) { + value = value.length === 2 ? cc.v2(value[0], value[1]) : cc.v3(value[0], value[1], value[2]); + } + return value; + }); if (motionPaths.length === 0 || values.length === 0) { return; } - values = values.map(function (value) { - return v2(value[0], value[1]); - }); + let motionPathValid = false; + for (let i = 0; i < motionPaths.length; i++) { + let motionPath = motionPaths[i]; + if (motionPath && !checkMotionPath(motionPath)) { + cc.errorID(3904, target ? target.name : '', 'position', i); + motionPath = null; + } + if (motionPath && motionPath.length > 0) { + motionPathValid = true; + break; + } + } + + if (!motionPathValid) { + return; + } if (values.length === 1) { - data.values = values; return; } diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index 842e4507908..dd9630573fb 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -24,53 +24,11 @@ ****************************************************************************/ const BufferAsset = require('../assets/CCBufferAsset'); -const renderer = require('../renderer'); - -import gfx from '../../renderer/gfx'; -import InputAssembler from '../../renderer/core/input-assembler'; -import { vec3, mat4 } from '../../core/vmath'; - -const _type2size = { - SCALAR: 1, - VEC2: 2, - VEC3: 3, - VEC4: 4, - MAT2: 4, - MAT3: 9, - MAT4: 16, -}; - -const _compType2Array = { - 5120: Int8Array, - 5121: Uint8Array, - 5122: Int16Array, - 5123: Uint16Array, - 5124: Int32Array, - 5125: Uint32Array, - 5126: Float32Array, -}; - -const _gltfAttribMap = { - POSITION: gfx.ATTR_POSITION, - NORMAL: gfx.ATTR_NORMAL, - TANGENT: gfx.ATTR_TANGENT, - COLOR_0: gfx.ATTR_COLOR0, - TEXCOORD_0: gfx.ATTR_UV0, - TEXCOORD_1: gfx.ATTR_UV1, - TEXCOORD_2: gfx.ATTR_UV2, - TEXCOORD_3: gfx.ATTR_UV3, - JOINTS_0: gfx.ATTR_JOINTS, - WEIGHTS_0: gfx.ATTR_WEIGHTS -}; let Model = cc.Class({ name: 'cc.Model', extends: cc.Asset, - ctor () { - this._nodesInited = false; - }, - properties: { _buffers: [BufferAsset], @@ -78,300 +36,6 @@ let Model = cc.Class({ default: {} } }, - - _initNodes () { - if (this._nodesInited) return; - this._nodesInited = true; - - let nodes = this._gltf.nodes; - for (let i = 0; i < nodes.length; i++) { - let node = nodes[i]; - - node.path = node.parent ? node.parent.path + '/' + node.name : ''; - - let children = node.children; - if (children) { - for (let j = 0; j < children.length; j++) { - let child = nodes[children[j]]; - child.parent = node; - } - } - } - }, - - initSkeleton (skeleton) { - this._initNodes(); - - let gltf = this._gltf; - let buffers = this._buffers; - let skinID = skeleton._skinID; - if (skinID >= gltf.skins.length) { - return null; - } - - let gltfSkin = gltf.skins[skinID]; - - // extract bindposes mat4 data - let accessor = gltf.accessors[gltfSkin.inverseBindMatrices]; - let bufView = gltf.bufferViews[accessor.bufferView]; - let bin = buffers[bufView.buffer]._buffer; - let data = new Float32Array(bin, bufView.byteOffset + accessor.byteOffset, accessor.count * 16); - let bindposes = new Array(accessor.count); - - for (let i = 0; i < accessor.count; ++i) { - bindposes[i] = mat4.create( - data[16 * i + 0], data[16 * i + 1], data[16 * i + 2], data[16 * i + 3], - data[16 * i + 4], data[16 * i + 5], data[16 * i + 6], data[16 * i + 7], - data[16 * i + 8], data[16 * i + 9], data[16 * i + 10], data[16 * i + 11], - data[16 * i + 12], data[16 * i + 13], data[16 * i + 14], data[16 * i + 15] - ); - } - - let jointIndices = gltfSkin.joints; - let jointPaths = skeleton.jointPaths; - jointPaths.length = 0; - let nodes = this._gltf.nodes; - for (let i = 0; i < jointIndices.length; i++) { - let node = nodes[jointIndices[i]]; - jointPaths.push(node.path); - } - skeleton.jointPaths = jointPaths; - skeleton.bindposes = bindposes; - }, - - _createVB (gltf, accessors, primitive) { - // create vertex-format - let vfmt = []; - let vcount = 0; - - let byteOffset = 10e7, maxByteOffset = 0; - let bufferViewIndex = -1; - let attributes = primitive.attributes; - for (let gltfAttribName in attributes) { - const gfxAttribName = _gltfAttribMap[gltfAttribName]; - if (gfxAttribName === undefined) { - console.error(`Found unacceptable GlTf attribute ${gltfAttribName}.`); - return; - } - let acc = accessors[attributes[gltfAttribName]]; - vcount = Math.max(acc.count, vcount); - - let vbView = gltf.bufferViews[acc.bufferView]; - bufferViewIndex = vbView.buffer; - vfmt.push({ - name: gfxAttribName, type: acc.componentType, num: _type2size[acc.type], - byteLength: vbView.byteLength, byteOffset: vbView.byteOffset - }); - - byteOffset = Math.min(byteOffset, vbView.byteOffset); - maxByteOffset = Math.max(maxByteOffset, vbView.byteOffset + vbView.byteLength); - } - - let gfxVFmt = new gfx.VertexFormat(vfmt); - let els = gfxVFmt._elements; - for (let i = 0; i < els.length; i++) { - let el = els[i]; - el.offset = vfmt[i].byteOffset - byteOffset; - el.stride = el.bytes; - } - - let bin = this._buffers[bufferViewIndex]._buffer; - - // create vertex-buffer - let vbData = new Uint8Array(bin, byteOffset, maxByteOffset - byteOffset); - let vb = new gfx.VertexBuffer( - renderer.device, - gfxVFmt, - gfx.USAGE_STATIC, - vbData, - vcount - ); - - return { - buffer: vb, - data: vbData - }; - }, - - _createIB (gltf, accessors, primitive) { - let ibAcc = accessors[primitive.indices]; - let ibView = gltf.bufferViews[ibAcc.bufferView]; - let bin = this._buffers[ibView.buffer]._buffer; - let ibData = new Uint16Array(bin, ibView.byteOffset, ibView.byteLength / 2); - let ibBuffer = new gfx.IndexBuffer( - renderer.device, - ibAcc.componentType, - gfx.USAGE_STATIC, - ibData, - ibAcc.count - ); - - return { - buffer: ibBuffer, - data: ibData - } - }, - - _createArray (gltf, accessorID) { - let acc = gltf.accessors[accessorID]; - let bufView = gltf.bufferViews[acc.bufferView]; - let bin = this._buffers[bufView.buffer]._buffer; - - let num = _type2size[acc.type]; - let typedArray = _compType2Array[acc.componentType]; - let result = new typedArray(bin, bufView.byteOffset + acc.byteOffset, acc.count * num); - - return result; - }, - - initMesh (meshAsset) { - const index = meshAsset._meshID; - - const gltf = this._gltf; - const gltfMesh = gltf.meshes[index]; - const accessors = gltf.accessors; - - // create index-buffer - let length = gltfMesh.primitives.length; - meshAsset._ibs.length = length; - meshAsset._vbs.length = length; - meshAsset._subMeshes.length = length; - vec3.set(meshAsset._minPos, Infinity, Infinity, Infinity); - vec3.set(meshAsset._maxPos, -Infinity, -Infinity, -Infinity); - for (let i = 0; i < length; ++i) { - let primitive = gltfMesh.primitives[i]; - - if (primitive.indices === undefined) continue; - - let vb = this._createVB(gltf, accessors, primitive); - let ib = this._createIB(gltf, accessors, primitive); - - if (primitive.attributes.POSITION) { - let gltfAccessor = accessors[primitive.attributes.POSITION]; - let minPos = meshAsset._minPos, maxPos = meshAsset._maxPos, - min = gltfAccessor.min, max = gltfAccessor.max; - minPos.x = Math.min(minPos.x, min[0]); - minPos.y = Math.min(minPos.y, min[1]); - minPos.z = Math.min(minPos.z, min[2]); - maxPos.x = Math.max(maxPos.x, max[0]); - maxPos.y = Math.max(maxPos.y, max[1]); - maxPos.z = Math.max(maxPos.z, max[2]); - } - - meshAsset._subMeshes[i] = new InputAssembler(vb.buffer, ib.buffer); - meshAsset._vbs[i] = vb; - meshAsset._ibs[i] = ib; - } - }, - - initAnimationClip (clip) { - this._initNodes(); - - let gltf = this._gltf; - let gltfAnimation = gltf.animations[clip._animationID]; - - clip.wrapMode = cc.WrapMode.Loop; - let duration = 0; - - let curveData = clip.curveData; - let paths = curveData.paths = {}; - - let nodes = gltf.nodes; - - let samplers = gltfAnimation.samplers; - let channels = gltfAnimation.channels; - for (let i = 0; i < channels.length; ++i) { - let gltfChannel = channels[i]; - let sampler = samplers[gltfChannel.sampler]; - - let inputArray = this._createArray(gltf, sampler.input); - let outputArray = this._createArray(gltf, sampler.output); - - let target = gltfChannel.target; - let node = nodes[target.node]; - - let path = node.path; - - let curves; - if (path === '') { - curves = curveData; - } - else { - if (!paths[path]) { - paths[path] = {}; - } - curves = paths[path]; - } - - if (!curves.props) { - curves.props = {}; - } - - let frames = []; - for (let frameIdx = 0; frameIdx < inputArray.length; frameIdx++) { - let frame = inputArray[frameIdx]; - if (frame > duration) { - duration = frame; - } - frames.push({ frame: frame }); - } - if (target.path === 'translation') { - for (let frameIdx = 0; frameIdx < inputArray.length; frameIdx++) { - let i = frameIdx * 3; - frames[frameIdx].value = cc.v3(outputArray[i], outputArray[i + 1], outputArray[i + 2]); - } - curves.props.position = frames; - } - else if (target.path === 'rotation') { - for (let frameIdx = 0; frameIdx < inputArray.length; frameIdx++) { - let i = frameIdx * 4; - frames[frameIdx].value = cc.quat(outputArray[i], outputArray[i + 1], outputArray[i + 2], outputArray[i + 3]); - } - curves.props.quat = frames; - } - else if (target.path === 'scale') { - for (let frameIdx = 0; frameIdx < inputArray.length; frameIdx++) { - let i = frameIdx * 3; - frames[frameIdx].value = cc.v3(outputArray[i], outputArray[i + 1], outputArray[i + 2]); - } - curves.props.scale = frames; - } - } - - for (let i = 1; i < nodes.length; i++) { - let node = nodes[i]; - if (paths[node.path]) continue; - - let curves = paths[node.path] = { props: {} }; - let props = curves.props; - - let rotation = node.rotation; - if (rotation) { - props.quat = [{ - frame: 0, - value: cc.quat(rotation[0], rotation[1], rotation[2], rotation[3]) - }]; - } - - let scale = node.scale; - if (scale) { - props.scale = [{ - frame: 0, - value: cc.v3(scale[0], scale[1], scale[2]) - }]; - } - - let translation = node.translation; - if (translation) { - props.position = [{ - frame: 0, - value: cc.v3(translation[0], translation[1], translation[2]) - }]; - } - } - - clip._duration = duration; - } }); cc.Model = module.exports = Model; diff --git a/cocos2d/core/3d/CCModelMeshResource.js b/cocos2d/core/3d/CCModelMeshResource.js deleted file mode 100644 index 6fb2b721e36..00000000000 --- a/cocos2d/core/3d/CCModelMeshResource.js +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://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 Model = require('./CCModel'); - -let ModelMeshResource = cc.Class({ - name: 'ModelMeshResource', - - ctor () { - this._subMeshes = []; - this._ibs = []; - this._vbs = []; - this._inited = false; - this._minPos = cc.v3(); - this._maxPos = cc.v3(); - }, - - properties: { - _meshID: -1, - _model: { - type: Model, - default: null - }, - - meshID: { - get () { - return this._meshID; - }, - set (val) { - this._meshID = val; - } - }, - - model: { - get () { - return this._model; - }, - set (val) { - this._model = val; - } - } - }, - - flush (mesh) { - if (!this._inited) { - this._inited = true; - this.model.initMesh(this); - } - - mesh._vbs = this._vbs; - mesh._ibs = this._ibs; - mesh._subMeshes = this._subMeshes; - mesh._minPos = this._minPos; - mesh._maxPos = this._maxPos; - } -}); - -module.exports = ModelMeshResource; diff --git a/cocos2d/core/3d/CCSkeleton.js b/cocos2d/core/3d/CCSkeleton.js index 5ef31c5296f..62ea6bc6408 100644 --- a/cocos2d/core/3d/CCSkeleton.js +++ b/cocos2d/core/3d/CCSkeleton.js @@ -1,48 +1,69 @@ +/**************************************************************************** + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://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 { mat4 } from '../../core/vmath'; let Skeleton = cc.Class({ name: 'cc.Skeleton', extends: cc.Asset, ctor () { - this.jointPaths = []; - this.bindposes = []; + // {[Mat4]} + this._bindposes = []; }, properties: { - _modelSetter: { - set: function (model) { - if (CC_EDITOR && Editor.isBuilder) { - // just building - return; - } - this._initWithModel(model); + _jointPaths: [], + /** + * Bindposes data stores in one array, it is better for data size. + */ + _bindposesData: [], + + jointPaths: { + get () { + return this._jointPaths; } }, - }, - - _initWithModel (model) { - if (!model) return; - this._model = model; - this._model.initSkeleton(this); - }, - - _serialize: CC_EDITOR && function (exporting) { - let modelUuid = this._modelUuid; - if (exporting) { - modelUuid = Editor.Utils.UuidUtils.compressUuid(modelUuid, true); + bindposes: { + get () { + return this._bindposes; + } } - return { - modelUuid: modelUuid, - skinID: this._skinID, - }; }, - _deserialize (data, handle) { - this._modelUuid = data.modelUuid; - this._skinID = data.skinID; - - if (this._modelUuid) { - handle.result.push(this, '_modelSetter', this._modelUuid); + onLoad () { + let data = this._bindposesData; + let poses = this._bindposes; + for (let i = 0; i < data.length; i++) { + let pose = data[i]; + poses[i] = mat4.create( + pose[0], pose[1], pose[2], pose[3], + pose[4], pose[5], pose[6], pose[7], + pose[8], pose[9], pose[10], pose[11], + pose[12], pose[13], pose[14], pose[15], + ); } } }); diff --git a/cocos2d/core/3d/CCSkeletonAnimation.js b/cocos2d/core/3d/CCSkeletonAnimation.js index 77ec7156618..a5ef5dac874 100644 --- a/cocos2d/core/3d/CCSkeletonAnimation.js +++ b/cocos2d/core/3d/CCSkeletonAnimation.js @@ -46,7 +46,11 @@ let SkeletonAnimation = cc.Class({ }, properties: { - _model: Model, + _model: { + default: null, + type: Model, + editorOnly: true + }, _defaultClip: { override: true, @@ -79,17 +83,10 @@ let SkeletonAnimation = cc.Class({ set (val) { this._model = val; }, - type: Model + type: Model, }, }, - getAnimationState (name) { - let state = this._super(name); - let clip = state.clip; - clip.init(); - return state; - }, - searchClips: CC_EDITOR && function () { this._clips.length = 0; let self = this; diff --git a/cocos2d/core/3d/CCSkeletonAnimationClip.js b/cocos2d/core/3d/CCSkeletonAnimationClip.js index f2df240637b..70347a0e696 100644 --- a/cocos2d/core/3d/CCSkeletonAnimationClip.js +++ b/cocos2d/core/3d/CCSkeletonAnimationClip.js @@ -23,7 +23,6 @@ THE SOFTWARE. ****************************************************************************/ -const Model = require('./CCModel'); const AnimationClip = require('../../animation/animation-clip'); /** @@ -40,55 +39,82 @@ var SkeletonAnimationClip = cc.Class({ extends: AnimationClip, properties: { - _modelSetter: { - set: function (model) { - this._model = model; + _nativeAsset: { + override: true, + get () { + return this._buffer; + }, + set (bin) { + let buffer = ArrayBuffer.isView(bin) ? bin.buffer : bin; + this._buffer = new Float32Array(buffer || bin, 0, buffer.byteLength/4); } }, - model: { - get () { - return this._model; - }, + /** + * Describe the data structure. + * { path: { offset, frameCount, property } } + */ + description: { + default: null, + type: Object, + }, - type: Model - } + /** + * SkeletonAnimationClip's curveData is generated from binary buffer. + * So should not serialize curveData. + */ + curveData: { + default: {}, + visible: false, + override: true, + serializable: false + }, }, - ctor () { - this._modelUuid = ''; - this._animationID = -1; - this._model = null; - this._inited = false; - }, + onLoad () { + let buffer = this._buffer; + let description = this.description; - init () { - if (this._inited) return; - this._inited = true; - this._model.initAnimationClip(this); - }, + let offset = 0; + function getValue () { + return buffer[offset++]; + } - _serialize: CC_EDITOR && function (exporting) { - let modelUuid = this._modelUuid; - if (exporting) { - modelUuid = Editor.Utils.UuidUtils.compressUuid(modelUuid, true); + if (!this.curveData) { + this.curveData = {}; } - return { - modelUuid: modelUuid, - animationID: this._animationID, - name: this._name, + if (!this.curveData.paths) { + this.curveData.paths = {}; } - }, + let paths = this.curveData.paths; - _deserialize (data, handle) { - this._modelUuid = data.modelUuid; - this._animationID = data.animationID; - this._name = data.name; + for (let path in description) { + let des = description[path]; + let curves = {}; + paths[path] = { props: curves }; + + for (let property in des) { + let frames = []; - if (this._modelUuid) { - handle.result.push(this, '_modelSetter', this._modelUuid); + let frameCount = des[property].frameCount; + offset = des[property].offset; + for (let i = 0; i < frameCount; i++) { + let frame = getValue(); + let value; + if (property === 'position' || property === 'scale') { + value = cc.v3(getValue(), getValue(), getValue()); + } + else if (property === 'quat') { + value = cc.quat(getValue(), getValue(), getValue(), getValue()); + } + frames.push({ frame, value }); + } + + curves[property] = frames; + } } } + }); cc.SkeletonAnimationClip = module.exports = SkeletonAnimationClip; diff --git a/cocos2d/core/3d/index.js b/cocos2d/core/3d/index.js index eb1c71fc90c..bcc4bfe214e 100644 --- a/cocos2d/core/3d/index.js +++ b/cocos2d/core/3d/index.js @@ -8,7 +8,6 @@ if (!CC_TEST && (!CC_EDITOR || !Editor.isMainProcess)) { require('./CCModel'); require('./CCSkeleton'); require('./CCSkeletonAnimationClip'); -require('./CCModelMeshResource'); require('./actions'); if (!CC_EDITOR || !Editor.isMainProcess) { diff --git a/cocos2d/core/assets/CCBufferAsset.js b/cocos2d/core/assets/CCBufferAsset.js index c9d1e915d21..24fb0f7a398 100644 --- a/cocos2d/core/assets/CCBufferAsset.js +++ b/cocos2d/core/assets/CCBufferAsset.js @@ -46,6 +46,9 @@ var BufferAsset = cc.Class({ }, override: true }, + buffer () { + return this._buffer; + } } }); diff --git a/cocos2d/core/mesh/CCMesh.js b/cocos2d/core/mesh/CCMesh.js index 5a860123583..d557185247d 100644 --- a/cocos2d/core/mesh/CCMesh.js +++ b/cocos2d/core/mesh/CCMesh.js @@ -23,12 +23,12 @@ THE SOFTWARE. ****************************************************************************/ -const MeshResource = require('./CCMeshResource'); const renderer = require('../renderer'); const EventTarget = require('../event/event-target'); import InputAssembler from '../../renderer/core/input-assembler'; import gfx from '../../renderer/gfx'; +import { Primitive, VertexBundle } from './mesh-data'; function applyColor (data, offset, value) { data[offset] = value._val; @@ -60,10 +60,26 @@ let Mesh = cc.Class({ mixins: [EventTarget], properties: { - _resource: { + _nativeAsset: { + override: true, + get () { + return this._buffer; + }, + set (bin) { + this._buffer = ArrayBuffer.isView(bin) ? bin.buffer : bin; + } + }, + + _vertexBundles: { default: null, - type: MeshResource + type: VertexBundle }, + _primitives: { + default: null, + Primitive + }, + _minPos: cc.v3(), + _maxPos: cc.v3(), /** * !#en Get ir set the sub meshes. @@ -85,18 +101,45 @@ let Mesh = cc.Class({ this._ibs = []; this._vbs = []; + }, - this._minPos = cc.v3(); - this._maxPos = cc.v3(); + onLoad () { + this._subMeshes.length = 0; - this._resourceInited = false; - }, + let primitives = this._primitives; + for (let i = 0; i < primitives.length; i++) { + let primitive = primitives[i]; + + // ib + let ibrange = primitive.data; + let ibData = new Uint16Array(this._buffer, ibrange.offset, ibrange.length / 2); + let ibBuffer = new gfx.IndexBuffer( + renderer.device, + primitive.indexUnit, + gfx.USAGE_STATIC, + ibData, + ibData.length + ); - _initResource () { - if (this._resourceInited || !this._resource) return; - this._resourceInited = true; + // vb + let vertexBundle = this._vertexBundles[primitive.vertexBundleIndices[0]]; + let vbRange = vertexBundle.data; + let gfxVFmt = new gfx.VertexFormat(vertexBundle.formats); + let vbData = new Uint8Array(this._buffer, vbRange.offset, vbRange.length); + let vbBuffer = new gfx.VertexBuffer( + renderer.device, + gfxVFmt, + gfx.USAGE_STATIC, + vbData, + vertexBundle.verticesCount + ); - this._resource.flush(this); + // create sub meshes + this._subMeshes.push(new InputAssembler(vbBuffer, ibBuffer)); + this._ibs.push({ buffer: ibBuffer, data: ibData }); + this._vbs.push({ buffer: vbBuffer, data: vbData }); + } + }, /** diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index dffdf5bd485..011f6b86fe9 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -173,10 +173,6 @@ let MeshRenderer = cc.Class({ _activateMaterial (force) { let mesh = this._mesh; - // TODO: should init mesh when mesh loaded, need asset load event support - if (mesh) { - mesh._initResource(); - } if (!mesh || mesh.subMeshes.length === 0) { this.disableRender(); diff --git a/cocos2d/core/mesh/CCMeshResource.js b/cocos2d/core/mesh/CCMeshResource.js deleted file mode 100644 index b54001e6d72..00000000000 --- a/cocos2d/core/mesh/CCMeshResource.js +++ /dev/null @@ -1,34 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://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. - ****************************************************************************/ - -let MeshResource = cc.Class({ - name: 'cc.MeshResource', - - flush (mesh) { - - } -}); - -module.exports = MeshResource; diff --git a/cocos2d/core/mesh/mesh-data.js b/cocos2d/core/mesh/mesh-data.js new file mode 100644 index 00000000000..60d2063a60e --- /dev/null +++ b/cocos2d/core/mesh/mesh-data.js @@ -0,0 +1,126 @@ +/**************************************************************************** + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://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 gfx from '../../renderer/gfx'; + +/** + * The class BufferRange denotes a range of the buffer. + */ +export let BufferRange = cc.Class({ + name: 'cc.BufferRange', + + properties: { + /** + * The offset of the range. + * @property {Number} offset + */ + offset: 0, + /** + * The length of the range. + * @property {Number} length + */ + length: 0 + } +}); + +export let VertexFormat = cc.Class({ + name: 'cc.mesh.VertexFormat', + + properties: { + name: '', + type: -1, + num: -1, + normalize: false + } +}); + +/** + * A vertex bundle describes a serials of vertex attributes. + * These vertex attributes occupy a range of the buffer and + * are interleaved, no padding bytes, in the range. + */ +export let VertexBundle = cc.Class({ + name: 'cc.mesh.VertexBundle', + properties: { + /** + * The data range of this bundle. + * This range of data is essentially mapped to a GPU vertex buffer. + * @property {BufferRange} data + */ + data: { + default: null, + type: BufferRange + }, + /** + * The attribute formats. + * @property {VertexFormat} formats + */ + formats: { + default: [], + type: VertexFormat + }, + /** + * The bundle's vertices count. + */ + verticesCount: 0, + } +}); + +/** + * A primitive is a geometry constituted with a list of + * same topology primitive graphic(such as points, lines or triangles). + */ +export let Primitive = cc.Class({ + name: 'cc.mesh.Primitive', + properties: { + /** + * The vertex bundle that the primitive use. + * @property {[Number]} vertexBundleIndices + */ + vertexBundleIndices: { + default: [], + type: Number + }, + /** + * The data range of the primitive. + * This range of data is essentially mapped to a GPU indices buffer. + * @property {BufferRange} data + */ + data: { + default: null, + type: BufferRange + }, + /** + * The type of this primitive's indices. + * @property {Number} indexUnit + */ + indexUnit: gfx.INDEX_FMT_UINT16, + /** + * The primitive's topology. + * @property {Number} topology + */ + topology: gfx.PT_TRIANGLES + } +}); diff --git a/test/qunit/unit-es5/test-animation.js b/test/qunit/unit-es5/test-animation.js index b5dc53506eb..bb425c5330c 100644 --- a/test/qunit/unit-es5/test-animation.js +++ b/test/qunit/unit-es5/test-animation.js @@ -44,11 +44,7 @@ test('DynamicAnimCurve', function () { var DynamicAnimCurve = cc._Test.DynamicAnimCurve; var anim = new DynamicAnimCurve(); var target = { - height: 1, - position: v2(123, 456), - foo: { - bar: color(128, 128, 128, 128), - } + height: 1 }; anim.target = target; anim.prop = 'height'; @@ -57,23 +53,6 @@ test('DynamicAnimCurve', function () { anim.sample(null, 0.1, null); strictEqual(target.height, 10, 'The keyframe value whose ratio is out of ranges should just clamped'); - - anim.prop = 'position'; - anim.subProps = ['x']; - anim.values = [50, 100]; - anim.ratios = [0.0, 1.0]; - anim.sample(null, 0.1, null); - - deepEqual(target.position, v2(55, 456, 0), 'The composed position should animated'); - - anim.target = target; - anim.prop = 'foo'; - anim.subProps = ['bar', 'a']; - anim.values = [128, 256]; - anim.ratios = [0.0, 1.0]; - anim.sample(null, 0.1, null); - - deepEqual(target.foo, { bar: color(128, 128, 128, 140) }, 'The composed color should animated'); }); test('AnimationState.getWrappedInfo', function () { @@ -201,23 +180,14 @@ test('initClipData', function () { { frame: 0, value: v2(50, 100) }, { frame: 5, value: v2(100, 75) }, { frame: 10, value: v2(100, 50) } - ], - 'scale.x': [ - { frame: 0, value: 10 }, - { frame: 10, value: 20 } - ], - 'scale.y': [ - { frame: 0, value: 10 }, - { frame: 5, value: 12 }, - { frame: 10, value: 20 } ] }, comps: { 'cc.Sprite': { - 'testColor.a': [ - { frame: 0, value: 1 }, - { frame: 10, value: 0 } + 'testColor': [ + { frame: 0, value: Color.BLACK }, + { frame: 10, value: Color.WHITE } ] } }, @@ -234,9 +204,9 @@ test('initClipData', function () { comps: { 'cc.Sprite': { - 'testColor.a': [ - { frame: 0, value: 1 }, - { frame: 10, value: 0 } + 'testColor': [ + { frame: 0, value: Color.BLACK }, + { frame: 10, value: Color.WHITE } ] } } @@ -248,23 +218,17 @@ test('initClipData', function () { initClipData(entity, state); var posCurve = state.curves[0]; - var scaleCurveX = state.curves[1]; - var scaleCurveY = state.curves[2]; - var colorCurve = state.curves[3]; + var colorCurve = state.curves[1]; - strictEqual(state.curves.length, 6, 'should create 6 curve'); + strictEqual(state.curves.length, 4, 'should create 6 curve'); strictEqual(posCurve.target, entity, 'target of posCurve should be transform'); strictEqual(posCurve.prop, 'pos', 'propName of posCurve should be pos'); - strictEqual(scaleCurveX.target, entity, 'target of scaleCurve should be transform'); - strictEqual(scaleCurveX.prop, 'scale', 'propName of scaleCurve should be scale'); strictEqual(colorCurve.target, renderer, 'target of colorCurve should be sprite renderer'); strictEqual(colorCurve.prop, 'testColor', 'propName of colorCurve should be testColor'); deepEqual(posCurve.values, [v2(50, 100), v2(100, 75), v2(100, 50)], 'values of posCurve should equals keyFrames'); - deepEqual(scaleCurveY.values, [10, 12, 20], 'values of scaleCurve should equals keyFrames'); - - deepEqual(colorCurve.values, [1, 0], 'values of colorCurve should equals keyFrames'); + deepEqual(colorCurve.values, [Color.BLACK, Color.WHITE], 'values of colorCurve should equals keyFrames'); deepEqual(posCurve.ratios, [0, 0.5, 1], 'ratios of posCurve should equals keyFrames'); deepEqual(colorCurve.ratios, [0, 1], 'ratios of colorCurve should equals keyFrames'); From f69fda4322b7093ee872251fc1e896f4211f3f75 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Mon, 25 Feb 2019 20:53:56 +0800 Subject: [PATCH 0475/1631] Fix dragonbones multiple texture bug (#3897) * Fix dragonbones change cloth bug * Adapt to old api-> on off once * DragonBonesAsset do not store dragonBones data * fix some error * fix web spine debug draw color error * Set limit time to 30s --- extensions/dragonbones/ArmatureCache.js | 35 ++---- extensions/dragonbones/ArmatureDisplay.js | 112 ++++++++++++------ extensions/dragonbones/CCFactory.js | 51 ++++---- extensions/dragonbones/DragonBonesAsset.js | 83 +++++-------- .../dragonbones/DragonBonesAtlasAsset.js | 53 +++------ extensions/dragonbones/lib/dragonBones.js | 18 +-- extensions/spine/spine-assembler.js | 1 - 7 files changed, 166 insertions(+), 187 deletions(-) diff --git a/extensions/dragonbones/ArmatureCache.js b/extensions/dragonbones/ArmatureCache.js index 8d6c176d8ec..590f84533a9 100644 --- a/extensions/dragonbones/ArmatureCache.js +++ b/extensions/dragonbones/ArmatureCache.js @@ -287,35 +287,20 @@ let ArmatureCache = cc.Class({ delete this._armatureCache[armatureKey]; }, - // When atlas asset be destroy, remove armature from db cache. - clearByAtlasName (atlasName) { - for (var armatureKey in this._armatureCache) { - var armatureInfo = this._armatureCache[armatureKey]; - if (armatureInfo && armatureInfo.atlasName === atlasName) { - this._removeArmature(armatureKey); - return; - } - } - }, - // When db assets be destroy, remove armature from db cache. - clearByDBName (dbName) { + resetArmature (uuid) { for (var armatureKey in this._armatureCache) { - var armatureInfo = this._armatureCache[armatureKey]; - if (armatureInfo && armatureInfo.dbName === dbName) { - this._removeArmature(armatureKey); - return; - } + if (armatureKey.indexOf(uuid) == -1) continue; + this._removeArmature(armatureKey); } }, - getArmatureCache (armatureName, dragonbonesName, atlasName) { - let armatureKey = armatureName + "#" + dragonbonesName + "#" + atlasName; + getArmatureCache (armatureName, armatureKey, atlasUUID) { let armatureInfo = this._armatureCache[armatureKey]; let armature; if (!armatureInfo) { let factory = dragonBones.CCFactory.getInstance(); - let proxy = factory.buildArmatureDisplay(armatureName, dragonbonesName, "", atlasName); + let proxy = factory.buildArmatureDisplay(armatureName, armatureKey, "", atlasUUID); if (!proxy || !proxy._armature) return; armature = proxy._armature; // If armature has child armature, can not be cache, because it's @@ -327,8 +312,6 @@ let ArmatureCache = cc.Class({ this._armatureCache[armatureKey] = { armature : armature, - dbName : dragonbonesName, - atlasName : atlasName, // Cache all kinds of animation frame. // When armature is dispose, clear all animation cache. animationsCache : {}, @@ -339,8 +322,7 @@ let ArmatureCache = cc.Class({ return armature; }, - getAnimationCache (armatureName, dragonbonesName, atlasName, animationName) { - let armatureKey = armatureName + "#" + dragonbonesName + "#" + atlasName; + getAnimationCache (armatureKey, animationName) { let armatureInfo = this._armatureCache[armatureKey]; if (!armatureInfo) return null; @@ -348,8 +330,7 @@ let ArmatureCache = cc.Class({ return animationsCache[animationName]; }, - updateAnimationCache (armatureName, dragonbonesName, atlasName, animationName) { - let armatureKey = armatureName + "#" + dragonbonesName + "#" + atlasName; + updateAnimationCache (armatureKey, animationName) { let armatureInfo = this._armatureCache[armatureKey]; let armature = armatureInfo && armatureInfo.armature; if (!armature) return null; @@ -373,7 +354,7 @@ let ArmatureCache = cc.Class({ } animationCache.update(armature); if (animationCache.totalTime >= MaxCacheTime) { - cc.warn("Animation cache is overflow, maybe animation's frame is infinite, please change armature render mode to REALTIME, dragonbones name is [%s], animation name is [%s]", dragonbonesName, animationName); + cc.warn("Animation cache is overflow, maybe animation's frame is infinite, please change armature render mode to REALTIME, dragonbones uuid is [%s], animation name is [%s]", armatureKey, animationName); } return animationCache; } diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 63366b26098..9a28cec0cb4 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -95,7 +95,6 @@ function setEnumAttr (obj, propName, enumDef) { let ArmatureDisplay = cc.Class({ name: 'dragonBones.ArmatureDisplay', extends: RenderComponent, - mixins: [EventTarget], editor: CC_EDITOR && { menu: 'i18n:MAIN_MENU.component.renderers/DragonBones', @@ -128,8 +127,6 @@ let ArmatureDisplay = cc.Class({ default: null, type: dragonBones.DragonBonesAsset, notify () { - // parse the asset data - this._parseDragonAsset(); this._refresh(); if (CC_EDITOR) { this._defaultArmatureIndex = 0; @@ -265,7 +262,7 @@ let ArmatureDisplay = cc.Class({ let animName = animsEnum[this._animationIndex]; if (animName !== undefined) { - this.animationName = animName; + this.playAnimation(animName, this.playTimes); } else { cc.errorID(7402, this.name); @@ -369,6 +366,9 @@ let ArmatureDisplay = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.enabled_batch' }, + // DragonBones data store key. + _armatureKey: "", + // Below properties will effect when render mode is SHARED_CACHE or PRIVATE_CACHE. // accumulate time _accTime: 0, @@ -391,6 +391,7 @@ let ArmatureDisplay = cc.Class({ // it will just use the _material,won't clone it. // So if invoke getMaterial,it only return _material,if you want to change all materialCache, // you can change materialCache directly. + this._eventTarget = null; this._materialCache = {}; this._inited = false; this._factory = dragonBones.CCFactory.getInstance(); @@ -437,7 +438,6 @@ let ArmatureDisplay = cc.Class({ this._renderMode = RenderMode.REALTIME; } - this._parseDragonAsset(); this._parseDragonAtlasAsset(); this._refresh(); @@ -509,7 +509,7 @@ let ArmatureDisplay = cc.Class({ // Animation Start, the event diffrent from dragonbones inner event, // It has no event object. if (this._accTime == 0 && this._playCount == 0) { - this.emit(dragonBones.EventObject.START); + this._eventTarget.emit(dragonBones.EventObject.START); } this._accTime += dt * this.timeScale; @@ -518,11 +518,11 @@ let ArmatureDisplay = cc.Class({ // Animation loop complete, the event diffrent from dragonbones inner event, // It has no event object. - this.emit(dragonBones.EventObject.LOOP_COMPLETE); + this._eventTarget.emit(dragonBones.EventObject.LOOP_COMPLETE); // Animation complete the event diffrent from dragonbones inner event, // It has no event object. - this.emit(dragonBones.EventObject.COMPLETE); + this._eventTarget.emit(dragonBones.EventObject.COMPLETE); this._playCount ++; if (this.playTimes === -1 || (this.playTimes > 0 && this._playCount >= this.playTimes)) { @@ -583,6 +583,7 @@ let ArmatureDisplay = cc.Class({ _buildArmature () { if (!this.dragonAsset || !this.dragonAtlasAsset || !this.armatureName) return; + // Switch Asset or Atlas or renderMode will rebuild armature. if (this._armature) { // dispose pre build armature @@ -603,21 +604,24 @@ let ArmatureDisplay = cc.Class({ this._curFrame = null; this._playing = false; this._preRenderMode = null; + this._eventTarget = null; } if (!CC_EDITOR) { if (this._renderMode === RenderMode.SHARED_CACHE) { this._armatureCache = ArmatureCache.sharedCache; + this._eventTarget = new EventTarget; } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { this._armatureCache = new ArmatureCache; + this._eventTarget = new EventTarget; } } - let atlasName = this.dragonAtlasAsset._textureAtlasData.name; - let dragonbonesName = this.dragonAsset._dragonBonesData.name; + let atlasUUID = this.dragonAtlasAsset._uuid; + this._armatureKey = this.dragonAsset.init(this._factory, atlasUUID); if (this.isCachedMode()) { - this._armature = this._armatureCache.getArmatureCache(this.armatureName, dragonbonesName, atlasName); + this._armature = this._armatureCache.getArmatureCache(this.armatureName, this._armatureKey, atlasUUID); if (!this._armature) { // Cache fail,swith to REALTIME render mode. this._renderMode = RenderMode.REALTIME; @@ -626,7 +630,7 @@ let ArmatureDisplay = cc.Class({ this._preRenderMode = this._renderMode; if (CC_EDITOR || this._renderMode === RenderMode.REALTIME) { - this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, dragonbonesName, "", atlasName); + this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, this._armatureKey, "", atlasUUID); if (!this._displayProxy) return; this._displayProxy._ccNode = this.node; this._armature = this._displayProxy._armature; @@ -643,12 +647,6 @@ let ArmatureDisplay = cc.Class({ } }, - _parseDragonAsset () { - if (this.dragonAsset) { - this.dragonAsset.init(this._factory); - } - }, - _parseDragonAtlasAsset () { if (this.dragonAtlasAsset) { this.dragonAtlasAsset.init(this._factory); @@ -669,9 +667,9 @@ let ArmatureDisplay = cc.Class({ _updateRenderModeEnum: CC_EDITOR && function () { if (this._armature && ArmatureCache.canCache(this._armature)) { - setEnumAttr(this, 'renderMode', RenderMode); + setEnumAttr(this, '_defaultRenderMode', RenderMode); } else { - setEnumAttr(this, 'renderMode', DefaultRenderMode); + setEnumAttr(this, '_defaultRenderMode', DefaultRenderMode); } }, @@ -721,11 +719,9 @@ let ArmatureDisplay = cc.Class({ this.animationName = animName; if (this.isCachedMode()) { - let atlasName = this.dragonAtlasAsset._textureAtlasData.name; - let dragonbonesName = this.dragonAsset._dragonBonesData.name; - let cache = this._armatureCache.getAnimationCache(this.armatureName, dragonbonesName, atlasName, animName); + let cache = this._armatureCache.getAnimationCache(this._armatureKey, animName); if (!cache) { - cache = this._armatureCache.updateAnimationCache(this.armatureName, dragonbonesName, atlasName, animName); + cache = this._armatureCache.updateAnimationCache(this._armatureKey, animName); } if (cache) { this._accTime = 0; @@ -751,9 +747,7 @@ let ArmatureDisplay = cc.Class({ */ updateAnimationCache (animName) { if (!this.isCachedMode()) return; - let atlasName = this.dragonAtlasAsset._textureAtlasData.name; - let dragonbonesName = this.dragonAsset._dragonBonesData.name; - let cache = this._armatureCache.updateAnimationCache(this.armatureName, dragonbonesName, atlasName, animName); + let cache = this._armatureCache.updateAnimationCache(this._armatureKey, animName); this._frameCache = cache || this._frameCache; }, @@ -766,7 +760,7 @@ let ArmatureDisplay = cc.Class({ * @returns {Array} */ getArmatureNames () { - let dragonBonesData = this.dragonAsset && this.dragonAsset._dragonBonesData; + let dragonBonesData = this._factory.getDragonBonesData(this._armatureKey); return (dragonBonesData && dragonBonesData.armatureNames) || []; }, @@ -781,8 +775,9 @@ let ArmatureDisplay = cc.Class({ */ getAnimationNames (armatureName) { let ret = []; - if (this.dragonAsset && this.dragonAsset._dragonBonesData) { - let armatureData = this.dragonAsset._dragonBonesData.getArmature(armatureName); + let dragonBonesData = this._factory.getDragonBonesData(this._armatureKey); + if (dragonBonesData) { + let armatureData = dragonBonesData.getArmature(armatureName); if (armatureData) { for (let animName in armatureData.animations) { if (armatureData.animations.hasOwnProperty(animName)) { @@ -791,10 +786,57 @@ let ArmatureDisplay = cc.Class({ } } } - return ret; }, + /** + * !#en + * Add event listener for the DragonBones Event, the same to addEventListener. + * !#zh + * 添加 DragonBones 事件监听器,与 addEventListener 作用相同。 + * @method on + * @param {String} type - A string representing the event type to listen for. + * @param {Function} listener - The callback that will be invoked when the event is dispatched. + * @param {Event} listener.event event + * @param {Object} [target] - The target (this object) to invoke the callback, can be null + */ + on (eventType, listener, target) { + this.addEventListener(eventType, listener, target); + }, + + /** + * !#en + * Remove the event listener for the DragonBones Event, the same to removeEventListener. + * !#zh + * 移除 DragonBones 事件监听器,与 removeEventListener 作用相同。 + * @method off + * @param {String} type - A string representing the event type to listen for. + * @param {Function} [listener] + * @param {Object} [target] + */ + off (eventType, listener, target) { + this.removeEventListener(eventType, listener, target); + }, + + /** + * !#en + * Add event listener for the DragonBones Event, the same to addEventListener. + * !#zh + * 添加 DragonBones 一次性事件监听器,回调会在第一时间被触发后删除自身。。 + * @method on + * @param {String} type - A string representing the event type to listen for. + * @param {Function} listener - The callback that will be invoked when the event is dispatched. + * @param {Event} listener.event event + * @param {Object} [target] - The target (this object) to invoke the callback, can be null + */ + once (eventType, listener, target) { + if (this._displayProxy) { + this._displayProxy.once(eventType, listener, target); + } else { + this._eventTarget.once(eventType, listener, target); + } + }, + /** * !#en * Add event listener for the DragonBones Event. @@ -808,9 +850,9 @@ let ArmatureDisplay = cc.Class({ */ addEventListener (eventType, listener, target) { if (this._displayProxy) { - this._displayProxy.addDBEventListener(eventType, listener, target); + this._displayProxy.on(eventType, listener, target); } else { - this.on(eventType, listener, target); + this._eventTarget.on(eventType, listener, target); } }, @@ -826,9 +868,9 @@ let ArmatureDisplay = cc.Class({ */ removeEventListener (eventType, listener, target) { if (this._displayProxy) { - this._displayProxy.removeDBEventListener(eventType, listener, target); + this._displayProxy.off(eventType, listener, target); } else { - this.off(eventType, listener, target); + this._eventTarget.off(eventType, listener, target); } }, diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index 9ee9b623157..87014219414 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -73,41 +73,15 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ this._dragonBones.advanceTime(dt); }, - parseDragonBonesDataOnly (rawData, name, scale) { - if (name === undefined) { name = null; } - if (scale === undefined) { scale = 1.0; } - var dataParser = rawData instanceof ArrayBuffer ? BaseFactory._binaryParser : this._dataParser; - var dragonBonesData = dataParser.parseDragonBonesData(rawData, scale); - return dragonBonesData; - }, - - handleTextureAtlasData (isBinary, name, scale) { - if (name === undefined) { name = null; } - if (scale === undefined) { scale = 1.0; } - - var dataParser = isBinary ? BaseFactory._binaryParser : this._dataParser; - - while (true) { - var textureAtlasData = this._buildTextureAtlasData(null, null); - if (dataParser.parseTextureAtlasData(null, textureAtlasData, scale)) { - this.addTextureAtlasData(textureAtlasData, name); - } - else { - textureAtlasData.returnToPool(); - break; - } - } - }, - // Build new aramture with a new display. buildArmatureDisplay (armatureName, dragonBonesName, skinName, textureAtlasName) { let armature = this.buildArmature(armatureName, dragonBonesName, skinName, textureAtlasName); return armature && armature._display; }, - parseTextureAtlasData (jsonString, texture) { + parseTextureAtlasData (jsonString, texture, atlasUUID) { var atlasJsonObj = JSON.parse(jsonString); - return this._super(atlasJsonObj, texture); + return this._super(atlasJsonObj, texture, atlasUUID); }, // Build sub armature from an exist armature component. @@ -189,5 +163,26 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ let display = slot; slot.init(slotData, displays, display, display); return slot; + }, + + getDragonBonesDataByUUID (uuid) { + for (var name in this._dragonBonesDataMap) { + if (name.indexOf(uuid) != -1) { + return this._dragonBonesDataMap[name]; + } + } + return null; + }, + + removeDragonBonesDataByUUID (uuid, disposeData) { + if (disposeData === void 0) { disposeData = true; } + for (var name in this._dragonBonesDataMap) { + if (disposeData) { + this._dragonBones.bufferObject(this._dragonBonesDataMap[name]); + } + if (name.indexOf(uuid) != -1) { + delete this._dragonBonesDataMap[name]; + } + } } }); diff --git a/extensions/dragonbones/DragonBonesAsset.js b/extensions/dragonbones/DragonBonesAsset.js index cbb9424d248..250fe480846 100644 --- a/extensions/dragonbones/DragonBonesAsset.js +++ b/extensions/dragonbones/DragonBonesAsset.js @@ -86,63 +86,31 @@ var DragonBonesAsset = cc.Class({ }, reset () { - this._dragonBonesData = null; + this._clear(); if (CC_EDITOR) { this._armaturesEnum = null; } }, - init (factory) { + init (factory, atlasUUID) { if (CC_EDITOR) { this._factory = factory || new dragonBones.CCFactory(); } else { this._factory = factory; } - if (this._dragonBonesData) { - let hasSame = this.checkSameNameData(this._dragonBonesData); - if (!hasSame) { - this._factory.addDragonBonesData(this._dragonBonesData); - } - } - else { - if (this.dragonBonesJson) { - this.initWithRawData(JSON.parse(this.dragonBonesJson), false); - } else { - this.initWithRawData(this._nativeAsset, true); - } - } - }, - - checkSameNameData (dragonBonesData) { - let sameNamedDragonBonesData = this._factory.getDragonBonesData(dragonBonesData.name); - if (sameNamedDragonBonesData) { - // already added asset, see #2002 - let armatureNames = dragonBonesData.armatureNames; - for (let i = 0; i < armatureNames.length; i++) { - let armatureName = armatureNames[i]; - if (!sameNamedDragonBonesData.armatures[armatureName]) { - sameNamedDragonBonesData.addArmature(dragonBonesData.armatures[armatureName]); - } - } - this._dragonBonesData = sameNamedDragonBonesData; - return true; - } - return false; - }, - - initWithRawData (rawData, isBinary) { - if (!rawData) { - return; - } + let armatureKey = this._uuid + "#" + atlasUUID; + let dragonBonesData = this._factory.getDragonBonesData(armatureKey); + if (dragonBonesData) return armatureKey; - let dragonBonesData = this._factory.parseDragonBonesDataOnly(rawData); - let hasSame = this.checkSameNameData(dragonBonesData); - if (!hasSame) { - this._dragonBonesData = dragonBonesData; - this._factory.handleTextureAtlasData(isBinary); - this._factory.addDragonBonesData(dragonBonesData); + let rawData = null; + if (this.dragonBonesJson) { + rawData = JSON.parse(this.dragonBonesJson); + } else { + rawData = this._nativeAsset; } + this._factory.parseDragonBonesData(rawData, armatureKey); + return armatureKey; }, // EDITOR @@ -152,8 +120,9 @@ var DragonBonesAsset = cc.Class({ return this._armaturesEnum; } this.init(); - if (this._dragonBonesData) { - var armatureNames = this._dragonBonesData.armatureNames; + let dragonBonesData = this._factory.getDragonBonesDataByUUID(this._uuid); + if (dragonBonesData) { + var armatureNames = dragonBonesData.armatureNames; var enumDef = {}; for (var i = 0; i < armatureNames.length; i++) { var name = armatureNames[i]; @@ -166,8 +135,10 @@ var DragonBonesAsset = cc.Class({ getAnimsEnum: CC_EDITOR && function (armatureName) { this.init(); - if (this._dragonBonesData) { - var armature = this._dragonBonesData.getArmature(armatureName); + + let dragonBonesData = this._factory.getDragonBonesDataByUUID(this._uuid); + if (dragonBonesData) { + var armature = dragonBonesData.getArmature(armatureName); if (!armature) { return null; } @@ -186,14 +157,16 @@ var DragonBonesAsset = cc.Class({ return null; }, - destroy () { - var useGlobalFactory = !CC_JSB; - if (useGlobalFactory && this._dragonBonesData) { - var factory = dragonBones.CCFactory.getInstance(); - let name = this._dragonBonesData.name; - factory.removeDragonBonesData(name, true); - ArmatureCache.clearByDBName(name); + _clear () { + if (CC_JSB) return; + if (this._factory) { + ArmatureCache.resetArmature(this._uuid); + this._factory.removeDragonBonesDataByUUID(this._uuid, true); } + }, + + destroy () { + this._clear(); this._super(); }, }); diff --git a/extensions/dragonbones/DragonBonesAtlasAsset.js b/extensions/dragonbones/DragonBonesAtlasAsset.js index c2e06aa9e03..086ad2143cc 100644 --- a/extensions/dragonbones/DragonBonesAtlasAsset.js +++ b/extensions/dragonbones/DragonBonesAtlasAsset.js @@ -40,7 +40,7 @@ var DragonBonesAtlasAsset = cc.Class({ extends: cc.Asset, ctor () { - this.reset(); + this._clear(); }, properties: { @@ -55,7 +55,7 @@ var DragonBonesAtlasAsset = cc.Class({ }, set: function (value) { this._atlasJson = value; - this.reset(); + this._clear(); } }, @@ -74,19 +74,17 @@ var DragonBonesAtlasAsset = cc.Class({ }, set (value) { this._texture = value; - this.reset(); + this._clear(); } }, + + _textureAtlasData: null, }, statics: { preventDeferredLoadDependents: true }, - reset () { - this._textureAtlasData = null; // instance of CCTextureAtlasData - }, - createNode: CC_EDITOR && function (callback) { var node = new cc.Node(this.name); var armatureDisplay = node.addComponent(dragonBones.ArmatureDisplay); @@ -96,40 +94,27 @@ var DragonBonesAtlasAsset = cc.Class({ }, init (factory) { + this._factory = factory; if (this._textureAtlasData) { - factory.addTextureAtlasData(this._textureAtlasData); + factory.addTextureAtlasData(this._textureAtlasData, this._uuid); } else { - this._textureAtlasData = factory.parseTextureAtlasData(this.atlasJson, this.texture); + this._textureAtlasData = factory.parseTextureAtlasData(this.atlasJson, this.texture, this._uuid); } - //// solve the error effect of DragonBones when re-enter an auto-released scene (#5053) - // var atlasName = atlasJsonObj.name; - // var atlasDataList = factory.getTextureAtlasData(atlasName); - // if (atlasDataList && atlasDataList.length > 0) { - // var texturePath = this.texture && this.texture.url; - // for (var idx in atlasDataList) { - // var data = atlasDataList[idx]; - // if (data && data.texture && data.texture.url === texturePath) { - // // found same named atlas, renew texture - // data.texture = this.texture; - // return; - // } - // } - // } }, - destroy () { - var useGlobalFactory = !CC_JSB; - if (useGlobalFactory && this._textureAtlasData) { - var factory = dragonBones.CCFactory.getInstance(); - // If the texture still referenced by any DragonBonesData in the factory, - // remember to remove them at the same time! - var name = this._textureAtlasData.name; - factory.removeTextureAtlasData(name, true); - factory.removeDragonBonesData(name, true); - ArmatureCache.clearByDBName(name); - ArmatureCache.clearByAtlasName(name); + _clear () { + if (CC_JSB) return; + if (this._factory) { + ArmatureCache.resetArmature(this._uuid); + this._factory.removeTextureAtlasData(this._uuid, true); + this._factory.removeDragonBonesDataByUUID(this._uuid, true); } + this._textureAtlasData = null; + }, + + destroy () { + this._clear(); this._super(); }, }); diff --git a/extensions/dragonbones/lib/dragonBones.js b/extensions/dragonbones/lib/dragonBones.js index fba16d6baeb..891fc1da9a5 100644 --- a/extensions/dragonbones/lib/dragonBones.js +++ b/extensions/dragonbones/lib/dragonBones.js @@ -13674,14 +13674,15 @@ var dragonBones; switch (displayData.type) { case 0 /* Image */: { var imageDisplayData = displayData; + + if (dataPackage !== null && dataPackage.textureAtlasName.length > 0) { + imageDisplayData.texture = this._getTextureData(dataPackage.textureAtlasName, displayData.path); + } + if (imageDisplayData.texture === null) { imageDisplayData.texture = this._getTextureData(dataName, displayData.path); } - if (imageDisplayData.texture === null || - (dataPackage !== null && dataPackage.textureAtlasName.length > 0)) { - imageDisplayData.texture = this._getTextureData(dataPackage.textureAtlasName, displayData.path); - } if (rawDisplayData !== null && rawDisplayData.type === 2 /* Mesh */ && this._isSupportMesh()) { display = slot.meshDisplay; } @@ -13692,12 +13693,15 @@ var dragonBones; } case 2 /* Mesh */: { var meshDisplayData = displayData; + + if (dataPackage !== null && dataPackage.textureAtlasName.length > 0) { + meshDisplayData.texture = this._getTextureData(dataPackage.textureAtlasName, meshDisplayData.path); + } + if (meshDisplayData.texture === null) { meshDisplayData.texture = this._getTextureData(dataName, meshDisplayData.path); } - else if (dataPackage !== null && dataPackage.textureAtlasName.length > 0) { - meshDisplayData.texture = this._getTextureData(dataPackage.textureAtlasName, meshDisplayData.path); - } + if (this._isSupportMesh()) { display = slot.meshDisplay; } diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index d2e60bfc99c..347560b6311 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -441,7 +441,6 @@ var spineAssembler = { for (let i = 0, n = locSkeleton.bones.length; i < n; i++) { bone = locSkeleton.bones[i]; - if (bone.parent == null) continue; let x = bone.data.length * bone.a + bone.worldX; let y = bone.data.length * bone.c + bone.worldY; From 8d697563d9e84919ffb3e5d11173a2a1afe2042b Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 26 Feb 2019 09:37:08 +0800 Subject: [PATCH 0476/1631] fix label rendering in open data context (#3911) --- cocos2d/core/renderer/utils/label/ttf.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 94fa0b7822c..104a5e18760 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -255,7 +255,12 @@ module.exports = { let lineHeight = this._getLineHeight(); //use round for line join to avoid sharp intersect point _context.lineJoin = 'round'; - _context.fillStyle = 'white'; + if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { + _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_color.a / 255})`; + } + else { + _context.fillStyle = 'white'; + } let underlineStartPosition; //do real rendering From 73b207a6cef12ff3b512874444806e3662b1fdb8 Mon Sep 17 00:00:00 2001 From: lingo Date: Tue, 26 Feb 2019 09:38:39 +0800 Subject: [PATCH 0477/1631] fix: shaders have same uniform name, different type will effect wrong (#3876) * fix: shaders have same uniform name, different type will effect wrong * fix shaders have same uniform name, different type will effect wrong * fix shaders have same uniform name, different type will effect wrong, refine --- cocos2d/core/renderer/render-engine.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 13261f2a379..852a6bd8457 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -10068,7 +10068,25 @@ Device.prototype.setTextureArray = function setTextureArray (name, textures, slo */ Device.prototype.setUniform = function setUniform (name, value) { var uniform = this._uniforms[name]; - if (!uniform) { + + var sameType = false; + do { + if (!uniform) { + break; + } + + if (uniform.isArray !== Array.isArray(value)) { + break; + } + + if (uniform.isArray && uniform.value.length !== value.length) { + break; + } + + sameType = true; + } while (false); + + if (!sameType) { var newValue = value; var isArray = false; if (value instanceof Float32Array || Array.isArray(value)) { @@ -10095,8 +10113,7 @@ Device.prototype.setUniform = function setUniform (name, value) { oldValue[i] = value[i]; } } - } - else { + } else { if (oldValue !== value) { dirty = true; uniform.value = value; From 228f4f2952e000205ed5a9850c01b715ea56ae54 Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 26 Feb 2019 11:31:56 +0800 Subject: [PATCH 0478/1631] add deprecated property in EditBox in v2.0 (#3912) --- cocos2d/core/components/editbox/CCEditBox.js | 10 ++++++---- editor/i18n/en/localization.js | 2 +- editor/i18n/zh/localization.js | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/components/editbox/CCEditBox.js b/cocos2d/core/components/editbox/CCEditBox.js index b87ad05d685..9fb234fb6b8 100644 --- a/cocos2d/core/components/editbox/CCEditBox.js +++ b/cocos2d/core/components/editbox/CCEditBox.js @@ -279,10 +279,11 @@ let EditBox = cc.Class({ }, /** - * !#en The input is always visible and be on top of the game view (only useful on Web). - * !zh 输入框总是可见,并且永远在游戏视图的上面(这个属性只有在 Web 上面修改有意义) + * !#en The input is always visible and be on top of the game view (only useful on Web), this property will be removed on v2.1 + * !zh 输入框总是可见,并且永远在游戏视图的上面(这个属性只有在 Web 上面修改有意义),该属性会在 v2.1 中移除 * Note: only available on Web at the moment. * @property {Boolean} stayOnTop + * @deprecated since 2.0.8 */ stayOnTop: { tooltip: CC_DEV && 'i18n:COMPONENT.editbox.stay_on_top', @@ -639,9 +640,10 @@ let EditBox = cc.Class({ }, /** - * !#en Let the EditBox get focus - * !#zh 让当前 EditBox 获得焦点 + * !#en Let the EditBox get focus, this method will be removed on v2.1 + * !#zh 让当前 EditBox 获得焦点, 这个方法会在 v2.1 中移除 * @method setFocus + * @deprecated since 2.0.8 */ setFocus () { if(this._impl) { diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index bc4fdf71a45..2045f942e3a 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -216,7 +216,7 @@ module.exports = { "input_mode": "Specify the input mode: multiline or single line.", "font_size": "The font size of input label.", "line_height": "The line height of input label.", - "stay_on_top": "Set to true and the input is always visible and be on top of the game view", + "stay_on_top": "Set to true and the input is always visible and be on top of the game view, this property will be removed on v2.1", "tab_index": "Set the tabIndex of the DOM input element, only useful on Web.", "font_color": "The font color of input label.", "placeholder": "The content string of placeholder.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 967a35ca4c6..fed5387588f 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -221,7 +221,7 @@ module.exports = { "font_size": "输入框文本的字体大小", "line_height": "输入框文本的行高", "font_color": "输入框文本的颜色", - "stay_on_top": "设置为 True 则输入框总是可见,并且永远在游戏视图的上面", + "stay_on_top": "设置为 True 则输入框总是可见,并且永远在游戏视图的上面,该属性会在 v2.1 中移除", "tab_index": "修改 DOM 输入元素的 tabIndex,这个属性只有在 Web 上面修改有意义。", "placeholder": "输入框占位符的文本内容", "placeholder_font_size": "输入框占位符的字体大小", From bd8fccf37deb893345051481747bf8a4bc58e915 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Tue, 26 Feb 2019 13:55:06 +0800 Subject: [PATCH 0479/1631] Fix dragonbones exception (#3914) --- extensions/dragonbones/CCFactory.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index 87014219414..c443762c4e0 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -177,12 +177,11 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ removeDragonBonesDataByUUID (uuid, disposeData) { if (disposeData === void 0) { disposeData = true; } for (var name in this._dragonBonesDataMap) { + if (name.indexOf(uuid) === -1) continue; if (disposeData) { this._dragonBones.bufferObject(this._dragonBonesDataMap[name]); } - if (name.indexOf(uuid) != -1) { - delete this._dragonBonesDataMap[name]; - } + delete this._dragonBonesDataMap[name]; } } }); From 557b4e1681a5773298d74cb17f1dc7b3524e170b Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 26 Feb 2019 13:57:48 +0800 Subject: [PATCH 0480/1631] add renderCamera, fixed camera.render() (#3913) --- cocos2d/core/camera/CCCamera.js | 4 ---- cocos2d/renderer/renderers/forward-renderer.js | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 5ca1d7fab6b..f7f9cad0fe5 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -105,8 +105,6 @@ let Camera = cc.Class({ 'opaque', ]); - let view = new View(); - camera.view = view; camera.dirty = true; this._inited = false; @@ -422,8 +420,6 @@ let Camera = cc.Class({ camera.setNear(0.1); camera.setFar(4096); - let view = new View(); - camera.view = view; camera.dirty = true; camera._cullingMask = 1 << cc.Node.BuiltinGroupIndex.DEBUG; diff --git a/cocos2d/renderer/renderers/forward-renderer.js b/cocos2d/renderer/renderers/forward-renderer.js index 39ad72cb513..b959c7bf53a 100644 --- a/cocos2d/renderer/renderers/forward-renderer.js +++ b/cocos2d/renderer/renderers/forward-renderer.js @@ -75,6 +75,20 @@ export default class ForwardRenderer extends BaseRenderer { } } + // direct render a single camera + renderCamera (camera, scene) { + this._reset(); + + const canvas = this._device._gl.canvas; + let width = canvas.width; + let height = canvas.height; + + let view = this._requestView(); + camera.extractView(view, width, height); + + this._render(view, scene); + } + _updateLights (scene) { this._directionalLights.length = 0; this._pointLights.length = 0; From d1494deca14b2d0e2f8a218098c20f2b745c9f1e Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 26 Feb 2019 14:15:38 +0800 Subject: [PATCH 0481/1631] support etc compress format (#3894) --- cocos2d/core/assets/CCTexture2D.js | 59 ++++++++++++++++--- cocos2d/core/assets/material/CCMaterial.js | 2 +- cocos2d/core/load-pipeline/loader.js | 31 ++++++---- cocos2d/core/platform/CCMacro.js | 10 +--- .../renderer/utils/dynamic-atlas/manager.js | 2 +- cocos2d/renderer/gfx/device.js | 1 + cocos2d/renderer/gfx/enums.js | 19 +++++- cocos2d/renderer/gfx/index.js | 2 + cocos2d/renderer/gfx/texture-2d.js | 8 +-- cocos2d/renderer/gfx/texture-cube.js | 8 +-- 10 files changed, 103 insertions(+), 39 deletions(-) diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 9a2cd48e2f0..51aeb50a0e4 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -154,12 +154,34 @@ const PixelFormat = cc.Enum({ */ RGBA_PVRTC_4BPPV1: gfx.TEXTURE_FMT_RGBA_PVRTC_4BPPV1, /** - * rgb etc + * rgb etc1 * @property RGB_ETC1 * @readonly * @type {Number} */ RGB_ETC1: gfx.TEXTURE_FMT_RGB_ETC1, + /** + * rgba etc1 + * @property RGBA_ETC1 + * @readonly + * @type {Number} + */ + RGBA_ETC1: gfx.glTextureFmtCount(), + + /** + * rgb etc2 + * @property RGB_ETC2 + * @readonly + * @type {Number} + */ + RGB_ETC2: gfx.TEXTURE_FMT_RGB_ETC2, + /** + * rgba etc2 + * @property RGBA_ETC2 + * @readonly + * @type {Number} + */ + RGBA_ETC2: gfx.TEXTURE_FMT_RGBA_ETC2, }); /** @@ -288,11 +310,6 @@ var Texture2D = cc.Class({ // predefined most common extnames extnames: ['.png', '.jpg', '.jpeg', '.bmp', '.webp', '.pvr', '.pkm'], - - _isCompressed (texture) { - let format = texture._format; - return (format >= PixelFormat.RGB_PVRTC_2BPPV1 && format <= PixelFormat.RGBA_PVRTC_4BPPV1) || format === PixelFormat.RGB_ETC1; - } }, ctor () { @@ -500,6 +517,9 @@ var Texture2D = cc.Class({ opts.wrapS = this._wrapS; opts.wrapT = this._wrapT; opts.format = pixelFormat; + if (pixelFormat === PixelFormat.RGBA_ETC1) { + opts.format = PixelFormat.RGB_ETC1; + } opts.width = pixelsWidth; opts.height = pixelsHeight; if (!this._texture) { @@ -601,6 +621,9 @@ var Texture2D = cc.Class({ opts.height = this.height; opts.hasMipmap = this._hasMipmap; opts.format = this._format; + if (this._format === PixelFormat.RGBA_ETC1) { + opts.format = PixelFormat.RGB_ETC1; + } opts.premultiplyAlpha = this._premultiplyAlpha; opts.flipY = this._flipY; opts.minFilter = FilterIndex[this._minFilter]; @@ -793,9 +816,11 @@ var Texture2D = cc.Class({ }, _deserialize: function (data, handle) { + let device = cc.renderer.device; + let fields = data.split(','); // decode extname - var extIdStr = fields[0]; + let extIdStr = fields[0]; if (extIdStr) { let extIds = extIdStr.split('_'); @@ -811,9 +836,23 @@ var Texture2D = cc.Class({ let index = SupportTextureFormats.indexOf(tmpExt); if (index !== -1 && index < extId) { + + let tmpFormat = extFormat[1] ? parseInt(extFormat[1]) : this._format; + + // check whether or not support compressed texture + if ( tmpExt === '.pvr' && !device.ext('WEBGL_compressed_texture_pvrtc')) { + continue; + } + else if ((tmpFormat === PixelFormat.RGB_ETC1 || tmpFormat === PixelFormat.RGBA_ETC1) && !device.ext('WEBGL_compressed_texture_etc1')) { + continue; + } + else if ((tmpFormat === PixelFormat.RGB_ETC2 || tmpFormat === PixelFormat.RGBA_ETC2) && !device.ext('WEBGL_compressed_texture_etc')) { + continue; + } + extId = index; ext = tmpExt; - format = extFormat[1] ? parseInt(extFormat[1]) : this._format; + format = tmpFormat; } } @@ -859,6 +898,10 @@ var Texture2D = cc.Class({ this._hash = parseInt(`${minFilter}${magFilter}${pixelFormat}${wrapS}${wrapT}${hasMipmap}${premultiplyAlpha}${flipY}`); this._hashDirty = false; return this._hash; + }, + + _isCompressed () { + return this._texture && this._texture._compressed; } }); diff --git a/cocos2d/core/assets/material/CCMaterial.js b/cocos2d/core/assets/material/CCMaterial.js index 04f10259d61..a26e0cd1b51 100644 --- a/cocos2d/core/assets/material/CCMaterial.js +++ b/cocos2d/core/assets/material/CCMaterial.js @@ -143,7 +143,7 @@ let Material = cc.Class({ if (this._effect) { if (val instanceof Texture) { this._effect.setProperty(name, val.getImpl()); - if (val.getPixelFormat() === PixelFormat.RGB_ETC1) { + if (val.getPixelFormat() === PixelFormat.RGBA_ETC1) { this.define('_USE_ETC1_' + name.toUpperCase(), true); } } diff --git a/cocos2d/core/load-pipeline/loader.js b/cocos2d/core/load-pipeline/loader.js index a04c7af2239..12f9c9ddadf 100644 --- a/cocos2d/core/load-pipeline/loader.js +++ b/cocos2d/core/load-pipeline/loader.js @@ -154,25 +154,34 @@ function loadPVRTex (item) { //===============// // ETC constants // //===============// -const ETC1_PKM_FORMAT_OFFSET = 6; -const ETC1_PKM_ENCODED_WIDTH_OFFSET = 8; -const ETC1_PKM_ENCODED_HEIGHT_OFFSET = 10; -const ETC1_PKM_WIDTH_OFFSET = 12; -const ETC1_PKM_HEIGHT_OFFSET = 14; -const ETC1_RGB_NO_MIPMAPS = 0; + 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]; } function loadPKMTex(item) { let buffer = item.content instanceof ArrayBuffer ? item.content : item.content.buffer; let header = new Uint8Array(buffer); - if (readBEUint16(header, ETC1_PKM_FORMAT_OFFSET) !== ETC1_RGB_NO_MIPMAPS) return new Error("Invalid magic number in ETC header"); - let width = readBEUint16(header, ETC1_PKM_WIDTH_OFFSET); - let height = readBEUint16(header, ETC1_PKM_HEIGHT_OFFSET); - let encodedWidth = readBEUint16(header, ETC1_PKM_ENCODED_WIDTH_OFFSET); - let encodedHeight = readBEUint16(header, ETC1_PKM_ENCODED_HEIGHT_OFFSET); + 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); let etcAsset = { _data: etcData, diff --git a/cocos2d/core/platform/CCMacro.js b/cocos2d/core/platform/CCMacro.js index 8b1d4672fdd..ff960b6fb4a 100644 --- a/cocos2d/core/platform/CCMacro.js +++ b/cocos2d/core/platform/CCMacro.js @@ -356,15 +356,7 @@ cc.macro = { }; -let SUPPORT_TEXTURE_FORMATS = ['.webp', '.jpg', '.jpeg', '.bmp', '.png']; -if (cc.sys.isMobile) { - if (cc.sys.os === cc.sys.OS_IOS) { - SUPPORT_TEXTURE_FORMATS = ['.pvr'].concat(SUPPORT_TEXTURE_FORMATS); - } - else if (cc.sys.os === cc.sys.OS_ANDROID) { - SUPPORT_TEXTURE_FORMATS = ['.pkm'].concat(SUPPORT_TEXTURE_FORMATS); - } -} +let SUPPORT_TEXTURE_FORMATS = ['.pkm', '.pvr', '.webp', '.jpg', '.jpeg', '.bmp', '.png']; /** * !en diff --git a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js index d187786cfa9..fe996eff9ba 100644 --- a/cocos2d/core/renderer/utils/dynamic-atlas/manager.js +++ b/cocos2d/core/renderer/utils/dynamic-atlas/manager.js @@ -108,7 +108,7 @@ let dynamicAtlasManager = { !spriteFrame || spriteFrame._original) return null; let texture = spriteFrame._texture; - if (texture instanceof cc.RenderTexture || cc.Texture2D._isCompressed(texture)) return null; + if (texture instanceof cc.RenderTexture || texture._isCompressed()) return null; let w = texture.width, h = texture.height; if (w > _maxFrameSize || h > _maxFrameSize || w <= _minFrameSize || h <= _minFrameSize diff --git a/cocos2d/renderer/gfx/device.js b/cocos2d/renderer/gfx/device.js index cef71fd0b85..0aa4528998d 100644 --- a/cocos2d/renderer/gfx/device.js +++ b/cocos2d/renderer/gfx/device.js @@ -623,6 +623,7 @@ export default class Device { 'OES_texture_half_float_linear', 'OES_vertex_array_object', 'WEBGL_compressed_texture_atc', + 'WEBGL_compressed_texture_etc', 'WEBGL_compressed_texture_etc1', 'WEBGL_compressed_texture_pvrtc', 'WEBGL_compressed_texture_s3tc', diff --git a/cocos2d/renderer/gfx/enums.js b/cocos2d/renderer/gfx/enums.js index 16e34dfc7a8..8e6c5a8a866 100644 --- a/cocos2d/renderer/gfx/enums.js +++ b/cocos2d/renderer/gfx/enums.js @@ -36,6 +36,9 @@ const GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; // ext.COMPRESSED_RGBA_PVRTC const GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; // ext.COMPRESSED_RGB_ETC1_WEBGL +const GL_COMPRESSED_RGB8_ETC2 = 0x9274; // ext.COMPRESSED_RGB8_ETC2 +const GL_COMPRESSED_RGBA8_ETC2_EAC = 0x9278; // ext.COMPRESSED_RGBA8_ETC2_EAC + const _filterGL = [ [ GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR ], [ GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR ], @@ -124,7 +127,13 @@ const _textureFmtGL = [ { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_INT }, // TEXTURE_FMT_D24S8: 27 - { format: null, internalFormat: null, pixelType: null }, + { format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_INT }, + + // TEXTURE_FMT_RGB_ETC2: 28 + { format: GL_RGB, internalFormat: GL_COMPRESSED_RGB8_ETC2, pixelType: null }, + + // TEXTURE_FMT_RGBA_ETC2: 29 + { format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA8_ETC2_EAC, pixelType: null }, ]; /** @@ -214,6 +223,10 @@ export const enums = { TEXTURE_FMT_D32: 26, TEXTURE_FMT_D24S8: 27, + // etc2 format + TEXTURE_FMT_RGB_ETC2: 28, + TEXTURE_FMT_RGBA_ETC2: 29, + // depth and stencil function DS_FUNC_NEVER: 512, // gl.NEVER DS_FUNC_LESS: 513, // gl.LESS @@ -333,4 +346,8 @@ export function glTextureFmt(fmt) { } return result; +} + +export function glTextureFmtCount() { + return _textureFmtGL.length; } \ No newline at end of file diff --git a/cocos2d/renderer/gfx/index.js b/cocos2d/renderer/gfx/index.js index 7687de67740..3fb03f0a670 100644 --- a/cocos2d/renderer/gfx/index.js +++ b/cocos2d/renderer/gfx/index.js @@ -3,6 +3,7 @@ import { attrTypeBytes, glFilter, glTextureFmt, + glTextureFmtCount } from './enums'; import VertexFormat from './vertex-format'; @@ -33,6 +34,7 @@ let gfx = { attrTypeBytes, glFilter, glTextureFmt, + glTextureFmtCount }; Object.assign(gfx, enums); diff --git a/cocos2d/renderer/gfx/texture-2d.js b/cocos2d/renderer/gfx/texture-2d.js index c2bad215f09..9a9a4c59fc2 100644 --- a/cocos2d/renderer/gfx/texture-2d.js +++ b/cocos2d/renderer/gfx/texture-2d.js @@ -65,10 +65,10 @@ export default class Texture2D extends Texture { } if (options.format !== undefined) { this._format = options.format; - this._compressed = ( - this._format >= enums.TEXTURE_FMT_RGB_DXT1 && - this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1 - ); + this._compressed = + (this._format >= enums.TEXTURE_FMT_RGB_DXT1 && this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1) || + (this._format >= enums.TEXTURE_FMT_RGB_ETC2 && this._format <= enums.TEXTURE_FMT_RGBA_ETC2) + ; } // check if generate mipmap diff --git a/cocos2d/renderer/gfx/texture-cube.js b/cocos2d/renderer/gfx/texture-cube.js index 0c019236d08..538b1612467 100644 --- a/cocos2d/renderer/gfx/texture-cube.js +++ b/cocos2d/renderer/gfx/texture-cube.js @@ -83,10 +83,10 @@ export default class TextureCube extends Texture { // } if (options.format !== undefined) { this._format = options.format; - this._compressed = ( - this._format >= enums.TEXTURE_FMT_RGB_DXT1 && - this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1 - ); + this._compressed = + (this._format >= enums.TEXTURE_FMT_RGB_DXT1 && this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1) || + (this._format >= enums.TEXTURE_FMT_RGB_ETC2 && this._format <= enums.TEXTURE_FMT_RGBA_ETC2) + ; } // check if generate mipmap From 652484cd0f692489298b51b233c73c454f9cec13 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 26 Feb 2019 14:38:58 +0800 Subject: [PATCH 0482/1631] refine PixelFormat.RGBA_ETC1 definition (#3915) --- cocos2d/core/assets/CCTexture2D.js | 3 ++- cocos2d/renderer/gfx/enums.js | 4 ---- cocos2d/renderer/gfx/index.js | 2 -- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 51aeb50a0e4..4d674e5b2cc 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -166,7 +166,8 @@ const PixelFormat = cc.Enum({ * @readonly * @type {Number} */ - RGBA_ETC1: gfx.glTextureFmtCount(), + // gfx do not have a standard definition for RGBA_ETC1, need define a specified number for it. + RGBA_ETC1: 1024, /** * rgb etc2 diff --git a/cocos2d/renderer/gfx/enums.js b/cocos2d/renderer/gfx/enums.js index 8e6c5a8a866..1b1f6a653a0 100644 --- a/cocos2d/renderer/gfx/enums.js +++ b/cocos2d/renderer/gfx/enums.js @@ -346,8 +346,4 @@ export function glTextureFmt(fmt) { } return result; -} - -export function glTextureFmtCount() { - return _textureFmtGL.length; } \ No newline at end of file diff --git a/cocos2d/renderer/gfx/index.js b/cocos2d/renderer/gfx/index.js index 3fb03f0a670..7687de67740 100644 --- a/cocos2d/renderer/gfx/index.js +++ b/cocos2d/renderer/gfx/index.js @@ -3,7 +3,6 @@ import { attrTypeBytes, glFilter, glTextureFmt, - glTextureFmtCount } from './enums'; import VertexFormat from './vertex-format'; @@ -34,7 +33,6 @@ let gfx = { attrTypeBytes, glFilter, glTextureFmt, - glTextureFmtCount }; Object.assign(gfx, enums); From ceeaad6d690e2469144b1bbdbfa2c70b3d91620d Mon Sep 17 00:00:00 2001 From: Knox Date: Tue, 26 Feb 2019 18:35:07 +0800 Subject: [PATCH 0483/1631] revert particles system attribute definition (#3919) --- cocos2d/particle/CCParticleSystem.js | 155 ++++++--------------------- 1 file changed, 31 insertions(+), 124 deletions(-) diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index a1baeeaf18b..465730c97bc 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -390,50 +390,35 @@ var properties = { * @property {Number} totalParticles * @default 150 */ - totalParticles: { - default: 150, - formerlySerializedAs: '_totalParticles' - }, + totalParticles: 150, /** * !#en How many seconds the emitter wil run. -1 means 'forever'. * !#zh 发射器生存时间,单位秒,-1表示持续发射。 * @property {Number} duration * @default ParticleSystem.DURATION_INFINITY */ - duration: { - default: -1, - formerlySerializedAs: '_duration' - }, + duration: -1, /** * !#en Emission rate of the particles. * !#zh 每秒发射的粒子数目。 * @property {Number} emissionRate * @default 10 */ - emissionRate: { - default: 10, - formerlySerializedAs: '_emissionRate' - }, + emissionRate: 10, /** * !#en Life of each particle setter. * !#zh 粒子的运行时间。 * @property {Number} life * @default 1 */ - life: { - default: 1, - formerlySerializedAs: '_life' - }, + life: 1, /** * !#en Variation of life. * !#zh 粒子的运行时间变化范围。 * @property {Number} lifeVar * @default 0 */ - lifeVar: { - default: 0, - formerlySerializedAs: '_lifeVar' - }, + lifeVar: 0, /** * !#en Start color of each particle. @@ -518,100 +503,70 @@ var properties = { * @property {Number} angle * @default 90 */ - angle: { - default: 90, - formerlySerializedAs: '_angle' - }, + angle: 90, /** * !#en Variation of angle of each particle setter. * !#zh 粒子角度变化范围。 * @property {Number} angleVar * @default 20 */ - angleVar: { - default: 20, - formerlySerializedAs: '_angleVar' - }, + angleVar: 20, /** * !#en Start size in pixels of each particle. * !#zh 粒子的初始大小。 * @property {Number} startSize * @default 50 */ - startSize: { - default: 50, - formerlySerializedAs: '_startSize' - }, + startSize: 50, /** * !#en Variation of start size in pixels. * !#zh 粒子初始大小的变化范围。 * @property {Number} startSizeVar * @default 0 */ - startSizeVar: { - default: 0, - formerlySerializedAs: '_startSizeVar' - }, + startSizeVar: 0, /** * !#en End size in pixels of each particle. * !#zh 粒子结束时的大小。 * @property {Number} endSize * @default 0 */ - endSize: { - default: 0, - formerlySerializedAs: '_endSize' - }, + endSize: 0, /** * !#en Variation of end size in pixels. * !#zh 粒子结束大小的变化范围。 * @property {Number} endSizeVar * @default 0 */ - endSizeVar: { - default: 0, - formerlySerializedAs: '_endSizeVar' - }, + endSizeVar: 0, /** * !#en Start angle of each particle. * !#zh 粒子开始自旋角度。 * @property {Number} startSpin * @default 0 */ - startSpin: { - default: 0, - formerlySerializedAs: '_startSpin' - }, + startSpin: 0, /** * !#en Variation of start angle. * !#zh 粒子开始自旋角度变化范围。 * @property {Number} startSpinVar * @default 0 */ - startSpinVar: { - default: 0, - formerlySerializedAs: '_startSpinVar' - }, + startSpinVar: 0, /** * !#en End angle of each particle. * !#zh 粒子结束自旋角度。 * @property {Number} endSpin * @default 0 */ - endSpin: { - default: 0, - formerlySerializedAs: '_endSpin' - }, + endSpin: 0, /** * !#en Variation of end angle. * !#zh 粒子结束自旋角度变化范围。 * @property {Number} endSpinVar * @default 0 */ - endSpinVar: { - default: 0, - formerlySerializedAs: '_endSpinVar' - }, + endSpinVar: 0, /** * !#en Source position of the emitter. @@ -619,10 +574,7 @@ var properties = { * @property {Vec2} sourcePos * @default cc.Vec2.ZERO */ - sourcePos: { - default: cc.Vec2.ZERO, - formerlySerializedAs: '_sourcePos' - }, + sourcePos: cc.Vec2.ZERO, /** * !#en Variation of source position. @@ -630,10 +582,7 @@ var properties = { * @property {Vec2} posVar * @default cc.Vec2.ZERO */ - posVar: { - default: cc.Vec2.ZERO, - formerlySerializedAs: '_posVar' - }, + posVar: cc.Vec2.ZERO, /** * !#en Particles movement type. @@ -665,70 +614,49 @@ var properties = { * @property {Vec2} gravity * @default cc.Vec2.ZERO */ - gravity: { - default: cc.Vec2.ZERO, - formerlySerializedAs: '_gravity' - }, + gravity: cc.Vec2.ZERO, /** * !#en Speed of the emitter. * !#zh 速度。 * @property {Number} speed * @default 180 */ - speed: { - default: 180, - formerlySerializedAs: '_speed' - }, + speed: 180, /** * !#en Variation of the speed. * !#zh 速度变化范围。 * @property {Number} speedVar * @default 50 */ - speedVar: { - default: 50, - formerlySerializedAs: '_speedVar' - }, + speedVar: 50, /** * !#en Tangential acceleration of each particle. Only available in 'Gravity' mode. * !#zh 每个粒子的切向加速度,即垂直于重力方向的加速度,只有在重力模式下可用。 * @property {Number} tangentialAccel * @default 80 */ - tangentialAccel: { - default: 80, - formerlySerializedAs: '_tangentialAccel' - }, + tangentialAccel: 80, /** * !#en Variation of the tangential acceleration. * !#zh 每个粒子的切向加速度变化范围。 * @property {Number} tangentialAccelVar * @default 0 */ - tangentialAccelVar: { - default: 0, - formerlySerializedAs: '_tangentialAccelVar' - }, + tangentialAccelVar: 0, /** * !#en Acceleration of each particle. Only available in 'Gravity' mode. * !#zh 粒子径向加速度,即平行于重力方向的加速度,只有在重力模式下可用。 * @property {Number} radialAccel * @default 0 */ - radialAccel: { - default: 0, - formerlySerializedAs: '_radialAccel' - }, + radialAccel: 0, /** * !#en Variation of the radial acceleration. * !#zh 粒子径向加速度变化范围。 * @property {Number} radialAccelVar * @default 0 */ - radialAccelVar: { - default: 0, - formerlySerializedAs: '_radialAccelVar' - }, + radialAccelVar: 0, /** * !#en Indicate whether the rotation of each particle equals to its direction. Only available in 'Gravity' mode. @@ -736,10 +664,7 @@ var properties = { * @property {Boolean} rotationIsDir * @default false */ - rotationIsDir: { - default: false, - formerlySerializedAs: '_rotationIsDir' - }, + rotationIsDir: false, // RADIUS MODE @@ -749,60 +674,42 @@ var properties = { * @property {Number} startRadius * @default 0 */ - startRadius: { - default: 0, - formerlySerializedAs: '_startRadius' - }, + startRadius: 0, /** * !#en Variation of the starting radius. * !#zh 初始半径变化范围。 * @property {Number} startRadiusVar * @default 0 */ - startRadiusVar: { - default: 0, - formerlySerializedAs: '_startRadiusVar' - }, + startRadiusVar: 0, /** * !#en Ending radius of the particles. Only available in 'Radius' mode. * !#zh 结束半径,只有在半径模式下可用。 * @property {Number} endRadius * @default 0 */ - endRadius: { - default: 0, - formerlySerializedAs: '_endRadius' - }, + endRadius: 0, /** * !#en Variation of the ending radius. * !#zh 结束半径变化范围。 * @property {Number} endRadiusVar * @default 0 */ - endRadiusVar: { - default: 0, - formerlySerializedAs: '_endRadiusVar' - }, + endRadiusVar: 0, /** * !#en Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode. * !#zh 粒子每秒围绕起始点的旋转角度,只有在半径模式下可用。 * @property {Number} rotatePerS * @default 0 */ - rotatePerS: { - default: 0, - formerlySerializedAs: '_rotatePerS' - }, + rotatePerS: 0, /** * !#en Variation of the degress to rotate a particle around the source pos per second. * !#zh 粒子每秒围绕起始点的旋转角度变化范围。 * @property {Number} rotatePerSVar * @default 0 */ - rotatePerSVar: { - default: 0, - formerlySerializedAs: '_rotatePerSVar' - } + rotatePerSVar: 0 }; From bfb3433966bb9bcde65bd9342aba3c2635a6e074 Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 27 Feb 2019 10:38:45 +0800 Subject: [PATCH 0484/1631] fix emit target scale changed events twice (#3922) --- cocos2d/core/components/CCButton.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index de644281242..5bb8448a7ca 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -422,12 +422,13 @@ let Button = cc.Class({ // // Restore button status let target = this._getTarget(); let transition = this.transition; + let originalScale = this._originalScale; + if (transition === Transition.COLOR && this.interactable) { this._setTargetColor(this.normalColor); } - else if (transition === Transition.SCALE && this._originalScale) { - target.scaleX = this._originalScale.x; - target.scaleY = this._originalScale.y; + else if (transition === Transition.SCALE && originalScale) { + target.setScale(originalScale.x, originalScale.y); } this._transitionFinished = true; }, @@ -656,19 +657,19 @@ let Button = cc.Class({ let touch = event.touch; let hit = this.node._hitTest(touch.getLocation()); let target = this._getTarget(); + let originalScale = this._originalScale; - if (this.transition === Transition.SCALE && this._originalScale) { + if (this.transition === Transition.SCALE && originalScale) { if (hit) { - this._fromScale.x = this._originalScale.x; - this._fromScale.y = this._originalScale.y; - this._toScale.x = this._originalScale.x * this.zoomScale; - this._toScale.y = this._originalScale.y * this.zoomScale; + this._fromScale.x = originalScale.x; + this._fromScale.y = originalScale.y; + this._toScale.x = originalScale.x * this.zoomScale; + this._toScale.y = originalScale.y * this.zoomScale; this._transitionFinished = false; } else { this.time = 0; this._transitionFinished = true; - target.scaleX = this._originalScale.x; - target.scaleY = this._originalScale.y; + target.setScale(originalScale.x, originalScale.y); } } else { let state; From b3dfa7b19fcbdc7e32f1db643e7f9ed729f0e019 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Wed, 27 Feb 2019 10:39:06 +0800 Subject: [PATCH 0485/1631] add the tween test case (#3908) * add the tween test case * modify the format of the test-tween.js 1. keep all chain method start at the char 'n' below * fixed the tween bugs --- cocos2d/actions/tween.js | 4 +- test/qunit/unit-es5/_init.js | 3 +- test/qunit/unit-es5/test-tween.js | 149 ++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 4 deletions(-) create mode 100644 test/qunit/unit-es5/test-tween.js diff --git a/cocos2d/actions/tween.js b/cocos2d/actions/tween.js index 92b021af555..d9761cfd93b 100644 --- a/cocos2d/actions/tween.js +++ b/cocos2d/actions/tween.js @@ -1,6 +1,6 @@ let TweenAction = cc.Class({ - name: 'TweenAction', + name: 'cc.TweenAction', extends: cc.ActionInterval, ctor (duration, props, opts) { @@ -224,7 +224,7 @@ Tween.prototype._get = function () { actions = actions[0]; } else { - actions = Tween.sequence(actions); + actions = cc.sequence(actions); } return actions; diff --git a/test/qunit/unit-es5/_init.js b/test/qunit/unit-es5/_init.js index 8e046b1ce61..1de2e837e65 100644 --- a/test/qunit/unit-es5/_init.js +++ b/test/qunit/unit-es5/_init.js @@ -211,9 +211,8 @@ function _resetGame (w, h) { } // Forbid render in test cc.renderer.render = function () {}; - cc.director.purgeDirector(); cc.loader.releaseAll(); - + cc.director.reset(); cc.director.runSceneImmediate(new cc.Scene()); //cc.director.pause(); } diff --git a/test/qunit/unit-es5/test-tween.js b/test/qunit/unit-es5/test-tween.js new file mode 100644 index 00000000000..7e40fab8645 --- /dev/null +++ b/test/qunit/unit-es5/test-tween.js @@ -0,0 +1,149 @@ +largeModule('Tween', SetupEngine); + +var tween = cc.tween; +// init a new node +function initNode(name) { + var node = new cc.Node(); + node.name = name; + node.position = cc.v2(0, 0); + node.scale = 1; + node.anchorX = 0.5; + node.anchorY = 0.5; + node.width = 100; + node.height = 100; + node.rotation = 0; + return node; +} + +asyncTest('basic test', function () { + cc.game.resume(); + var node1 = initNode('node1'); + tween(node1) + .to(1, { scale: 2 }) + .call(function () { + strictEqual(node1.scale, 2, 'tween to scale'); + }) + .by(1, { scale: 2 }) + .call(function () { + strictEqual(node1.scale, 4, 'tween by scale'); + start(); + }) + .start(); + + var obj = { a: 0 }; + tween(obj) + .to(0.5, { a: 100 }) + .call(function () { + strictEqual(obj.a, 100, 'Object propertype test'); + }) + .start(); + + var node2 = initNode('node2'); + var node3 = initNode('node3'); + let count = 0; + function check() { + if (node2.scale !== 1 && node3.scale !== 1) { + count++; + if (count === 2) { + strictEqual(node2.scale, 2, 'run tween on different target: node2'); + strictEqual(node3.scale, 2, 'run tween on different target: node3'); + } + } + } + var tmpTween = tween().to(0.5, { scale: 2 }).call(check); + // run tween on different target + tmpTween.clone(node2).start(); + tmpTween.clone(node3).start(); +}); + +function actionUpdate(action, node, t) { + if (action._actions.length <= 0) return; + let actions = action._actions; + for (let i = 0; i < actions.length; i++) { + actions[i].startWithTarget(node); + // The range of t is 0 ~ 1 + actions[i].update(t); + } +} + +test('ease test', function () { + cc.game.resume(); + // builtin easing + var node = initNode('easeNode'); + let action = tween(node).to(0.1, { scale: 2 }, { easing: 'sineOutIn' }); + actionUpdate(action, node, 0.5); + deepEqual(node.scale, 1.5, 'easeing can set value'); + + // custom easing + node.scale = 1; + action = tween(node).to(0.1, { scale: 2 }, { easing: function (t) { return t * t; } }); + actionUpdate(action, node, 0.9); + deepEqual(node.scale, 1.81, 'easeing can set calculation equation.'); + + // easing to single property + node.scale = 1; + action = tween(node) + .to(0.5, { + scale: 2, + position: { + value: cc.v2(100, 100), + easing: 'sineOutIn' + } + }); + actionUpdate(action, node, 1 / 6.0); + deepClose(node.scale, 1 + (1 / 6.0), 0.01, 'easeing can set multiple value: scale'); + deepClose(node.position, cc.v2(25, 25), 0.01, 'easeing can set multiple value: position'); + +}); + +asyncTest('progress test', function () { + cc.game.resume(); + var node = initNode('progressNode'); + // custom property progress + tween(node) + .to(0.1, { scale: 2 }, { + progress: function (start, end, current, t) { + return start + (end - start) * t; + } + }) + .call(function () { strictEqual(node.scale, 2, 'tween can set progress property'); }) + .start(); + // custom property progress to single property + node.scale = 1; + tween(node) + .to(0.5, { + scale: 2, + position: { + value: cc.v2(100, 100), + progress: function (start, end, current, t) { + return start.lerp(end, t, current); + } + } + }) + .call(function () { + strictEqual(node.scale, 2, 'custom property progress: scale not setting'); + deepEqual(node.position, cc.v2(100, 100), 'custom property progress to single property: position'); + start(); + }) + .start(); +}); + +asyncTest('reuse test', function () { + cc.game.resume(); + var scale = tween().to(0.5, { scale: 2 }); + var angle = tween().to(0.5, { rotation: 90 }); + var position = tween().to(0.5, { position: cc.v2(100, 100) }); + + var node = initNode('reuseNode'); + tween(node) + .then(scale) + .then(angle) + .then(position) + .call(function () { + strictEqual(node.scale, 2, 'reuse check: scale'); + strictEqual(node.rotation, 90, 'reuse check: rotation'); + deepEqual(node.position, cc.v2(100, 100), 'reuse check: postion'); + start(); + }) + .start(); +}); \ No newline at end of file From a2627db9046f228d7bea14aa284264aeabf174f1 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Wed, 27 Feb 2019 14:59:03 +0800 Subject: [PATCH 0486/1631] Fix spine premultipliedAlpha serialize bug (#3924) --- extensions/spine/Skeleton.js | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 31e8db7ba4e..8443e29c381 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -310,7 +310,6 @@ sp.Skeleton = cc.Class({ */ premultipliedAlpha: { default: true, - formerlySerializedAs: "_premultipliedAlpha", tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.premultipliedAlpha' }, From ef9d55bfea794368468b8c372b6daa6574ea50bf Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Thu, 28 Feb 2019 09:24:22 +0800 Subject: [PATCH 0487/1631] cancel disable dynamic atlas on chrome. (#3929) --- cocos2d/core/CCGame.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 07ee3911eca..c53297e5a82 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -796,10 +796,6 @@ var game = { if (!cc.macro.CLEANUP_IMAGE_CACHE && dynamicAtlasManager) { dynamicAtlasManager.enabled = true; } - // Disable dynamicAtlasManager to fix rendering residue for transparent images on Chrome69. - if (cc.sys.browserType === cc.sys.BROWSER_TYPE_CHROME && parseFloat(cc.sys.browserVersion) >= 69.0) { - dynamicAtlasManager.enabled = false; - } } if (!this._renderContext) { this.renderType = this.RENDER_TYPE_CANVAS; From 6c8a09aa09c52b97ca194493576eddd890d33dba Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Thu, 28 Feb 2019 10:35:36 +0800 Subject: [PATCH 0488/1631] Add cache mode of label. (#3916) * Add cache mode of label. * fix revised comments of pr. * Simplified variable name. * share canvas pool. * cancel use node color. * modify comment and reserve _batchAsBitMap. * optimize the assignment of color and delete blendFactor. * delete reserveImage. * modify to center alignment. * modify letter-font do not use node color. * add outline support of letter-font * add letter atlas reset on editor when scene loaded. * change LETTER to CHAR * modify comment --- cocos2d/core/assets/CCTexture2D.js | 14 +- cocos2d/core/components/CCLabel.js | 98 +- .../core/renderer/utils/label/letter-font.js | 915 ++++++++++++++++++ cocos2d/core/renderer/utils/label/ttf.js | 70 +- .../renderer/webgl/assemblers/label/index.js | 29 +- .../webgl/assemblers/label/letter-font.js | 135 +++ .../renderer/webgl/assemblers/label/ttf.js | 7 +- editor/i18n/en/localization.js | 2 +- editor/i18n/zh/localization.js | 2 +- 9 files changed, 1182 insertions(+), 90 deletions(-) create mode 100644 cocos2d/core/renderer/utils/label/letter-font.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/label/letter-font.js diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index a9409d8cce3..86aac6f52c8 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -558,11 +558,7 @@ var Texture2D = cc.Class({ this.emit("load"); if (cc.macro.CLEANUP_IMAGE_CACHE && this._image instanceof HTMLImageElement) { - // wechat game platform will cache image parsed data, - // so image will consume much more memory than web, releasing it - this._image.src = ""; - // Release image in loader cache - cc.loader.removeItem(this._image.id); + this._clearImage(); } }, @@ -735,6 +731,14 @@ var Texture2D = cc.Class({ this._hash = parseInt(`${minFilter}${magFilter}${pixelFormat}${wrapS}${wrapT}${hasMipmap}${premultiplyAlpha}${flipY}`); this._hashDirty = false; return this._hash; + }, + + _clearImage () { + // wechat game platform will cache image parsed data, + // so image will consume much more memory than web, releasing it + this._image.src = ""; + // Release image in loader cache + cc.loader.removeItem(this._image.id); } }); diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index e7bd86d6284..e78d91c1a3d 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -128,6 +128,27 @@ const Overflow = cc.Enum({ * @property {Number} SystemFont */ + /** + * !#en Do not do any caching. + * !#zh 不做任何缓存。 + * @property {Number} NONE + */ +/** + * !#en In BITMAP mode, cache the label as a static image and add it to the dynamic atlas for batch rendering, and can batching with Sprites using broken images. + * !#zh BITMAP 模式,将 label 缓存成静态图像并加入到动态图集,以便进行批次合并,可与使用碎图的 Sprite 进行合批(注:动态图集在 Chrome 以及微信小游戏暂时关闭,该功能无效)。 + * @property {Number} BITMAP + */ +/** + * !#en In CHAR mode, split text into characters and cache characters into a dynamic atlas which the size of 2048*2048. + * !#zh CHAR 模式,将文本拆分为字符,并将字符缓存到一张单独的大小为 2048*2048 的图集中进行重复使用,不再使用动态图集(注:当图集满时将不再进行缓存,暂时不支持 SHRINK 自适应文本尺寸(后续完善))。 + * @property {Number} CHAR + */ +const CacheMode = cc.Enum({ + NONE: 0, + BITMAP: 1, + CHAR: 2, +}); + /** * !#en The Label Component. * !#zh 文字标签组件 @@ -148,6 +169,7 @@ let Label = cc.Class({ this._frame = null; this._ttfTexture = null; + this._letterTexture = null; }, editor: CC_EDITOR && { @@ -433,29 +455,32 @@ let Label = cc.Class({ } }, + //For compatibility with v2.0.x temporary reservation. _batchAsBitmap: false, + /** - * !#en Whether cache label to static texture and draw in dynamicAtlas. - * !#zh 是否将label缓存成静态图像并加入到动态图集.(对于静态文本建议使用该选项,便于批次合并减少drawcall) - * @property {Boolean} batchAsBitmap + * !#en The cache mode of label. This mode only supports system fonts. + * !#zh 文本缓存模式, 该模式只支持系统字体。 + * @property {Label.CacheMode} cacheMode */ - batchAsBitmap: { - get () { - return this._batchAsBitmap; - }, - set (value) { - if (this._batchAsBitmap === value) return; - - this._batchAsBitmap = value; - - if (!this._batchAsBitmap && !(this.font instanceof cc.BitmapFont)) { + cacheMode: { + default: CacheMode.NONE, + type: CacheMode, + tooltip: CC_DEV && 'i18n:COMPONENT.label.cacheMode', + notify (oldValue) { + if (this.cacheMode === oldValue) return; + + if (oldValue === CacheMode.BITMAP && !(this.font instanceof cc.BitmapFont)) { this._frame._resetDynamicAtlasFrame(); } - this._activateMaterial(true); - this._updateRenderData(); + + if (oldValue === CacheMode.CHAR) { + this._ttfTexture = null; + } + + this._updateRenderData(true); }, - animatable: false, - tooltip: CC_DEV && 'i18n:COMPONENT.label.batch_as_bitmap', + animatable: false }, _isBold: { @@ -476,6 +501,15 @@ let Label = cc.Class({ HorizontalAlign: HorizontalAlign, VerticalAlign: VerticalAlign, Overflow: Overflow, + CacheMode: CacheMode, + }, + + onLoad () { + // For compatibility with v2.0.x temporary reservation. + if (this._batchAsBitmap && this.cacheMode === CacheMode.NONE) { + this.cacheMode = CacheMode.BITMAP; + this._batchAsBitmap = false; + } }, onEnable () { @@ -507,6 +541,7 @@ let Label = cc.Class({ onDestroy () { this._assembler && this._assembler._resetAssemblerData && this._assembler._resetAssemblerData(this._assemblerData); this._assemblerData = null; + this._letterTexture = null; if (this._ttfTexture) { this._ttfTexture.destroy(); this._ttfTexture = null; @@ -555,7 +590,6 @@ let Label = cc.Class({ // TODO: old texture in material have been released by loader self._frame._texture = spriteFrame._texture; self._activateMaterial(force); - if (force) { self._assembler && self._assembler.updateRenderData(self); } @@ -574,18 +608,21 @@ let Label = cc.Class({ } } else { - if (!this._ttfTexture) { - this._ttfTexture = new cc.Texture2D(); - this._assemblerData = this._assembler._getAssemblerData(); - this._ttfTexture.initWithElement(this._assemblerData.canvas); - } if (!this._frame) { this._frame = new LabelFrame(); } - this._frame._refreshTexture(this._ttfTexture); - + if (this.cacheMode === CacheMode.CHAR) { + this._letterTexture = this._assembler._getAssemblerData(); + this._frame._refreshTexture(this._letterTexture); + } else if (!this._ttfTexture) { + this._ttfTexture = new cc.Texture2D(); + this._assemblerData = this._assembler._getAssemblerData(); + this._ttfTexture.initWithElement(this._assemblerData.canvas); + this._frame._refreshTexture(this._ttfTexture); + } + this._activateMaterial(force); if (force) { @@ -594,6 +631,17 @@ let Label = cc.Class({ } }, + _updateColor () { + let font = this.font; + if (font instanceof cc.BitmapFont) { + this._super(); + } + else { + this._updateRenderData(); + this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; + } + }, + _activateMaterial (force) { let material = this._material; if (material && !force) { diff --git a/cocos2d/core/renderer/utils/label/letter-font.js b/cocos2d/core/renderer/utils/label/letter-font.js new file mode 100644 index 00000000000..58e869aceec --- /dev/null +++ b/cocos2d/core/renderer/utils/label/letter-font.js @@ -0,0 +1,915 @@ +/**************************************************************************** + Copyright (c) 2018 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 macro = require('../../../platform/CCMacro'); +const Label = require('../../../components/CCLabel'); +const LabelOutline = require('../../../components/CCLabelOutline'); +const textUtils = require('../../../utils/text-utils'); +const Component = require('../../../components/CCComponent'); +const RenderTexture = require('../../../assets/CCRenderTexture'); +const OUTLINE_SUPPORTED = cc.js.isChildClassOf(LabelOutline, Component); +const Overflow = Label.Overflow; +const WHITE = cc.Color.WHITE; +const space = 2; + +let LetterInfo = function() { + this.char = ''; + this.valid = true; + this.x = 0; + this.y = 0; + this.line = 0; + this.hash = ""; +}; + +let FontLetterDefinition = function() { + this.u = 0; + this.v = 0; + this.w = 0; + this.h = 0; + this.texture = null; + this.offsetX = 0; + this.offsetY = 0; + this.valid = false; + this.xAdvance = 0; +}; + +let _backgroundStyle = 'rgba(255, 255, 255, 0.005)'; + +function LetterTexture(char, labelInfo) { + this._texture = null; + this._labelInfo = labelInfo; + this._char = char; + this._hash = null; + this._data = null; + this._canvas = null; + this._context = null; + this._width = 0; + this._height = 0; + this._hash = char.charCodeAt(0) + labelInfo.hash; +} + +LetterTexture.prototype = { + constructor: LetterTexture, + + updateRenderData () { + this._updateProperties(); + this._updateTexture(); + }, + _updateProperties () { + this._texture = new cc.Texture2D(); + this._data = Label._canvasPool.get(); + this._canvas = this._data.canvas; + this._context = this._data.context; + this._context.font = this._labelInfo.fontDesc; + let width = textUtils.safeMeasureText(this._context, this._char); + this._width = parseFloat(width.toFixed(2)) + 2 * this._labelInfo.margin; + this._height = this._labelInfo.lineHeight; + + if (this._canvas.width !== this._width) { + this._canvas.width = this._width; + } + + if (this._canvas.height !== this._height) { + this._canvas.height = this._height; + } + + this._texture.initWithElement(this._canvas); + }, + _updateTexture () { + let context = this._context; + let labelInfo = this._labelInfo, + width = this._canvas.width, + height = this._canvas.height; + + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.clearRect(0, 0, width, height); + //Add a white background to avoid black edges. + context.fillStyle = _backgroundStyle; + context.fillRect(0, 0, width, height); + context.font = labelInfo.fontDesc; + + let startX = width / 2; + let startY = height / 2; + let color = labelInfo.color; + //use round for line join to avoid sharp intersect point + context.lineJoin = 'round'; + context.fillStyle = `rgba(${color.r}, ${color.g}, ${color.b}, ${1})`; + if (labelInfo.isOutlined) { + let strokeColor = labelInfo.out || WHITE; + context.strokeStyle = `rgba(${strokeColor.r}, ${strokeColor.g}, ${strokeColor.b}, ${strokeColor.a / 255})`; + context.lineWidth = labelInfo.margin * 2; + context.strokeText(this._char, startX, startY); + } + context.fillText(this._char, startX, startY); + + this._texture.handleLoadedTexture(); + }, + + destroy () { + this._texture.destroy(); + this._texture = null; + Label._canvasPool.put(this._data); + }, +} + +function LetterAtlas (width, height) { + let texture = new RenderTexture(); + texture.initWithSize(width, height); + texture.update(); + + this._texture = texture; + + this._x = space; + this._y = space; + this._nexty = space; + + this._width = width; + this._height = height; + + this._letterDefinitions = {}; + + if (CC_EDITOR) { + cc.director.on(cc.Director.EVENT_BEFORE_SCENE_LAUNCH, this.beforeSceneLoad, this); + } +} + +cc.js.mixin(LetterAtlas.prototype, { + insertLetterTexture (letterTexture) { + let texture = letterTexture._texture; + let width = texture.width, height = texture.height; + + if ((this._x + width + space) > this._width) { + this._x = space; + this._y = this._nexty; + } + + if ((this._y + height) > this._nexty) { + this._nexty = this._y + height + space; + } + + if (this._nexty > this._height) { + return null; + } + + this._texture.drawTextureAt(texture, this._x, this._y); + + this._dirty = true; + + let letterDefinition = new FontLetterDefinition(); + letterDefinition.u = this._x; + letterDefinition.v = this._y; + letterDefinition.texture = this._texture; + letterDefinition.valid = true; + letterDefinition.w = letterTexture._width; + letterDefinition.h = letterTexture._height; + letterDefinition.xAdvance = letterTexture._width; + + this._x += width + space; + + this._letterDefinitions[letterTexture._hash] = letterDefinition; + + return letterDefinition + }, + + update () { + if (!this._dirty) return; + this._texture.update(); + this._dirty = false; + }, + + reset () { + this._x = space; + this._y = space; + this._nexty = space; + + let chars = this._letterDefinitions; + for (let i = 0, l = chars.length; i < l; i++) { + let char = chars[i]; + if (!char.isValid) { + continue; + } + char.destroy(); + } + + this._letterDefinitions = {}; + }, + + destroy () { + this.reset(); + this._texture.destroy(); + }, + + beforeSceneLoad () { + this.reset(); + }, + + getLetter (key) { + return this._letterDefinitions[key]; + }, + + addLetterDefinitions: function(key, letterDefinition) { + this._letterDefinitions[key] = letterDefinition; + }, + cloneLetterDefinition: function() { + let copyLetterDefinitions = {}; + for (let key in this._letterDefinitions) { + let value = new FontLetterDefinition(); + cc.js.mixin(value, this._letterDefinitions[key]); + copyLetterDefinitions[key] = value; + } + return copyLetterDefinitions; + }, + assignLetterDefinitions: function(letterDefinition) { + for (let key in this._letterDefinitions) { + let newValue = letterDefinition[key]; + let oldValue = this._letterDefinitions[key]; + cc.js.mixin(oldValue, newValue); + } + }, + scaleFontLetterDefinition: function(scaleFactor) { + for (let fontDefinition in this._letterDefinitions) { + let letterDefinitions = this._letterDefinitions[fontDefinition]; + letterDefinitions.w *= scaleFactor; + letterDefinitions.h *= scaleFactor; + letterDefinitions.offsetX *= scaleFactor; + letterDefinitions.offsetY *= scaleFactor; + letterDefinitions.xAdvance *= scaleFactor; + } + }, + getLetterDefinitionForChar: function(char, labelInfo) { + let hash = char.charCodeAt(0) + labelInfo.hash; + let letterDefinition = this._letterDefinitions[hash]; + if (!letterDefinition) { + let temp = new LetterTexture(char, labelInfo); + temp.updateRenderData(); + letterDefinition = this.insertLetterTexture(temp); + temp.destroy(); + } + + return letterDefinition; + } +}); + +let _tmpRect = cc.rect(); + +let _comp = null; + +let _horizontalKernings = []; +let _lettersInfo = []; +let _linesWidth = []; +let _linesOffsetX = []; +let _labelDimensions = cc.size(); + +let _fontAtlas = null; +let _fntConfig = null; +let _numberOfLines = 0; +let _textDesiredHeight = 0; +let _letterOffsetY = 0; +let _tailoredTopY = 0; +let _tailoredBottomY = 0; +let _bmfontScale = 1.0; +let _lineBreakWithoutSpaces = false; +let _lineSpacing = 0; +let _string = ''; +let _fontSize = 0; +let _originFontSize = 0; +let _contentSize = cc.size(); +let _hAlign = 0; +let _vAlign = 0; +let _spacingX = 0; +let _lineHeight = 0; +let _overflow = 0; +let _isWrapText = false; +let _labelWidth = 0; +let _labelHeight = 0; +let _maxLineWidth = 0; +let _atlasWidth = 2048; +let _atlasHeight = 2048; +let _fontFamily = ""; +let _isBold = false; +let _labelInfo = { + fontSize:0, + lineHeight:0, + hash:"", + fontFamily:"", + fontDesc:"Arial", + hAlign:0, + vAlign:0, + color:WHITE, + isOutlined:false, + out:WHITE, + margin:0, +}; + +module.exports = { + _getAssemblerData () { + if (!_fontAtlas) { + _fontAtlas = new LetterAtlas(_atlasWidth, _atlasHeight); + } + + return _fontAtlas._texture + }, + + updateRenderData (comp) { + if (!comp._renderData.vertDirty) return; + if (_comp === comp) return; + + _comp = comp; + + this._updateFontFamily(comp); + _labelInfo.fontFamily = _fontFamily; + + this._updateProperties(); + _labelInfo.fontDesc = this._getFontDesc(); + + this._updateContent(); + + _comp._actualFontSize = _fontSize; + _comp.node.setContentSize(_contentSize); + + _comp._renderData.vertDirty = _comp._renderData.uvDirty = false; + + _comp = null; + + this._resetProperties(); + }, + + _updateFontScale () { + _bmfontScale = _fontSize / _originFontSize; + }, + + _updateProperties () { + _string = _comp.string.toString(); + _fontSize = _comp.fontSize; + _originFontSize = _fontSize; + _contentSize.width = _comp.node._contentSize.width; + _contentSize.height = _comp.node._contentSize.height; + _hAlign = _comp.horizontalAlign; + _vAlign = _comp.verticalAlign; + _spacingX = _comp.spacingX; + _overflow = _comp.overflow; + _lineHeight = _comp._lineHeight; + _isBold = _comp._isBold; + + // should wrap text + if (_overflow === Overflow.NONE) { + _isWrapText = false; + } + else if (_overflow === Overflow.RESIZE_HEIGHT) { + _isWrapText = true; + } + else { + _isWrapText = _comp.enableWrapText; + } + + // outline + let outline = OUTLINE_SUPPORTED && _comp.getComponent(LabelOutline); + if (outline && outline.enabled) { + _labelInfo.isOutlined = true; + _labelInfo.margin = outline.width; + _labelInfo.out = outline.color; + _labelInfo.out.a = outline.color.a * _comp.node.color.a / 255.0; + } + else { + _labelInfo.isOutlined = false; + _labelInfo.margin = 0; + } + + _labelInfo.lineHeight = _lineHeight; + _labelInfo.fontSize = _fontSize; + _labelInfo.fontFamily = _fontFamily; + _labelInfo.color = _comp.node.color; + _labelInfo.hash = this._computeHash(_labelInfo); + + this._setupBMFontOverflowMetrics(); + + }, + + _updateFontFamily (comp) { + if (!comp.useSystemFont) { + if (comp.font) { + if (comp.font._nativeAsset) { + _fontFamily = comp.font._nativeAsset; + } + else { + _fontFamily = cc.loader.getRes(comp.font.nativeUrl); + if (!_fontFamily) { + cc.loader.load(comp.font.nativeUrl, function (err, fontFamily) { + _fontFamily = fontFamily || 'Arial'; + comp.font._nativeAsset = fontFamily; + comp._updateRenderData(true); + }); + } + } + } + else { + _fontFamily = 'Arial'; + } + } + else { + _fontFamily = comp.fontFamily; + } + }, + + _computeHash (labelInfo) { + let hashData = ''; + let color = labelInfo.color.toHEX("#rrggbb"); + let out = ''; + if (labelInfo.isOutlined) { + out = labelInfo.out.toHEX("#rrggbb"); + }; + + return hashData + labelInfo.fontSize + labelInfo.fontFamily + color + out; + }, + + _getFontDesc () { + let fontDesc = _fontSize.toString() + 'px '; + fontDesc = fontDesc + _fontFamily; + if (_isBold) { + fontDesc = "bold " + fontDesc; + } + + return fontDesc; + }, + + _resetProperties () { + + }, + + _updateContent () { + this._updateFontScale(); + //this._computeHorizontalKerningForText(); + this._alignText(); + }, + + _computeHorizontalKerningForText () { + let string = _string; + let stringLen = string.length; + + let kerningDict = _fntConfig.kerningDict; + let horizontalKernings = _horizontalKernings; + + let prev = -1; + for (let i = 0; i < stringLen; ++i) { + let key = string.charCodeAt(i); + let kerningAmount = kerningDict[(prev << 16) | (key & 0xffff)] || 0; + if (i < stringLen - 1) { + horizontalKernings[i] = kerningAmount; + } else { + horizontalKernings[i] = 0; + } + prev = key; + } + }, + + _multilineTextWrap: function(nextTokenFunc) { + let textLen = _string.length; + + let lineIndex = 0; + let nextTokenX = 0; + let nextTokenY = 0; + let longestLine = 0; + let letterRight = 0; + + let highestY = 0; + let lowestY = 0; + let letterDef = null; + let letterPosition = cc.v2(0, 0); + + this._updateFontScale(); + + for (let index = 0; index < textLen;) { + let character = _string.charAt(index); + if (character === "\n") { + _linesWidth.push(letterRight); + letterRight = 0; + lineIndex++; + nextTokenX = 0; + nextTokenY -= _lineHeight * _bmfontScale + _lineSpacing; + this._recordPlaceholderInfo(index, character); + index++; + continue; + } + + let tokenLen = nextTokenFunc(_string, index, textLen); + let tokenHighestY = highestY; + let tokenLowestY = lowestY; + let tokenRight = letterRight; + let nextLetterX = nextTokenX; + let newLine = false; + + for (let tmp = 0; tmp < tokenLen; ++tmp) { + let letterIndex = index + tmp; + character = _string.charAt(letterIndex); + if (character === "\r") { + this._recordPlaceholderInfo(letterIndex, character); + continue; + } + letterDef = _fontAtlas.getLetterDefinitionForChar(character, _labelInfo); + if (!letterDef) { + this._recordPlaceholderInfo(letterIndex, character); + continue; + } + + let letterX = nextLetterX + letterDef.offsetX * _bmfontScale; + + if (_isWrapText + && _maxLineWidth > 0 + && nextTokenX > 0 + && letterX + letterDef.w * _bmfontScale > _maxLineWidth + && !textUtils.isUnicodeSpace(character)) { + _linesWidth.push(letterRight); + letterRight = 0; + lineIndex++; + nextTokenX = 0; + nextTokenY -= (_lineHeight * _bmfontScale + _lineSpacing); + newLine = true; + break; + } else { + letterPosition.x = letterX; + } + + letterPosition.y = nextTokenY - letterDef.offsetY * _bmfontScale; + this._recordLetterInfo(letterPosition, character, letterIndex, lineIndex); + + if (letterIndex + 1 < _horizontalKernings.length && letterIndex < textLen - 1) { + nextLetterX += _horizontalKernings[letterIndex + 1]; + } + + nextLetterX += letterDef.xAdvance * _bmfontScale + _spacingX; + + tokenRight = letterPosition.x + letterDef.w * _bmfontScale; + + if (tokenHighestY < letterPosition.y) { + tokenHighestY = letterPosition.y; + } + + if (tokenLowestY > letterPosition.y - letterDef.h * _bmfontScale) { + tokenLowestY = letterPosition.y - letterDef.h * _bmfontScale; + } + + } //end of for loop + + if (newLine) continue; + + nextTokenX = nextLetterX; + letterRight = tokenRight; + + if (highestY < tokenHighestY) { + highestY = tokenHighestY; + } + if (lowestY > tokenLowestY) { + lowestY = tokenLowestY; + } + if (longestLine < letterRight) { + longestLine = letterRight; + } + + index += tokenLen; + } //end of for loop + + _linesWidth.push(letterRight); + + _numberOfLines = lineIndex + 1; + _textDesiredHeight = _numberOfLines * _lineHeight * _bmfontScale; + if (_numberOfLines > 1) { + _textDesiredHeight += (_numberOfLines - 1) * _lineSpacing; + } + + _contentSize.width = _labelWidth; + _contentSize.height = _labelHeight; + if (_labelWidth <= 0) { + _contentSize.width = parseFloat(longestLine.toFixed(2)); + } + if (_labelHeight <= 0) { + _contentSize.height = parseFloat(_textDesiredHeight.toFixed(2)); + } + + _tailoredTopY = _contentSize.height; + _tailoredBottomY = 0; + if (highestY > 0) { + _tailoredTopY = _contentSize.height + highestY; + } + if (lowestY < -_textDesiredHeight) { + _tailoredBottomY = _textDesiredHeight + lowestY; + } + + return true; + }, + + _getFirstCharLen: function() { + return 1; + }, + + _getFirstWordLen: function(text, startIndex, textLen) { + let character = text.charAt(startIndex); + if (textUtils.isUnicodeCJK(character) + || character === "\n" + || textUtils.isUnicodeSpace(character)) { + return 1; + } + + let len = 1; + let letterDef = _fontAtlas.getLetterDefinitionForChar(character, _labelInfo); + if (!letterDef) { + return len; + } + let nextLetterX = letterDef.xAdvance * _bmfontScale + _spacingX; + let letterX; + for (let index = startIndex + 1; index < textLen; ++index) { + character = text.charAt(index); + + letterDef = _fontAtlas.getLetterDefinitionForChar(character, _labelInfo); + if (!letterDef) { + break; + } + letterX = nextLetterX + letterDef.offsetX * _bmfontScale; + + if(letterX + letterDef.w * _bmfontScale > _maxLineWidth + && !textUtils.isUnicodeSpace(character) + && _maxLineWidth > 0) { + return len; + } + nextLetterX += letterDef.xAdvance * _bmfontScale + _spacingX; + if (character === "\n" + || textUtils.isUnicodeSpace(character) + || textUtils.isUnicodeCJK(character)) { + break; + } + len++; + } + + return len; + }, + + _multilineTextWrapByWord: function() { + return this._multilineTextWrap(this._getFirstWordLen); + }, + + _multilineTextWrapByChar: function() { + return this._multilineTextWrap(this._getFirstCharLen); + }, + + _recordPlaceholderInfo: function(letterIndex, char) { + if (letterIndex >= _lettersInfo.length) { + let tmpInfo = new LetterInfo(); + _lettersInfo.push(tmpInfo); + } + + _lettersInfo[letterIndex].char = char; + _lettersInfo[letterIndex].hash = char.charCodeAt(0) + _labelInfo.hash; + _lettersInfo[letterIndex].valid = false; + }, + + _recordLetterInfo: function(letterPosition, character, letterIndex, lineIndex) { + if (letterIndex >= _lettersInfo.length) { + let tmpInfo = new LetterInfo(); + _lettersInfo.push(tmpInfo); + } + let char = character.charCodeAt(0); + let key = char + _labelInfo.hash; + _lettersInfo[letterIndex].line = lineIndex; + _lettersInfo[letterIndex].char = character; + _lettersInfo[letterIndex].hash = key; + _lettersInfo[letterIndex].valid = _fontAtlas.getLetter(key).valid; + _lettersInfo[letterIndex].x = letterPosition.x; + _lettersInfo[letterIndex].y = letterPosition.y; + }, + + _alignText: function() { + _textDesiredHeight = 0; + _linesWidth.length = 0; + + if (!_lineBreakWithoutSpaces) { + this._multilineTextWrapByWord(); + } else { + this._multilineTextWrapByChar(); + } + + this._computeAlignmentOffset(); + + this._updateQuads() + //shrink + // if (_overflow === Overflow.SHRINK) { + // if (_fontSize > 0 && this._isVerticalClamp()) { + // this._shrinkLabelToContentSize(this._isVerticalClamp); + // } + // } + + // if (!this._updateQuads()) { + // if (_overflow === Overflow.SHRINK) { + // this._shrinkLabelToContentSize(this._isHorizontalClamp); + // } + // } + }, + + _scaleFontSizeDown (fontSize) { + let shouldUpdateContent = true; + if (!fontSize) { + fontSize = 0.1; + shouldUpdateContent = false; + } + _fontSize = fontSize; + + if (shouldUpdateContent) { + this._updateContent(); + } + }, + + _isVerticalClamp () { + if (_textDesiredHeight > _contentSize.height) { + return true; + } else { + return false; + } + }, + + _isHorizontalClamp () { + let letterClamp = false; + for (let ctr = 0, l = _string.length; ctr < l; ++ctr) { + let letterInfo = _lettersInfo[ctr]; + if (letterInfo.valid) { + let letterDef = _fontAtlas.getLetter(letterInfo.hash); + + let px = letterInfo.x + letterDef.w / 2 * _bmfontScale; + let lineIndex = letterInfo.line; + if (_labelWidth > 0) { + if (!_isWrapText) { + if(px > _contentSize.width){ + letterClamp = true; + break; + } + }else{ + let wordWidth = _linesWidth[lineIndex]; + if (wordWidth > _contentSize.width && (px > _contentSize.width || px < 0)) { + letterClamp = true; + break; + } + } + } + } + } + + return letterClamp; + }, + + _isHorizontalClamped (px, lineIndex) { + let wordWidth = _linesWidth[lineIndex]; + let letterOverClamp = (px > _contentSize.width || px < 0); + + if(!_isWrapText){ + return letterOverClamp; + }else{ + return (wordWidth > _contentSize.width && letterOverClamp); + } + }, + + _updateQuads () { + + let texture = _fontAtlas._texture; + + let node = _comp.node; + let renderData = _comp._renderData; + renderData.dataLength = renderData.vertexCount = renderData.indiceCount = 0; + + let contentSize = _contentSize, + appx = node._anchorPoint.x * contentSize.width, + appy = node._anchorPoint.y * contentSize.height; + + let ret = true; + for (let ctr = 0, l = _string.length; ctr < l; ++ctr) { + let letterInfo = _lettersInfo[ctr]; + if (!letterInfo.valid) continue; + let letterDef = _fontAtlas.getLetter(letterInfo.hash); + + _tmpRect.height = letterDef.h; + _tmpRect.width = letterDef.w; + _tmpRect.x = letterDef.u; + _tmpRect.y = letterDef.v; + + let py = letterInfo.y + _letterOffsetY; + + if (_labelHeight > 0) { + if (py > _tailoredTopY) { + let clipTop = py - _tailoredTopY; + _tmpRect.y += clipTop; + _tmpRect.height -= clipTop; + py = py - clipTop; + } + + if (py - letterDef.h * _bmfontScale < _tailoredBottomY) { + _tmpRect.height = (py < _tailoredBottomY) ? 0 : (py - _tailoredBottomY); + } + } + + let lineIndex = letterInfo.line; + let px = letterInfo.x + letterDef.w / 2 * _bmfontScale + _linesOffsetX[lineIndex]; + + if (_labelWidth > 0) { + if (this._isHorizontalClamped(px, lineIndex)) { + if (_overflow === Overflow.CLAMP) { + _tmpRect.width = 0; + } else if (_overflow === Overflow.SHRINK) { + if (_contentSize.width > letterDef.w) { + ret = false; + break; + } else { + _tmpRect.width = 0; + } + } + } + } + + if (_tmpRect.height > 0 && _tmpRect.width > 0) { + let letterPositionX = letterInfo.x + _linesOffsetX[letterInfo.line]; + this.appendQuad(renderData, texture, _tmpRect, false, letterPositionX - appx, py - appy, _bmfontScale); + } + } + + return ret; + }, + + appendQuad (renderData, texture, rect, rotated, x, y, scale) { + }, + + _computeAlignmentOffset: function() { + _linesOffsetX.length = 0; + + switch (_hAlign) { + case macro.TextAlignment.LEFT: + for (let i = 0; i < _numberOfLines; ++i) { + _linesOffsetX.push(0); + } + break; + case macro.TextAlignment.CENTER: + for (let i = 0, l = _linesWidth.length; i < l; i++) { + _linesOffsetX.push((_contentSize.width - _linesWidth[i]) / 2); + } + break; + case macro.TextAlignment.RIGHT: + for (let i = 0, l = _linesWidth.length; i < l; i++) { + _linesOffsetX.push(_contentSize.width - _linesWidth[i]); + } + break; + default: + break; + } + + switch (_vAlign) { + case macro.VerticalTextAlignment.TOP: + _letterOffsetY = _contentSize.height; + break; + case macro.VerticalTextAlignment.CENTER: + _letterOffsetY = (_contentSize.height + _textDesiredHeight) / 2; + break; + case macro.VerticalTextAlignment.BOTTOM: + _letterOffsetY = _textDesiredHeight; + break; + default: + break; + } + }, + + _setupBMFontOverflowMetrics () { + let newWidth = _contentSize.width, + newHeight = _contentSize.height; + + if (_overflow === Overflow.RESIZE_HEIGHT) { + newHeight = 0; + } + + if (_overflow === Overflow.NONE) { + newWidth = 0; + newHeight = 0; + } + + _labelWidth = newWidth; + _labelHeight = newHeight; + _labelDimensions.width = newWidth; + _labelDimensions.height = newHeight; + _maxLineWidth = newWidth; + } +}; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 104a5e18760..dd8ac540782 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -51,7 +51,7 @@ let _color = null; let _fontFamily = ''; let _overflow = Overflow.NONE; let _isWrapText = false; -let _backgroundAlpha = 0.005; +let _backgroundStyle = 'rgba(255, 255, 255, 0.005)'; // outline let _isOutlined = false; @@ -65,54 +65,16 @@ let _isUnderline = false; let _sharedLabelData; -// -let _canvasPool = { - pool: [], - get () { - let data = this.pool.pop(); - - if (!data) { - let canvas = document.createElement("canvas"); - let context = canvas.getContext("2d"); - data = { - canvas: canvas, - context: context - } - } - - return data; - }, - put (canvas) { - if (this.pool.length >= 32) { - return; - } - this.pool.push(canvas); - } -}; - - module.exports = { _getAssemblerData () { - if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { - _sharedLabelData = _canvasPool.get(); - } - else { - if (!_sharedLabelData) { - let labelCanvas = document.createElement("canvas"); - _sharedLabelData = { - canvas: labelCanvas, - context: labelCanvas.getContext("2d") - }; - } - } - _sharedLabelData.canvas.width = _sharedLabelData.canvas.height = 1; + _sharedLabelData = Label._canvasPool.get(); return _sharedLabelData; }, _resetAssemblerData (assemblerData) { - if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS && assemblerData) { - _canvasPool.put(assemblerData); + if (assemblerData) { + Label._canvasPool.put(assemblerData); } }, @@ -247,7 +209,7 @@ module.exports = { _context.clearRect(0, 0, _canvas.width, _canvas.height); //Add a white background to avoid black edges. //TODO: it is best to add alphaTest to filter out the background color. - _context.fillStyle = `rgba(${255}, ${255}, ${255}, ${_backgroundAlpha})`; + _context.fillStyle = _backgroundStyle; _context.fillRect(0, 0, _canvas.width, _canvas.height); _context.font = _fontDesc; @@ -255,14 +217,9 @@ module.exports = { let lineHeight = this._getLineHeight(); //use round for line join to avoid sharp intersect point _context.lineJoin = 'round'; - if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { - _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_color.a / 255})`; - } - else { - _context.fillStyle = 'white'; - } - let underlineStartPosition; + _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${1})`; + let underlineStartPosition; //do real rendering for (let i = 0; i < _splitedStrings.length; ++i) { if (_isOutlined) { @@ -278,7 +235,7 @@ module.exports = { _context.save(); _context.beginPath(); _context.lineWidth = _fontSize / 8; - _context.strokeStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_color.a / 255})`; + _context.strokeStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${1})`; _context.moveTo(underlineStartPosition.x, underlineStartPosition.y + i * lineHeight - 1); _context.lineTo(underlineStartPosition.x + _canvas.width, underlineStartPosition.y + i * lineHeight - 1); _context.stroke(); @@ -290,7 +247,7 @@ module.exports = { }, _calDynamicAtlas (comp) { - if(!comp.batchAsBitmap) return; + if(comp.cacheMode !== Label.CacheMode.BITMAP) return; if (!comp._frame._original) { comp._frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height)); @@ -343,9 +300,14 @@ module.exports = { _canvasSize.width += _drawFontsize * Math.tan(12 * 0.0174532925); } } + + if (_canvas.width !== _canvasSize.width) { + _canvas.width = _canvasSize.width; + } - _canvas.width = _canvasSize.width; - _canvas.height = _canvasSize.height; + if (_canvas.height !== _canvasSize.height) { + _canvas.height = _canvasSize.height; + } }, _calculateTextBaseline () { diff --git a/cocos2d/core/renderer/webgl/assemblers/label/index.js b/cocos2d/core/renderer/webgl/assemblers/label/index.js index 7bac03a3f00..155f1b7a2c9 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/index.js @@ -26,6 +26,31 @@ const Label = require('../../../../components/CCLabel'); const ttfAssembler = require('./ttf'); const bmfontAssembler = require('./bmfont'); +const letterAssembler = require('./letter-font') + +let canvasPool = { + pool: [], + get () { + let data = this.pool.pop(); + + if (!data) { + let canvas = document.createElement("canvas"); + let context = canvas.getContext("2d"); + data = { + canvas: canvas, + context: context + } + } + + return data; + }, + put (canvas) { + if (this.pool.length >= 32) { + return; + } + this.pool.push(canvas); + } +}; var labelAssembler = { getAssembler (comp) { @@ -33,6 +58,8 @@ var labelAssembler = { if (comp.font instanceof cc.BitmapFont) { assembler = bmfontAssembler; + } else if (comp.cacheMode === Label.CacheMode.CHAR) { + assembler = letterAssembler; } return assembler; @@ -45,5 +72,5 @@ var labelAssembler = { }; Label._assembler = labelAssembler; - +Label._canvasPool = canvasPool; module.exports = labelAssembler; \ No newline at end of file diff --git a/cocos2d/core/renderer/webgl/assemblers/label/letter-font.js b/cocos2d/core/renderer/webgl/assemblers/label/letter-font.js new file mode 100644 index 00000000000..3b4a9607265 --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/label/letter-font.js @@ -0,0 +1,135 @@ +/**************************************************************************** + Copyright (c) 2018 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 fontUtils = require('../../../utils/label/letter-font'); +const WHITE = cc.color(255, 255, 255, 255); + +module.exports = js.addon({ + createData (comp) { + return comp.requestRenderData(); + }, + + fillBuffers (comp, renderer) { + let node = comp.node, + renderData = comp._renderData, + data = renderData._data; + + let matrix = node._worldMatrix, + a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, + tx = matrix.m12, ty = matrix.m13; + + WHITE._fastSetA(node.color.a); + let color = WHITE._val; + let buffer = renderer._meshBuffer; + let vertexCount = renderData.vertexCount; + let offsetInfo = buffer.request(vertexCount, renderData.indiceCount); + + // buffer data may be realloc, need get reference after request. + let indiceOffset = offsetInfo.indiceOffset, + vertexOffset = offsetInfo.byteOffset >> 2, + vertexId = offsetInfo.vertexOffset, + vbuf = buffer._vData, + uintbuf = buffer._uintVData, + ibuf = buffer._iData; + + + for (let i = 0; i < vertexCount; i++) { + let vert = data[i]; + vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; + vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; + vbuf[vertexOffset++] = vert.u; + vbuf[vertexOffset++] = vert.v; + uintbuf[vertexOffset++] = color; + } + + // fill indice data + for (let i = 0, count = vertexCount / 4; i < count; i++) + { + let start = vertexId + i * 4; + ibuf[indiceOffset++] = start; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 2; + ibuf[indiceOffset++] = start + 1; + ibuf[indiceOffset++] = start + 3; + ibuf[indiceOffset++] = start + 2; + } + }, + + appendQuad (renderData, texture, rect, rotated, x, y, scale) { + let dataOffset = renderData.dataLength; + + renderData.dataLength += 4; + renderData.vertexCount = renderData.dataLength; + renderData.indiceCount = renderData.dataLength / 2 * 3; + + let data = renderData._data; + let texw = texture.width, + texh = texture.height; + + let rectWidth = rect.width, + rectHeight = rect.height; + + let l, b, r, t; + if (!rotated) { + l = (rect.x) / texw; + r = (rect.x + rectWidth) / texw; + b = (rect.y + rectHeight) / texh; + t = (rect.y) / texh; + + data[dataOffset].u = l; + data[dataOffset].v = b; + data[dataOffset+1].u = r; + data[dataOffset+1].v = b; + data[dataOffset+2].u = l; + data[dataOffset+2].v = t; + data[dataOffset+3].u = r; + data[dataOffset+3].v = t; + } else { + l = (rect.x) / texw; + r = (rect.x + rectHeight) / texw; + b = (rect.y + rectWidth) / texh; + t = (rect.y) / texh; + + data[dataOffset].u = l; + data[dataOffset].v = t; + data[dataOffset+1].u = l; + data[dataOffset+1].v = b; + data[dataOffset+2].u = r; + data[dataOffset+2].v = t; + data[dataOffset+3].u = r; + data[dataOffset+3].v = b; + } + + data[dataOffset].x = x; + data[dataOffset].y = y - rectHeight * scale; + data[dataOffset+1].x = x + rectWidth * scale; + data[dataOffset+1].y = y - rectHeight * scale; + data[dataOffset+2].x = x; + data[dataOffset+2].y = y; + data[dataOffset+3].x = x + rectWidth * scale; + data[dataOffset+3].y = y; + }, +}, fontUtils); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js index 1d3d32ac01b..2530ff44db4 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/ttf.js @@ -25,6 +25,7 @@ const js = require('../../../../platform/js'); const ttfUtls = require('../../../utils/label/ttf'); +const WHITE = cc.color(255, 255, 255, 255); module.exports = js.addon({ createData (comp) { @@ -40,13 +41,13 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let data = comp._renderData._data, node = comp.node, - color = node.color._val, matrix = node._worldMatrix, a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, tx = matrix.m12, ty = matrix.m13; - - let buffer = renderer._meshBuffer; + WHITE._fastSetA(node.color.a); + let color = WHITE._val; + let buffer = renderer._meshBuffer; let offsetInfo = buffer.request(4, 6); // buffer data may be realloc, need get reference after request. diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 2045f942e3a..3be6d90eaf6 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -97,7 +97,7 @@ module.exports = { "wrap": "Wrap text?", "font": "What font to use", "system_font": "Whether to use the system default font", - 'batch_as_bitmap': 'Whether to set to static text for batch merging, select this will add text to the dynamic atlas for batch merging, but can not dynamically modify text content frequently' + 'cacheMode': 'The text cache mode includes the following three types: \n 1. NONE : Do not do any caching, text content is drawn once. \n 2. BITMAP: Add text as a static image to the dynamic atlas for batch merging, but not frequently dynamically Text content \n 3. CHAR: Splits text into characters and caches characters into character atlas, suitable for text content with repeated and frequently updated character content' }, "progress": { "bar_sprite": "A progress bar is displayed with the Sprite node that can dynamically change the size", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index fed5387588f..e88b36f2246 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -100,7 +100,7 @@ module.exports = { 'wrap': '是否允许自动换行', 'font': 'Label 使用的字体资源', 'system_font': '是否使用系统默认字体,选中此项会将 file 属性置空', - 'batch_as_bitmap': '是否设置为静态文本进行批次合并,选中此项将会把文本加入动态图集进行批次合并,但是不能频繁动态修改文本内容' + 'cacheMode': '文本缓存模式,包括以下三种:\n 1. NONE : 不做任何缓存,文本内容进行一次绘制 \n 2. BITMAP: 将文本作为静态图像加入动态图集进行批次合并,但是不能频繁动态修改文本内容 \n 3. CHAR: 将文本拆分为字符并且把字符纹理缓存到一张字符图集中进行复用,适用于字符内容重复并且频繁更新的文本内容' }, 'progress': { 'bar_sprite': '进度条显示用的 Sprite 节点,可以动态改变尺寸', From dd797af1ca2d01c03f8e81a9c50720eb38615f41 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 28 Feb 2019 14:56:10 +0800 Subject: [PATCH 0489/1631] Wechat -> WeChat --- CHANGELOG.txt | 2 +- cocos2d/core/components/SwanSubContextView.js | 2 +- cocos2d/core/components/WXSubContextView.js | 2 +- cocos2d/core/platform/CCMacro.js | 4 ++-- predefine.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 6c0475d26c6..57656d09073 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -323,7 +323,7 @@ Cocos2d-JS v3.2 @ Dec.29, 2014 * Replaced `transform` function with `setTransform` function under canvas render mode for better performance. * Added a timer in `cc.audioEngine` to check audio element loading event, prevent the loading process being stucked when load audio file failed. * Added some new browser types to `cc.sys`. -* Added some audio resource loading codes to ensure compatibility with Wechat browser. +* Added some audio resource loading codes to ensure compatibility with WeChat browser. * Added check for WebAudio support to ensure compatibility. * Bug fixes: diff --git a/cocos2d/core/components/SwanSubContextView.js b/cocos2d/core/components/SwanSubContextView.js index 258ba829722..2541e7acd6a 100644 --- a/cocos2d/core/components/SwanSubContextView.js +++ b/cocos2d/core/components/SwanSubContextView.js @@ -36,7 +36,7 @@ if (!CC_EDITOR && !isBaiduGame) { } else { /** - * !#en SwanSubContextView is a view component which controls open data context viewport in Wechat game platform.
+ * !#en SwanSubContextView is a view component which controls open data context viewport in WeChat game platform.
* The component's node size decide the viewport of the sub context content in main context, * the entire sub context texture will be scaled to the node's bounding box area.
* This component provides multiple important features:
diff --git a/cocos2d/core/components/WXSubContextView.js b/cocos2d/core/components/WXSubContextView.js index 62b46080b03..9e6e7b34d81 100644 --- a/cocos2d/core/components/WXSubContextView.js +++ b/cocos2d/core/components/WXSubContextView.js @@ -35,7 +35,7 @@ if (!CC_EDITOR && !CC_WECHATGAME) { } else { /** - * !#en WXSubContextView is a view component which controls open data context viewport in Wechat game platform.
+ * !#en WXSubContextView is a view component which controls open data context viewport in WeChat game platform.
* The component's node size decide the viewport of the sub context content in main context, * the entire sub context texture will be scaled to the node's bounding box area.
* This component provides multiple important features:
diff --git a/cocos2d/core/platform/CCMacro.js b/cocos2d/core/platform/CCMacro.js index e3dceb738d4..fc3e2790f46 100644 --- a/cocos2d/core/platform/CCMacro.js +++ b/cocos2d/core/platform/CCMacro.js @@ -331,8 +331,8 @@ cc.macro = { * Whether or not clear dom Image object cache after uploading to gl texture. * Concretely, we are setting image.src to empty string to release the cache. * Normally you don't need to enable this option, because on web the Image object doesn't consume too much memory. - * But on Wechat Game platform, the current version cache decoded data in Image object, which has high memory usage. - * So we enabled this option by default on Wechat, so that we can release Image cache immediately after uploaded to GPU. + * But on WeChat Game platform, the current version cache decoded data in Image object, which has high memory usage. + * So we enabled this option by default on WeChat, so that we can release Image cache immediately after uploaded to GPU. * !#zh * 是否在将贴图上传至 GPU 之后删除 DOM Image 缓存。 * 具体来说,我们通过设置 image.src 为空字符串来释放这部分内存。 diff --git a/predefine.js b/predefine.js index 970ec54f507..b875e73439d 100644 --- a/predefine.js +++ b/predefine.js @@ -106,7 +106,7 @@ * @property {Boolean} CC_TEST - Running in the engine's unit test. */ /** - * @property {Boolean} CC_WECHATGAME - Running in the Wechat's mini game. + * @property {Boolean} CC_WECHATGAME - Running in the WeChat's mini game. */ /** * @property {Boolean} CC_QQPLAY - Running in the bricks. From 904ffc543e7032b64ede5d0fe3d108438944dd62 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Thu, 28 Feb 2019 16:03:10 +0800 Subject: [PATCH 0490/1631] Add spine render mode chinese tip (#3933) --- editor/i18n/zh/localization.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index e88b36f2246..eb8c57f6084 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -262,7 +262,9 @@ module.exports = { "debug_slots": "是否显示 slot 的 debug 信息", "debug_bones": "是否显示 bone 的 debug 信息", "premultipliedAlpha": "是否启用贴图预乘", - "use_tint": "是否启用染色效果" + "use_tint": "是否启用染色效果", + "enabled_batch": "是否开启合批", + "render_mode": "当前骨骼动画的渲染模式\nREALTIME 表示实时计算,支持动画融合,较耗性能\nSHARED_CACHE 表示预计算且共享动画数据,性能较高,占用较少内存\nPRIVATE_CACHE 表示预计算但不共享动画数据,性能较高,占用较多内存\n以上两种缓存模式,不支持动作融合", }, "dragon_bones": { "dragon_bones_asset": "骨骼信息数据,拖拽 DragonBones 导出的骨骼动画信息 json 资源到这里来开始使用", @@ -273,7 +275,7 @@ module.exports = { "play_times": "播放默认动画的循环次数\n-1 表示使用配置文件中的默认值\n0 表示无限循环\n>0 表示循环次数", "debug_bones": "是否显示 bone 的 debug 信息", "enabled_batch": "是否开启合批", - "render_mode": "当前骨骼动画的渲染模式\nrealtime 表示实时计算,支持动画融合,较耗性能\nsharedCache 表示预计算且共享动画数据,性能较高,占用较少内存\nprivateCache 表示预计算但不共享动画数据,性能较高,占用较多内存\n以上两种缓存模式,不支持骨骼嵌套,不支持fade相关接口", + "render_mode": "当前骨骼动画的渲染模式\nREALTIME 表示实时计算,支持动画融合,较耗性能\nSHARED_CACHE 表示预计算且共享动画数据,性能较高,占用较少内存\nPRIVATE_CACHE 表示预计算但不共享动画数据,性能较高,占用较多内存\n以上两种缓存模式,不支持骨骼嵌套,不支持fade相关接口", }, 'motionStreak': { 'fadeTime': "拖尾的渐隐时间,以秒为单位", From 19698da168bb0e2c10dd75f48cc192029fc4a9be Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Thu, 28 Feb 2019 18:58:27 +0800 Subject: [PATCH 0491/1631] fix label rendering error on native (#3936) * fix label rendering error on native * fix rendering error on native * revert first commit --- cocos2d/core/renderer/utils/label/ttf.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index dd8ac540782..b130079ca6a 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -69,6 +69,7 @@ module.exports = { _getAssemblerData () { _sharedLabelData = Label._canvasPool.get(); + _sharedLabelData.canvas.width = _sharedLabelData.canvas.height = 1; return _sharedLabelData; }, From 3cc0eca5c89a4fccbed747b7a7547bb175652a58 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Fri, 1 Mar 2019 13:53:58 +0800 Subject: [PATCH 0492/1631] clear letter atlas when scene launch. (#3938) --- cocos2d/core/renderer/utils/label/letter-font.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/utils/label/letter-font.js b/cocos2d/core/renderer/utils/label/letter-font.js index 58e869aceec..d72e72bbbf8 100644 --- a/cocos2d/core/renderer/utils/label/letter-font.js +++ b/cocos2d/core/renderer/utils/label/letter-font.js @@ -151,9 +151,7 @@ function LetterAtlas (width, height) { this._letterDefinitions = {}; - if (CC_EDITOR) { - cc.director.on(cc.Director.EVENT_BEFORE_SCENE_LAUNCH, this.beforeSceneLoad, this); - } + cc.director.on(cc.Director.EVENT_BEFORE_SCENE_LAUNCH, this.beforeSceneLoad, this); } cc.js.mixin(LetterAtlas.prototype, { @@ -223,7 +221,13 @@ cc.js.mixin(LetterAtlas.prototype, { }, beforeSceneLoad () { - this.reset(); + this.destroy(); + + let texture = new RenderTexture(); + texture.initWithSize(this._width, this._height); + texture.update(); + + this._texture = texture; }, getLetter (key) { From a7fac9c0f534ffe3ccb64aa9a09a9fb306d787b0 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Fri, 1 Mar 2019 13:54:59 +0800 Subject: [PATCH 0493/1631] reset the CHAR mode to NONE on subdomin. (#3940) * reset the CHAR mode to NONE on subdomin. * reset CHAR mode on subdomin --- cocos2d/core/components/CCLabel.js | 4 ++-- cocos2d/core/renderer/webgl/assemblers/label/index.js | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index e78d91c1a3d..9b50a75e5c8 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -612,8 +612,8 @@ let Label = cc.Class({ if (!this._frame) { this._frame = new LabelFrame(); } - - if (this.cacheMode === CacheMode.CHAR) { + + if (this.cacheMode === CacheMode.CHAR && cc.sys.browserType !== cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { this._letterTexture = this._assembler._getAssemblerData(); this._frame._refreshTexture(this._letterTexture); } else if (!this._ttfTexture) { diff --git a/cocos2d/core/renderer/webgl/assemblers/label/index.js b/cocos2d/core/renderer/webgl/assemblers/label/index.js index 155f1b7a2c9..4df9f1ddaa4 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/index.js @@ -59,7 +59,11 @@ var labelAssembler = { if (comp.font instanceof cc.BitmapFont) { assembler = bmfontAssembler; } else if (comp.cacheMode === Label.CacheMode.CHAR) { - assembler = letterAssembler; + if (cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { + cc.warn('sorry, subdomain does not support CHAR mode currently!'); + } else { + assembler = letterAssembler; + } } return assembler; From 574473d4548bed12fbb39dd599d36bff19301108 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 1 Mar 2019 14:57:28 +0800 Subject: [PATCH 0494/1631] set rigidbody awake visible is false (#3941) --- cocos2d/core/physics/CCRigidBody.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/physics/CCRigidBody.js b/cocos2d/core/physics/CCRigidBody.js index e721800a947..2975539a14b 100644 --- a/cocos2d/core/physics/CCRigidBody.js +++ b/cocos2d/core/physics/CCRigidBody.js @@ -372,6 +372,7 @@ var RigidBody = cc.Class({ * @default false */ awake: { + visible: false, tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.awake', get: function () { return this._b2Body ? this._b2Body.IsAwake() : false; From 9f0962226b0b394e754a9d5b900665f87abca35a Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Fri, 1 Mar 2019 15:58:54 +0800 Subject: [PATCH 0495/1631] fix canvasPool error on subdomin (#3942) --- .../renderer/canvas/renderers/label/index.js | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/renderer/canvas/renderers/label/index.js b/cocos2d/core/renderer/canvas/renderers/label/index.js index 58dd876686a..77433680fb7 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/index.js +++ b/cocos2d/core/renderer/canvas/renderers/label/index.js @@ -22,10 +22,36 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ - +const Label = require('../../../../components/CCLabel'); const ttf = require('./ttf'); const bmfont = require('./bmfont'); +let canvasPool = { + pool: [], + get () { + let data = this.pool.pop(); + + if (!data) { + let canvas = document.createElement("canvas"); + let context = canvas.getContext("2d"); + data = { + canvas: canvas, + context: context + } + } + + return data; + }, + put (canvas) { + if (this.pool.length >= 32) { + return; + } + this.pool.push(canvas); + } +}; + +Label._canvasPool = canvasPool; + module.exports = { getAssembler (comp) { let assembler = ttf; From 61b11170f53deae8b38c30c371674c69869b91f4 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 1 Mar 2019 16:19:26 +0800 Subject: [PATCH 0496/1631] update rigidbody awake tips and add awakeOnLoad (#3944) --- cocos2d/core/physics/CCRigidBody.js | 20 ++++++++++++++++++-- editor/i18n/en/localization.js | 3 ++- editor/i18n/zh/localization.js | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/physics/CCRigidBody.js b/cocos2d/core/physics/CCRigidBody.js index 2975539a14b..352ca14278e 100644 --- a/cocos2d/core/physics/CCRigidBody.js +++ b/cocos2d/core/physics/CCRigidBody.js @@ -365,9 +365,9 @@ var RigidBody = cc.Class({ /** * !#en - * Is this body initially awake or sleeping? + * Set the sleep state of the body. A sleeping body has very low CPU cost.(When the rigid body is hit, if the rigid body is in sleep state, it will be immediately awakened.) * !#zh - * 是否立刻唤醒此刚体 + * 设置刚体的睡眠状态。 睡眠的刚体具有非常低的 CPU 成本。(当刚体被碰撞到时,如果刚体处于睡眠状态,它会立即被唤醒) * @property {Boolean} awake * @default false */ @@ -384,6 +384,20 @@ var RigidBody = cc.Class({ } }, + /** + * !#en + * Whether to wake up this rigid body during initialization + * !#zh + * 是否在初始化时唤醒此刚体 + * @property {Boolean} awakeOnLoad + * @default true + */ + awakeOnLoad: { + default: true, + tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.awakeOnLoad', + animatable: false, + }, + /** * !#en * Set the active state of the body. An inactive body is not @@ -896,6 +910,8 @@ var RigidBody = cc.Class({ bodyDef.position = new b2.Vec2(pos.x / PTM_RATIO, pos.y / PTM_RATIO); bodyDef.angle = -(Math.PI / 180) * getWorldRotation(node); + bodyDef.awake = this.awakeOnLoad; + cc.director.getPhysicsManager()._addBody(this, bodyDef); this._inited = true; diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 3be6d90eaf6..55f8c0664a3 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -346,7 +346,8 @@ module.exports = { 'linearVelocity': 'The linear velocity of the body\'s origin in world co-ordinates', 'angularVelocity': 'The angular velocity of the body.', 'fixedRotation': 'Should this body be prevented from rotating?', - 'awake': 'Is this body initially awake or sleeping?' + 'awake': 'Set the sleep state of the body. A sleeping body has very low CPU cost.(When the rigid body is hit, if the rigid body is in sleep state, it will be immediately awakened.)', + 'awakeOnLoad': 'Whether to wake up this rigid body during initialization', }, 'physics_collider': { 'density': 'The density', diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index eb8c57f6084..28fa2016c8b 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -350,7 +350,8 @@ module.exports = { 'linearVelocity': '刚体在世界坐标下的线性速度', 'angularVelocity': '刚体的角速度', 'fixedRotation': '是否禁止此刚体进行旋转', - 'awake': '是否立刻唤醒此刚体' + 'awake': '设置刚体的睡眠状态。 睡眠的刚体具有非常低的 CPU 成本。(当刚体被碰撞到时,如果刚体处于睡眠状态,它会立即被唤醒)', + 'awakeOnLoad': '是否在初始化时唤醒此刚体', }, 'physics_collider': { 'density': '密度', From 56c17c7de105d6300d2daa16833ba9874d87a47b Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Fri, 1 Mar 2019 16:32:40 +0800 Subject: [PATCH 0497/1631] fix label error when font change on editor. (#3946) --- cocos2d/core/components/CCLabel.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 9b50a75e5c8..b90c3b682f6 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -620,8 +620,11 @@ let Label = cc.Class({ this._ttfTexture = new cc.Texture2D(); this._assemblerData = this._assembler._getAssemblerData(); this._ttfTexture.initWithElement(this._assemblerData.canvas); - this._frame._refreshTexture(this._ttfTexture); } + + if (this.cacheMode !== CacheMode.CHAR) { + this._frame._refreshTexture(this._ttfTexture); + } this._activateMaterial(force); From e9f968d01fd040e56b825dd3de843b9b6b8746e6 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Fri, 1 Mar 2019 18:48:34 +0800 Subject: [PATCH 0498/1631] Rename skeleton RenderMode to AnimationCacheMode (#3947) * Rename skeleton RenderMode to AnimationCacheMode * Rename skeleton RenderMode to AnimationCacheMode --- editor/i18n/en/localization.js | 4 +- editor/i18n/zh/localization.js | 4 +- extensions/dragonbones/ArmatureDisplay.js | 104 +++++++++++----------- extensions/dragonbones/webgl-assembler.js | 2 +- extensions/spine/Skeleton.js | 99 ++++++++++---------- extensions/spine/spine-assembler.js | 2 +- 6 files changed, 105 insertions(+), 110 deletions(-) diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 55f8c0664a3..24adf30403e 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -260,7 +260,7 @@ module.exports = { "premultipliedAlpha": "Indicates whether to enable premultiplied alpha.", "use_tint": "Indicates whether to use tint effect.", "enabled_batch": "Indicates whether enabled batch model", - "render_mode": "The render mode of current armature. \n'REALTIME' means REALTIME calculate animation data, support animation blend but low performance. \n'SHARED_CACHE' means precomputation animation data and share data with same armature, high performance and less memery. \n'PRIVATE_CACHE' means precomputation animation data but not share data with other same armature, high performance and more memery.\nAbove two cache mode, not support nest armature, not support 'fade' related interface.", + "animation_cache_mode": "REALTIME model, the animation data is calculated while running, all features supported. SHARED_CACHE mode, the animation data is pre-calculated and cached globally, the data is shared between skeleton animation instances. Shared cache mode has great performance advantage, but it has some limitation. It doesn't support action blending and addition and it only supports the start and end events. In the memory usage aspect, as same skeleton animation instances are sharing the same animation data, this mode can save a lot of memory. More instances are sharing, more memory saved. In conclusion SHARED_CACHE mode is suitable for the skeletons which could be replicated, such as effects animation, monster, NPC and so on.\nPRIVATE_CACHE mode, similar to SHARED_CACHE, but the animation data and texture data are not shared between skeleton instances. So there is no advantage in memory compare to REALTIME mode. The PRIVATE_CACHE is suitable when there is no animation blending or addition needed, but the skeleton could change textures of sub bone (e.g. weapon).", }, "dragon_bones": { "dragon_bones_asset": "The json data contains the DragonBones information, drag the json file exported from DragonBones to get started.", @@ -271,7 +271,7 @@ module.exports = { "play_times": "The play times of the default animation.\n-1 means using the value of config file\n0 means repeat for ever\n>0 means repeat times", "debug_bones": "Indicates whether open debug bones", "enabled_batch": "Indicates whether enabled batch model", - "render_mode": "The render mode of current armature. \n'REALTIME' means REALTIME calculate animation data, support animation blend but low performance. \n'SHARED_CACHE' means precomputation animation data and share data with same armature, high performance and less memery. \n'PRIVATE_CACHE' means precomputation animation data but not share data with other same armature, high performance and more memery.\nAbove two cache mode, not support nest armature, not support 'fade' related interface.", + "animation_cache_mode": "REALTIME model, the animation data is calculated while running, all features supported. SHARED_CACHE mode, the animation data is pre-calculated and cached globally, the data is shared between skeleton animation instances. Shared cache mode has great performance advantage, but it has some limitation. It doesn't support action blending and addition and it only supports the start and end events. In the memory usage aspect, as same skeleton animation instances are sharing the same animation data, this mode can save a lot of memory. More instances are sharing, more memory saved. In conclusion SHARED_CACHE mode is suitable for the skeletons which could be replicated, such as effects animation, monster, NPC and so on.\nPRIVATE_CACHE mode, similar to SHARED_CACHE, but the animation data and texture data are not shared between skeleton instances. So there is no advantage in memory compare to REALTIME mode. The PRIVATE_CACHE is suitable when there is no animation blending or addition needed, but the skeleton could change textures of sub bone (e.g. weapon).", }, 'motionStreak': { 'fadeTime': "Trail fragment fade time, in seconds", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 28fa2016c8b..ca453cc721b 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -264,7 +264,7 @@ module.exports = { "premultipliedAlpha": "是否启用贴图预乘", "use_tint": "是否启用染色效果", "enabled_batch": "是否开启合批", - "render_mode": "当前骨骼动画的渲染模式\nREALTIME 表示实时计算,支持动画融合,较耗性能\nSHARED_CACHE 表示预计算且共享动画数据,性能较高,占用较少内存\nPRIVATE_CACHE 表示预计算但不共享动画数据,性能较高,占用较多内存\n以上两种缓存模式,不支持动作融合", + "animation_cache_mode": "REALTIME 模式,实时运算,支持 Spine 所有的功能。\nSHARED_CACHE 模式,将骨骼动画及贴图数据进行缓存并共享,相当于预烘焙骨骼动画。拥有较高性能,但不支持动作融合、动作叠加,只支持动作开始和结束事件。至于内存方面,当创建 N(N>=3) 个相同骨骼、相同动作的动画时,会呈现内存优势。N 值越大,优势越明显。综上 SHARED_CACHE 模式适用于场景动画,特效,副本怪物,NPC 等,能极大提高帧率和降低内存。\nPRIVATE_CACHE 模式,与 SHARED_CACHE 类似,但不共享动画及贴图数据,所以在内存方面没有优势,仅存在性能优势。当想利用缓存模式的高性能,但又存在换装的需求,因此不能共享贴图数据时,那么 PRIVATE_CACHE 就适合你。", }, "dragon_bones": { "dragon_bones_asset": "骨骼信息数据,拖拽 DragonBones 导出的骨骼动画信息 json 资源到这里来开始使用", @@ -275,7 +275,7 @@ module.exports = { "play_times": "播放默认动画的循环次数\n-1 表示使用配置文件中的默认值\n0 表示无限循环\n>0 表示循环次数", "debug_bones": "是否显示 bone 的 debug 信息", "enabled_batch": "是否开启合批", - "render_mode": "当前骨骼动画的渲染模式\nREALTIME 表示实时计算,支持动画融合,较耗性能\nSHARED_CACHE 表示预计算且共享动画数据,性能较高,占用较少内存\nPRIVATE_CACHE 表示预计算但不共享动画数据,性能较高,占用较多内存\n以上两种缓存模式,不支持骨骼嵌套,不支持fade相关接口", + "animation_cache_mode": "REALTIME 模式,实时运算,支持 DragonBones 所有的功能。\nSHARED_CACHE 模式,将骨骼动画及贴图数据进行缓存并共享,相当于预烘焙骨骼动画。拥有较高性能,但不支持动作融合、动作叠加、骨骼嵌套,只支持动作开始和结束事件。至于内存方面,当创建 N(N>=3) 个相同骨骼、相同动作的动画时,会呈现内存优势。N 值越大,优势越明显。综上 SHARED_CACHE 模式适用于场景动画,特效,副本怪物,NPC 等,能极大提高帧率和降低内存。\nPRIVATE_CACHE 模式,与 SHARED_CACHE 类似,但不共享动画及贴图数据,所以在内存方面没有优势,仅存在性能优势。当想利用缓存模式的高性能,但又存在换装的需求,因此不能共享贴图数据时,那么 PRIVATE_CACHE 就适合你。", }, 'motionStreak': { 'fadeTime': "拖尾的渐隐时间,以秒为单位", diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 9a28cec0cb4..136d519ba5e 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -40,14 +40,14 @@ let ArmatureCache = require('./ArmatureCache'); let DefaultArmaturesEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); -let DefaultRenderMode = cc.Enum({ 'REALTIME': 0 }); +let DefaultCacheMode = cc.Enum({ 'REALTIME': 0 }); /** - * !#en Enum for render mode type. + * !#en Enum for cache mode type. * !#zh Dragonbones渲染类型 - * @enum ArmatureDisplay.RenderMode + * @enum ArmatureDisplay.AnimationCacheMode */ -let RenderMode = cc.Enum({ +let AnimationCacheMode = cc.Enum({ /** * !#en The realtime mode. * !#zh 实时计算模式。 @@ -102,7 +102,7 @@ let ArmatureDisplay = cc.Class({ }, statics: { - RenderMode: RenderMode, + AnimationCacheMode: AnimationCacheMode, }, properties: { @@ -178,13 +178,13 @@ let ArmatureDisplay = cc.Class({ } } - if (this._armature && !this.isCachedMode()) { + if (this._armature && !this.isAnimationCached()) { this._factory._dragonBones.clock.remove(this._armature); } this._refresh(); - if (this._armature && !this.isCachedMode()) { + if (this._armature && !this.isAnimationCached()) { this._factory._dragonBones.clock.add(this._armature); } @@ -275,20 +275,20 @@ let ArmatureDisplay = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.animation_name' }, - // Record pre render mode. - _preRenderMode: -1, - _renderMode: RenderMode.REALTIME, - _defaultRenderMode: { + // Record pre cache mode. + _preCacheMode: -1, + _cacheMode: AnimationCacheMode.REALTIME, + _defaultCacheMode: { default: 0, - type: RenderMode, + type: AnimationCacheMode, notify () { - this.setRenderMode(this._defaultRenderMode); + this.setAnimationCacheMode(this._defaultCacheMode); }, editorOnly: true, visible: true, animatable: false, - displayName: "Render Mode", - tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.render_mode' + displayName: "Animation Cache Mode", + tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.animation_cache_mode' }, /** @@ -369,7 +369,7 @@ let ArmatureDisplay = cc.Class({ // DragonBones data store key. _armatureKey: "", - // Below properties will effect when render mode is SHARED_CACHE or PRIVATE_CACHE. + // Below properties will effect when cache mode is SHARED_CACHE or PRIVATE_CACHE. // accumulate time _accTime: 0, // Play times counter @@ -435,7 +435,7 @@ let ArmatureDisplay = cc.Class({ this._inited = true; if (CC_JSB) { - this._renderMode = RenderMode.REALTIME; + this._cacheMode = AnimationCacheMode.REALTIME; } this._parseDragonAtlasAsset(); @@ -453,21 +453,21 @@ let ArmatureDisplay = cc.Class({ /** * !#en - * It's best to set render mode before set property 'dragonAsset', or will waste some cpu time. + * It's best to set cache mode before set property 'dragonAsset', or will waste some cpu time. * If set the mode in editor, then no need to worry about order problem. * !#zh * 若想切换渲染模式,最好在设置'dragonAsset'之前,先设置好渲染模式,否则有运行时开销。 * 若在编辑中设置渲染模式,则无需担心设置次序的问题。 * - * @method setRenderMode - * @param {RenderMode} renderMode + * @method setAnimationCacheMode + * @param {AnimationCacheMode} cacheMode * * @example - * armatureDisplay.setRenderMode(dragonBones.ArmatureDisplay.RenderMode.SHARED_CACHE); + * armatureDisplay.setAnimationCacheMode(dragonBones.ArmatureDisplay.AnimationCacheMode.SHARED_CACHE); */ - setRenderMode (renderMode) { + setAnimationCacheMode (cacheMode) { if (CC_JSB) return; - if (this._preRenderMode !== renderMode) { - this._renderMode = renderMode; + if (this._preCacheMode !== cacheMode) { + this._cacheMode = cacheMode; this._buildArmature(); } }, @@ -475,31 +475,31 @@ let ArmatureDisplay = cc.Class({ /** * !#en Whether in cached mode. * !#zh 当前是否处于缓存模式。 - * @method isCachedMode + * @method isAnimationCached */ - isCachedMode () { + isAnimationCached () { if (CC_EDITOR) return false; - return this._renderMode !== RenderMode.REALTIME; + return this._cacheMode !== AnimationCacheMode.REALTIME; }, onEnable () { this._super(); - // If render mode is cache, no need to update by dragonbones library. - if (this._armature && !this.isCachedMode()) { + // If cache mode is cache, no need to update by dragonbones library. + if (this._armature && !this.isAnimationCached()) { this._factory._dragonBones.clock.add(this._armature); } }, onDisable () { this._super(); - // If render mode is cache, no need to update by dragonbones library. - if (this._armature && !this.isCachedMode()) { + // If cache mode is cache, no need to update by dragonbones library. + if (this._armature && !this.isAnimationCached()) { this._factory._dragonBones.clock.remove(this._armature); } }, update (dt) { - if (!this.isCachedMode()) return; + if (!this.isAnimationCached()) return; if (!this._playing) return; let frames = this._frameCache.frames; @@ -543,11 +543,11 @@ let ArmatureDisplay = cc.Class({ this._inited = false; if (!CC_EDITOR) { - if (this._renderMode === RenderMode.PRIVATE_CACHE) { + if (this._cacheMode === AnimationCacheMode.PRIVATE_CACHE) { this._armatureCache.dispose(); this._armatureCache = null; this._armature = null; - } else if (this._renderMode === RenderMode.SHARED_CACHE) { + } else if (this._cacheMode === AnimationCacheMode.SHARED_CACHE) { this._armatureCache = null; this._armature = null; } else if (this._armature) { @@ -584,13 +584,13 @@ let ArmatureDisplay = cc.Class({ _buildArmature () { if (!this.dragonAsset || !this.dragonAtlasAsset || !this.armatureName) return; - // Switch Asset or Atlas or renderMode will rebuild armature. + // Switch Asset or Atlas or cacheMode will rebuild armature. if (this._armature) { // dispose pre build armature if (!CC_EDITOR) { - if (this._preRenderMode === RenderMode.PRIVATE_CACHE) { + if (this._preCacheMode === AnimationCacheMode.PRIVATE_CACHE) { this._armatureCache.dispose(); - } else if (this._preRenderMode === RenderMode.REALTIME) { + } else if (this._preCacheMode === AnimationCacheMode.REALTIME) { this._armature.dispose(); } } else { @@ -603,15 +603,15 @@ let ArmatureDisplay = cc.Class({ this._frameCache = null; this._curFrame = null; this._playing = false; - this._preRenderMode = null; + this._preCacheMode = null; this._eventTarget = null; } if (!CC_EDITOR) { - if (this._renderMode === RenderMode.SHARED_CACHE) { + if (this._cacheMode === AnimationCacheMode.SHARED_CACHE) { this._armatureCache = ArmatureCache.sharedCache; this._eventTarget = new EventTarget; - } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { + } else if (this._cacheMode === AnimationCacheMode.PRIVATE_CACHE) { this._armatureCache = new ArmatureCache; this._eventTarget = new EventTarget; } @@ -620,16 +620,16 @@ let ArmatureDisplay = cc.Class({ let atlasUUID = this.dragonAtlasAsset._uuid; this._armatureKey = this.dragonAsset.init(this._factory, atlasUUID); - if (this.isCachedMode()) { + if (this.isAnimationCached()) { this._armature = this._armatureCache.getArmatureCache(this.armatureName, this._armatureKey, atlasUUID); if (!this._armature) { - // Cache fail,swith to REALTIME render mode. - this._renderMode = RenderMode.REALTIME; + // Cache fail,swith to REALTIME cache mode. + this._cacheMode = AnimationCacheMode.REALTIME; } } - this._preRenderMode = this._renderMode; - if (CC_EDITOR || this._renderMode === RenderMode.REALTIME) { + this._preCacheMode = this._cacheMode; + if (CC_EDITOR || this._cacheMode === AnimationCacheMode.REALTIME) { this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, this._armatureKey, "", atlasUUID); if (!this._displayProxy) return; this._displayProxy._ccNode = this.node; @@ -637,7 +637,7 @@ let ArmatureDisplay = cc.Class({ this._armature.animation.timeScale = this.timeScale; } - if (this._renderMode !== RenderMode.REALTIME && this.debugBones) { + if (this._cacheMode !== AnimationCacheMode.REALTIME && this.debugBones) { cc.warn("Debug bones is invalid in cached mode"); } @@ -660,16 +660,16 @@ let ArmatureDisplay = cc.Class({ // update inspector this._updateArmatureEnum(); this._updateAnimEnum(); - this._updateRenderModeEnum(); + this._updateCacheModeEnum(); Editor.Utils.refreshSelectedInspector('node', this.node.uuid); } }, - _updateRenderModeEnum: CC_EDITOR && function () { + _updateCacheModeEnum: CC_EDITOR && function () { if (this._armature && ArmatureCache.canCache(this._armature)) { - setEnumAttr(this, '_defaultRenderMode', RenderMode); + setEnumAttr(this, '_defaultCacheMode', AnimationCacheMode); } else { - setEnumAttr(this, '_defaultRenderMode', DefaultRenderMode); + setEnumAttr(this, '_defaultCacheMode', DefaultCacheMode); } }, @@ -718,7 +718,7 @@ let ArmatureDisplay = cc.Class({ this.playTimes = (playTimes === undefined) ? -1 : playTimes; this.animationName = animName; - if (this.isCachedMode()) { + if (this.isAnimationCached()) { let cache = this._armatureCache.getAnimationCache(this._armatureKey, animName); if (!cache) { cache = this._armatureCache.updateAnimationCache(this._armatureKey, animName); @@ -746,7 +746,7 @@ let ArmatureDisplay = cc.Class({ * @param {String} animName */ updateAnimationCache (animName) { - if (!this.isCachedMode()) return; + if (!this.isAnimationCached()) return; let cache = this._armatureCache.updateAnimationCache(this._armatureKey, animName); this._frameCache = cache || this._frameCache; }, diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 46de7b607a8..37f0a257150 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -317,7 +317,7 @@ let armatureAssembler = { _handleVal |= NEED_BATCH; } - if (comp.isCachedMode()) { + if (comp.isAnimationCached()) { // Traverse input assembler. this.cacheTraverse(comp._curFrame, worldMat); } else { diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 8443e29c381..4eea89de3b1 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -39,11 +39,11 @@ let DefaultSkinsEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); /** - * !#en Enum for render mode type. - * !#zh Spine渲染类型 - * @enum Skeleton.RenderMode + * !#en Enum for animation cache mode type. + * !#zh Spine动画缓存类型 + * @enum Skeleton.AnimationCacheMode */ -let RenderMode = cc.Enum({ +let AnimationCacheMode = cc.Enum({ /** * !#en The realtime mode. * !#zh 实时计算模式。 @@ -98,7 +98,7 @@ sp.Skeleton = cc.Class({ }, statics: { - RenderMode: RenderMode, + AnimationCacheMode: AnimationCacheMode, }, properties: { @@ -168,7 +168,7 @@ sp.Skeleton = cc.Class({ */ animation: { get () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { return this._animationName; } else { var entry = this.getCurrent(0); @@ -272,20 +272,20 @@ sp.Skeleton = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.animation' }, - // Record pre render mode. - _preRenderMode: -1, - _renderMode: RenderMode.REALTIME, - _defaultRenderMode: { + // Record pre cache mode. + _preCacheMode: -1, + _cacheMode: AnimationCacheMode.REALTIME, + _defaultCacheMode: { default: 0, - type: RenderMode, + type: AnimationCacheMode, notify () { - this.setRenderMode(this._defaultRenderMode); + this.setAnimationCacheMode(this._defaultCacheMode); }, editorOnly: true, visible: true, animatable: false, - displayName: "Render Mode", - tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.render_mode' + displayName: "Animation Cache Mode", + tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.animation_cache_mode' }, /** @@ -382,7 +382,7 @@ sp.Skeleton = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.enabled_batch' }, - // Below properties will effect when render mode is SHARED_CACHE or PRIVATE_CACHE. + // Below properties will effect when cache mode is SHARED_CACHE or PRIVATE_CACHE. // accumulate time _accTime: 0, // Play times counter @@ -461,7 +461,7 @@ sp.Skeleton = cc.Class({ this.node.setContentSize(skeletonData.width, skeletonData.height); } - if (this.isCachedMode()) { + if (this.isAnimationCached()) { let skeletonInfo = this._skeletonCache.getSkeletonCache(this.skeletonData._uuid, skeletonData); this._skeleton = skeletonInfo.skeleton; this._clipper = skeletonInfo.clipper; @@ -480,7 +480,7 @@ sp.Skeleton = cc.Class({ * @param {sp.spine.SkeletonData} skeletonData */ setSlotsRange (startSlotIndex, endSlotIndex) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("Slots visible range can not be modified in cached mode."); } else { this._startSlotIndex = startSlotIndex; @@ -497,7 +497,7 @@ sp.Skeleton = cc.Class({ * @param {sp.spine.AnimationStateData} stateData */ setAnimationStateData (stateData) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("'setAnimationStateData' interface can not be invoked in cached mode."); } else { var state = new spine.AnimationState(stateData); @@ -530,7 +530,7 @@ sp.Skeleton = cc.Class({ } if (CC_JSB) { - this._renderMode = RenderMode.REALTIME; + this._cacheMode = AnimationCacheMode.REALTIME; } this._updateSkeletonData(); @@ -541,21 +541,21 @@ sp.Skeleton = cc.Class({ /** * !#en - * It's best to set render mode before set property 'dragonAsset', or will waste some cpu time. + * It's best to set cache mode before set property 'dragonAsset', or will waste some cpu time. * If set the mode in editor, then no need to worry about order problem. * !#zh * 若想切换渲染模式,最好在设置'dragonAsset'之前,先设置好渲染模式,否则有运行时开销。 * 若在编辑中设置渲染模式,则无需担心设置次序的问题。 * - * @method setRenderMode - * @param {RenderMode} renderMode + * @method setAnimationCacheMode + * @param {AnimationCacheMode} cacheMode * * @example - * armatureDisplay.setRenderMode(sp.Skeleton.RenderMode.SHARED_CACHE); + * armatureDisplay.setAnimationCacheMode(sp.Skeleton.AnimationCacheMode.SHARED_CACHE); */ - setRenderMode (renderMode) { + setAnimationCacheMode (cacheMode) { if (CC_JSB) return; - if (this._preRenderMode !== renderMode) { - this._renderMode = renderMode; + if (this._preCacheMode !== cacheMode) { + this._cacheMode = cacheMode; this._updateSkeletonData(); } }, @@ -563,18 +563,18 @@ sp.Skeleton = cc.Class({ /** * !#en Whether in cached mode. * !#zh 当前是否处于缓存模式。 - * @method isCachedMode + * @method isAnimationCached */ - isCachedMode () { + isAnimationCached () { if (CC_EDITOR) return false; - return this._renderMode !== RenderMode.REALTIME; + return this._cacheMode !== AnimationCacheMode.REALTIME; }, update (dt) { if (CC_EDITOR) return; if (this.paused) return; - if (this.isCachedMode()) { + if (this.isAnimationCached()) { // Cache mode and has animation queue. if (this._isAniComplete) { @@ -670,7 +670,7 @@ sp.Skeleton = cc.Class({ * cc.log(bone.worldX); // return -23.12; */ updateWorldTransform () { - if (!this.isCachedMode()) return; + if (!this.isAnimationCached()) return; if (this._skeleton) { this._skeleton.updateWorldTransform(); @@ -683,7 +683,7 @@ sp.Skeleton = cc.Class({ * @method setToSetupPose */ setToSetupPose () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { cc.warn("'SetToSetupPose' interface can not be invoked in cached mode."); } else { if (this._skeleton) { @@ -702,7 +702,7 @@ sp.Skeleton = cc.Class({ * @method setBonesToSetupPose */ setBonesToSetupPose () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { cc.warn("'setBonesToSetupPose' interface can not be invoked in cached mode."); } else { if (this._skeleton) { @@ -721,7 +721,7 @@ sp.Skeleton = cc.Class({ * @method setSlotsToSetupPose */ setSlotsToSetupPose () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { cc.warn("'setSlotsToSetupPose' interface can not be invoked in cached mode."); } else { if (this._skeleton) { @@ -739,7 +739,7 @@ sp.Skeleton = cc.Class({ * @param {String} animName */ updateAnimationCache (animName) { - if (!this.isCachedMode()) return; + if (!this.isAnimationCached()) return; let cache = this._skeletonCache.updateAnimationCache(this.skeletonData._uuid, animName); this._frameCache = cache || this._frameCache; }, @@ -800,7 +800,7 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.Skin} */ setSkin (skinName) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { this._skeletonCache.resetSkeleton(); this._animationName && (this.animation = this._animationName); } else { @@ -892,7 +892,7 @@ sp.Skeleton = cc.Class({ this._playTimes = loop ? 0 : 1; this._animationName = name; - if (this.isCachedMode()) { + if (this.isAnimationCached()) { if (trackIndex !== 0) { cc.warn("Track index can not greater than 0 in cached mode."); } @@ -935,7 +935,7 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.TrackEntry} */ addAnimation (trackIndex, name, loop, delay) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { if (trackIndex !== 0) { cc.warn("Track index can not greater than 0 in cached mode."); } @@ -978,7 +978,7 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.TrackEntry} */ getCurrent (trackIndex) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("'getCurrent' interface can not be invoked in cached mode."); } else { if (this._state) { @@ -994,7 +994,7 @@ sp.Skeleton = cc.Class({ * @method clearTracks */ clearTracks () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("'clearTracks' interface can not be invoked in cached mode."); } else { if (this._state) { @@ -1010,7 +1010,7 @@ sp.Skeleton = cc.Class({ * @param {number} trackIndex */ clearTrack (trackIndex) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("'clearTrack' interface can not be invoked in cached mode."); } else { if (this._state) { @@ -1203,20 +1203,20 @@ sp.Skeleton = cc.Class({ if (!data) return; if (!CC_EDITOR) { - if (this._renderMode === RenderMode.SHARED_CACHE) { + if (this._cacheMode === AnimationCacheMode.SHARED_CACHE) { this._skeletonCache = SkeletonCache.sharedCache; - } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { + } else if (this._cacheMode === AnimationCacheMode.PRIVATE_CACHE) { this._skeletonCache = new SkeletonCache; } } - if (this.isCachedMode() && (this.debugBones || this.debugSlots)) { + if (this.isAnimationCached() && (this.debugBones || this.debugSlots)) { cc.warn("Debug bones or slots is invalid in cached mode"); } try { this.setSkeletonData(data); - if (!this.isCachedMode()) { + if (!this.isAnimationCached()) { this.setAnimationStateData(new spine.AnimationStateData(this._skeleton.data)); } this.defaultSkin && this.setSkin(this.defaultSkin); @@ -1225,7 +1225,7 @@ sp.Skeleton = cc.Class({ cc.warn(e); } - this._preRenderMode = this._renderMode; + this._preCacheMode = this._cacheMode; this.animation = this.defaultAnimation; }, @@ -1233,14 +1233,9 @@ sp.Skeleton = cc.Class({ // update inspector this._updateAnimEnum(); this._updateSkinEnum(); - this._updateRenderModeEnum(); Editor.Utils.refreshSelectedInspector('node', this.node.uuid); }, - _updateRenderModeEnum: CC_EDITOR && function () { - setEnumAttr(this, 'renderMode', RenderMode); - }, - _updateDebugDraw: function () { if (this.debugBones || this.debugSlots) { if (!this._debugRenderer) { @@ -1254,7 +1249,7 @@ sp.Skeleton = cc.Class({ } this._debugRenderer.node.parent = this.node; - if (this.isCachedMode()) { + if (this.isAnimationCached()) { cc.warn("Debug bones or slots is invalid in cached mode"); } } diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 347560b6311..1ac4ec0c4b8 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -621,7 +621,7 @@ var spineAssembler = { _handleVal |= FLAG_BATCH; } - if (comp.isCachedMode()) { + if (comp.isAnimationCached()) { // Traverse input assembler. this.cacheTraverse(worldMat); } else { From 39e4bda428207ce4f6040598d09f99ee7b355744 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Sat, 2 Mar 2019 15:06:08 +0800 Subject: [PATCH 0499/1631] fix label blur when using dark font color (#3949) --- cocos2d/core/CCNode.js | 2 +- cocos2d/core/renderer/utils/label/ttf.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index 4f2d7b3b1ea..bce8daec758 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1177,7 +1177,7 @@ var Node = cc.Class({ // OVERRIDES - _onSiblingIndexChanged (index) { + _onSiblingIndexChanged () { // update rendering scene graph, sort them by arrivalOrder var parent = this._parent; var siblings = parent._children; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index b130079ca6a..6f8cee5dd94 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -51,7 +51,7 @@ let _color = null; let _fontFamily = ''; let _overflow = Overflow.NONE; let _isWrapText = false; -let _backgroundStyle = 'rgba(255, 255, 255, 0.005)'; +const _invisibleAlpha = (1 / 255).toFixed(3); // outline let _isOutlined = false; @@ -210,7 +210,7 @@ module.exports = { _context.clearRect(0, 0, _canvas.width, _canvas.height); //Add a white background to avoid black edges. //TODO: it is best to add alphaTest to filter out the background color. - _context.fillStyle = _backgroundStyle; + _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_invisibleAlpha})`; _context.fillRect(0, 0, _canvas.width, _canvas.height); _context.font = _fontDesc; @@ -218,7 +218,7 @@ module.exports = { let lineHeight = this._getLineHeight(); //use round for line join to avoid sharp intersect point _context.lineJoin = 'round'; - _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${1})`; + _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, 1)`; let underlineStartPosition; //do real rendering From 9b8dea74708c92ee225b274a39df1a1ecd7811f0 Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 4 Mar 2019 09:53:14 +0800 Subject: [PATCH 0500/1631] optimize editBox style (#3952) --- cocos2d/core/components/editbox/CCEditBoxImpl.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js index 7a71ef00eb2..36fd3d6b657 100644 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -615,8 +615,8 @@ _p._createDomInput = function () { tmpEdTxt.style.bottom = "0px"; tmpEdTxt.style.left = LEFT_PADDING + "px"; tmpEdTxt.style['-moz-appearance'] = 'textfield'; - tmpEdTxt.style.className = "cocosEditBox"; tmpEdTxt.style.fontFamily = 'Arial'; + tmpEdTxt.className = "cocosEditBox"; registerInputEventListener(tmpEdTxt, this); @@ -627,7 +627,6 @@ _p._createDomTextArea = function () { this.removeDom(); let tmpEdTxt = this._edTxt = document.createElement('textarea'); - tmpEdTxt.type = 'text'; tmpEdTxt.style.fontSize = this._edFontSize + 'px'; tmpEdTxt.style.color = '#000000'; tmpEdTxt.style.border = 0; @@ -644,8 +643,8 @@ _p._createDomTextArea = function () { tmpEdTxt.style.position = "absolute"; tmpEdTxt.style.bottom = "0px"; tmpEdTxt.style.left = LEFT_PADDING + "px"; - tmpEdTxt.style.className = "cocosEditBox"; tmpEdTxt.style.fontFamily = 'Arial'; + tmpEdTxt.className = "cocosEditBox"; registerInputEventListener(tmpEdTxt, this, true); From 75c580174c1185158f03eb8fda7236da244c3787 Mon Sep 17 00:00:00 2001 From: ColinCollins <35832931+ColinCollins@users.noreply.github.com> Date: Mon, 4 Mar 2019 14:53:39 +0800 Subject: [PATCH 0501/1631] To adapt the adjust of the webview impl in the jsb (#3697) (#3951) --- cocos2d/webview/CCWebView.js | 6 +++--- cocos2d/webview/webview-impl.js | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cocos2d/webview/CCWebView.js b/cocos2d/webview/CCWebView.js index a740a2e044a..d9091b079f4 100644 --- a/cocos2d/webview/CCWebView.js +++ b/cocos2d/webview/CCWebView.js @@ -107,17 +107,17 @@ let WebView = cc.Class({ statics: { EventType: EventType, + // Impl will be overrided in the different platform. Impl: WebViewImpl }, - ctor () { - this._impl = new WebViewImpl(); + this._impl = new WebView.Impl(); }, onRestore () { if (!this._impl) { - this._impl = new WebViewImpl(); + this._impl = new WebView.Impl(); } }, diff --git a/cocos2d/webview/webview-impl.js b/cocos2d/webview/webview-impl.js index 9df5c8ccae8..f9ef1e89352 100644 --- a/cocos2d/webview/webview-impl.js +++ b/cocos2d/webview/webview-impl.js @@ -182,6 +182,7 @@ let WebViewImpl = cc.Class({ setOnJSCallback (callback) {}, setJavascriptInterfaceScheme (scheme) {}, + // private method loadData (data, MIMEType, encoding, baseURL) {}, loadHTMLString (string, baseURL) {}, From bf8efdc8cb191fc1237a808b0c628f540b2d3a98 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Mon, 4 Mar 2019 18:47:56 +0800 Subject: [PATCH 0502/1631] fix the problem of label that first modified is invalid. (#3959) --- cocos2d/core/renderer/utils/label/letter-font.js | 2 +- cocos2d/core/renderer/utils/label/ttf.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/renderer/utils/label/letter-font.js b/cocos2d/core/renderer/utils/label/letter-font.js index d72e72bbbf8..af14d5c2899 100644 --- a/cocos2d/core/renderer/utils/label/letter-font.js +++ b/cocos2d/core/renderer/utils/label/letter-font.js @@ -87,7 +87,7 @@ LetterTexture.prototype = { this._width = parseFloat(width.toFixed(2)) + 2 * this._labelInfo.margin; this._height = this._labelInfo.lineHeight; - if (this._canvas.width !== this._width) { + if (this._canvas.width !== this._width || CC_QQPLAY) { this._canvas.width = this._width; } diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index 6f8cee5dd94..f9dc7c7c9b7 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -302,7 +302,7 @@ module.exports = { } } - if (_canvas.width !== _canvasSize.width) { + if (_canvas.width !== _canvasSize.width || CC_QQPLAY) { _canvas.width = _canvasSize.width; } From c30716878cad0fe0ed623f84fa9516604bb77466 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Tue, 5 Mar 2019 15:38:26 +0800 Subject: [PATCH 0503/1631] Fix create ArmatureDisplay by code but no set asset, then invoke some api about event, will throw error (#3966) --- extensions/dragonbones/ArmatureDisplay.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 136d519ba5e..c4a7870cb0c 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -509,7 +509,7 @@ let ArmatureDisplay = cc.Class({ // Animation Start, the event diffrent from dragonbones inner event, // It has no event object. if (this._accTime == 0 && this._playCount == 0) { - this._eventTarget.emit(dragonBones.EventObject.START); + this._eventTarget && this._eventTarget.emit(dragonBones.EventObject.START); } this._accTime += dt * this.timeScale; @@ -518,11 +518,11 @@ let ArmatureDisplay = cc.Class({ // Animation loop complete, the event diffrent from dragonbones inner event, // It has no event object. - this._eventTarget.emit(dragonBones.EventObject.LOOP_COMPLETE); + this._eventTarget && this._eventTarget.emit(dragonBones.EventObject.LOOP_COMPLETE); // Animation complete the event diffrent from dragonbones inner event, // It has no event object. - this._eventTarget.emit(dragonBones.EventObject.COMPLETE); + this._eventTarget && this._eventTarget.emit(dragonBones.EventObject.COMPLETE); this._playCount ++; if (this.playTimes === -1 || (this.playTimes > 0 && this._playCount >= this.playTimes)) { @@ -832,7 +832,7 @@ let ArmatureDisplay = cc.Class({ once (eventType, listener, target) { if (this._displayProxy) { this._displayProxy.once(eventType, listener, target); - } else { + } else if (this._eventTarget) { this._eventTarget.once(eventType, listener, target); } }, @@ -851,7 +851,7 @@ let ArmatureDisplay = cc.Class({ addEventListener (eventType, listener, target) { if (this._displayProxy) { this._displayProxy.on(eventType, listener, target); - } else { + } else if (this._eventTarget) { this._eventTarget.on(eventType, listener, target); } }, @@ -869,7 +869,7 @@ let ArmatureDisplay = cc.Class({ removeEventListener (eventType, listener, target) { if (this._displayProxy) { this._displayProxy.off(eventType, listener, target); - } else { + } else if (this._eventTarget) { this._eventTarget.off(eventType, listener, target); } }, From 0a270c0f089067dffc40ce8522c79163a05bb44b Mon Sep 17 00:00:00 2001 From: Knox Date: Sat, 9 Mar 2019 22:28:55 +0800 Subject: [PATCH 0504/1631] fix get auido state bug (#3974) --- cocos2d/audio/CCAudio.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cocos2d/audio/CCAudio.js b/cocos2d/audio/CCAudio.js index 734086efcbc..69ba941afb1 100644 --- a/cocos2d/audio/CCAudio.js +++ b/cocos2d/audio/CCAudio.js @@ -267,13 +267,16 @@ Audio.State = { }; proto.getState = function () { - if (!CC_WECHATGAME && !CC_QQPLAY) { + let elem = this._element; + if (!CC_WECHATGAME && !CC_QQPLAY && elem) { // HACK: in some browser, audio may not fire 'ended' event // so we need to force updating the Audio state - let elem = this._element; - if (elem && Audio.State.PLAYING === this._state && elem.paused) { + if (Audio.State.PLAYING === this._state && elem.paused) { this._state = Audio.State.STOPPED; } + else if (Audio.State.STOPPED === this._state && !elem.paused) { + this._state = Audio.State.PLAYING; + } } return this._state; }; From 5d61e3e57037a7e726d030d57f8619ae0c530840 Mon Sep 17 00:00:00 2001 From: gaolizheng Date: Sat, 9 Mar 2019 23:31:25 +0800 Subject: [PATCH 0505/1631] Update loading-items.js (#3989) Fix typo in loading-items.js --- cocos2d/core/load-pipeline/loading-items.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/load-pipeline/loading-items.js b/cocos2d/core/load-pipeline/loading-items.js index 2903a317224..e3a7803466f 100644 --- a/cocos2d/core/load-pipeline/loading-items.js +++ b/cocos2d/core/load-pipeline/loading-items.js @@ -142,7 +142,7 @@ function checkCircleReference(owner, item, recursiveCall) { * !#zh * LoadingItems 是一个加载对象队列,可以用来输送加载对象到加载管线中。
* 请不要直接使用 new 构造这个类的对象,你可以使用 {{#crossLink "LoadingItems.create"}}cc.LoadingItems.create{{/crossLink}} 来创建一个新的加载队列,这样可以允许我们的内部对象池回收并重利用加载队列。 - * 它有一个 map 属性用来存放加载项,在 map 对象中已 url 为 key 值。
+ * 它有一个 map 属性用来存放加载项,在 map 对象中以 url 为 key 值。
* 每个对象都会包含下列属性:
* - id:该对象的标识,通常与 url 相同。
* - url:路径
From ac0216d8ce739ac6e6d1a3e42f20cc244a77c56f Mon Sep 17 00:00:00 2001 From: 2youyouo2 <501251991@qq.com> Date: Mon, 11 Mar 2019 14:32:19 +0800 Subject: [PATCH 0506/1631] small fixed --- cocos2d/core/components/CCSprite.js | 2 +- .../webgl/assemblers/label/2d/letter.js | 4 +- .../webgl/assemblers/label/letter-font.js | 135 ------------------ cocos2d/core/utils/blend-func.js | 4 +- cocos2d/particle/CCParticleSystem.js | 2 +- extensions/spine/Skeleton.js | 13 -- 6 files changed, 6 insertions(+), 154 deletions(-) delete mode 100644 cocos2d/core/renderer/webgl/assemblers/label/letter-font.js diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index fb0b9256b6a..8046522e6da 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -155,7 +155,7 @@ var State = cc.Enum({ var Sprite = cc.Class({ name: 'cc.Sprite', extends: RenderComponent, - mixins: BlendFunc, + mixins: [BlendFunc], ctor () { this._graySpriteMaterial = null; diff --git a/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js index 1b11f107e8b..e55b4f93776 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js @@ -25,7 +25,7 @@ const js = require('../../../../../platform/js'); const bmfintAssembler = require('./bmfont'); -const ttfUtls = require('../../../../utils/label/ttf'); +const fontUtils = require('../../../../utils/label/letter-font'); const fillMeshVertices = require('../../utils').fillMeshVertices; const WHITE = cc.color(255, 255, 255, 255); @@ -41,4 +41,4 @@ module.exports = js.addon({ }, appendQuad: bmfintAssembler.appendQuad -}, ttfUtls); +}, fontUtils); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/letter-font.js b/cocos2d/core/renderer/webgl/assemblers/label/letter-font.js deleted file mode 100644 index 3b4a9607265..00000000000 --- a/cocos2d/core/renderer/webgl/assemblers/label/letter-font.js +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** - Copyright (c) 2018 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 fontUtils = require('../../../utils/label/letter-font'); -const WHITE = cc.color(255, 255, 255, 255); - -module.exports = js.addon({ - createData (comp) { - return comp.requestRenderData(); - }, - - fillBuffers (comp, renderer) { - let node = comp.node, - renderData = comp._renderData, - data = renderData._data; - - let matrix = node._worldMatrix, - a = matrix.m00, b = matrix.m01, c = matrix.m04, d = matrix.m05, - tx = matrix.m12, ty = matrix.m13; - - WHITE._fastSetA(node.color.a); - let color = WHITE._val; - let buffer = renderer._meshBuffer; - let vertexCount = renderData.vertexCount; - let offsetInfo = buffer.request(vertexCount, renderData.indiceCount); - - // buffer data may be realloc, need get reference after request. - let indiceOffset = offsetInfo.indiceOffset, - vertexOffset = offsetInfo.byteOffset >> 2, - vertexId = offsetInfo.vertexOffset, - vbuf = buffer._vData, - uintbuf = buffer._uintVData, - ibuf = buffer._iData; - - - for (let i = 0; i < vertexCount; i++) { - let vert = data[i]; - vbuf[vertexOffset++] = vert.x * a + vert.y * c + tx; - vbuf[vertexOffset++] = vert.x * b + vert.y * d + ty; - vbuf[vertexOffset++] = vert.u; - vbuf[vertexOffset++] = vert.v; - uintbuf[vertexOffset++] = color; - } - - // fill indice data - for (let i = 0, count = vertexCount / 4; i < count; i++) - { - let start = vertexId + i * 4; - ibuf[indiceOffset++] = start; - ibuf[indiceOffset++] = start + 1; - ibuf[indiceOffset++] = start + 2; - ibuf[indiceOffset++] = start + 1; - ibuf[indiceOffset++] = start + 3; - ibuf[indiceOffset++] = start + 2; - } - }, - - appendQuad (renderData, texture, rect, rotated, x, y, scale) { - let dataOffset = renderData.dataLength; - - renderData.dataLength += 4; - renderData.vertexCount = renderData.dataLength; - renderData.indiceCount = renderData.dataLength / 2 * 3; - - let data = renderData._data; - let texw = texture.width, - texh = texture.height; - - let rectWidth = rect.width, - rectHeight = rect.height; - - let l, b, r, t; - if (!rotated) { - l = (rect.x) / texw; - r = (rect.x + rectWidth) / texw; - b = (rect.y + rectHeight) / texh; - t = (rect.y) / texh; - - data[dataOffset].u = l; - data[dataOffset].v = b; - data[dataOffset+1].u = r; - data[dataOffset+1].v = b; - data[dataOffset+2].u = l; - data[dataOffset+2].v = t; - data[dataOffset+3].u = r; - data[dataOffset+3].v = t; - } else { - l = (rect.x) / texw; - r = (rect.x + rectHeight) / texw; - b = (rect.y + rectWidth) / texh; - t = (rect.y) / texh; - - data[dataOffset].u = l; - data[dataOffset].v = t; - data[dataOffset+1].u = l; - data[dataOffset+1].v = b; - data[dataOffset+2].u = r; - data[dataOffset+2].v = t; - data[dataOffset+3].u = r; - data[dataOffset+3].v = b; - } - - data[dataOffset].x = x; - data[dataOffset].y = y - rectHeight * scale; - data[dataOffset+1].x = x + rectWidth * scale; - data[dataOffset+1].y = y - rectHeight * scale; - data[dataOffset+2].x = x; - data[dataOffset+2].y = y; - data[dataOffset+3].x = x + rectWidth * scale; - data[dataOffset+3].y = y; - }, -}, fontUtils); diff --git a/cocos2d/core/utils/blend-func.js b/cocos2d/core/utils/blend-func.js index e31839056f1..e165c3576e8 100644 --- a/cocos2d/core/utils/blend-func.js +++ b/cocos2d/core/utils/blend-func.js @@ -1,9 +1,9 @@ +const RenderComponent = require('../components/CCRenderComponent'); const BlendFactor = require('../platform/CCMacro').BlendFactor; +const gfx = require('../../renderer/gfx'); let BlendFunc = cc.Class({ - name: 'cc.BlendFunc', - properties: { _srcBlendFactor: BlendFactor.SRC_ALPHA, _dstBlendFactor: BlendFactor.ONE_MINUS_SRC_ALPHA, diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 716afaa4ec1..471dcfd0da6 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -711,7 +711,7 @@ var properties = { var ParticleSystem = cc.Class({ name: 'cc.ParticleSystem', extends: RenderComponent, - mixins: BlendFunc, + mixins: [BlendFunc], editor: CC_EDITOR && { menu: 'i18n:MAIN_MENU.component.renderers/ParticleSystem', inspector: 'packages://inspector/inspectors/comps/particle-system.js', diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index fbf16d86932..a7ddb017f8e 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -1206,15 +1206,9 @@ sp.Skeleton = cc.Class({ if (!data) return; if (!CC_EDITOR) { -<<<<<<< HEAD - if (this._renderMode === RenderMode.SHARED_CACHE) { - this._skeletonCache = SkeletonCache.sharedCache; - } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { -======= if (this._cacheMode === AnimationCacheMode.SHARED_CACHE) { this._skeletonCache = SkeletonCache.sharedCache; } else if (this._cacheMode === AnimationCacheMode.PRIVATE_CACHE) { ->>>>>>> 0a270c0f089067dffc40ce8522c79163a05bb44b this._skeletonCache = new SkeletonCache; } } @@ -1245,13 +1239,6 @@ sp.Skeleton = cc.Class({ Editor.Utils.refreshSelectedInspector('node', this.node.uuid); }, -<<<<<<< HEAD - _updateRenderModeEnum: CC_EDITOR && function () { - setEnumAttr(this, 'renderMode', RenderMode); - }, - -======= ->>>>>>> 0a270c0f089067dffc40ce8522c79163a05bb44b _updateDebugDraw: function () { if (this.debugBones || this.debugSlots) { if (!this._debugRenderer) { From 05ccb4414d3264e9503f871812f63dc754aa2659 Mon Sep 17 00:00:00 2001 From: 2youyouo2 <501251991@qq.com> Date: Mon, 11 Mar 2019 15:04:06 +0800 Subject: [PATCH 0507/1631] small fixed --- cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js index e55b4f93776..b3c3adf4c2a 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js @@ -24,7 +24,7 @@ ****************************************************************************/ const js = require('../../../../../platform/js'); -const bmfintAssembler = require('./bmfont'); +const bmfontAssembler = require('./bmfont'); const fontUtils = require('../../../../utils/label/letter-font'); const fillMeshVertices = require('../../utils').fillMeshVertices; const WHITE = cc.color(255, 255, 255, 255); @@ -40,5 +40,5 @@ module.exports = js.addon({ fillMeshVertices(node, renderer._meshBuffer, comp._renderData, WHITE._val); }, - appendQuad: bmfintAssembler.appendQuad + appendQuad: bmfontAssembler.appendQuad }, fontUtils); From d32ffa8b423f21f6dc05fd08309c8216b7ed481f Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 11 Mar 2019 16:41:52 +0800 Subject: [PATCH 0508/1631] optimize 3d skeleton animation performance (#3960) * fixed dynamicAtlasManager is not defined when disable dynamic atlas module * fixed fps debug info can not show * add cc.sys.glExtension * add device.setUniformDirectly * sync #3876 * optimize 3d skeleton animation performance * use Float32Array insteadof Mat4 for jointMatrix * move skeleton files to skeleton folder --- cocos2d/core/3d/CCModel.js | 47 +++- cocos2d/core/3d/CCSkeletonAnimationClip.js | 120 -------- cocos2d/core/3d/index.js | 8 +- cocos2d/core/3d/{ => skeleton}/CCSkeleton.js | 34 +-- .../3d/{ => skeleton}/CCSkeletonAnimation.js | 14 +- .../3d/skeleton/CCSkeletonAnimationClip.js | 265 ++++++++++++++++++ .../{ => skeleton}/CCSkinnedMeshRenderer.js | 162 +++++++---- cocos2d/core/CCGame.js | 2 +- cocos2d/core/camera/CCCamera.js | 4 + cocos2d/core/mesh/CCMeshRenderer.js | 4 + cocos2d/core/mesh/mesh-renderer.js | 2 +- cocos2d/core/platform/CCSys.js | 12 + cocos2d/renderer/core/base-renderer.js | 3 +- cocos2d/renderer/core/effect.js | 6 - cocos2d/renderer/gfx/device.js | 29 +- 15 files changed, 497 insertions(+), 215 deletions(-) delete mode 100644 cocos2d/core/3d/CCSkeletonAnimationClip.js rename cocos2d/core/3d/{ => skeleton}/CCSkeleton.js (74%) rename cocos2d/core/3d/{ => skeleton}/CCSkeletonAnimation.js (92%) create mode 100644 cocos2d/core/3d/skeleton/CCSkeletonAnimationClip.js rename cocos2d/core/3d/{ => skeleton}/CCSkinnedMeshRenderer.js (53%) diff --git a/cocos2d/core/3d/CCModel.js b/cocos2d/core/3d/CCModel.js index dd9630573fb..7ec93acac09 100644 --- a/cocos2d/core/3d/CCModel.js +++ b/cocos2d/core/3d/CCModel.js @@ -23,19 +23,56 @@ THE SOFTWARE. ****************************************************************************/ -const BufferAsset = require('../assets/CCBufferAsset'); - let Model = cc.Class({ name: 'cc.Model', extends: cc.Asset, + ctor () { + this._nodeMap = {}; + }, + properties: { - _buffers: [BufferAsset], + _nodes: { + default: [] + }, + + _precomputeJointMatrix: false, - _gltf: { - default: {} + nodes: { + get () { + return this._nodes; + } + }, + nodeMap: { + get () { + return this._nodeMap; + } + }, + + precomputeJointMatrix: { + get () { + return this._precomputeJointMatrix; + } } }, + + onLoad () { + let nodes = this._nodes; + let map = this._nodeMap; + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i]; + node.position = cc.v3.apply(this, node.position); + node.scale = cc.v3.apply(this, node.scale); + node.quat = cc.quat.apply(this, node.quat); + + let pose = node.bindpose; + if (pose) { + node.bindpose = cc.mat4.apply(this, pose); + } + + map[node.path] = node; + } + } }); cc.Model = module.exports = Model; diff --git a/cocos2d/core/3d/CCSkeletonAnimationClip.js b/cocos2d/core/3d/CCSkeletonAnimationClip.js deleted file mode 100644 index 70347a0e696..00000000000 --- a/cocos2d/core/3d/CCSkeletonAnimationClip.js +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - http://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 AnimationClip = require('../../animation/animation-clip'); - - /** - * @module cc - */ -/** - * !#en SkeletonAnimationClip Asset. - * !#zh 骨骼动画剪辑。 - * @class SkeletonAnimationClip - * @extends AnimationClip - */ -var SkeletonAnimationClip = cc.Class({ - name: 'cc.SkeletonAnimationClip', - extends: AnimationClip, - - properties: { - _nativeAsset: { - override: true, - get () { - return this._buffer; - }, - set (bin) { - let buffer = ArrayBuffer.isView(bin) ? bin.buffer : bin; - this._buffer = new Float32Array(buffer || bin, 0, buffer.byteLength/4); - } - }, - - /** - * Describe the data structure. - * { path: { offset, frameCount, property } } - */ - description: { - default: null, - type: Object, - }, - - /** - * SkeletonAnimationClip's curveData is generated from binary buffer. - * So should not serialize curveData. - */ - curveData: { - default: {}, - visible: false, - override: true, - serializable: false - }, - }, - - onLoad () { - let buffer = this._buffer; - let description = this.description; - - let offset = 0; - function getValue () { - return buffer[offset++]; - } - - if (!this.curveData) { - this.curveData = {}; - } - if (!this.curveData.paths) { - this.curveData.paths = {}; - } - let paths = this.curveData.paths; - - for (let path in description) { - let des = description[path]; - let curves = {}; - paths[path] = { props: curves }; - - for (let property in des) { - let frames = []; - - let frameCount = des[property].frameCount; - offset = des[property].offset; - for (let i = 0; i < frameCount; i++) { - let frame = getValue(); - let value; - if (property === 'position' || property === 'scale') { - value = cc.v3(getValue(), getValue(), getValue()); - } - else if (property === 'quat') { - value = cc.quat(getValue(), getValue(), getValue(), getValue()); - } - frames.push({ frame, value }); - } - - curves[property] = frames; - } - } - } - -}); - -cc.SkeletonAnimationClip = module.exports = SkeletonAnimationClip; diff --git a/cocos2d/core/3d/index.js b/cocos2d/core/3d/index.js index bcc4bfe214e..3fb28bdbc56 100644 --- a/cocos2d/core/3d/index.js +++ b/cocos2d/core/3d/index.js @@ -6,12 +6,12 @@ if (!CC_TEST && (!CC_EDITOR || !Editor.isMainProcess)) { } require('./CCModel'); -require('./CCSkeleton'); -require('./CCSkeletonAnimationClip'); +require('./skeleton/CCSkeleton'); +require('./skeleton/CCSkeletonAnimationClip'); require('./actions'); if (!CC_EDITOR || !Editor.isMainProcess) { - require('./CCSkeletonAnimation'); - require('./CCSkinnedMeshRenderer'); + require('./skeleton/CCSkeletonAnimation'); + require('./skeleton/CCSkinnedMeshRenderer'); require('./CCLightComponent'); } diff --git a/cocos2d/core/3d/CCSkeleton.js b/cocos2d/core/3d/skeleton/CCSkeleton.js similarity index 74% rename from cocos2d/core/3d/CCSkeleton.js rename to cocos2d/core/3d/skeleton/CCSkeleton.js index 62ea6bc6408..941765fb836 100644 --- a/cocos2d/core/3d/CCSkeleton.js +++ b/cocos2d/core/3d/skeleton/CCSkeleton.js @@ -23,23 +23,19 @@ THE SOFTWARE. ****************************************************************************/ -import { mat4 } from '../../core/vmath'; let Skeleton = cc.Class({ name: 'cc.Skeleton', extends: cc.Asset, ctor () { - // {[Mat4]} this._bindposes = []; + this._jointPaths = []; }, properties: { - _jointPaths: [], - /** - * Bindposes data stores in one array, it is better for data size. - */ - _bindposesData: [], + _model: cc.Model, + _jointIndices: [], jointPaths: { get () { @@ -50,20 +46,24 @@ let Skeleton = cc.Class({ get () { return this._bindposes; } + }, + + model: { + get () { + return this._model; + } } }, onLoad () { - let data = this._bindposesData; - let poses = this._bindposes; - for (let i = 0; i < data.length; i++) { - let pose = data[i]; - poses[i] = mat4.create( - pose[0], pose[1], pose[2], pose[3], - pose[4], pose[5], pose[6], pose[7], - pose[8], pose[9], pose[10], pose[11], - pose[12], pose[13], pose[14], pose[15], - ); + let nodes = this._model.nodes; + let jointIndices = this._jointIndices; + let jointPaths = this._jointPaths; + let bindposes = this._bindposes; + for (let i = 0; i < jointIndices.length; i++) { + let node = nodes[jointIndices[i]]; + jointPaths[i] = node.path; + bindposes[i] = node.bindpose; } } }); diff --git a/cocos2d/core/3d/CCSkeletonAnimation.js b/cocos2d/core/3d/skeleton/CCSkeletonAnimation.js similarity index 92% rename from cocos2d/core/3d/CCSkeletonAnimation.js rename to cocos2d/core/3d/skeleton/CCSkeletonAnimation.js index a5ef5dac874..e18fa6b9add 100644 --- a/cocos2d/core/3d/CCSkeletonAnimation.js +++ b/cocos2d/core/3d/skeleton/CCSkeletonAnimation.js @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -const Animation = require('../components/CCAnimation'); -const Model = require('./CCModel'); +const Animation = require('../../components/CCAnimation'); +const Model = require('../CCModel'); const SkeletonAnimationClip = require('./CCSkeletonAnimationClip'); /** @@ -48,8 +48,7 @@ let SkeletonAnimation = cc.Class({ properties: { _model: { default: null, - type: Model, - editorOnly: true + type: Model }, _defaultClip: { @@ -87,6 +86,13 @@ let SkeletonAnimation = cc.Class({ }, }, + getAnimationState (name) { + let state = this._super(name); + let clip = state.clip; + clip._init(this._model); + return state; + }, + searchClips: CC_EDITOR && function () { this._clips.length = 0; let self = this; diff --git a/cocos2d/core/3d/skeleton/CCSkeletonAnimationClip.js b/cocos2d/core/3d/skeleton/CCSkeletonAnimationClip.js new file mode 100644 index 00000000000..3743961f551 --- /dev/null +++ b/cocos2d/core/3d/skeleton/CCSkeletonAnimationClip.js @@ -0,0 +1,265 @@ +/**************************************************************************** + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + + http://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 AnimationClip = require('../../../animation/animation-clip'); +import mat4 from '../../vmath/mat4'; + +function maxtrixToArray (matrix) { + let data = new Float32Array(16); + data[0] = matrix.m00; + data[1] = matrix.m01; + data[2] = matrix.m02; + data[3] = matrix.m03; + data[4] = matrix.m04; + data[5] = matrix.m05; + data[6] = matrix.m06; + data[7] = matrix.m07; + data[8] = matrix.m08; + data[9] = matrix.m09; + data[10] = matrix.m10; + data[11] = matrix.m11; + data[12] = matrix.m12; + data[13] = matrix.m13; + data[14] = matrix.m14; + data[15] = matrix.m15; + return data; +} + +/** +* @module cc +*/ +/** + * !#en SkeletonAnimationClip Asset. + * !#zh 骨骼动画剪辑。 + * @class SkeletonAnimationClip + * @extends AnimationClip + */ +let SkeletonAnimationClip = cc.Class({ + name: 'cc.SkeletonAnimationClip', + extends: AnimationClip, + + properties: { + _nativeAsset: { + override: true, + get () { + return this._buffer; + }, + set (bin) { + let buffer = ArrayBuffer.isView(bin) ? bin.buffer : bin; + this._buffer = new Float32Array(buffer || bin, 0, buffer.byteLength / 4); + } + }, + + /** + * Describe the data structure. + * { path: { offset, frameCount, property } } + */ + description: { + default: null, + type: Object, + }, + + /** + * SkeletonAnimationClip's curveData is generated from binary buffer. + * So should not serialize curveData. + */ + curveData: { + visible: false, + override: true, + get () { + return this._curveData || {}; + }, + set () {} + } + }, + + _init (model) { + if (this._curveData) { + return this._curveData; + } + + this._curveData = {}; + + this._generateCommonCurve(); + + this._model = model; + if (this._model.precomputeJointMatrix) { + this._generateJointMatrixCurve(); + } + + return this._curveData; + }, + + _generateCommonCurve () { + let buffer = this._buffer; + let description = this.description; + + let offset = 0; + function getValue () { + return buffer[offset++]; + } + + if (!this._curveData.paths) { + this._curveData.paths = {}; + } + let paths = this._curveData.paths; + + for (let path in description) { + let des = description[path]; + let curves = {}; + paths[path] = { props: curves }; + + for (let property in des) { + let frames = []; + + let frameCount = des[property].frameCount; + offset = des[property].offset; + for (let i = 0; i < frameCount; i++) { + let frame = getValue(); + let value; + if (property === 'position' || property === 'scale') { + value = cc.v3(getValue(), getValue(), getValue()); + } + else if (property === 'quat') { + value = cc.quat(getValue(), getValue(), getValue(), getValue()); + } + frames.push({ frame, value }); + } + + curves[property] = frames; + } + } + }, + + _generateJointMatrixCurve () { + let joints = this._model.nodeMap; + let curveData = this._curveData; + let paths = curveData.paths; + + // first build a virtual node tree, + // each virtual node should contain position, scale, quat, bindpose properties. + let root = { children: [] }; + for (let path in paths) { + let nodeLevels = path.split('/'); + let node = root; + let currentPath = ''; + for (let i = 0; i < nodeLevels.length; i++) { + let nodeName = nodeLevels[i]; + currentPath += i === 0 ? nodeName : '/' + nodeName; + if (!node.children[nodeName]) { + let joint = joints[currentPath]; + if (!joint) { + cc.warn(`Can not find joint ${currentPath} when generate joint matrix curve.`) + break; + } + node.children[nodeName] = { + name: nodeName, + path: currentPath, + children: {}, + position: joint.position, + quat: joint.quat, + scale: joint.scale, + bindpose: joint.bindpose + }; + } + node = node.children[nodeName]; + } + } + + // walk through node tree to calculate node's joint matrix at time. + function walk (node, time, pm) { + let matrix; + let EPSILON = 10e-5; + + if (node !== root) { + let props = paths[node.path].props; + for (let prop in props) { + let frames = props[prop]; + for (let i = 0; i < frames.length; i++) { + let end = frames[i]; + + if (Math.abs(end.frame - time) < EPSILON) { + node[prop].set(end.value); + break; + } + else if (end.frame > time) { + let start = frames[i - 1]; + let ratio = (time - start.frame) / (end.frame - start.frame); + start.value.lerp(end.value, ratio, node[prop]); + break; + } + } + } + + matrix = mat4.create(); + mat4.fromRTS(matrix, node.quat, node.position, node.scale); + + if (pm) { + mat4.mul(matrix, pm, matrix); + } + + if (!props._jointMatrix) { + props._jointMatrix = []; + } + + let bindWorldMatrix; + if (node.bindpose) { + bindWorldMatrix = mat4.create(); + mat4.mul(bindWorldMatrix, matrix, node.bindpose); + } + + props._jointMatrix.push({ + frame: time, + value: maxtrixToArray(bindWorldMatrix || matrix) + }); + } + + let children = node.children; + for (let name in children) { + let child = children[name]; + walk(child, time, matrix); + } + } + + let time = 0; + let duration = this.duration; + let step = 1 / this.sample; + + while (time < duration) { + walk(root, time); + time += step; + } + + // do not need position, quat, scale property curve any more. + for (let path in paths) { + let props = paths[path].props; + delete props.position; + delete props.quat; + delete props.scale; + } + } +}); + +cc.SkeletonAnimationClip = module.exports = SkeletonAnimationClip; diff --git a/cocos2d/core/3d/CCSkinnedMeshRenderer.js b/cocos2d/core/3d/skeleton/CCSkinnedMeshRenderer.js similarity index 53% rename from cocos2d/core/3d/CCSkinnedMeshRenderer.js rename to cocos2d/core/3d/skeleton/CCSkinnedMeshRenderer.js index 5a911badcc5..0b98034b010 100644 --- a/cocos2d/core/3d/CCSkinnedMeshRenderer.js +++ b/cocos2d/core/3d/skeleton/CCSkinnedMeshRenderer.js @@ -24,11 +24,14 @@ ****************************************************************************/ const Skeleton = require('./CCSkeleton'); -const MeshRenderer = require('../mesh/CCMeshRenderer'); +const MeshRenderer = require('../../mesh/CCMeshRenderer'); +const RenderFlow = require('../../renderer/render-flow'); const mat4 = cc.vmath.mat4; let _m4_tmp = mat4.create(); +const dummyNode = new cc.Node(); + let SkinnedMeshRenderer = cc.Class({ name: 'cc.SkinnedMeshRenderer', extends: MeshRenderer, @@ -38,10 +41,9 @@ let SkinnedMeshRenderer = cc.Class({ }, ctor () { - this._jointsTextureData = null; + this._jointsData = null; this._jointsTexture = null; this._joints = []; - this._matrices = []; this._assembler = MeshRenderer._assembler; }, @@ -56,8 +58,7 @@ let SkinnedMeshRenderer = cc.Class({ }, set (val) { this._skeleton = val; - this._initJoints(); - this._initJointsTexture(); + this._init(); this._activateMaterial(true); }, type: Skeleton @@ -69,14 +70,14 @@ let SkinnedMeshRenderer = cc.Class({ }, set (val) { this._rootBone = val; - this._initJoints(); + this._init(); }, type: cc.Node } }, _activateMaterial (force) { - if (!this._jointsTextureData) { + if (!this._jointsData) { this.disableRender(); return; } @@ -85,30 +86,67 @@ let SkinnedMeshRenderer = cc.Class({ }, __preload () { + this._init(); + }, + + _init () { + this._model = this._skeleton && this._skeleton.model; + this._initJoints(); this._initJointsTexture(); }, + _calcWorldMatrixToRoot (joint) { + let worldMatrixToRoot = joint._worldMatrixToRoot; + if (!worldMatrixToRoot) { + joint._worldMatrixToRoot = worldMatrixToRoot = cc.mat4(); + joint.getLocalMatrix(worldMatrixToRoot); + } + else { + return; + } + + let parent = joint.parent; + if (parent !== this.rootBone) { + if (!parent._worldMatrixToRoot) { + this._calcWorldMatrixToRoot(parent); + } + mat4.mul(worldMatrixToRoot, parent._worldMatrixToRoot, worldMatrixToRoot); + } + }, + _initJoints () { let joints = this._joints; joints.length = 0; if (!this.skeleton || !this.rootBone) return; + let useJointMatrix = this._useJointMatrix(); + let jointPaths = this.skeleton.jointPaths; let rootBone = this.rootBone; - let matrices = this._matrices; - matrices.length = 0; for (let i = 0; i < jointPaths.length; i++) { - let bone = cc.find(jointPaths[i], rootBone); - if (!bone) { + let joint = cc.find(jointPaths[i], rootBone); + if (!joint) { cc.warn('Can not find joint in root bone [%s] with path [%s]', rootBone.name, jointPaths[i]); } - joints.push(bone); - matrices.push(mat4.create()); + + if (useJointMatrix) { + joint._renderFlag &= ~RenderFlow.FLAG_CHILDREN; + this._calcWorldMatrixToRoot(joint); + } + + joints.push(joint); } - this.updateMatrices(); + if (useJointMatrix) { + const bindposes = this.skeleton.bindposes; + for (let i = 0; i < jointPaths.length; i++) { + let joint = joints[i]; + mat4.mul(_m4_tmp, joint._worldMatrixToRoot, bindposes[i]); + joint._jointMatrix = mat4.array([], _m4_tmp); + } + } }, _initJointsTexture () { @@ -117,7 +155,7 @@ let SkinnedMeshRenderer = cc.Class({ let jointCount = this._joints.length; let customProperties = this._customProperties; - let ALLOW_FLOAT_TEXTURE = !!cc.renderer.device.ext('OES_texture_float'); + let ALLOW_FLOAT_TEXTURE = !!cc.sys.glExtension('OES_texture_float'); if (ALLOW_FLOAT_TEXTURE) { // set jointsTexture let size; @@ -131,10 +169,10 @@ let SkinnedMeshRenderer = cc.Class({ size = 8; } - this._jointsTextureData = new Float32Array(size * size * 4); + this._jointsData = new Float32Array(size * size * 4); let texture = this._jointsTexture || new cc.Texture2D(); - texture.initWithData(this._jointsTextureData, cc.Texture2D.PixelFormat.RGBA32F, size, size); + texture.initWithData(this._jointsData, cc.Texture2D.PixelFormat.RGBA32F, size, size); this._jointsTexture = texture; @@ -142,61 +180,75 @@ let SkinnedMeshRenderer = cc.Class({ customProperties.setProperty('_jointsTextureSize', this._jointsTexture.width); } else { - this._jointsTextureData = new Float32Array(jointCount * 16); - customProperties.setProperty('_jointMatrices', this._jointsTextureData); + this._jointsData = new Float32Array(jointCount * 16); + customProperties.setProperty('_jointMatrices', this._jointsData); } customProperties.define('_USE_SKINNING', true); customProperties.define('_USE_JOINTS_TEXTRUE', ALLOW_FLOAT_TEXTURE); }, - _setJointsTextureData (iMatrix, matrix) { - let arr = this._jointsTextureData; - arr[16 * iMatrix + 0] = matrix.m00; - arr[16 * iMatrix + 1] = matrix.m01; - arr[16 * iMatrix + 2] = matrix.m02; - arr[16 * iMatrix + 3] = matrix.m03; - arr[16 * iMatrix + 4] = matrix.m04; - arr[16 * iMatrix + 5] = matrix.m05; - arr[16 * iMatrix + 6] = matrix.m06; - arr[16 * iMatrix + 7] = matrix.m07; - arr[16 * iMatrix + 8] = matrix.m08; - arr[16 * iMatrix + 9] = matrix.m09; - arr[16 * iMatrix + 10] = matrix.m10; - arr[16 * iMatrix + 11] = matrix.m11; - arr[16 * iMatrix + 12] = matrix.m12; - arr[16 * iMatrix + 13] = matrix.m13; - arr[16 * iMatrix + 14] = matrix.m14; - arr[16 * iMatrix + 15] = matrix.m15; + _setJointsDataWithArray (iMatrix, matrixArray) { + let data = this._jointsData; + data.set(matrixArray, iMatrix * 16); + }, + + _setJointsDataWithMatrix (iMatrix, matrix) { + let data = this._jointsData; + + data[16 * iMatrix + 0] = matrix.m00; + data[16 * iMatrix + 1] = matrix.m01; + data[16 * iMatrix + 2] = matrix.m02; + data[16 * iMatrix + 3] = matrix.m03; + data[16 * iMatrix + 4] = matrix.m04; + data[16 * iMatrix + 5] = matrix.m05; + data[16 * iMatrix + 6] = matrix.m06; + data[16 * iMatrix + 7] = matrix.m07; + data[16 * iMatrix + 8] = matrix.m08; + data[16 * iMatrix + 9] = matrix.m09; + data[16 * iMatrix + 10] = matrix.m10; + data[16 * iMatrix + 11] = matrix.m11; + data[16 * iMatrix + 12] = matrix.m12; + data[16 * iMatrix + 13] = matrix.m13; + data[16 * iMatrix + 14] = matrix.m14; + data[16 * iMatrix + 15] = matrix.m15; }, _commitJointsData () { if (this._jointsTexture) { - this._jointsTexture.update({ image: this._jointsTextureData }); + this._jointsTexture.update({ image: this._jointsData }); } }, - updateMatrices () { - for (let i = 0; i < this._joints.length; ++i) { - let joint = this._joints[i]; - if (!joint || !joint.activeInHierarchy) continue; - joint.getWorldMatrix(this._matrices[i]); - } + _useJointMatrix () { + return this._model && this._model.precomputeJointMatrix; + }, + + getRenderNode () { + return this._useJointMatrix() ? this.rootBone : dummyNode; }, update () { if (!this.skeleton || !this.rootBone) return; - const bindposes = this.skeleton.bindposes; - const matrices = this._matrices; - - this.updateMatrices(); - - for (let i = 0; i < bindposes.length; ++i) { - let bindpose = bindposes[i]; - let worldMatrix = matrices[i]; - - mat4.multiply(_m4_tmp, worldMatrix, bindpose); - this._setJointsTextureData(i, _m4_tmp); + const joints = this._joints; + + if (this._useJointMatrix()) { + for (let i = 0; i < joints.length; ++i) { + let joint = joints[i]; + let jointMatrix = joint._jointMatrix; + + this._setJointsDataWithArray(i, jointMatrix); + } + } + else { + const bindposes = this.skeleton.bindposes; + for (let i = 0; i < joints.length; ++i) { + let joint = joints[i]; + + joint._updateWorldMatrix(); + mat4.multiply(_m4_tmp, joint._worldMatrix, bindposes[i]); + this._setJointsDataWithMatrix(i, _m4_tmp); + } } this._commitJointsData(); diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index a590a931cc2..0743a1aa62f 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -799,7 +799,7 @@ var game = { dynamicAtlasManager.enabled = true; } // Disable dynamicAtlasManager to fix rendering residue for transparent images on Chrome69. - if (cc.sys.browserType === cc.sys.BROWSER_TYPE_CHROME && parseFloat(cc.sys.browserVersion) >= 69.0) { + if (dynamicAtlasManager && cc.sys.browserType === cc.sys.BROWSER_TYPE_CHROME && parseFloat(cc.sys.browserVersion) >= 69.0) { dynamicAtlasManager.enabled = false; } } diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index f7f9cad0fe5..0810c361564 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -416,6 +416,10 @@ let Camera = cc.Class({ let camera = new RendererCamera(); _debugCamera = camera; + camera.setStages([ + 'opaque', + ]); + camera.setFov(Math.PI * 60 / 180); camera.setNear(0.1); camera.setFar(4096); diff --git a/cocos2d/core/mesh/CCMeshRenderer.js b/cocos2d/core/mesh/CCMeshRenderer.js index 011f6b86fe9..d9da47dd11b 100644 --- a/cocos2d/core/mesh/CCMeshRenderer.js +++ b/cocos2d/core/mesh/CCMeshRenderer.js @@ -157,6 +157,10 @@ let MeshRenderer = cc.Class({ this._setMesh(null); }, + getRenderNode () { + return this.node; + }, + _setMesh (mesh) { if (this._mesh) { this._mesh.off('init-format', this._updateMeshAttribute, this); diff --git a/cocos2d/core/mesh/mesh-renderer.js b/cocos2d/core/mesh/mesh-renderer.js index eafc62ab1ed..e05050559e6 100644 --- a/cocos2d/core/mesh/mesh-renderer.js +++ b/cocos2d/core/mesh/mesh-renderer.js @@ -98,7 +98,7 @@ let meshRendererAssembler = { let tmpMaterial = renderer.material; let tmpNode = renderer.node; - renderer.node = comp instanceof cc.SkinnedMeshRenderer ? renderer._dummyNode : comp.node; + renderer.node = comp.getRenderNode(); renderer.customProperties = comp._customProperties; let tmpCustomProperties = renderer.customProperties; diff --git a/cocos2d/core/platform/CCSys.js b/cocos2d/core/platform/CCSys.js index b53eaefea36..36b3abba5ce 100644 --- a/cocos2d/core/platform/CCSys.js +++ b/cocos2d/core/platform/CCSys.js @@ -574,6 +574,18 @@ function initSys () { * @property {Boolean} isBrowser */ sys.isBrowser = typeof window === 'object' && typeof document === 'object' && !CC_WECHATGAME && !CC_QQPLAY && !CC_JSB && !CC_RUNTIME && !isBaiduGame; + + /** + * Is webgl extension support? + * @method glExtension + * @param name + */ + sys.glExtension = function (name) { + if (CC_WECHATGAME && name === 'OES_texture_float') { + return false; + } + return !!cc.renderer.device.ext(name); + } if (CC_EDITOR && Editor.isMainProcess) { sys.isMobile = false; diff --git a/cocos2d/renderer/core/base-renderer.js b/cocos2d/renderer/core/base-renderer.js index 75f276605a1..c4c261083b6 100644 --- a/cocos2d/renderer/core/base-renderer.js +++ b/cocos2d/renderer/core/base-renderer.js @@ -499,7 +499,8 @@ export default class Base { } else { let convertedValue; if (param instanceof Float32Array || param instanceof Int32Array) { - convertedValue = param; + device.setUniformDirectly(prop.name, param); + return; } else if (prop.size !== undefined) { let convertArray = _type2uniformArrayValue[prop.type]; diff --git a/cocos2d/renderer/core/effect.js b/cocos2d/renderer/core/effect.js index 07065a41cbd..23cfe96341e 100644 --- a/cocos2d/renderer/core/effect.js +++ b/cocos2d/renderer/core/effect.js @@ -97,17 +97,11 @@ class Effect { extractProperties(out = {}) { Object.assign(out, this._properties); - if (this._dynamicConfig) { - Object.assign(out, this._dynamicConfig._uniforms); - } return out; } extractDefines(out = {}) { Object.assign(out, this._defines); - if (this._dynamicConfig) { - Object.assign(out, this._dynamicConfig._defines); - } return out; } diff --git a/cocos2d/renderer/gfx/device.js b/cocos2d/renderer/gfx/device.js index 0aa4528998d..f53bef6eeb8 100644 --- a/cocos2d/renderer/gfx/device.js +++ b/cocos2d/renderer/gfx/device.js @@ -1174,7 +1174,25 @@ export default class Device { */ setUniform(name, value) { let uniform = this._uniforms[name]; - if (!uniform || (uniform.isArray && uniform.value.length < value.length)) { + + let sameType = false; + do { + if (!uniform) { + break; + } + + if (uniform.isArray !== Array.isArray(value)) { + break; + } + + if (uniform.isArray && uniform.value.length !== value.length) { + break; + } + + sameType = true; + } while (false); + + if (!sameType) { let newValue = value; let isArray = false; if (value instanceof Float32Array || Array.isArray(value)) { @@ -1216,6 +1234,15 @@ export default class Device { this._uniforms[name] = uniform; } + setUniformDirectly(name, value) { + let uniform = this._uniforms[name]; + if (!uniform) { + this._uniforms[name] = uniform = {}; + } + uniform.dirty = true; + uniform.value = value; + } + /** * @method setPrimitiveType * @param {PT_*} type From 9c498d752a31b201c31f1028da2962dd503a6e1a Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 11 Mar 2019 16:59:40 +0800 Subject: [PATCH 0509/1631] V2.1 release merge v2.0 release (#3995) * Add RenderMode TS support (#3879) Add spine assembler var define * fix unit test for sprite (#3870) * Fix 1.x to 2.x particle custom data is invalid bug (#3885) * Improve particle definition data code (#3892) * fix event failed to reorder after modifying zIndex for 2d-tasks/issues/1130 (#3895) * Move BlendFunctionFactors to Sprite and ParticleSystem only (#3900) * change API:loadSubpackage to load index.js (#3899) * mark component.enabled as animatable (#3898) * ban JIT support on baidugame (#3903) * Fix dragonbones multiple texture bug (#3897) * Fix dragonbones change cloth bug * Adapt to old api-> on off once * DragonBonesAsset do not store dragonBones data * fix some error * fix web spine debug draw color error * Set limit time to 30s * fix label rendering in open data context (#3911) * fix: shaders have same uniform name, different type will effect wrong (#3876) * fix: shaders have same uniform name, different type will effect wrong * fix shaders have same uniform name, different type will effect wrong * fix shaders have same uniform name, different type will effect wrong, refine * add deprecated property in EditBox in v2.0 (#3912) * Fix dragonbones exception (#3914) * revert particles system attribute definition (#3919) * fix emit target scale changed events twice (#3922) * add the tween test case (#3908) * add the tween test case * modify the format of the test-tween.js 1. keep all chain method start at the char 'n' below * fixed the tween bugs * Fix spine premultipliedAlpha serialize bug (#3924) * cancel disable dynamic atlas on chrome. (#3929) * Add cache mode of label. (#3916) * Add cache mode of label. * fix revised comments of pr. * Simplified variable name. * share canvas pool. * cancel use node color. * modify comment and reserve _batchAsBitMap. * optimize the assignment of color and delete blendFactor. * delete reserveImage. * modify to center alignment. * modify letter-font do not use node color. * add outline support of letter-font * add letter atlas reset on editor when scene loaded. * change LETTER to CHAR * modify comment * Wechat -> WeChat * Add spine render mode chinese tip (#3933) * fix label rendering error on native (#3936) * fix label rendering error on native * fix rendering error on native * revert first commit * clear letter atlas when scene launch. (#3938) * reset the CHAR mode to NONE on subdomin. (#3940) * reset the CHAR mode to NONE on subdomin. * reset CHAR mode on subdomin * set rigidbody awake visible is false (#3941) * fix canvasPool error on subdomin (#3942) * update rigidbody awake tips and add awakeOnLoad (#3944) * fix label error when font change on editor. (#3946) * Rename skeleton RenderMode to AnimationCacheMode (#3947) * Rename skeleton RenderMode to AnimationCacheMode * Rename skeleton RenderMode to AnimationCacheMode * fix label blur when using dark font color (#3949) * optimize editBox style (#3952) * To adapt the adjust of the webview impl in the jsb (#3697) (#3951) * fix the problem of label that first modified is invalid. (#3959) * Fix create ArmatureDisplay by code but no set asset, then invoke some api about event, will throw error (#3966) * fix get auido state bug (#3974) * small fixed * small fixed --- CHANGELOG.txt | 2 +- cocos2d/actions/tween.js | 4 +- cocos2d/audio/CCAudio.js | 9 +- cocos2d/core/CCGame.js | 4 - cocos2d/core/CCNode.js | 4 +- cocos2d/core/assets/CCTexture2D.js | 14 +- cocos2d/core/components/CCButton.js | 21 +- cocos2d/core/components/CCComponent.js | 3 +- cocos2d/core/components/CCLabel.js | 103 +- cocos2d/core/components/CCRenderComponent.js | 73 +- cocos2d/core/components/CCSprite.js | 3 +- cocos2d/core/components/SwanSubContextView.js | 2 +- cocos2d/core/components/WXSubContextView.js | 2 +- cocos2d/core/components/editbox/CCEditBox.js | 12 +- .../core/components/editbox/CCEditBoxImpl.js | 701 +++++++++++++ cocos2d/core/load-pipeline/downloader.js | 2 +- cocos2d/core/physics/CCRigidBody.js | 21 +- cocos2d/core/platform/CCClass.js | 4 +- cocos2d/core/platform/CCMacro.js | 4 +- .../renderer/canvas/renderers/label/index.js | 28 +- .../renderer/canvas/renderers/sprite/index.js | 7 +- .../core/renderer/utils/label/letter-font.js | 919 ++++++++++++++++++ cocos2d/core/renderer/utils/label/ttf.js | 65 +- .../webgl/assemblers/label/2d/letter.js | 44 + .../renderer/webgl/assemblers/label/2d/ttf.js | 4 +- .../webgl/assemblers/label/3d/letter.js | 37 + .../renderer/webgl/assemblers/label/3d/ttf.js | 4 +- .../renderer/webgl/assemblers/label/index.js | 34 +- cocos2d/core/utils/blend-func.js | 88 ++ cocos2d/particle/CCParticleSystem.js | 9 +- editor/i18n/en/localization.js | 10 +- editor/i18n/zh/localization.js | 12 +- extensions/dragonbones/ArmatureCache.js | 35 +- extensions/dragonbones/ArmatureDisplay.js | 255 ++--- extensions/dragonbones/CCFactory.js | 50 +- extensions/dragonbones/DragonBonesAsset.js | 83 +- .../dragonbones/DragonBonesAtlasAsset.js | 53 +- extensions/dragonbones/lib/dragonBones.js | 18 +- extensions/dragonbones/webgl-assembler.js | 2 +- extensions/spine/Skeleton.js | 139 +-- extensions/spine/spine-assembler.js | 3 +- gulp/util/utils.js | 4 +- predefine.js | 2 +- test/qunit/unit-es5/_init.js | 3 +- test/qunit/unit-es5/test-spriteRenderer.js | 17 +- test/qunit/unit-es5/test-tween.js | 149 +++ 46 files changed, 2477 insertions(+), 585 deletions(-) create mode 100644 cocos2d/core/components/editbox/CCEditBoxImpl.js create mode 100644 cocos2d/core/renderer/utils/label/letter-font.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js create mode 100644 cocos2d/core/renderer/webgl/assemblers/label/3d/letter.js create mode 100644 cocos2d/core/utils/blend-func.js create mode 100644 test/qunit/unit-es5/test-tween.js diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 6c0475d26c6..57656d09073 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -323,7 +323,7 @@ Cocos2d-JS v3.2 @ Dec.29, 2014 * Replaced `transform` function with `setTransform` function under canvas render mode for better performance. * Added a timer in `cc.audioEngine` to check audio element loading event, prevent the loading process being stucked when load audio file failed. * Added some new browser types to `cc.sys`. -* Added some audio resource loading codes to ensure compatibility with Wechat browser. +* Added some audio resource loading codes to ensure compatibility with WeChat browser. * Added check for WebAudio support to ensure compatibility. * Bug fixes: diff --git a/cocos2d/actions/tween.js b/cocos2d/actions/tween.js index 92b021af555..d9761cfd93b 100644 --- a/cocos2d/actions/tween.js +++ b/cocos2d/actions/tween.js @@ -1,6 +1,6 @@ let TweenAction = cc.Class({ - name: 'TweenAction', + name: 'cc.TweenAction', extends: cc.ActionInterval, ctor (duration, props, opts) { @@ -224,7 +224,7 @@ Tween.prototype._get = function () { actions = actions[0]; } else { - actions = Tween.sequence(actions); + actions = cc.sequence(actions); } return actions; diff --git a/cocos2d/audio/CCAudio.js b/cocos2d/audio/CCAudio.js index 734086efcbc..69ba941afb1 100644 --- a/cocos2d/audio/CCAudio.js +++ b/cocos2d/audio/CCAudio.js @@ -267,13 +267,16 @@ Audio.State = { }; proto.getState = function () { - if (!CC_WECHATGAME && !CC_QQPLAY) { + let elem = this._element; + if (!CC_WECHATGAME && !CC_QQPLAY && elem) { // HACK: in some browser, audio may not fire 'ended' event // so we need to force updating the Audio state - let elem = this._element; - if (elem && Audio.State.PLAYING === this._state && elem.paused) { + if (Audio.State.PLAYING === this._state && elem.paused) { this._state = Audio.State.STOPPED; } + else if (Audio.State.STOPPED === this._state && !elem.paused) { + this._state = Audio.State.PLAYING; + } } return this._state; }; diff --git a/cocos2d/core/CCGame.js b/cocos2d/core/CCGame.js index 0743a1aa62f..13ebbeb4f9e 100644 --- a/cocos2d/core/CCGame.js +++ b/cocos2d/core/CCGame.js @@ -798,10 +798,6 @@ var game = { if (!cc.macro.CLEANUP_IMAGE_CACHE && dynamicAtlasManager) { dynamicAtlasManager.enabled = true; } - // Disable dynamicAtlasManager to fix rendering residue for transparent images on Chrome69. - if (dynamicAtlasManager && cc.sys.browserType === cc.sys.BROWSER_TYPE_CHROME && parseFloat(cc.sys.browserVersion) >= 69.0) { - dynamicAtlasManager.enabled = false; - } } if (!this._renderContext) { this.renderType = this.RENDER_TYPE_CANVAS; diff --git a/cocos2d/core/CCNode.js b/cocos2d/core/CCNode.js index b69ab9e2638..e6eaacbb794 100644 --- a/cocos2d/core/CCNode.js +++ b/cocos2d/core/CCNode.js @@ -1134,7 +1134,7 @@ let NodeDefines = { this._localZOrder = (this._localZOrder & 0x0000ffff) | (value << 16); if (this._parent) { - this._parent._delaySort(); + this._onSiblingIndexChanged(); } } } @@ -1190,7 +1190,7 @@ let NodeDefines = { // OVERRIDES - _onSiblingIndexChanged (index) { + _onSiblingIndexChanged () { // update rendering scene graph, sort them by arrivalOrder var parent = this._parent; var siblings = parent._children; diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 4d674e5b2cc..3b8a28ba314 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -644,11 +644,7 @@ var Texture2D = cc.Class({ this.emit("load"); if (cc.macro.CLEANUP_IMAGE_CACHE && this._image instanceof HTMLImageElement) { - // wechat game platform will cache image parsed data, - // so image will consume much more memory than web, releasing it - this._image.src = ""; - // Release image in loader cache - cc.loader.removeItem(this._image.id); + this._clearImage(); } }, @@ -903,6 +899,14 @@ var Texture2D = cc.Class({ _isCompressed () { return this._texture && this._texture._compressed; + }, + + _clearImage () { + // wechat game platform will cache image parsed data, + // so image will consume much more memory than web, releasing it + this._image.src = ""; + // Release image in loader cache + cc.loader.removeItem(this._image.id); } }); diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 9f6a43c01e5..45e572fe9d2 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -422,12 +422,13 @@ let Button = cc.Class({ // // Restore button status let target = this._getTarget(); let transition = this.transition; + let originalScale = this._originalScale; + if (transition === Transition.COLOR && this.interactable) { this._setTargetColor(this.normalColor); } - else if (transition === Transition.SCALE && this._originalScale) { - target.scaleX = this._originalScale.x; - target.scaleY = this._originalScale.y; + else if (transition === Transition.SCALE && originalScale) { + target.setScale(originalScale.x, originalScale.y); } this._transitionFinished = true; }, @@ -656,19 +657,19 @@ let Button = cc.Class({ let touch = event.touch; let hit = this.node._hitTest(touch.getLocation()); let target = this._getTarget(); + let originalScale = this._originalScale; - if (this.transition === Transition.SCALE && this._originalScale) { + if (this.transition === Transition.SCALE && originalScale) { if (hit) { - this._fromScale.x = this._originalScale.x; - this._fromScale.y = this._originalScale.y; - this._toScale.x = this._originalScale.x * this.zoomScale; - this._toScale.y = this._originalScale.y * this.zoomScale; + this._fromScale.x = originalScale.x; + this._fromScale.y = originalScale.y; + this._toScale.x = originalScale.x * this.zoomScale; + this._toScale.y = originalScale.y * this.zoomScale; this._transitionFinished = false; } else { this.time = 0; this._transitionFinished = true; - target.scaleX = this._originalScale.x; - target.scaleY = this._originalScale.y; + target.setScale(originalScale.x, originalScale.y); } } else { let state; diff --git a/cocos2d/core/components/CCComponent.js b/cocos2d/core/components/CCComponent.js index 2496ecb5593..135e208d3b8 100644 --- a/cocos2d/core/components/CCComponent.js +++ b/cocos2d/core/components/CCComponent.js @@ -176,7 +176,8 @@ var Component = cc.Class({ } } }, - visible: false + visible: false, + animatable: true }, /** diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 97c35fc1000..0c68079c4ca 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -126,6 +126,27 @@ const Overflow = cc.Enum({ * @property {Number} SystemFont */ + /** + * !#en Do not do any caching. + * !#zh 不做任何缓存。 + * @property {Number} NONE + */ +/** + * !#en In BITMAP mode, cache the label as a static image and add it to the dynamic atlas for batch rendering, and can batching with Sprites using broken images. + * !#zh BITMAP 模式,将 label 缓存成静态图像并加入到动态图集,以便进行批次合并,可与使用碎图的 Sprite 进行合批(注:动态图集在 Chrome 以及微信小游戏暂时关闭,该功能无效)。 + * @property {Number} BITMAP + */ +/** + * !#en In CHAR mode, split text into characters and cache characters into a dynamic atlas which the size of 2048*2048. + * !#zh CHAR 模式,将文本拆分为字符,并将字符缓存到一张单独的大小为 2048*2048 的图集中进行重复使用,不再使用动态图集(注:当图集满时将不再进行缓存,暂时不支持 SHRINK 自适应文本尺寸(后续完善))。 + * @property {Number} CHAR + */ +const CacheMode = cc.Enum({ + NONE: 0, + BITMAP: 1, + CHAR: 2, +}); + /** * !#en The Label Component. * !#zh 文字标签组件 @@ -146,6 +167,7 @@ let Label = cc.Class({ this._frame = null; this._ttfTexture = null; + this._letterTexture = null; }, editor: CC_EDITOR && { @@ -431,29 +453,32 @@ let Label = cc.Class({ } }, + //For compatibility with v2.0.x temporary reservation. _batchAsBitmap: false, + /** - * !#en Whether cache label to static texture and draw in dynamicAtlas. - * !#zh 是否将label缓存成静态图像并加入到动态图集.(对于静态文本建议使用该选项,便于批次合并减少drawcall) - * @property {Boolean} batchAsBitmap + * !#en The cache mode of label. This mode only supports system fonts. + * !#zh 文本缓存模式, 该模式只支持系统字体。 + * @property {Label.CacheMode} cacheMode */ - batchAsBitmap: { - get () { - return this._batchAsBitmap; - }, - set (value) { - if (this._batchAsBitmap === value) return; - - this._batchAsBitmap = value; - - if (!this._batchAsBitmap && !(this.font instanceof cc.BitmapFont)) { + cacheMode: { + default: CacheMode.NONE, + type: CacheMode, + tooltip: CC_DEV && 'i18n:COMPONENT.label.cacheMode', + notify (oldValue) { + if (this.cacheMode === oldValue) return; + + if (oldValue === CacheMode.BITMAP && !(this.font instanceof cc.BitmapFont)) { this._frame._resetDynamicAtlasFrame(); } - this._activateMaterial(true); - this._updateRenderData(); + + if (oldValue === CacheMode.CHAR) { + this._ttfTexture = null; + } + + this._updateRenderData(true); }, - animatable: false, - tooltip: CC_DEV && 'i18n:COMPONENT.label.batch_as_bitmap', + animatable: false }, _isBold: { @@ -474,6 +499,15 @@ let Label = cc.Class({ HorizontalAlign: HorizontalAlign, VerticalAlign: VerticalAlign, Overflow: Overflow, + CacheMode: CacheMode, + }, + + onLoad () { + // For compatibility with v2.0.x temporary reservation. + if (this._batchAsBitmap && this.cacheMode === CacheMode.NONE) { + this.cacheMode = CacheMode.BITMAP; + this._batchAsBitmap = false; + } }, onEnable () { @@ -505,6 +539,7 @@ let Label = cc.Class({ onDestroy () { this._assembler && this._assembler._resetAssemblerData && this._assembler._resetAssemblerData(this._assemblerData); this._assemblerData = null; + this._letterTexture = null; if (this._ttfTexture) { this._ttfTexture.destroy(); this._ttfTexture = null; @@ -559,8 +594,7 @@ let Label = cc.Class({ // TODO: old texture in material have been released by loader self._frame._texture = spriteFrame._texture; self._activateMaterial(force); - - if (CC_EDITOR || force) { + if (force) { self._assembler && self._assembler.updateRenderData(self); } }; @@ -578,18 +612,24 @@ let Label = cc.Class({ } } else { - if (!this._ttfTexture) { - this._ttfTexture = new cc.Texture2D(); - this._assemblerData = this._assembler._getAssemblerData(); - this._ttfTexture.initWithElement(this._assemblerData.canvas); - } if (!this._frame) { this._frame = new LabelFrame(); } + + if (this.cacheMode === CacheMode.CHAR && cc.sys.browserType !== cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { + this._letterTexture = this._assembler._getAssemblerData(); + this._frame._refreshTexture(this._letterTexture); + } else if (!this._ttfTexture) { + this._ttfTexture = new cc.Texture2D(); + this._assemblerData = this._assembler._getAssemblerData(); + this._ttfTexture.initWithElement(this._assemblerData.canvas); + } - this._frame._refreshTexture(this._ttfTexture); - + if (this.cacheMode !== CacheMode.CHAR) { + this._frame._refreshTexture(this._ttfTexture); + } + this._activateMaterial(force); if (force) { @@ -598,6 +638,17 @@ let Label = cc.Class({ } }, + _updateColor () { + let font = this.font; + if (font instanceof cc.BitmapFont) { + this._super(); + } + else { + this._updateRenderData(); + this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; + } + }, + _activateMaterial (force) { let material = this.sharedMaterials[0]; if (material && !force) { diff --git a/cocos2d/core/components/CCRenderComponent.js b/cocos2d/core/components/CCRenderComponent.js index eecb9fe2610..d4dbe7f125b 100644 --- a/cocos2d/core/components/CCRenderComponent.js +++ b/cocos2d/core/components/CCRenderComponent.js @@ -50,55 +50,6 @@ let RenderComponent = cc.Class({ }, properties: { - _srcBlendFactor: BlendFactor.SRC_ALPHA, - _dstBlendFactor: BlendFactor.ONE_MINUS_SRC_ALPHA, - - /** - * !#en specify the source Blend Factor, this will generate a custom material object, please pay attention to the memory cost. - * !#zh 指定原图的混合模式,这会克隆一个新的材质对象,注意这带来的开销 - * @property srcBlendFactor - * @type {macro.BlendFactor} - * @example - * sprite.srcBlendFactor = cc.macro.BlendFactor.ONE; - */ - srcBlendFactor: { - get: function() { - return this._srcBlendFactor; - }, - set: function(value) { - if (this._srcBlendFactor === value) return; - this._srcBlendFactor = value; - this._updateBlendFunc(); - }, - animatable: false, - type:BlendFactor, - tooltip: CC_DEV && 'i18n:COMPONENT.sprite.src_blend_factor', - visible: false - }, - - /** - * !#en specify the destination Blend Factor. - * !#zh 指定目标的混合模式 - * @property dstBlendFactor - * @type {macro.BlendFactor} - * @example - * sprite.dstBlendFactor = cc.macro.BlendFactor.ONE; - */ - dstBlendFactor: { - get: function() { - return this._dstBlendFactor; - }, - set: function(value) { - if (this._dstBlendFactor === value) return; - this._dstBlendFactor = value; - this._updateBlendFunc(); - }, - animatable: false, - type: BlendFactor, - tooltip: CC_DEV && 'i18n:COMPONENT.sprite.dst_blend_factor', - visible: false - }, - _materials: { default: [], type: Material, @@ -220,36 +171,14 @@ let RenderComponent = cc.Class({ return this._materials[index]; }, + setMaterial (index, material) { this._materials[index] = material; if (material) { - this._updateMaterialBlendFunc(material); this.markForUpdateRenderData(true); } }, - _updateBlendFunc: function () { - let materials = this._materials; - for (let i = 0; i < materials.length; i++) { - let material = materials[i]; - this._updateMaterialBlendFunc(material); - } - }, - - _updateMaterialBlendFunc (material) { - let passes = material._effect.getDefaultTechnique().passes; - for (let j = 0; j < passes.length; j++) { - let pass = passes[j]; - pass.setBlend( - true, - gfx.BLEND_FUNC_ADD, - this._srcBlendFactor, this._dstBlendFactor, - gfx.BLEND_FUNC_ADD, - this._srcBlendFactor, this._dstBlendFactor - ); - } - }, - _activateMaterial (force) { }, }); diff --git a/cocos2d/core/components/CCSprite.js b/cocos2d/core/components/CCSprite.js index 9fc53c2eee5..8046522e6da 100644 --- a/cocos2d/core/components/CCSprite.js +++ b/cocos2d/core/components/CCSprite.js @@ -28,7 +28,7 @@ const misc = require('../utils/misc'); const NodeEvent = require('../CCNode').EventType; const RenderComponent = require('./CCRenderComponent'); const RenderFlow = require('../renderer/render-flow'); -const dynamicAtlasManager = require('../renderer/utils/dynamic-atlas/manager'); +const BlendFunc = require('../utils/blend-func'); const Material = require('../assets/material/CCMaterial'); @@ -155,6 +155,7 @@ var State = cc.Enum({ var Sprite = cc.Class({ name: 'cc.Sprite', extends: RenderComponent, + mixins: [BlendFunc], ctor () { this._graySpriteMaterial = null; diff --git a/cocos2d/core/components/SwanSubContextView.js b/cocos2d/core/components/SwanSubContextView.js index 258ba829722..2541e7acd6a 100644 --- a/cocos2d/core/components/SwanSubContextView.js +++ b/cocos2d/core/components/SwanSubContextView.js @@ -36,7 +36,7 @@ if (!CC_EDITOR && !isBaiduGame) { } else { /** - * !#en SwanSubContextView is a view component which controls open data context viewport in Wechat game platform.
+ * !#en SwanSubContextView is a view component which controls open data context viewport in WeChat game platform.
* The component's node size decide the viewport of the sub context content in main context, * the entire sub context texture will be scaled to the node's bounding box area.
* This component provides multiple important features:
diff --git a/cocos2d/core/components/WXSubContextView.js b/cocos2d/core/components/WXSubContextView.js index 62b46080b03..9e6e7b34d81 100644 --- a/cocos2d/core/components/WXSubContextView.js +++ b/cocos2d/core/components/WXSubContextView.js @@ -35,7 +35,7 @@ if (!CC_EDITOR && !CC_WECHATGAME) { } else { /** - * !#en WXSubContextView is a view component which controls open data context viewport in Wechat game platform.
+ * !#en WXSubContextView is a view component which controls open data context viewport in WeChat game platform.
* The component's node size decide the viewport of the sub context content in main context, * the entire sub context texture will be scaled to the node's bounding box area.
* This component provides multiple important features:
diff --git a/cocos2d/core/components/editbox/CCEditBox.js b/cocos2d/core/components/editbox/CCEditBox.js index 5adc2cfbbb1..01629005ab4 100644 --- a/cocos2d/core/components/editbox/CCEditBox.js +++ b/cocos2d/core/components/editbox/CCEditBox.js @@ -265,10 +265,11 @@ let EditBox = cc.Class({ }, /** - * !#en The input is always visible and be on top of the game view (only useful on Web). - * !zh 输入框总是可见,并且永远在游戏视图的上面(这个属性只有在 Web 上面修改有意义),这个属性已经在 v2.0.9 中废弃。 - * Note: only available on Web at the moment, this property has been deprecated since v2.0.9 + * !#en The input is always visible and be on top of the game view (only useful on Web), this property will be removed on v2.1 + * !zh 输入框总是可见,并且永远在游戏视图的上面(这个属性只有在 Web 上面修改有意义),该属性会在 v2.1 中移除 + * Note: only available on Web at the moment. * @property {Boolean} stayOnTop + * @deprecated since 2.0.8 */ stayOnTop: { tooltip: CC_DEV && 'i18n:COMPONENT.editbox.stay_on_top', @@ -610,9 +611,10 @@ let EditBox = cc.Class({ }, /** - * !#en Let the EditBox get focus, this method has been deprecated since v2.0.8, please use focus() instead. Call blur() in turn. - * !#zh 让当前 EditBox 获得焦点, 这个方法已经在 v2.0.8 中废弃,请使用 focus(). 相反的请使用 blur() + * !#en Let the EditBox get focus, this method will be removed on v2.1 + * !#zh 让当前 EditBox 获得焦点, 这个方法会在 v2.1 中移除 * @method setFocus + * @deprecated since 2.0.8 */ setFocus () { cc.warnID(1400, 'setFocus()', 'focus()'); diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js new file mode 100644 index 00000000000..36fd3d6b657 --- /dev/null +++ b/cocos2d/core/components/editbox/CCEditBoxImpl.js @@ -0,0 +1,701 @@ +/**************************************************************************** + Copyright (c) 2011-2012 cocos2d-x.org + Copyright (c) 2012 James Chen + Copyright (c) 2013-2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 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 utils = require('../../platform/utils'); +const macro = require('../../platform/CCMacro'); +const Types = require('./types'); +const InputMode = Types.InputMode; +const InputFlag = Types.InputFlag; +const KeyboardReturnType = Types.KeyboardReturnType; + +// https://segmentfault.com/q/1010000002914610 +let SCROLLY = 40; +let LEFT_PADDING = 2; +let DELAY_TIME = 400; +let FOCUS_DELAY_UC = 400; +let FOCUS_DELAY_FIREFOX = 0; + +let math = cc.vmath; +let _worldMat = math.mat4.create(); +let _cameraMat = math.mat4.create(); +let _vec3 = cc.v3(); + +let _currentEditBoxImpl = null; + +// polyfill +let polyfill = { + zoomInvalid: false +}; + +if (cc.sys.OS_ANDROID === cc.sys.os && + (cc.sys.browserType === cc.sys.BROWSER_TYPE_SOUGOU || + cc.sys.browserType === cc.sys.BROWSER_TYPE_360)) { + polyfill.zoomInvalid = true; +} + +function getKeyboardReturnType (type) { + switch (type) { + case KeyboardReturnType.DEFAULT: + case KeyboardReturnType.DONE: + return 'done'; + case KeyboardReturnType.SEND: + return 'send'; + case KeyboardReturnType.SEARCH: + return 'search'; + case KeyboardReturnType.GO: + return 'go'; + case KeyboardReturnType.NEXT: + return 'next'; + } + return 'done'; +} + +let EditBoxImpl = cc.Class({ + ctor () { + this._delegate = null; + this._inputMode = -1; + this._inputFlag = -1; + this._returnType = KeyboardReturnType.DEFAULT; + this._maxLength = 50; + this._text = ''; + this._placeholderText = ''; + this._alwaysOnTop = false; + this._size = cc.size(); + this._node = null; + this._editing = false; + + this.__eventListeners = {}; + this.__fullscreen = false; + this.__autoResize = false; + this.__rotateScreen = false; + this.__orientationChanged = null; + + // matrix cache + this._m00 = 0; + this._m01 = 0; + this._m04 = 0; + this._m05 = 0; + this._m12 = 0; + this._m13 = 0; + this._w = 0; + this._h = 0; + }, + + onEnable () { + if (!this._edTxt) { + return; + } + if (this._alwaysOnTop) { + this._edTxt.style.display = ''; + } + else { + this._edTxt.style.display = 'none'; + } + }, + + onDisable () { + if (!this._edTxt) { + return; + } + this._edTxt.style.display = 'none'; + }, + + setTabIndex (index) { + if (this._edTxt) { + this._edTxt.tabIndex = index; + } + }, + + setFocus () { + this._beginEditing(); + }, + + isFocused() { + if (this._edTxt) { + return document.activeElement === this._edTxt; + } + cc.warnID(4700); + return false; + }, + + stayOnTop (flag) { + if(this._alwaysOnTop === flag || !this._edTxt) return; + + this._alwaysOnTop = flag; + + if (flag) { + this._edTxt.style.display = ''; + } else { + this._edTxt.style.display = 'none'; + } + }, + + setMaxLength (maxLength) { + if (!isNaN(maxLength)) { + if(maxLength < 0) { + //we can't set Number.MAX_VALUE to input's maxLength property + //so we use a magic number here, it should works at most use cases. + maxLength = 65535; + } + this._maxLength = maxLength; + this._edTxt && (this._edTxt.maxLength = maxLength); + } + }, + + setString (text) { + this._text = text; + this._edTxt && (this._edTxt.value = text); + }, + + getString () { + return this._text; + }, + + setPlaceholderText (text) { + this._placeholderText = text; + }, + + getPlaceholderText () { + return this._placeholderText; + }, + + setDelegate (delegate) { + this._delegate = delegate; + }, + + setInputMode (inputMode) { + if (this._inputMode === inputMode) return; + + this._inputMode = inputMode; + this.createInput(); + + this._updateDomInputType(); + this._updateSize(this._size.width, this._size.height); + }, + + setInputFlag (inputFlag) { + if (this._inputFlag === inputFlag) return; + + this._inputFlag = inputFlag; + this._updateDomInputType(); + + let textTransform = 'none'; + + if (inputFlag === InputFlag.INITIAL_CAPS_ALL_CHARACTERS) { + textTransform = 'uppercase'; + } + else if (inputFlag === InputFlag.INITIAL_CAPS_WORD) { + textTransform = 'capitalize'; + } + + if (this._edTxt) { + this._edTxt.style.textTransform = textTransform; + this._edTxt.value = this._text; + } + }, + + setReturnType (returnType) { + this._returnType = returnType; + this._updateDomInputType(); + }, + + setFontSize (fontSize) { + this._edFontSize = fontSize || this._edFontSize; + this._edTxt && (this._edTxt.style.fontSize = this._edFontSize + 'px'); + }, + + setFontColor (color) { + this._textColor = color; + this._edTxt && (this._edTxt.style.color = color.toCSS('rgba')); + }, + + setSize (width, height) { + this._size.width = width; + this._size.height = height; + this._updateSize(width, height); + }, + + setNode (node) { + this._node = node; + }, + + update () { + // TODO: find better way to update matrix + // if (this._editing) { + this._updateMatrix(); + // } + }, + + clear () { + this._node = null; + this.setDelegate(null); + this.removeDom(); + this.removeOrientationchangeEvent(); + }, + + _onTouchBegan (touch) { + + }, + + _onTouchEnded () { + this._beginEditing(); + }, + + _beginEditing () { + if (cc.sys.isMobile && !this._editing) { + // Pre adaptation add orientationchange event + this.addOrientationchangeEvent(); + } + + if (this._edTxt) { + this._edTxt.style.display = ''; + + let self = this; + function startFocus () { + self._edTxt.focus(); + } + + if (cc.sys.browserType === cc.sys.BROWSER_TYPE_UC) { + setTimeout(startFocus, FOCUS_DELAY_UC); + } + else if (cc.sys.browserType === cc.sys.BROWSER_TYPE_FIREFOX) { + setTimeout(startFocus, FOCUS_DELAY_FIREFOX); + } + else { + startFocus(); + } + } + + this._editing = true; + }, + + _endEditing () { + let self = this; + let hideDomInputAndShowLabel = function () { + if (!self._alwaysOnTop && self._edTxt) { + self._edTxt.style.display = 'none'; + } + if (self._delegate && self._delegate.editBoxEditingDidEnded) { + self._delegate.editBoxEditingDidEnded(); + } + }; + if (this._editing) { + if (cc.sys.isMobile) { + // Delay end editing adaptation to ensure virtual keyboard is disapeared + setTimeout(function () { + self._endEditingOnMobile(); + hideDomInputAndShowLabel(); + }, DELAY_TIME); + } + else { + hideDomInputAndShowLabel(); + } + } + this._editing = false; + }, + + _updateDomInputType () { + let inputMode = this._inputMode; + let edTxt = this._edTxt; + if (!edTxt) return; + + if (this._inputFlag === InputFlag.PASSWORD) { + edTxt.type = 'password'; + return; + } + + let type = edTxt.type; + if (inputMode === InputMode.EMAIL_ADDR) { + type = 'email'; + } else if(inputMode === InputMode.NUMERIC || inputMode === InputMode.DECIMAL) { + type = 'number'; + } else if(inputMode === InputMode.PHONE_NUMBER) { + type = 'number'; + edTxt.pattern = '[0-9]*'; + } else if(inputMode === InputMode.URL) { + type = 'url'; + } else { + type = 'text'; + + if (this._returnType === KeyboardReturnType.SEARCH) { + type = 'search'; + } + } + + edTxt.type = type; + }, + + _updateSize (newWidth, newHeight) { + let edTxt = this._edTxt; + if (!edTxt) return; + + edTxt.style.width = newWidth + 'px'; + edTxt.style.height = newHeight + 'px'; + }, + + _updateMatrix () { + if (!this._edTxt) return; + + let node = this._node; + node.getWorldMatrix(_worldMat); + + // check whether need to update + if (this._m00 === _worldMat.m00 && this._m01 === _worldMat.m01 && + this._m04 === _worldMat.m04 && this._m05 === _worldMat.m05 && + this._m12 === _worldMat.m12 && this._m13 === _worldMat.m13 && + this._w === node._contentSize.width && this._h === node._contentSize.height) { + return; + } + + // update matrix cache + this._m00 = _worldMat.m00; + this._m01 = _worldMat.m01; + this._m04 = _worldMat.m04; + this._m05 = _worldMat.m05; + this._m12 = _worldMat.m12; + this._m13 = _worldMat.m13; + this._w = node._contentSize.width; + this._h = node._contentSize.height; + + let scaleX = cc.view._scaleX, scaleY = cc.view._scaleY, + viewport = cc.view._viewportRect, + dpr = cc.view._devicePixelRatio; + + _vec3.x = -node._anchorPoint.x * this._w; + _vec3.y = -node._anchorPoint.y * this._h; + + math.mat4.translate(_worldMat, _worldMat, _vec3); + + // can't find camera in editor + if (CC_EDITOR) { + _cameraMat = _worldMat; + } + else { + let camera = cc.Camera.findCamera(node); + camera.getWorldToCameraMatrix(_cameraMat); + math.mat4.mul(_cameraMat, _cameraMat, _worldMat); + } + + + scaleX /= dpr; + scaleY /= dpr; + + let container = cc.game.container; + let a = _cameraMat.m00 * scaleX, b = _cameraMat.m01, c = _cameraMat.m04, d = _cameraMat.m05 * scaleY; + + let offsetX = container && container.style.paddingLeft && parseInt(container.style.paddingLeft); + offsetX += viewport.x / dpr; + let offsetY = container && container.style.paddingBottom && parseInt(container.style.paddingBottom); + offsetY += viewport.y / dpr; + let tx = _cameraMat.m12 * scaleX + offsetX, ty = _cameraMat.m13 * scaleY + offsetY; + + if (polyfill.zoomInvalid) { + this._updateSize(this._size.width * a, this._size.height * d); + a = 1; + d = 1; + } + + let matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")"; + this._edTxt.style['transform'] = matrix; + this._edTxt.style['-webkit-transform'] = matrix; + this._edTxt.style['transform-origin'] = '0px 100% 0px'; + this._edTxt.style['-webkit-transform-origin'] = '0px 100% 0px'; + }, + + _adjustEditBoxPosition () { + this._node.getWorldMatrix(_worldMat); + let y = _worldMat.m13; + let windowHeight = cc.visibleRect.height; + let windowWidth = cc.visibleRect.width; + let factor = 0.5; + if (windowWidth > windowHeight) { + factor = 0.7; + } + setTimeout(function() { + if (window.scrollY < SCROLLY && y < windowHeight * factor) { + let scrollOffset = windowHeight * factor - y - window.scrollY; + if (scrollOffset < 35) scrollOffset = 35; + if (scrollOffset > 320) scrollOffset = 320; + window.scrollTo(0, scrollOffset); + } + }, DELAY_TIME); + } +}); + +let _p = EditBoxImpl.prototype; + +_p.createInput = function() { + if (this._inputMode === InputMode.ANY) { + this._createDomTextArea(); + } + else { + this._createDomInput(); + } +}; + +// Called before editbox focus to register cc.view status +_p._beginEditingOnMobile = function () { + // add orientationchange event + this.addOrientationchangeEvent(); + + if (cc.view.isAutoFullScreenEnabled()) { + this.__fullscreen = true; + cc.view.enableAutoFullScreen(false); + cc.screen.exitFullScreen(); + } else { + this.__fullscreen = false; + } + this.__autoResize = cc.view._resizeWithBrowserSize; + cc.view.resizeWithBrowserSize(false); + _currentEditBoxImpl = this; +}; + +// Called after keyboard disappeared to readapte the game view +_p._endEditingOnMobile = function () { + if (this.__rotateScreen) { + cc.game.container.style['-webkit-transform'] = 'rotate(90deg)'; + cc.game.container.style.transform = 'rotate(90deg)'; + + let view = cc.view; + let width = view._originalDesignResolutionSize.width; + let height = view._originalDesignResolutionSize.height; + if (width > 0) { + view.setDesignResolutionSize(width, height, view._resolutionPolicy); + } + this.__rotateScreen = false; + } + + // remove orientationchange event + this.removeOrientationchangeEvent(); + + if(this.__fullscreen) { + cc.view.enableAutoFullScreen(true); + } + + // In case focus on editBox A from editBox B + // A disable resizeWithBrowserSize + // whilte B enable resizeWithBrowserSize + // Only _currentEditBoxImpl can enable resizeWithBrowserSize + if (this.__autoResize && _currentEditBoxImpl === this) { + cc.view.resizeWithBrowserSize(true); + } +}; + +function _inputValueHandle (input, editBoxImpl) { + if (input.value.length > editBoxImpl._maxLength) { + input.value = input.value.slice(0, editBoxImpl._maxLength); + } + if (editBoxImpl._delegate && editBoxImpl._delegate.editBoxTextChanged) { + if (editBoxImpl._text !== input.value) { + editBoxImpl._text = input.value; + editBoxImpl._delegate.editBoxTextChanged(editBoxImpl._text); + } + } +} + +function registerInputEventListener (tmpEdTxt, editBoxImpl, isTextarea) { + let inputLock = false; + let blurWhenComposition = false; + let cbs = editBoxImpl.__eventListeners; + cbs.compositionstart = function () { + inputLock = true; + }; + tmpEdTxt.addEventListener('compositionstart', cbs.compositionstart); + + cbs.compositionend = function () { + inputLock = false; + if (blurWhenComposition) { + // restore input value when composition not complete and blur input + this.value = editBoxImpl._text; + blurWhenComposition = false; + } + _inputValueHandle(this, editBoxImpl); + }; + tmpEdTxt.addEventListener('compositionend', cbs.compositionend); + + cbs.input = function () { + if (inputLock) { + return; + } + _inputValueHandle(this, editBoxImpl); + }; + tmpEdTxt.addEventListener('input', cbs.input); + + cbs.focus = function () { + this.style.fontSize = editBoxImpl._edFontSize + 'px'; + this.style.color = editBoxImpl._textColor.toCSS('rgba'); + // When stayOnTop, input will swallow touch event + if (editBoxImpl._alwaysOnTop) { + editBoxImpl._editing = true; + } + + if (cc.sys.isMobile) { + editBoxImpl._beginEditingOnMobile(); + } + + if (editBoxImpl._delegate && editBoxImpl._delegate.editBoxEditingDidBegan) { + editBoxImpl._delegate.editBoxEditingDidBegan(); + } + + }; + tmpEdTxt.addEventListener('focus', cbs.focus); + + cbs.keypress = function (e) { + if (e.keyCode === macro.KEY.enter) { + e.stopPropagation(); + + if (editBoxImpl._delegate && editBoxImpl._delegate.editBoxEditingReturn) { + editBoxImpl._delegate.editBoxEditingReturn(); + } + if (!isTextarea) { + editBoxImpl._text = this.value; + editBoxImpl._endEditing(); + cc.game.canvas.focus(); + } + } + }; + tmpEdTxt.addEventListener('keypress', cbs.keypress); + + cbs.blur = function () { + if (inputLock) { + blurWhenComposition = true; + } + else { + editBoxImpl._text = this.value; + } + editBoxImpl._endEditing(); + }; + tmpEdTxt.addEventListener('blur', cbs.blur); + + editBoxImpl._addDomToGameContainer(); +} + +_p._createDomInput = function () { + this.removeDom(); + + let tmpEdTxt = this._edTxt = document.createElement('input'); + tmpEdTxt.type = 'text'; + tmpEdTxt.style.fontSize = this._edFontSize + 'px'; + tmpEdTxt.style.color = '#000000'; + tmpEdTxt.style.border = 0; + tmpEdTxt.style.background = 'transparent'; + tmpEdTxt.style.width = '100%'; + tmpEdTxt.style.height = '100%'; + tmpEdTxt.style.active = 0; + tmpEdTxt.style.outline = 'medium'; + tmpEdTxt.style.padding = '0'; + tmpEdTxt.style.textTransform = 'uppercase'; + tmpEdTxt.style.display = 'none'; + tmpEdTxt.style.position = "absolute"; + tmpEdTxt.style.bottom = "0px"; + tmpEdTxt.style.left = LEFT_PADDING + "px"; + tmpEdTxt.style['-moz-appearance'] = 'textfield'; + tmpEdTxt.style.fontFamily = 'Arial'; + tmpEdTxt.className = "cocosEditBox"; + + registerInputEventListener(tmpEdTxt, this); + + return tmpEdTxt; +}; + +_p._createDomTextArea = function () { + this.removeDom(); + + let tmpEdTxt = this._edTxt = document.createElement('textarea'); + tmpEdTxt.style.fontSize = this._edFontSize + 'px'; + tmpEdTxt.style.color = '#000000'; + tmpEdTxt.style.border = 0; + tmpEdTxt.style.background = 'transparent'; + tmpEdTxt.style.width = '100%'; + tmpEdTxt.style.height = '100%'; + tmpEdTxt.style.active = 0; + tmpEdTxt.style.outline = 'medium'; + tmpEdTxt.style.padding = '0'; + tmpEdTxt.style.resize = 'none'; + tmpEdTxt.style.textTransform = 'uppercase'; + tmpEdTxt.style.overflow_y = 'scroll'; + tmpEdTxt.style.display = 'none'; + tmpEdTxt.style.position = "absolute"; + tmpEdTxt.style.bottom = "0px"; + tmpEdTxt.style.left = LEFT_PADDING + "px"; + tmpEdTxt.style.fontFamily = 'Arial'; + tmpEdTxt.className = "cocosEditBox"; + + registerInputEventListener(tmpEdTxt, this, true); + + return tmpEdTxt; +}; + +_p._addDomToGameContainer = function () { + cc.game.container.appendChild(this._edTxt); +}; + +_p.removeDom = function () { + let edTxt = this._edTxt; + if (edTxt) { + // Remove listeners + let cbs = this.__eventListeners; + edTxt.removeEventListener('compositionstart', cbs.compositionstart); + edTxt.removeEventListener('compositionend', cbs.compositionend); + edTxt.removeEventListener('input', cbs.input); + edTxt.removeEventListener('focus', cbs.focus); + edTxt.removeEventListener('keypress', cbs.keypress); + edTxt.removeEventListener('blur', cbs.blur); + cbs.compositionstart = null; + cbs.compositionend = null; + cbs.input = null; + cbs.focus = null; + cbs.keypress = null; + cbs.blur = null; + + let hasChild = utils.contains(cc.game.container, edTxt); + if (hasChild) { + cc.game.container.removeChild(edTxt); + } + } + this._edTxt = null; +}; + +_p.addOrientationchangeEvent = function () { + let self = this; + if (!self.__orientationChanged) { + self.__orientationChanged = function () { + self._adjustEditBoxPosition(); + }; + } + window.addEventListener('orientationchange', self.__orientationChanged); +}; + +_p.removeOrientationchangeEvent = function () { + if (this.__orientationChanged) { + window.removeEventListener('orientationchange', this.__orientationChanged); + this.__orientationChanged = null; + } +}; + +module.exports = EditBoxImpl; diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index 9ec3c69022e..1c25575813f 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -305,7 +305,7 @@ Downloader.prototype.loadSubpackage = function (name, completeCallback) { if (completeCallback) completeCallback(); } else { - downloadScript({url: pac.path + 'game.js'}, function (err) { + downloadScript({url: pac.path + 'index.js'}, function (err) { if (!err) { pac.loaded = true; } diff --git a/cocos2d/core/physics/CCRigidBody.js b/cocos2d/core/physics/CCRigidBody.js index e721800a947..352ca14278e 100644 --- a/cocos2d/core/physics/CCRigidBody.js +++ b/cocos2d/core/physics/CCRigidBody.js @@ -365,13 +365,14 @@ var RigidBody = cc.Class({ /** * !#en - * Is this body initially awake or sleeping? + * Set the sleep state of the body. A sleeping body has very low CPU cost.(When the rigid body is hit, if the rigid body is in sleep state, it will be immediately awakened.) * !#zh - * 是否立刻唤醒此刚体 + * 设置刚体的睡眠状态。 睡眠的刚体具有非常低的 CPU 成本。(当刚体被碰撞到时,如果刚体处于睡眠状态,它会立即被唤醒) * @property {Boolean} awake * @default false */ awake: { + visible: false, tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.awake', get: function () { return this._b2Body ? this._b2Body.IsAwake() : false; @@ -383,6 +384,20 @@ var RigidBody = cc.Class({ } }, + /** + * !#en + * Whether to wake up this rigid body during initialization + * !#zh + * 是否在初始化时唤醒此刚体 + * @property {Boolean} awakeOnLoad + * @default true + */ + awakeOnLoad: { + default: true, + tooltip: CC_DEV && 'i18n:COMPONENT.physics.rigidbody.awakeOnLoad', + animatable: false, + }, + /** * !#en * Set the active state of the body. An inactive body is not @@ -895,6 +910,8 @@ var RigidBody = cc.Class({ bodyDef.position = new b2.Vec2(pos.x / PTM_RATIO, pos.y / PTM_RATIO); bodyDef.angle = -(Math.PI / 180) * getWorldRotation(node); + bodyDef.awake = this.awakeOnLoad; + cc.director.getPhysicsManager()._addBody(this, bodyDef); this._inited = true; diff --git a/cocos2d/core/platform/CCClass.js b/cocos2d/core/platform/CCClass.js index cec4acf62be..f5063e75505 100644 --- a/cocos2d/core/platform/CCClass.js +++ b/cocos2d/core/platform/CCClass.js @@ -1189,8 +1189,8 @@ function parseAttributes (cls, attrs, className, propName, usedInGetter) { if (CC_EDITOR) { parseSimpleAttr('notifyFor', 'string'); - if ('animatable' in attrs && !attrs.animatable) { - (attrsProto || getAttrsProto())[attrsProtoKey + 'animatable'] = false; + if ('animatable' in attrs) { + (attrsProto || getAttrsProto())[attrsProtoKey + 'animatable'] = !!attrs.animatable; } } diff --git a/cocos2d/core/platform/CCMacro.js b/cocos2d/core/platform/CCMacro.js index ff960b6fb4a..3cd6a8bb6ad 100644 --- a/cocos2d/core/platform/CCMacro.js +++ b/cocos2d/core/platform/CCMacro.js @@ -331,8 +331,8 @@ cc.macro = { * Whether or not clear dom Image object cache after uploading to gl texture. * Concretely, we are setting image.src to empty string to release the cache. * Normally you don't need to enable this option, because on web the Image object doesn't consume too much memory. - * But on Wechat Game platform, the current version cache decoded data in Image object, which has high memory usage. - * So we enabled this option by default on Wechat, so that we can release Image cache immediately after uploaded to GPU. + * But on WeChat Game platform, the current version cache decoded data in Image object, which has high memory usage. + * So we enabled this option by default on WeChat, so that we can release Image cache immediately after uploaded to GPU. * !#zh * 是否在将贴图上传至 GPU 之后删除 DOM Image 缓存。 * 具体来说,我们通过设置 image.src 为空字符串来释放这部分内存。 diff --git a/cocos2d/core/renderer/canvas/renderers/label/index.js b/cocos2d/core/renderer/canvas/renderers/label/index.js index 58dd876686a..77433680fb7 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/index.js +++ b/cocos2d/core/renderer/canvas/renderers/label/index.js @@ -22,10 +22,36 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ - +const Label = require('../../../../components/CCLabel'); const ttf = require('./ttf'); const bmfont = require('./bmfont'); +let canvasPool = { + pool: [], + get () { + let data = this.pool.pop(); + + if (!data) { + let canvas = document.createElement("canvas"); + let context = canvas.getContext("2d"); + data = { + canvas: canvas, + context: context + } + } + + return data; + }, + put (canvas) { + if (this.pool.length >= 32) { + return; + } + this.pool.push(canvas); + } +}; + +Label._canvasPool = canvasPool; + module.exports = { getAssembler (comp) { let assembler = ttf; diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/index.js b/cocos2d/core/renderer/canvas/renderers/sprite/index.js index 4ffa73820f7..3df28b1d657 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/index.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/index.js @@ -30,6 +30,11 @@ let simple = require('./simple'); let sliced = require('./sliced'); let tiled = require('./tiled'); +if (CC_TEST) { + // 2.x not support test with the canvas simple, in order to test in local test construct. + cc._Test._spriteWebGLAssembler = require('../../../webgl/assemblers/sprite/index.js'); +} + module.exports = { getAssembler: function (sprite) { switch (sprite.type) { @@ -52,4 +57,4 @@ module.exports = { createData (sprite) { return sprite._assembler.createData(sprite); } -}; \ No newline at end of file +}; diff --git a/cocos2d/core/renderer/utils/label/letter-font.js b/cocos2d/core/renderer/utils/label/letter-font.js new file mode 100644 index 00000000000..af14d5c2899 --- /dev/null +++ b/cocos2d/core/renderer/utils/label/letter-font.js @@ -0,0 +1,919 @@ +/**************************************************************************** + Copyright (c) 2018 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 macro = require('../../../platform/CCMacro'); +const Label = require('../../../components/CCLabel'); +const LabelOutline = require('../../../components/CCLabelOutline'); +const textUtils = require('../../../utils/text-utils'); +const Component = require('../../../components/CCComponent'); +const RenderTexture = require('../../../assets/CCRenderTexture'); +const OUTLINE_SUPPORTED = cc.js.isChildClassOf(LabelOutline, Component); +const Overflow = Label.Overflow; +const WHITE = cc.Color.WHITE; +const space = 2; + +let LetterInfo = function() { + this.char = ''; + this.valid = true; + this.x = 0; + this.y = 0; + this.line = 0; + this.hash = ""; +}; + +let FontLetterDefinition = function() { + this.u = 0; + this.v = 0; + this.w = 0; + this.h = 0; + this.texture = null; + this.offsetX = 0; + this.offsetY = 0; + this.valid = false; + this.xAdvance = 0; +}; + +let _backgroundStyle = 'rgba(255, 255, 255, 0.005)'; + +function LetterTexture(char, labelInfo) { + this._texture = null; + this._labelInfo = labelInfo; + this._char = char; + this._hash = null; + this._data = null; + this._canvas = null; + this._context = null; + this._width = 0; + this._height = 0; + this._hash = char.charCodeAt(0) + labelInfo.hash; +} + +LetterTexture.prototype = { + constructor: LetterTexture, + + updateRenderData () { + this._updateProperties(); + this._updateTexture(); + }, + _updateProperties () { + this._texture = new cc.Texture2D(); + this._data = Label._canvasPool.get(); + this._canvas = this._data.canvas; + this._context = this._data.context; + this._context.font = this._labelInfo.fontDesc; + let width = textUtils.safeMeasureText(this._context, this._char); + this._width = parseFloat(width.toFixed(2)) + 2 * this._labelInfo.margin; + this._height = this._labelInfo.lineHeight; + + if (this._canvas.width !== this._width || CC_QQPLAY) { + this._canvas.width = this._width; + } + + if (this._canvas.height !== this._height) { + this._canvas.height = this._height; + } + + this._texture.initWithElement(this._canvas); + }, + _updateTexture () { + let context = this._context; + let labelInfo = this._labelInfo, + width = this._canvas.width, + height = this._canvas.height; + + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.clearRect(0, 0, width, height); + //Add a white background to avoid black edges. + context.fillStyle = _backgroundStyle; + context.fillRect(0, 0, width, height); + context.font = labelInfo.fontDesc; + + let startX = width / 2; + let startY = height / 2; + let color = labelInfo.color; + //use round for line join to avoid sharp intersect point + context.lineJoin = 'round'; + context.fillStyle = `rgba(${color.r}, ${color.g}, ${color.b}, ${1})`; + if (labelInfo.isOutlined) { + let strokeColor = labelInfo.out || WHITE; + context.strokeStyle = `rgba(${strokeColor.r}, ${strokeColor.g}, ${strokeColor.b}, ${strokeColor.a / 255})`; + context.lineWidth = labelInfo.margin * 2; + context.strokeText(this._char, startX, startY); + } + context.fillText(this._char, startX, startY); + + this._texture.handleLoadedTexture(); + }, + + destroy () { + this._texture.destroy(); + this._texture = null; + Label._canvasPool.put(this._data); + }, +} + +function LetterAtlas (width, height) { + let texture = new RenderTexture(); + texture.initWithSize(width, height); + texture.update(); + + this._texture = texture; + + this._x = space; + this._y = space; + this._nexty = space; + + this._width = width; + this._height = height; + + this._letterDefinitions = {}; + + cc.director.on(cc.Director.EVENT_BEFORE_SCENE_LAUNCH, this.beforeSceneLoad, this); +} + +cc.js.mixin(LetterAtlas.prototype, { + insertLetterTexture (letterTexture) { + let texture = letterTexture._texture; + let width = texture.width, height = texture.height; + + if ((this._x + width + space) > this._width) { + this._x = space; + this._y = this._nexty; + } + + if ((this._y + height) > this._nexty) { + this._nexty = this._y + height + space; + } + + if (this._nexty > this._height) { + return null; + } + + this._texture.drawTextureAt(texture, this._x, this._y); + + this._dirty = true; + + let letterDefinition = new FontLetterDefinition(); + letterDefinition.u = this._x; + letterDefinition.v = this._y; + letterDefinition.texture = this._texture; + letterDefinition.valid = true; + letterDefinition.w = letterTexture._width; + letterDefinition.h = letterTexture._height; + letterDefinition.xAdvance = letterTexture._width; + + this._x += width + space; + + this._letterDefinitions[letterTexture._hash] = letterDefinition; + + return letterDefinition + }, + + update () { + if (!this._dirty) return; + this._texture.update(); + this._dirty = false; + }, + + reset () { + this._x = space; + this._y = space; + this._nexty = space; + + let chars = this._letterDefinitions; + for (let i = 0, l = chars.length; i < l; i++) { + let char = chars[i]; + if (!char.isValid) { + continue; + } + char.destroy(); + } + + this._letterDefinitions = {}; + }, + + destroy () { + this.reset(); + this._texture.destroy(); + }, + + beforeSceneLoad () { + this.destroy(); + + let texture = new RenderTexture(); + texture.initWithSize(this._width, this._height); + texture.update(); + + this._texture = texture; + }, + + getLetter (key) { + return this._letterDefinitions[key]; + }, + + addLetterDefinitions: function(key, letterDefinition) { + this._letterDefinitions[key] = letterDefinition; + }, + cloneLetterDefinition: function() { + let copyLetterDefinitions = {}; + for (let key in this._letterDefinitions) { + let value = new FontLetterDefinition(); + cc.js.mixin(value, this._letterDefinitions[key]); + copyLetterDefinitions[key] = value; + } + return copyLetterDefinitions; + }, + assignLetterDefinitions: function(letterDefinition) { + for (let key in this._letterDefinitions) { + let newValue = letterDefinition[key]; + let oldValue = this._letterDefinitions[key]; + cc.js.mixin(oldValue, newValue); + } + }, + scaleFontLetterDefinition: function(scaleFactor) { + for (let fontDefinition in this._letterDefinitions) { + let letterDefinitions = this._letterDefinitions[fontDefinition]; + letterDefinitions.w *= scaleFactor; + letterDefinitions.h *= scaleFactor; + letterDefinitions.offsetX *= scaleFactor; + letterDefinitions.offsetY *= scaleFactor; + letterDefinitions.xAdvance *= scaleFactor; + } + }, + getLetterDefinitionForChar: function(char, labelInfo) { + let hash = char.charCodeAt(0) + labelInfo.hash; + let letterDefinition = this._letterDefinitions[hash]; + if (!letterDefinition) { + let temp = new LetterTexture(char, labelInfo); + temp.updateRenderData(); + letterDefinition = this.insertLetterTexture(temp); + temp.destroy(); + } + + return letterDefinition; + } +}); + +let _tmpRect = cc.rect(); + +let _comp = null; + +let _horizontalKernings = []; +let _lettersInfo = []; +let _linesWidth = []; +let _linesOffsetX = []; +let _labelDimensions = cc.size(); + +let _fontAtlas = null; +let _fntConfig = null; +let _numberOfLines = 0; +let _textDesiredHeight = 0; +let _letterOffsetY = 0; +let _tailoredTopY = 0; +let _tailoredBottomY = 0; +let _bmfontScale = 1.0; +let _lineBreakWithoutSpaces = false; +let _lineSpacing = 0; +let _string = ''; +let _fontSize = 0; +let _originFontSize = 0; +let _contentSize = cc.size(); +let _hAlign = 0; +let _vAlign = 0; +let _spacingX = 0; +let _lineHeight = 0; +let _overflow = 0; +let _isWrapText = false; +let _labelWidth = 0; +let _labelHeight = 0; +let _maxLineWidth = 0; +let _atlasWidth = 2048; +let _atlasHeight = 2048; +let _fontFamily = ""; +let _isBold = false; +let _labelInfo = { + fontSize:0, + lineHeight:0, + hash:"", + fontFamily:"", + fontDesc:"Arial", + hAlign:0, + vAlign:0, + color:WHITE, + isOutlined:false, + out:WHITE, + margin:0, +}; + +module.exports = { + _getAssemblerData () { + if (!_fontAtlas) { + _fontAtlas = new LetterAtlas(_atlasWidth, _atlasHeight); + } + + return _fontAtlas._texture + }, + + updateRenderData (comp) { + if (!comp._renderData.vertDirty) return; + if (_comp === comp) return; + + _comp = comp; + + this._updateFontFamily(comp); + _labelInfo.fontFamily = _fontFamily; + + this._updateProperties(); + _labelInfo.fontDesc = this._getFontDesc(); + + this._updateContent(); + + _comp._actualFontSize = _fontSize; + _comp.node.setContentSize(_contentSize); + + _comp._renderData.vertDirty = _comp._renderData.uvDirty = false; + + _comp = null; + + this._resetProperties(); + }, + + _updateFontScale () { + _bmfontScale = _fontSize / _originFontSize; + }, + + _updateProperties () { + _string = _comp.string.toString(); + _fontSize = _comp.fontSize; + _originFontSize = _fontSize; + _contentSize.width = _comp.node._contentSize.width; + _contentSize.height = _comp.node._contentSize.height; + _hAlign = _comp.horizontalAlign; + _vAlign = _comp.verticalAlign; + _spacingX = _comp.spacingX; + _overflow = _comp.overflow; + _lineHeight = _comp._lineHeight; + _isBold = _comp._isBold; + + // should wrap text + if (_overflow === Overflow.NONE) { + _isWrapText = false; + } + else if (_overflow === Overflow.RESIZE_HEIGHT) { + _isWrapText = true; + } + else { + _isWrapText = _comp.enableWrapText; + } + + // outline + let outline = OUTLINE_SUPPORTED && _comp.getComponent(LabelOutline); + if (outline && outline.enabled) { + _labelInfo.isOutlined = true; + _labelInfo.margin = outline.width; + _labelInfo.out = outline.color; + _labelInfo.out.a = outline.color.a * _comp.node.color.a / 255.0; + } + else { + _labelInfo.isOutlined = false; + _labelInfo.margin = 0; + } + + _labelInfo.lineHeight = _lineHeight; + _labelInfo.fontSize = _fontSize; + _labelInfo.fontFamily = _fontFamily; + _labelInfo.color = _comp.node.color; + _labelInfo.hash = this._computeHash(_labelInfo); + + this._setupBMFontOverflowMetrics(); + + }, + + _updateFontFamily (comp) { + if (!comp.useSystemFont) { + if (comp.font) { + if (comp.font._nativeAsset) { + _fontFamily = comp.font._nativeAsset; + } + else { + _fontFamily = cc.loader.getRes(comp.font.nativeUrl); + if (!_fontFamily) { + cc.loader.load(comp.font.nativeUrl, function (err, fontFamily) { + _fontFamily = fontFamily || 'Arial'; + comp.font._nativeAsset = fontFamily; + comp._updateRenderData(true); + }); + } + } + } + else { + _fontFamily = 'Arial'; + } + } + else { + _fontFamily = comp.fontFamily; + } + }, + + _computeHash (labelInfo) { + let hashData = ''; + let color = labelInfo.color.toHEX("#rrggbb"); + let out = ''; + if (labelInfo.isOutlined) { + out = labelInfo.out.toHEX("#rrggbb"); + }; + + return hashData + labelInfo.fontSize + labelInfo.fontFamily + color + out; + }, + + _getFontDesc () { + let fontDesc = _fontSize.toString() + 'px '; + fontDesc = fontDesc + _fontFamily; + if (_isBold) { + fontDesc = "bold " + fontDesc; + } + + return fontDesc; + }, + + _resetProperties () { + + }, + + _updateContent () { + this._updateFontScale(); + //this._computeHorizontalKerningForText(); + this._alignText(); + }, + + _computeHorizontalKerningForText () { + let string = _string; + let stringLen = string.length; + + let kerningDict = _fntConfig.kerningDict; + let horizontalKernings = _horizontalKernings; + + let prev = -1; + for (let i = 0; i < stringLen; ++i) { + let key = string.charCodeAt(i); + let kerningAmount = kerningDict[(prev << 16) | (key & 0xffff)] || 0; + if (i < stringLen - 1) { + horizontalKernings[i] = kerningAmount; + } else { + horizontalKernings[i] = 0; + } + prev = key; + } + }, + + _multilineTextWrap: function(nextTokenFunc) { + let textLen = _string.length; + + let lineIndex = 0; + let nextTokenX = 0; + let nextTokenY = 0; + let longestLine = 0; + let letterRight = 0; + + let highestY = 0; + let lowestY = 0; + let letterDef = null; + let letterPosition = cc.v2(0, 0); + + this._updateFontScale(); + + for (let index = 0; index < textLen;) { + let character = _string.charAt(index); + if (character === "\n") { + _linesWidth.push(letterRight); + letterRight = 0; + lineIndex++; + nextTokenX = 0; + nextTokenY -= _lineHeight * _bmfontScale + _lineSpacing; + this._recordPlaceholderInfo(index, character); + index++; + continue; + } + + let tokenLen = nextTokenFunc(_string, index, textLen); + let tokenHighestY = highestY; + let tokenLowestY = lowestY; + let tokenRight = letterRight; + let nextLetterX = nextTokenX; + let newLine = false; + + for (let tmp = 0; tmp < tokenLen; ++tmp) { + let letterIndex = index + tmp; + character = _string.charAt(letterIndex); + if (character === "\r") { + this._recordPlaceholderInfo(letterIndex, character); + continue; + } + letterDef = _fontAtlas.getLetterDefinitionForChar(character, _labelInfo); + if (!letterDef) { + this._recordPlaceholderInfo(letterIndex, character); + continue; + } + + let letterX = nextLetterX + letterDef.offsetX * _bmfontScale; + + if (_isWrapText + && _maxLineWidth > 0 + && nextTokenX > 0 + && letterX + letterDef.w * _bmfontScale > _maxLineWidth + && !textUtils.isUnicodeSpace(character)) { + _linesWidth.push(letterRight); + letterRight = 0; + lineIndex++; + nextTokenX = 0; + nextTokenY -= (_lineHeight * _bmfontScale + _lineSpacing); + newLine = true; + break; + } else { + letterPosition.x = letterX; + } + + letterPosition.y = nextTokenY - letterDef.offsetY * _bmfontScale; + this._recordLetterInfo(letterPosition, character, letterIndex, lineIndex); + + if (letterIndex + 1 < _horizontalKernings.length && letterIndex < textLen - 1) { + nextLetterX += _horizontalKernings[letterIndex + 1]; + } + + nextLetterX += letterDef.xAdvance * _bmfontScale + _spacingX; + + tokenRight = letterPosition.x + letterDef.w * _bmfontScale; + + if (tokenHighestY < letterPosition.y) { + tokenHighestY = letterPosition.y; + } + + if (tokenLowestY > letterPosition.y - letterDef.h * _bmfontScale) { + tokenLowestY = letterPosition.y - letterDef.h * _bmfontScale; + } + + } //end of for loop + + if (newLine) continue; + + nextTokenX = nextLetterX; + letterRight = tokenRight; + + if (highestY < tokenHighestY) { + highestY = tokenHighestY; + } + if (lowestY > tokenLowestY) { + lowestY = tokenLowestY; + } + if (longestLine < letterRight) { + longestLine = letterRight; + } + + index += tokenLen; + } //end of for loop + + _linesWidth.push(letterRight); + + _numberOfLines = lineIndex + 1; + _textDesiredHeight = _numberOfLines * _lineHeight * _bmfontScale; + if (_numberOfLines > 1) { + _textDesiredHeight += (_numberOfLines - 1) * _lineSpacing; + } + + _contentSize.width = _labelWidth; + _contentSize.height = _labelHeight; + if (_labelWidth <= 0) { + _contentSize.width = parseFloat(longestLine.toFixed(2)); + } + if (_labelHeight <= 0) { + _contentSize.height = parseFloat(_textDesiredHeight.toFixed(2)); + } + + _tailoredTopY = _contentSize.height; + _tailoredBottomY = 0; + if (highestY > 0) { + _tailoredTopY = _contentSize.height + highestY; + } + if (lowestY < -_textDesiredHeight) { + _tailoredBottomY = _textDesiredHeight + lowestY; + } + + return true; + }, + + _getFirstCharLen: function() { + return 1; + }, + + _getFirstWordLen: function(text, startIndex, textLen) { + let character = text.charAt(startIndex); + if (textUtils.isUnicodeCJK(character) + || character === "\n" + || textUtils.isUnicodeSpace(character)) { + return 1; + } + + let len = 1; + let letterDef = _fontAtlas.getLetterDefinitionForChar(character, _labelInfo); + if (!letterDef) { + return len; + } + let nextLetterX = letterDef.xAdvance * _bmfontScale + _spacingX; + let letterX; + for (let index = startIndex + 1; index < textLen; ++index) { + character = text.charAt(index); + + letterDef = _fontAtlas.getLetterDefinitionForChar(character, _labelInfo); + if (!letterDef) { + break; + } + letterX = nextLetterX + letterDef.offsetX * _bmfontScale; + + if(letterX + letterDef.w * _bmfontScale > _maxLineWidth + && !textUtils.isUnicodeSpace(character) + && _maxLineWidth > 0) { + return len; + } + nextLetterX += letterDef.xAdvance * _bmfontScale + _spacingX; + if (character === "\n" + || textUtils.isUnicodeSpace(character) + || textUtils.isUnicodeCJK(character)) { + break; + } + len++; + } + + return len; + }, + + _multilineTextWrapByWord: function() { + return this._multilineTextWrap(this._getFirstWordLen); + }, + + _multilineTextWrapByChar: function() { + return this._multilineTextWrap(this._getFirstCharLen); + }, + + _recordPlaceholderInfo: function(letterIndex, char) { + if (letterIndex >= _lettersInfo.length) { + let tmpInfo = new LetterInfo(); + _lettersInfo.push(tmpInfo); + } + + _lettersInfo[letterIndex].char = char; + _lettersInfo[letterIndex].hash = char.charCodeAt(0) + _labelInfo.hash; + _lettersInfo[letterIndex].valid = false; + }, + + _recordLetterInfo: function(letterPosition, character, letterIndex, lineIndex) { + if (letterIndex >= _lettersInfo.length) { + let tmpInfo = new LetterInfo(); + _lettersInfo.push(tmpInfo); + } + let char = character.charCodeAt(0); + let key = char + _labelInfo.hash; + _lettersInfo[letterIndex].line = lineIndex; + _lettersInfo[letterIndex].char = character; + _lettersInfo[letterIndex].hash = key; + _lettersInfo[letterIndex].valid = _fontAtlas.getLetter(key).valid; + _lettersInfo[letterIndex].x = letterPosition.x; + _lettersInfo[letterIndex].y = letterPosition.y; + }, + + _alignText: function() { + _textDesiredHeight = 0; + _linesWidth.length = 0; + + if (!_lineBreakWithoutSpaces) { + this._multilineTextWrapByWord(); + } else { + this._multilineTextWrapByChar(); + } + + this._computeAlignmentOffset(); + + this._updateQuads() + //shrink + // if (_overflow === Overflow.SHRINK) { + // if (_fontSize > 0 && this._isVerticalClamp()) { + // this._shrinkLabelToContentSize(this._isVerticalClamp); + // } + // } + + // if (!this._updateQuads()) { + // if (_overflow === Overflow.SHRINK) { + // this._shrinkLabelToContentSize(this._isHorizontalClamp); + // } + // } + }, + + _scaleFontSizeDown (fontSize) { + let shouldUpdateContent = true; + if (!fontSize) { + fontSize = 0.1; + shouldUpdateContent = false; + } + _fontSize = fontSize; + + if (shouldUpdateContent) { + this._updateContent(); + } + }, + + _isVerticalClamp () { + if (_textDesiredHeight > _contentSize.height) { + return true; + } else { + return false; + } + }, + + _isHorizontalClamp () { + let letterClamp = false; + for (let ctr = 0, l = _string.length; ctr < l; ++ctr) { + let letterInfo = _lettersInfo[ctr]; + if (letterInfo.valid) { + let letterDef = _fontAtlas.getLetter(letterInfo.hash); + + let px = letterInfo.x + letterDef.w / 2 * _bmfontScale; + let lineIndex = letterInfo.line; + if (_labelWidth > 0) { + if (!_isWrapText) { + if(px > _contentSize.width){ + letterClamp = true; + break; + } + }else{ + let wordWidth = _linesWidth[lineIndex]; + if (wordWidth > _contentSize.width && (px > _contentSize.width || px < 0)) { + letterClamp = true; + break; + } + } + } + } + } + + return letterClamp; + }, + + _isHorizontalClamped (px, lineIndex) { + let wordWidth = _linesWidth[lineIndex]; + let letterOverClamp = (px > _contentSize.width || px < 0); + + if(!_isWrapText){ + return letterOverClamp; + }else{ + return (wordWidth > _contentSize.width && letterOverClamp); + } + }, + + _updateQuads () { + + let texture = _fontAtlas._texture; + + let node = _comp.node; + let renderData = _comp._renderData; + renderData.dataLength = renderData.vertexCount = renderData.indiceCount = 0; + + let contentSize = _contentSize, + appx = node._anchorPoint.x * contentSize.width, + appy = node._anchorPoint.y * contentSize.height; + + let ret = true; + for (let ctr = 0, l = _string.length; ctr < l; ++ctr) { + let letterInfo = _lettersInfo[ctr]; + if (!letterInfo.valid) continue; + let letterDef = _fontAtlas.getLetter(letterInfo.hash); + + _tmpRect.height = letterDef.h; + _tmpRect.width = letterDef.w; + _tmpRect.x = letterDef.u; + _tmpRect.y = letterDef.v; + + let py = letterInfo.y + _letterOffsetY; + + if (_labelHeight > 0) { + if (py > _tailoredTopY) { + let clipTop = py - _tailoredTopY; + _tmpRect.y += clipTop; + _tmpRect.height -= clipTop; + py = py - clipTop; + } + + if (py - letterDef.h * _bmfontScale < _tailoredBottomY) { + _tmpRect.height = (py < _tailoredBottomY) ? 0 : (py - _tailoredBottomY); + } + } + + let lineIndex = letterInfo.line; + let px = letterInfo.x + letterDef.w / 2 * _bmfontScale + _linesOffsetX[lineIndex]; + + if (_labelWidth > 0) { + if (this._isHorizontalClamped(px, lineIndex)) { + if (_overflow === Overflow.CLAMP) { + _tmpRect.width = 0; + } else if (_overflow === Overflow.SHRINK) { + if (_contentSize.width > letterDef.w) { + ret = false; + break; + } else { + _tmpRect.width = 0; + } + } + } + } + + if (_tmpRect.height > 0 && _tmpRect.width > 0) { + let letterPositionX = letterInfo.x + _linesOffsetX[letterInfo.line]; + this.appendQuad(renderData, texture, _tmpRect, false, letterPositionX - appx, py - appy, _bmfontScale); + } + } + + return ret; + }, + + appendQuad (renderData, texture, rect, rotated, x, y, scale) { + }, + + _computeAlignmentOffset: function() { + _linesOffsetX.length = 0; + + switch (_hAlign) { + case macro.TextAlignment.LEFT: + for (let i = 0; i < _numberOfLines; ++i) { + _linesOffsetX.push(0); + } + break; + case macro.TextAlignment.CENTER: + for (let i = 0, l = _linesWidth.length; i < l; i++) { + _linesOffsetX.push((_contentSize.width - _linesWidth[i]) / 2); + } + break; + case macro.TextAlignment.RIGHT: + for (let i = 0, l = _linesWidth.length; i < l; i++) { + _linesOffsetX.push(_contentSize.width - _linesWidth[i]); + } + break; + default: + break; + } + + switch (_vAlign) { + case macro.VerticalTextAlignment.TOP: + _letterOffsetY = _contentSize.height; + break; + case macro.VerticalTextAlignment.CENTER: + _letterOffsetY = (_contentSize.height + _textDesiredHeight) / 2; + break; + case macro.VerticalTextAlignment.BOTTOM: + _letterOffsetY = _textDesiredHeight; + break; + default: + break; + } + }, + + _setupBMFontOverflowMetrics () { + let newWidth = _contentSize.width, + newHeight = _contentSize.height; + + if (_overflow === Overflow.RESIZE_HEIGHT) { + newHeight = 0; + } + + if (_overflow === Overflow.NONE) { + newWidth = 0; + newHeight = 0; + } + + _labelWidth = newWidth; + _labelHeight = newHeight; + _labelDimensions.width = newWidth; + _labelDimensions.height = newHeight; + _maxLineWidth = newWidth; + } +}; diff --git a/cocos2d/core/renderer/utils/label/ttf.js b/cocos2d/core/renderer/utils/label/ttf.js index a0ec1e22918..bc3345bacf1 100644 --- a/cocos2d/core/renderer/utils/label/ttf.js +++ b/cocos2d/core/renderer/utils/label/ttf.js @@ -52,7 +52,7 @@ let _color = null; let _fontFamily = ''; let _overflow = Overflow.NONE; let _isWrapText = false; -let _backgroundAlpha = 0.005; +const _invisibleAlpha = (1 / 255).toFixed(3); // outline let _isOutlined = false; @@ -70,54 +70,17 @@ let _drawUnderlinePos = cc.v2(); let _sharedLabelData; -// -let _canvasPool = { - pool: [], - get () { - let data = this.pool.pop(); - - if (!data) { - let canvas = document.createElement("canvas"); - let context = canvas.getContext("2d"); - data = { - canvas: canvas, - context: context - } - } - - return data; - }, - put (canvas) { - if (this.pool.length >= 32) { - return; - } - this.pool.push(canvas); - } -}; - - module.exports = { _getAssemblerData () { - if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS) { - _sharedLabelData = _canvasPool.get(); - } - else { - if (!_sharedLabelData) { - let labelCanvas = document.createElement("canvas"); - _sharedLabelData = { - canvas: labelCanvas, - context: labelCanvas.getContext("2d") - }; - } - } + _sharedLabelData = Label._canvasPool.get(); _sharedLabelData.canvas.width = _sharedLabelData.canvas.height = 1; return _sharedLabelData; }, _resetAssemblerData (assemblerData) { - if (cc.game.renderType === cc.game.RENDER_TYPE_CANVAS && assemblerData) { - _canvasPool.put(assemblerData); + if (assemblerData) { + Label._canvasPool.put(assemblerData); } }, @@ -252,7 +215,7 @@ module.exports = { _context.clearRect(0, 0, _canvas.width, _canvas.height); //Add a white background to avoid black edges. //TODO: it is best to add alphaTest to filter out the background color. - _context.fillStyle = `rgba(${255}, ${255}, ${255}, ${_backgroundAlpha})`; + _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${_invisibleAlpha})`; _context.fillRect(0, 0, _canvas.width, _canvas.height); _context.font = _fontDesc; @@ -260,8 +223,9 @@ module.exports = { let lineHeight = this._getLineHeight(); //use round for line join to avoid sharp intersect point _context.lineJoin = 'round'; - _context.fillStyle = 'white'; + _context.fillStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, 1)`; + let underlineStartPosition; //do real rendering for (let i = 0; i < _splitedStrings.length; ++i) { _drawTextPos.x = startPosition.x; @@ -272,8 +236,8 @@ module.exports = { _drawUnderlinePos.y = _drawTextPos.y + _underlineThickness; _context.save(); _context.beginPath(); - _context.lineWidth = _underlineThickness; - _context.strokeStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, 1)`; + _context.lineWidth = _fontSize / 8; + _context.strokeStyle = `rgba(${_color.r}, ${_color.g}, ${_color.b}, ${1})`; _context.moveTo(_drawUnderlinePos.x, _drawUnderlinePos.y); _context.lineTo(_drawUnderlinePos.x + _canvas.width, _drawUnderlinePos.y); _context.stroke(); @@ -293,7 +257,7 @@ module.exports = { }, _calDynamicAtlas (comp) { - if (!comp.batchAsBitmap) return; + if(comp.cacheMode !== Label.CacheMode.BITMAP) return; let frame = comp._frame; if (!frame._original) { @@ -326,9 +290,14 @@ module.exports = { _canvasSize.width += _drawFontSize * Math.tan(12 * 0.0174532925); } } + + if (_canvas.width !== _canvasSize.width || CC_QQPLAY) { + _canvas.width = _canvasSize.width; + } - _canvas.width = _canvasSize.width; - _canvas.height = _canvasSize.height; + if (_canvas.height !== _canvasSize.height) { + _canvas.height = _canvasSize.height; + } }, _calculateTextBaseline () { diff --git a/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js new file mode 100644 index 00000000000..b3c3adf4c2a --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/letter.js @@ -0,0 +1,44 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 bmfontAssembler = require('./bmfont'); +const fontUtils = require('../../../../utils/label/letter-font'); +const fillMeshVertices = require('../../utils').fillMeshVertices; +const WHITE = cc.color(255, 255, 255, 255); + +module.exports = js.addon({ + createData (comp) { + return comp.requestRenderData(); + }, + + fillBuffers (comp, renderer) { + let node = comp.node; + WHITE._fastSetA(node.color.a); + fillMeshVertices(node, renderer._meshBuffer, comp._renderData, WHITE._val); + }, + + appendQuad: bmfontAssembler.appendQuad +}, fontUtils); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js index 836c03a0470..8c740f93e8f 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/2d/ttf.js @@ -26,6 +26,7 @@ const js = require('../../../../../platform/js'); const ttfUtls = require('../../../../utils/label/ttf'); const fillMeshVertices = require('../../utils').fillMeshVertices; +const WHITE = cc.color(255, 255, 255, 255); module.exports = js.addon({ createData (comp) { @@ -40,7 +41,8 @@ module.exports = js.addon({ fillBuffers (comp, renderer) { let node = comp.node; - fillMeshVertices(node, renderer._meshBuffer, comp._renderData, node.color._val); + WHITE._fastSetA(node.color.a); + fillMeshVertices(node, renderer._meshBuffer, comp._renderData, WHITE._val); }, _updateVerts (comp) { diff --git a/cocos2d/core/renderer/webgl/assemblers/label/3d/letter.js b/cocos2d/core/renderer/webgl/assemblers/label/3d/letter.js new file mode 100644 index 00000000000..68a8f7696da --- /dev/null +++ b/cocos2d/core/renderer/webgl/assemblers/label/3d/letter.js @@ -0,0 +1,37 @@ +/**************************************************************************** + Copyright (c) 2017-2018 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 assembler = require('../2d/letter'); +const fillMeshVertices3D = require('../../utils').fillMeshVertices3D; +const WHITE = cc.color(255, 255, 255, 255); + +module.exports = js.addon({ + fillBuffers (comp, renderer) { + let node = comp.node; + WHITE._fastSetA(node.color.a); + fillMeshVertices3D(comp.node, renderer._meshBuffer3D, comp._renderData, WHITE._val); + } +}, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js index 36bbf5f8ad9..e27669e75b8 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/3d/ttf.js @@ -26,10 +26,12 @@ const js = require('../../../../../platform/js'); const assembler = require('../2d/ttf'); const fillMeshVertices3D = require('../../utils').fillMeshVertices3D; +const WHITE = cc.color(255, 255, 255, 255); module.exports = js.addon({ fillBuffers (comp, renderer) { let node = comp.node; - fillMeshVertices3D(comp.node, renderer._meshBuffer3D, comp._renderData, node.color._val); + WHITE._fastSetA(node.color.a); + fillMeshVertices3D(comp.node, renderer._meshBuffer3D, comp._renderData, WHITE._val); } }, assembler); diff --git a/cocos2d/core/renderer/webgl/assemblers/label/index.js b/cocos2d/core/renderer/webgl/assemblers/label/index.js index c4c47c55a03..835ff8f031b 100644 --- a/cocos2d/core/renderer/webgl/assemblers/label/index.js +++ b/cocos2d/core/renderer/webgl/assemblers/label/index.js @@ -27,9 +27,35 @@ const Label = require('../../../../components/CCLabel'); const ttfAssembler = require('./2d/ttf'); const bmfontAssembler = require('./2d/bmfont'); +const letterAssembler = require('./2d/letter'); const ttfAssembler3D = require('./3d/ttf'); const bmfontAssembler3D = require('./3d/bmfont'); +const letterAssembler3D = require('./3d/letter'); + +let canvasPool = { + pool: [], + get () { + let data = this.pool.pop(); + + if (!data) { + let canvas = document.createElement("canvas"); + let context = canvas.getContext("2d"); + data = { + canvas: canvas, + context: context + } + } + + return data; + }, + put (canvas) { + if (this.pool.length >= 32) { + return; + } + this.pool.push(canvas); + } +}; var labelAssembler = { getAssembler (comp) { @@ -38,6 +64,12 @@ var labelAssembler = { if (comp.font instanceof cc.BitmapFont) { assembler = is3DNode ? bmfontAssembler3D : bmfontAssembler; + } else if (comp.cacheMode === Label.CacheMode.CHAR) { + if (cc.sys.browserType === cc.sys.BROWSER_TYPE_WECHAT_GAME_SUB) { + cc.warn('sorry, subdomain does not support CHAR mode currently!'); + } else { + assembler = is3DNode ? letterAssembler3D : letterAssembler; + } } return assembler; @@ -50,5 +82,5 @@ var labelAssembler = { }; Label._assembler = labelAssembler; - +Label._canvasPool = canvasPool; module.exports = labelAssembler; \ No newline at end of file diff --git a/cocos2d/core/utils/blend-func.js b/cocos2d/core/utils/blend-func.js new file mode 100644 index 00000000000..e165c3576e8 --- /dev/null +++ b/cocos2d/core/utils/blend-func.js @@ -0,0 +1,88 @@ + +const RenderComponent = require('../components/CCRenderComponent'); +const BlendFactor = require('../platform/CCMacro').BlendFactor; +const gfx = require('../../renderer/gfx'); + +let BlendFunc = cc.Class({ + properties: { + _srcBlendFactor: BlendFactor.SRC_ALPHA, + _dstBlendFactor: BlendFactor.ONE_MINUS_SRC_ALPHA, + + /** + * !#en specify the source Blend Factor, this will generate a custom material object, please pay attention to the memory cost. + * !#zh 指定原图的混合模式,这会克隆一个新的材质对象,注意这带来的开销 + * @property srcBlendFactor + * @type {macro.BlendFactor} + * @example + * sprite.srcBlendFactor = cc.macro.BlendFactor.ONE; + */ + srcBlendFactor: { + get: function() { + return this._srcBlendFactor; + }, + set: function(value) { + if (this._srcBlendFactor === value) return; + this._srcBlendFactor = value; + this._updateBlendFunc(); + }, + animatable: false, + type:BlendFactor, + tooltip: CC_DEV && 'i18n:COMPONENT.sprite.src_blend_factor', + visible: false + }, + + /** + * !#en specify the destination Blend Factor. + * !#zh 指定目标的混合模式 + * @property dstBlendFactor + * @type {macro.BlendFactor} + * @example + * sprite.dstBlendFactor = cc.macro.BlendFactor.ONE; + */ + dstBlendFactor: { + get: function() { + return this._dstBlendFactor; + }, + set: function(value) { + if (this._dstBlendFactor === value) return; + this._dstBlendFactor = value; + this._updateBlendFunc(); + }, + animatable: false, + type: BlendFactor, + tooltip: CC_DEV && 'i18n:COMPONENT.sprite.dst_blend_factor', + visible: false + }, + }, + + setMaterial (index, material) { + RenderComponent.prototype.setMaterial.call(this, index, material); + if (material) { + this._updateMaterialBlendFunc(material); + } + }, + + _updateBlendFunc () { + let materials = this._materials; + for (let i = 0; i < materials.length; i++) { + let material = materials[i]; + this._updateMaterialBlendFunc(material); + } + }, + + _updateMaterialBlendFunc (material) { + let passes = material._effect.getDefaultTechnique().passes; + for (let j = 0; j < passes.length; j++) { + let pass = passes[j]; + pass.setBlend( + true, + gfx.BLEND_FUNC_ADD, + this._srcBlendFactor, this._dstBlendFactor, + gfx.BLEND_FUNC_ADD, + this._srcBlendFactor, this._dstBlendFactor + ); + } + }, +}); + +module.exports = BlendFunc; diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js index 36a23befb91..471dcfd0da6 100644 --- a/cocos2d/particle/CCParticleSystem.js +++ b/cocos2d/particle/CCParticleSystem.js @@ -34,6 +34,7 @@ const textureUtil = require('../core/utils/texture-util'); const RenderFlow = require('../core/renderer/render-flow'); const ParticleSimulator = require('./particle-simulator'); const Material = require('../core/assets/material/CCMaterial'); +const BlendFunc = require('../core/utils/blend-func'); function getImageFormatByData (imgData) { // if it is a png file buffer. @@ -525,7 +526,7 @@ var properties = { * @property {Vec2} sourcePos * @default cc.Vec2.ZERO */ - sourcePos: cc.v2(0, 0), + sourcePos: cc.Vec2.ZERO, /** * !#en Variation of source position. @@ -533,7 +534,7 @@ var properties = { * @property {Vec2} posVar * @default cc.Vec2.ZERO */ - posVar: cc.v2(0, 0), + posVar: cc.Vec2.ZERO, /** * !#en Particles movement type. @@ -565,7 +566,7 @@ var properties = { * @property {Vec2} gravity * @default cc.Vec2.ZERO */ - gravity: cc.v2(0, 0), + gravity: cc.Vec2.ZERO, /** * !#en Speed of the emitter. * !#zh 速度。 @@ -661,6 +662,7 @@ var properties = { * @default 0 */ rotatePerSVar: 0 + }; /** @@ -709,6 +711,7 @@ var properties = { var ParticleSystem = cc.Class({ name: 'cc.ParticleSystem', extends: RenderComponent, + mixins: [BlendFunc], editor: CC_EDITOR && { menu: 'i18n:MAIN_MENU.component.renderers/ParticleSystem', inspector: 'packages://inspector/inspectors/comps/particle-system.js', diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 1540fa58068..b90ce8b773b 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -97,7 +97,7 @@ module.exports = { "wrap": "Wrap text?", "font": "What font to use", "system_font": "Whether to use the system default font", - 'batch_as_bitmap': 'Whether to set to static text for batch merging, select this will add text to the dynamic atlas for batch merging, but can not dynamically modify text content frequently' + 'cacheMode': 'The text cache mode includes the following three types: \n 1. NONE : Do not do any caching, text content is drawn once. \n 2. BITMAP: Add text as a static image to the dynamic atlas for batch merging, but not frequently dynamically Text content \n 3. CHAR: Splits text into characters and caches characters into character atlas, suitable for text content with repeated and frequently updated character content' }, "progress": { "bar_sprite": "A progress bar is displayed with the Sprite node that can dynamically change the size", @@ -216,6 +216,7 @@ module.exports = { "input_mode": "Specify the input mode: multiline or single line.", "font_size": "The font size of input label.", "line_height": "The line height of input label.", + "stay_on_top": "Set to true and the input is always visible and be on top of the game view, this property will be removed on v2.1", "tab_index": "Set the tabIndex of the DOM input element, only useful on Web.", "font_color": "The font color of input label.", "placeholder": "The content string of placeholder.", @@ -259,7 +260,7 @@ module.exports = { "premultipliedAlpha": "Indicates whether to enable premultiplied alpha.", "use_tint": "Indicates whether to use tint effect.", "enabled_batch": "Indicates whether enabled batch model", - "render_mode": "The render mode of current armature. \n'REALTIME' means REALTIME calculate animation data, support animation blend but low performance. \n'SHARED_CACHE' means precomputation animation data and share data with same armature, high performance and less memery. \n'PRIVATE_CACHE' means precomputation animation data but not share data with other same armature, high performance and more memery.\nAbove two cache mode, not support nest armature, not support 'fade' related interface.", + "animation_cache_mode": "REALTIME model, the animation data is calculated while running, all features supported. SHARED_CACHE mode, the animation data is pre-calculated and cached globally, the data is shared between skeleton animation instances. Shared cache mode has great performance advantage, but it has some limitation. It doesn't support action blending and addition and it only supports the start and end events. In the memory usage aspect, as same skeleton animation instances are sharing the same animation data, this mode can save a lot of memory. More instances are sharing, more memory saved. In conclusion SHARED_CACHE mode is suitable for the skeletons which could be replicated, such as effects animation, monster, NPC and so on.\nPRIVATE_CACHE mode, similar to SHARED_CACHE, but the animation data and texture data are not shared between skeleton instances. So there is no advantage in memory compare to REALTIME mode. The PRIVATE_CACHE is suitable when there is no animation blending or addition needed, but the skeleton could change textures of sub bone (e.g. weapon).", }, "dragon_bones": { "dragon_bones_asset": "The json data contains the DragonBones information, drag the json file exported from DragonBones to get started.", @@ -270,7 +271,7 @@ module.exports = { "play_times": "The play times of the default animation.\n-1 means using the value of config file\n0 means repeat for ever\n>0 means repeat times", "debug_bones": "Indicates whether open debug bones", "enabled_batch": "Indicates whether enabled batch model", - "render_mode": "The render mode of current armature. \n'REALTIME' means REALTIME calculate animation data, support animation blend but low performance. \n'SHARED_CACHE' means precomputation animation data and share data with same armature, high performance and less memery. \n'PRIVATE_CACHE' means precomputation animation data but not share data with other same armature, high performance and more memery.\nAbove two cache mode, not support nest armature, not support 'fade' related interface.", + "animation_cache_mode": "REALTIME model, the animation data is calculated while running, all features supported. SHARED_CACHE mode, the animation data is pre-calculated and cached globally, the data is shared between skeleton animation instances. Shared cache mode has great performance advantage, but it has some limitation. It doesn't support action blending and addition and it only supports the start and end events. In the memory usage aspect, as same skeleton animation instances are sharing the same animation data, this mode can save a lot of memory. More instances are sharing, more memory saved. In conclusion SHARED_CACHE mode is suitable for the skeletons which could be replicated, such as effects animation, monster, NPC and so on.\nPRIVATE_CACHE mode, similar to SHARED_CACHE, but the animation data and texture data are not shared between skeleton instances. So there is no advantage in memory compare to REALTIME mode. The PRIVATE_CACHE is suitable when there is no animation blending or addition needed, but the skeleton could change textures of sub bone (e.g. weapon).", }, 'motionStreak': { 'fadeTime': "Trail fragment fade time, in seconds", @@ -345,7 +346,8 @@ module.exports = { 'linearVelocity': 'The linear velocity of the body\'s origin in world co-ordinates', 'angularVelocity': 'The angular velocity of the body.', 'fixedRotation': 'Should this body be prevented from rotating?', - 'awake': 'Is this body initially awake or sleeping?' + 'awake': 'Set the sleep state of the body. A sleeping body has very low CPU cost.(When the rigid body is hit, if the rigid body is in sleep state, it will be immediately awakened.)', + 'awakeOnLoad': 'Whether to wake up this rigid body during initialization', }, 'physics_collider': { 'density': 'The density', diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 59607640569..a7cb5e41ac9 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -100,7 +100,7 @@ module.exports = { 'wrap': '是否允许自动换行', 'font': 'Label 使用的字体资源', 'system_font': '是否使用系统默认字体,选中此项会将 file 属性置空', - 'batch_as_bitmap': '是否设置为静态文本进行批次合并,选中此项将会把文本加入动态图集进行批次合并,但是不能频繁动态修改文本内容' + 'cacheMode': '文本缓存模式,包括以下三种:\n 1. NONE : 不做任何缓存,文本内容进行一次绘制 \n 2. BITMAP: 将文本作为静态图像加入动态图集进行批次合并,但是不能频繁动态修改文本内容 \n 3. CHAR: 将文本拆分为字符并且把字符纹理缓存到一张字符图集中进行复用,适用于字符内容重复并且频繁更新的文本内容' }, 'progress': { 'bar_sprite': '进度条显示用的 Sprite 节点,可以动态改变尺寸', @@ -221,6 +221,7 @@ module.exports = { "font_size": "输入框文本的字体大小", "line_height": "输入框文本的行高", "font_color": "输入框文本的颜色", + "stay_on_top": "设置为 True 则输入框总是可见,并且永远在游戏视图的上面,该属性会在 v2.1 中移除", "tab_index": "修改 DOM 输入元素的 tabIndex,这个属性只有在 Web 上面修改有意义。", "placeholder": "输入框占位符的文本内容", "placeholder_font_size": "输入框占位符的字体大小", @@ -261,7 +262,9 @@ module.exports = { "debug_slots": "是否显示 slot 的 debug 信息", "debug_bones": "是否显示 bone 的 debug 信息", "premultipliedAlpha": "是否启用贴图预乘", - "use_tint": "是否启用染色效果" + "use_tint": "是否启用染色效果", + "enabled_batch": "是否开启合批", + "animation_cache_mode": "REALTIME 模式,实时运算,支持 Spine 所有的功能。\nSHARED_CACHE 模式,将骨骼动画及贴图数据进行缓存并共享,相当于预烘焙骨骼动画。拥有较高性能,但不支持动作融合、动作叠加,只支持动作开始和结束事件。至于内存方面,当创建 N(N>=3) 个相同骨骼、相同动作的动画时,会呈现内存优势。N 值越大,优势越明显。综上 SHARED_CACHE 模式适用于场景动画,特效,副本怪物,NPC 等,能极大提高帧率和降低内存。\nPRIVATE_CACHE 模式,与 SHARED_CACHE 类似,但不共享动画及贴图数据,所以在内存方面没有优势,仅存在性能优势。当想利用缓存模式的高性能,但又存在换装的需求,因此不能共享贴图数据时,那么 PRIVATE_CACHE 就适合你。", }, "dragon_bones": { "dragon_bones_asset": "骨骼信息数据,拖拽 DragonBones 导出的骨骼动画信息 json 资源到这里来开始使用", @@ -272,7 +275,7 @@ module.exports = { "play_times": "播放默认动画的循环次数\n-1 表示使用配置文件中的默认值\n0 表示无限循环\n>0 表示循环次数", "debug_bones": "是否显示 bone 的 debug 信息", "enabled_batch": "是否开启合批", - "render_mode": "当前骨骼动画的渲染模式\nrealtime 表示实时计算,支持动画融合,较耗性能\nsharedCache 表示预计算且共享动画数据,性能较高,占用较少内存\nprivateCache 表示预计算但不共享动画数据,性能较高,占用较多内存\n以上两种缓存模式,不支持骨骼嵌套,不支持fade相关接口", + "animation_cache_mode": "REALTIME 模式,实时运算,支持 DragonBones 所有的功能。\nSHARED_CACHE 模式,将骨骼动画及贴图数据进行缓存并共享,相当于预烘焙骨骼动画。拥有较高性能,但不支持动作融合、动作叠加、骨骼嵌套,只支持动作开始和结束事件。至于内存方面,当创建 N(N>=3) 个相同骨骼、相同动作的动画时,会呈现内存优势。N 值越大,优势越明显。综上 SHARED_CACHE 模式适用于场景动画,特效,副本怪物,NPC 等,能极大提高帧率和降低内存。\nPRIVATE_CACHE 模式,与 SHARED_CACHE 类似,但不共享动画及贴图数据,所以在内存方面没有优势,仅存在性能优势。当想利用缓存模式的高性能,但又存在换装的需求,因此不能共享贴图数据时,那么 PRIVATE_CACHE 就适合你。", }, 'motionStreak': { 'fadeTime': "拖尾的渐隐时间,以秒为单位", @@ -347,7 +350,8 @@ module.exports = { 'linearVelocity': '刚体在世界坐标下的线性速度', 'angularVelocity': '刚体的角速度', 'fixedRotation': '是否禁止此刚体进行旋转', - 'awake': '是否立刻唤醒此刚体' + 'awake': '设置刚体的睡眠状态。 睡眠的刚体具有非常低的 CPU 成本。(当刚体被碰撞到时,如果刚体处于睡眠状态,它会立即被唤醒)', + 'awakeOnLoad': '是否在初始化时唤醒此刚体', }, 'physics_collider': { 'density': '密度', diff --git a/extensions/dragonbones/ArmatureCache.js b/extensions/dragonbones/ArmatureCache.js index 8d6c176d8ec..590f84533a9 100644 --- a/extensions/dragonbones/ArmatureCache.js +++ b/extensions/dragonbones/ArmatureCache.js @@ -287,35 +287,20 @@ let ArmatureCache = cc.Class({ delete this._armatureCache[armatureKey]; }, - // When atlas asset be destroy, remove armature from db cache. - clearByAtlasName (atlasName) { - for (var armatureKey in this._armatureCache) { - var armatureInfo = this._armatureCache[armatureKey]; - if (armatureInfo && armatureInfo.atlasName === atlasName) { - this._removeArmature(armatureKey); - return; - } - } - }, - // When db assets be destroy, remove armature from db cache. - clearByDBName (dbName) { + resetArmature (uuid) { for (var armatureKey in this._armatureCache) { - var armatureInfo = this._armatureCache[armatureKey]; - if (armatureInfo && armatureInfo.dbName === dbName) { - this._removeArmature(armatureKey); - return; - } + if (armatureKey.indexOf(uuid) == -1) continue; + this._removeArmature(armatureKey); } }, - getArmatureCache (armatureName, dragonbonesName, atlasName) { - let armatureKey = armatureName + "#" + dragonbonesName + "#" + atlasName; + getArmatureCache (armatureName, armatureKey, atlasUUID) { let armatureInfo = this._armatureCache[armatureKey]; let armature; if (!armatureInfo) { let factory = dragonBones.CCFactory.getInstance(); - let proxy = factory.buildArmatureDisplay(armatureName, dragonbonesName, "", atlasName); + let proxy = factory.buildArmatureDisplay(armatureName, armatureKey, "", atlasUUID); if (!proxy || !proxy._armature) return; armature = proxy._armature; // If armature has child armature, can not be cache, because it's @@ -327,8 +312,6 @@ let ArmatureCache = cc.Class({ this._armatureCache[armatureKey] = { armature : armature, - dbName : dragonbonesName, - atlasName : atlasName, // Cache all kinds of animation frame. // When armature is dispose, clear all animation cache. animationsCache : {}, @@ -339,8 +322,7 @@ let ArmatureCache = cc.Class({ return armature; }, - getAnimationCache (armatureName, dragonbonesName, atlasName, animationName) { - let armatureKey = armatureName + "#" + dragonbonesName + "#" + atlasName; + getAnimationCache (armatureKey, animationName) { let armatureInfo = this._armatureCache[armatureKey]; if (!armatureInfo) return null; @@ -348,8 +330,7 @@ let ArmatureCache = cc.Class({ return animationsCache[animationName]; }, - updateAnimationCache (armatureName, dragonbonesName, atlasName, animationName) { - let armatureKey = armatureName + "#" + dragonbonesName + "#" + atlasName; + updateAnimationCache (armatureKey, animationName) { let armatureInfo = this._armatureCache[armatureKey]; let armature = armatureInfo && armatureInfo.armature; if (!armature) return null; @@ -373,7 +354,7 @@ let ArmatureCache = cc.Class({ } animationCache.update(armature); if (animationCache.totalTime >= MaxCacheTime) { - cc.warn("Animation cache is overflow, maybe animation's frame is infinite, please change armature render mode to REALTIME, dragonbones name is [%s], animation name is [%s]", dragonbonesName, animationName); + cc.warn("Animation cache is overflow, maybe animation's frame is infinite, please change armature render mode to REALTIME, dragonbones uuid is [%s], animation name is [%s]", armatureKey, animationName); } return animationCache; } diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 9ce7a63636f..0a04cc153d5 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -31,7 +31,6 @@ let EventTarget = require('../../cocos2d/core/event/event-target'); const Node = require('../../cocos2d/core/CCNode'); const Graphics = require('../../cocos2d/core/graphics/graphics'); -const BlendFactor = require('../../cocos2d/core/platform/CCMacro').BlendFactor; let ArmatureCache = require('./ArmatureCache'); @@ -41,14 +40,14 @@ let ArmatureCache = require('./ArmatureCache'); let DefaultArmaturesEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); -let DefaultRenderMode = cc.Enum({ 'REALTIME': 0 }); +let DefaultCacheMode = cc.Enum({ 'REALTIME': 0 }); /** - * !#en Enum for render mode type. + * !#en Enum for cache mode type. * !#zh Dragonbones渲染类型 - * @enum ArmatureDisplay.RenderMode + * @enum ArmatureDisplay.AnimationCacheMode */ -let RenderMode = cc.Enum({ +let AnimationCacheMode = cc.Enum({ /** * !#en The realtime mode. * !#zh 实时计算模式。 @@ -96,7 +95,6 @@ function setEnumAttr (obj, propName, enumDef) { let ArmatureDisplay = cc.Class({ name: 'dragonBones.ArmatureDisplay', extends: RenderComponent, - mixins: [EventTarget], editor: CC_EDITOR && { menu: 'i18n:MAIN_MENU.component.renderers/DragonBones', @@ -104,7 +102,7 @@ let ArmatureDisplay = cc.Class({ }, statics: { - RenderMode: RenderMode, + AnimationCacheMode: AnimationCacheMode, }, properties: { @@ -114,44 +112,6 @@ let ArmatureDisplay = cc.Class({ serializable: false, }, - /** - * !#en don't try to get or set srcBlendFactor,it doesn't affect,if you want to change dragonbones blend mode,please set it in dragonbones editor directly. - * !#zh 不要试图去获取或者设置 srcBlendFactor,没有意义,如果你想设置 dragonbones 的 blendMode,直接在 dragonbones 编辑器中设置即可。 - * @property srcBlendFactor - * @type {macro.BlendFactor} - */ - srcBlendFactor: { - get: function() { - return this._srcBlendFactor; - }, - set: function(value) { - // shield set _srcBlendFactor - }, - animatable: false, - type:BlendFactor, - override: true, - visible: false - }, - - /** - * !#en don't try to get or set dstBlendFactor,it doesn't affect,if you want to change dragonbones blend mode,please set it in dragonbones editor directly. - * !#zh 不要试图去获取或者设置 dstBlendFactor,没有意义,如果想设置 dragonbones 的 blendMode,直接在 dragonbones 编辑器中设置即可。 - * @property dstBlendFactor - * @type {macro.BlendFactor} - */ - dstBlendFactor: { - get: function() { - return this._dstBlendFactor; - }, - set: function(value) { - // shield set _dstBlendFactor - }, - animatable: false, - type: BlendFactor, - override: true, - visible: false - }, - /** * !#en * The DragonBones data contains the armatures information (bind pose bones, slots, draw order, @@ -167,8 +127,6 @@ let ArmatureDisplay = cc.Class({ default: null, type: dragonBones.DragonBonesAsset, notify () { - // parse the asset data - this._parseDragonAsset(); this._refresh(); if (CC_EDITOR) { this._defaultArmatureIndex = 0; @@ -221,13 +179,13 @@ let ArmatureDisplay = cc.Class({ } } - if (this._armature && !this.isCachedMode()) { + if (this._armature && !this.isAnimationCached()) { this._factory._dragonBones.clock.remove(this._armature); } this._refresh(); - if (this._armature && !this.isCachedMode()) { + if (this._armature && !this.isAnimationCached()) { this._factory._dragonBones.clock.add(this._armature); } @@ -305,7 +263,7 @@ let ArmatureDisplay = cc.Class({ let animName = animsEnum[this._animationIndex]; if (animName !== undefined) { - this.animationName = animName; + this.playAnimation(animName, this.playTimes); } else { cc.errorID(7402, this.name); @@ -318,20 +276,20 @@ let ArmatureDisplay = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.animation_name' }, - // Record pre render mode. - _preRenderMode: -1, - _renderMode: RenderMode.REALTIME, - _defaultRenderMode: { + // Record pre cache mode. + _preCacheMode: -1, + _cacheMode: AnimationCacheMode.REALTIME, + _defaultCacheMode: { default: 0, - type: RenderMode, + type: AnimationCacheMode, notify () { - this.setRenderMode(this._defaultRenderMode); + this.setAnimationCacheMode(this._defaultCacheMode); }, editorOnly: true, visible: true, animatable: false, - displayName: "Render Mode", - tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.render_mode' + displayName: "Animation Cache Mode", + tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.animation_cache_mode' }, /** @@ -409,7 +367,10 @@ let ArmatureDisplay = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.dragon_bones.enabled_batch' }, - // Below properties will effect when render mode is SHARED_CACHE or PRIVATE_CACHE. + // DragonBones data store key. + _armatureKey: "", + + // Below properties will effect when cache mode is SHARED_CACHE or PRIVATE_CACHE. // accumulate time _accTime: 0, // Play times counter @@ -431,6 +392,7 @@ let ArmatureDisplay = cc.Class({ // it will just use the _material,won't clone it. // So if invoke getMaterial,it only return _material,if you want to change all materialCache, // you can change materialCache directly. + this._eventTarget = null; this._materialCache = {}; this._inited = false; this._factory = dragonBones.CCFactory.getInstance(); @@ -474,10 +436,9 @@ let ArmatureDisplay = cc.Class({ this._inited = true; if (CC_JSB) { - this._renderMode = RenderMode.REALTIME; + this._cacheMode = AnimationCacheMode.REALTIME; } - this._parseDragonAsset(); this._parseDragonAtlasAsset(); this._refresh(); @@ -495,21 +456,21 @@ let ArmatureDisplay = cc.Class({ /** * !#en - * It's best to set render mode before set property 'dragonAsset', or will waste some cpu time. + * It's best to set cache mode before set property 'dragonAsset', or will waste some cpu time. * If set the mode in editor, then no need to worry about order problem. * !#zh * 若想切换渲染模式,最好在设置'dragonAsset'之前,先设置好渲染模式,否则有运行时开销。 * 若在编辑中设置渲染模式,则无需担心设置次序的问题。 * - * @method setRenderMode - * @param {RenderMode} renderMode + * @method setAnimationCacheMode + * @param {AnimationCacheMode} cacheMode * * @example - * armatureDisplay.setRenderMode(dragonBones.ArmatureDisplay.RenderMode.SHARED_CACHE); + * armatureDisplay.setAnimationCacheMode(dragonBones.ArmatureDisplay.AnimationCacheMode.SHARED_CACHE); */ - setRenderMode (renderMode) { + setAnimationCacheMode (cacheMode) { if (CC_JSB) return; - if (this._preRenderMode !== renderMode) { - this._renderMode = renderMode; + if (this._preCacheMode !== cacheMode) { + this._cacheMode = cacheMode; this._buildArmature(); } }, @@ -517,31 +478,31 @@ let ArmatureDisplay = cc.Class({ /** * !#en Whether in cached mode. * !#zh 当前是否处于缓存模式。 - * @method isCachedMode + * @method isAnimationCached */ - isCachedMode () { + isAnimationCached () { if (CC_EDITOR) return false; - return this._renderMode !== RenderMode.REALTIME; + return this._cacheMode !== AnimationCacheMode.REALTIME; }, onEnable () { this._super(); - // If render mode is cache, no need to update by dragonbones library. - if (this._armature && !this.isCachedMode()) { + // If cache mode is cache, no need to update by dragonbones library. + if (this._armature && !this.isAnimationCached()) { this._factory._dragonBones.clock.add(this._armature); } }, onDisable () { this._super(); - // If render mode is cache, no need to update by dragonbones library. - if (this._armature && !this.isCachedMode()) { + // If cache mode is cache, no need to update by dragonbones library. + if (this._armature && !this.isAnimationCached()) { this._factory._dragonBones.clock.remove(this._armature); } }, update (dt) { - if (!this.isCachedMode()) return; + if (!this.isAnimationCached()) return; if (!this._playing) return; let frames = this._frameCache.frames; @@ -551,7 +512,7 @@ let ArmatureDisplay = cc.Class({ // Animation Start, the event diffrent from dragonbones inner event, // It has no event object. if (this._accTime == 0 && this._playCount == 0) { - this.emit(dragonBones.EventObject.START); + this._eventTarget && this._eventTarget.emit(dragonBones.EventObject.START); } this._accTime += dt * this.timeScale; @@ -560,11 +521,11 @@ let ArmatureDisplay = cc.Class({ // Animation loop complete, the event diffrent from dragonbones inner event, // It has no event object. - this.emit(dragonBones.EventObject.LOOP_COMPLETE); + this._eventTarget && this._eventTarget.emit(dragonBones.EventObject.LOOP_COMPLETE); // Animation complete the event diffrent from dragonbones inner event, // It has no event object. - this.emit(dragonBones.EventObject.COMPLETE); + this._eventTarget && this._eventTarget.emit(dragonBones.EventObject.COMPLETE); this._playCount ++; if (this.playTimes === -1 || (this.playTimes > 0 && this._playCount >= this.playTimes)) { @@ -585,11 +546,11 @@ let ArmatureDisplay = cc.Class({ this._inited = false; if (!CC_EDITOR) { - if (this._renderMode === RenderMode.PRIVATE_CACHE) { + if (this._cacheMode === AnimationCacheMode.PRIVATE_CACHE) { this._armatureCache.dispose(); this._armatureCache = null; this._armature = null; - } else if (this._renderMode === RenderMode.SHARED_CACHE) { + } else if (this._cacheMode === AnimationCacheMode.SHARED_CACHE) { this._armatureCache = null; this._armature = null; } else if (this._armature) { @@ -648,13 +609,14 @@ let ArmatureDisplay = cc.Class({ _buildArmature () { if (!this.dragonAsset || !this.dragonAtlasAsset || !this.armatureName) return; - // Switch Asset or Atlas or renderMode will rebuild armature. + + // Switch Asset or Atlas or cacheMode will rebuild armature. if (this._armature) { // dispose pre build armature if (!CC_EDITOR) { - if (this._preRenderMode === RenderMode.PRIVATE_CACHE) { + if (this._preCacheMode === AnimationCacheMode.PRIVATE_CACHE) { this._armatureCache.dispose(); - } else if (this._preRenderMode === RenderMode.REALTIME) { + } else if (this._preCacheMode === AnimationCacheMode.REALTIME) { this._armature.dispose(); } } else { @@ -667,38 +629,41 @@ let ArmatureDisplay = cc.Class({ this._frameCache = null; this._curFrame = null; this._playing = false; - this._preRenderMode = null; + this._preCacheMode = null; + this._eventTarget = null; } if (!CC_EDITOR) { - if (this._renderMode === RenderMode.SHARED_CACHE) { + if (this._cacheMode === AnimationCacheMode.SHARED_CACHE) { this._armatureCache = ArmatureCache.sharedCache; - } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { + this._eventTarget = new EventTarget; + } else if (this._cacheMode === AnimationCacheMode.PRIVATE_CACHE) { this._armatureCache = new ArmatureCache; + this._eventTarget = new EventTarget; } } - let atlasName = this.dragonAtlasAsset._textureAtlasData.name; - let dragonbonesName = this.dragonAsset._dragonBonesData.name; + let atlasUUID = this.dragonAtlasAsset._uuid; + this._armatureKey = this.dragonAsset.init(this._factory, atlasUUID); - if (this.isCachedMode()) { - this._armature = this._armatureCache.getArmatureCache(this.armatureName, dragonbonesName, atlasName); + if (this.isAnimationCached()) { + this._armature = this._armatureCache.getArmatureCache(this.armatureName, this._armatureKey, atlasUUID); if (!this._armature) { - // Cache fail,swith to REALTIME render mode. - this._renderMode = RenderMode.REALTIME; + // Cache fail,swith to REALTIME cache mode. + this._cacheMode = AnimationCacheMode.REALTIME; } } - this._preRenderMode = this._renderMode; - if (CC_EDITOR || this._renderMode === RenderMode.REALTIME) { - this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, dragonbonesName, "", atlasName); + this._preCacheMode = this._cacheMode; + if (CC_EDITOR || this._cacheMode === AnimationCacheMode.REALTIME) { + this._displayProxy = this._factory.buildArmatureDisplay(this.armatureName, this._armatureKey, "", atlasUUID); if (!this._displayProxy) return; this._displayProxy._ccNode = this.node; this._armature = this._displayProxy._armature; this._armature.animation.timeScale = this.timeScale; } - if (this._renderMode !== RenderMode.REALTIME && this.debugBones) { + if (this._cacheMode !== AnimationCacheMode.REALTIME && this.debugBones) { cc.warn("Debug bones is invalid in cached mode"); } @@ -708,12 +673,6 @@ let ArmatureDisplay = cc.Class({ } }, - _parseDragonAsset () { - if (this.dragonAsset) { - this.dragonAsset.init(this._factory); - } - }, - _parseDragonAtlasAsset () { if (this.dragonAtlasAsset) { this.dragonAtlasAsset.init(this._factory); @@ -727,16 +686,16 @@ let ArmatureDisplay = cc.Class({ // update inspector this._updateArmatureEnum(); this._updateAnimEnum(); - this._updateRenderModeEnum(); + this._updateCacheModeEnum(); Editor.Utils.refreshSelectedInspector('node', this.node.uuid); } }, - _updateRenderModeEnum: CC_EDITOR && function () { + _updateCacheModeEnum: CC_EDITOR && function () { if (this._armature && ArmatureCache.canCache(this._armature)) { - setEnumAttr(this, 'renderMode', RenderMode); + setEnumAttr(this, '_defaultCacheMode', AnimationCacheMode); } else { - setEnumAttr(this, 'renderMode', DefaultRenderMode); + setEnumAttr(this, '_defaultCacheMode', DefaultCacheMode); } }, @@ -785,12 +744,10 @@ let ArmatureDisplay = cc.Class({ this.playTimes = (playTimes === undefined) ? -1 : playTimes; this.animationName = animName; - if (this.isCachedMode()) { - let atlasName = this.dragonAtlasAsset._textureAtlasData.name; - let dragonbonesName = this.dragonAsset._dragonBonesData.name; - let cache = this._armatureCache.getAnimationCache(this.armatureName, dragonbonesName, atlasName, animName); + if (this.isAnimationCached()) { + let cache = this._armatureCache.getAnimationCache(this._armatureKey, animName); if (!cache) { - cache = this._armatureCache.updateAnimationCache(this.armatureName, dragonbonesName, atlasName, animName); + cache = this._armatureCache.updateAnimationCache(this._armatureKey, animName); } if (cache) { this._accTime = 0; @@ -815,10 +772,8 @@ let ArmatureDisplay = cc.Class({ * @param {String} animName */ updateAnimationCache (animName) { - if (!this.isCachedMode()) return; - let atlasName = this.dragonAtlasAsset._textureAtlasData.name; - let dragonbonesName = this.dragonAsset._dragonBonesData.name; - let cache = this._armatureCache.updateAnimationCache(this.armatureName, dragonbonesName, atlasName, animName); + if (!this.isAnimationCached()) return; + let cache = this._armatureCache.updateAnimationCache(this._armatureKey, animName); this._frameCache = cache || this._frameCache; }, @@ -831,7 +786,7 @@ let ArmatureDisplay = cc.Class({ * @returns {Array} */ getArmatureNames () { - let dragonBonesData = this.dragonAsset && this.dragonAsset._dragonBonesData; + let dragonBonesData = this._factory.getDragonBonesData(this._armatureKey); return (dragonBonesData && dragonBonesData.armatureNames) || []; }, @@ -846,8 +801,9 @@ let ArmatureDisplay = cc.Class({ */ getAnimationNames (armatureName) { let ret = []; - if (this.dragonAsset && this.dragonAsset._dragonBonesData) { - let armatureData = this.dragonAsset._dragonBonesData.getArmature(armatureName); + let dragonBonesData = this._factory.getDragonBonesData(this._armatureKey); + if (dragonBonesData) { + let armatureData = dragonBonesData.getArmature(armatureName); if (armatureData) { for (let animName in armatureData.animations) { if (armatureData.animations.hasOwnProperty(animName)) { @@ -856,10 +812,57 @@ let ArmatureDisplay = cc.Class({ } } } - return ret; }, + /** + * !#en + * Add event listener for the DragonBones Event, the same to addEventListener. + * !#zh + * 添加 DragonBones 事件监听器,与 addEventListener 作用相同。 + * @method on + * @param {String} type - A string representing the event type to listen for. + * @param {Function} listener - The callback that will be invoked when the event is dispatched. + * @param {Event} listener.event event + * @param {Object} [target] - The target (this object) to invoke the callback, can be null + */ + on (eventType, listener, target) { + this.addEventListener(eventType, listener, target); + }, + + /** + * !#en + * Remove the event listener for the DragonBones Event, the same to removeEventListener. + * !#zh + * 移除 DragonBones 事件监听器,与 removeEventListener 作用相同。 + * @method off + * @param {String} type - A string representing the event type to listen for. + * @param {Function} [listener] + * @param {Object} [target] + */ + off (eventType, listener, target) { + this.removeEventListener(eventType, listener, target); + }, + + /** + * !#en + * Add event listener for the DragonBones Event, the same to addEventListener. + * !#zh + * 添加 DragonBones 一次性事件监听器,回调会在第一时间被触发后删除自身。。 + * @method on + * @param {String} type - A string representing the event type to listen for. + * @param {Function} listener - The callback that will be invoked when the event is dispatched. + * @param {Event} listener.event event + * @param {Object} [target] - The target (this object) to invoke the callback, can be null + */ + once (eventType, listener, target) { + if (this._displayProxy) { + this._displayProxy.once(eventType, listener, target); + } else if (this._eventTarget) { + this._eventTarget.once(eventType, listener, target); + } + }, + /** * !#en * Add event listener for the DragonBones Event. @@ -873,9 +876,9 @@ let ArmatureDisplay = cc.Class({ */ addEventListener (eventType, listener, target) { if (this._displayProxy) { - this._displayProxy.addDBEventListener(eventType, listener, target); - } else { - this.on(eventType, listener, target); + this._displayProxy.on(eventType, listener, target); + } else if (this._eventTarget) { + this._eventTarget.on(eventType, listener, target); } }, @@ -891,9 +894,9 @@ let ArmatureDisplay = cc.Class({ */ removeEventListener (eventType, listener, target) { if (this._displayProxy) { - this._displayProxy.removeDBEventListener(eventType, listener, target); - } else { - this.off(eventType, listener, target); + this._displayProxy.off(eventType, listener, target); + } else if (this._eventTarget) { + this._eventTarget.off(eventType, listener, target); } }, diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index 9ee9b623157..c443762c4e0 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -73,41 +73,15 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ this._dragonBones.advanceTime(dt); }, - parseDragonBonesDataOnly (rawData, name, scale) { - if (name === undefined) { name = null; } - if (scale === undefined) { scale = 1.0; } - var dataParser = rawData instanceof ArrayBuffer ? BaseFactory._binaryParser : this._dataParser; - var dragonBonesData = dataParser.parseDragonBonesData(rawData, scale); - return dragonBonesData; - }, - - handleTextureAtlasData (isBinary, name, scale) { - if (name === undefined) { name = null; } - if (scale === undefined) { scale = 1.0; } - - var dataParser = isBinary ? BaseFactory._binaryParser : this._dataParser; - - while (true) { - var textureAtlasData = this._buildTextureAtlasData(null, null); - if (dataParser.parseTextureAtlasData(null, textureAtlasData, scale)) { - this.addTextureAtlasData(textureAtlasData, name); - } - else { - textureAtlasData.returnToPool(); - break; - } - } - }, - // Build new aramture with a new display. buildArmatureDisplay (armatureName, dragonBonesName, skinName, textureAtlasName) { let armature = this.buildArmature(armatureName, dragonBonesName, skinName, textureAtlasName); return armature && armature._display; }, - parseTextureAtlasData (jsonString, texture) { + parseTextureAtlasData (jsonString, texture, atlasUUID) { var atlasJsonObj = JSON.parse(jsonString); - return this._super(atlasJsonObj, texture); + return this._super(atlasJsonObj, texture, atlasUUID); }, // Build sub armature from an exist armature component. @@ -189,5 +163,25 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ let display = slot; slot.init(slotData, displays, display, display); return slot; + }, + + getDragonBonesDataByUUID (uuid) { + for (var name in this._dragonBonesDataMap) { + if (name.indexOf(uuid) != -1) { + return this._dragonBonesDataMap[name]; + } + } + return null; + }, + + removeDragonBonesDataByUUID (uuid, disposeData) { + if (disposeData === void 0) { disposeData = true; } + for (var name in this._dragonBonesDataMap) { + if (name.indexOf(uuid) === -1) continue; + if (disposeData) { + this._dragonBones.bufferObject(this._dragonBonesDataMap[name]); + } + delete this._dragonBonesDataMap[name]; + } } }); diff --git a/extensions/dragonbones/DragonBonesAsset.js b/extensions/dragonbones/DragonBonesAsset.js index cbb9424d248..250fe480846 100644 --- a/extensions/dragonbones/DragonBonesAsset.js +++ b/extensions/dragonbones/DragonBonesAsset.js @@ -86,63 +86,31 @@ var DragonBonesAsset = cc.Class({ }, reset () { - this._dragonBonesData = null; + this._clear(); if (CC_EDITOR) { this._armaturesEnum = null; } }, - init (factory) { + init (factory, atlasUUID) { if (CC_EDITOR) { this._factory = factory || new dragonBones.CCFactory(); } else { this._factory = factory; } - if (this._dragonBonesData) { - let hasSame = this.checkSameNameData(this._dragonBonesData); - if (!hasSame) { - this._factory.addDragonBonesData(this._dragonBonesData); - } - } - else { - if (this.dragonBonesJson) { - this.initWithRawData(JSON.parse(this.dragonBonesJson), false); - } else { - this.initWithRawData(this._nativeAsset, true); - } - } - }, - - checkSameNameData (dragonBonesData) { - let sameNamedDragonBonesData = this._factory.getDragonBonesData(dragonBonesData.name); - if (sameNamedDragonBonesData) { - // already added asset, see #2002 - let armatureNames = dragonBonesData.armatureNames; - for (let i = 0; i < armatureNames.length; i++) { - let armatureName = armatureNames[i]; - if (!sameNamedDragonBonesData.armatures[armatureName]) { - sameNamedDragonBonesData.addArmature(dragonBonesData.armatures[armatureName]); - } - } - this._dragonBonesData = sameNamedDragonBonesData; - return true; - } - return false; - }, - - initWithRawData (rawData, isBinary) { - if (!rawData) { - return; - } + let armatureKey = this._uuid + "#" + atlasUUID; + let dragonBonesData = this._factory.getDragonBonesData(armatureKey); + if (dragonBonesData) return armatureKey; - let dragonBonesData = this._factory.parseDragonBonesDataOnly(rawData); - let hasSame = this.checkSameNameData(dragonBonesData); - if (!hasSame) { - this._dragonBonesData = dragonBonesData; - this._factory.handleTextureAtlasData(isBinary); - this._factory.addDragonBonesData(dragonBonesData); + let rawData = null; + if (this.dragonBonesJson) { + rawData = JSON.parse(this.dragonBonesJson); + } else { + rawData = this._nativeAsset; } + this._factory.parseDragonBonesData(rawData, armatureKey); + return armatureKey; }, // EDITOR @@ -152,8 +120,9 @@ var DragonBonesAsset = cc.Class({ return this._armaturesEnum; } this.init(); - if (this._dragonBonesData) { - var armatureNames = this._dragonBonesData.armatureNames; + let dragonBonesData = this._factory.getDragonBonesDataByUUID(this._uuid); + if (dragonBonesData) { + var armatureNames = dragonBonesData.armatureNames; var enumDef = {}; for (var i = 0; i < armatureNames.length; i++) { var name = armatureNames[i]; @@ -166,8 +135,10 @@ var DragonBonesAsset = cc.Class({ getAnimsEnum: CC_EDITOR && function (armatureName) { this.init(); - if (this._dragonBonesData) { - var armature = this._dragonBonesData.getArmature(armatureName); + + let dragonBonesData = this._factory.getDragonBonesDataByUUID(this._uuid); + if (dragonBonesData) { + var armature = dragonBonesData.getArmature(armatureName); if (!armature) { return null; } @@ -186,14 +157,16 @@ var DragonBonesAsset = cc.Class({ return null; }, - destroy () { - var useGlobalFactory = !CC_JSB; - if (useGlobalFactory && this._dragonBonesData) { - var factory = dragonBones.CCFactory.getInstance(); - let name = this._dragonBonesData.name; - factory.removeDragonBonesData(name, true); - ArmatureCache.clearByDBName(name); + _clear () { + if (CC_JSB) return; + if (this._factory) { + ArmatureCache.resetArmature(this._uuid); + this._factory.removeDragonBonesDataByUUID(this._uuid, true); } + }, + + destroy () { + this._clear(); this._super(); }, }); diff --git a/extensions/dragonbones/DragonBonesAtlasAsset.js b/extensions/dragonbones/DragonBonesAtlasAsset.js index c2e06aa9e03..086ad2143cc 100644 --- a/extensions/dragonbones/DragonBonesAtlasAsset.js +++ b/extensions/dragonbones/DragonBonesAtlasAsset.js @@ -40,7 +40,7 @@ var DragonBonesAtlasAsset = cc.Class({ extends: cc.Asset, ctor () { - this.reset(); + this._clear(); }, properties: { @@ -55,7 +55,7 @@ var DragonBonesAtlasAsset = cc.Class({ }, set: function (value) { this._atlasJson = value; - this.reset(); + this._clear(); } }, @@ -74,19 +74,17 @@ var DragonBonesAtlasAsset = cc.Class({ }, set (value) { this._texture = value; - this.reset(); + this._clear(); } }, + + _textureAtlasData: null, }, statics: { preventDeferredLoadDependents: true }, - reset () { - this._textureAtlasData = null; // instance of CCTextureAtlasData - }, - createNode: CC_EDITOR && function (callback) { var node = new cc.Node(this.name); var armatureDisplay = node.addComponent(dragonBones.ArmatureDisplay); @@ -96,40 +94,27 @@ var DragonBonesAtlasAsset = cc.Class({ }, init (factory) { + this._factory = factory; if (this._textureAtlasData) { - factory.addTextureAtlasData(this._textureAtlasData); + factory.addTextureAtlasData(this._textureAtlasData, this._uuid); } else { - this._textureAtlasData = factory.parseTextureAtlasData(this.atlasJson, this.texture); + this._textureAtlasData = factory.parseTextureAtlasData(this.atlasJson, this.texture, this._uuid); } - //// solve the error effect of DragonBones when re-enter an auto-released scene (#5053) - // var atlasName = atlasJsonObj.name; - // var atlasDataList = factory.getTextureAtlasData(atlasName); - // if (atlasDataList && atlasDataList.length > 0) { - // var texturePath = this.texture && this.texture.url; - // for (var idx in atlasDataList) { - // var data = atlasDataList[idx]; - // if (data && data.texture && data.texture.url === texturePath) { - // // found same named atlas, renew texture - // data.texture = this.texture; - // return; - // } - // } - // } }, - destroy () { - var useGlobalFactory = !CC_JSB; - if (useGlobalFactory && this._textureAtlasData) { - var factory = dragonBones.CCFactory.getInstance(); - // If the texture still referenced by any DragonBonesData in the factory, - // remember to remove them at the same time! - var name = this._textureAtlasData.name; - factory.removeTextureAtlasData(name, true); - factory.removeDragonBonesData(name, true); - ArmatureCache.clearByDBName(name); - ArmatureCache.clearByAtlasName(name); + _clear () { + if (CC_JSB) return; + if (this._factory) { + ArmatureCache.resetArmature(this._uuid); + this._factory.removeTextureAtlasData(this._uuid, true); + this._factory.removeDragonBonesDataByUUID(this._uuid, true); } + this._textureAtlasData = null; + }, + + destroy () { + this._clear(); this._super(); }, }); diff --git a/extensions/dragonbones/lib/dragonBones.js b/extensions/dragonbones/lib/dragonBones.js index fba16d6baeb..891fc1da9a5 100644 --- a/extensions/dragonbones/lib/dragonBones.js +++ b/extensions/dragonbones/lib/dragonBones.js @@ -13674,14 +13674,15 @@ var dragonBones; switch (displayData.type) { case 0 /* Image */: { var imageDisplayData = displayData; + + if (dataPackage !== null && dataPackage.textureAtlasName.length > 0) { + imageDisplayData.texture = this._getTextureData(dataPackage.textureAtlasName, displayData.path); + } + if (imageDisplayData.texture === null) { imageDisplayData.texture = this._getTextureData(dataName, displayData.path); } - if (imageDisplayData.texture === null || - (dataPackage !== null && dataPackage.textureAtlasName.length > 0)) { - imageDisplayData.texture = this._getTextureData(dataPackage.textureAtlasName, displayData.path); - } if (rawDisplayData !== null && rawDisplayData.type === 2 /* Mesh */ && this._isSupportMesh()) { display = slot.meshDisplay; } @@ -13692,12 +13693,15 @@ var dragonBones; } case 2 /* Mesh */: { var meshDisplayData = displayData; + + if (dataPackage !== null && dataPackage.textureAtlasName.length > 0) { + meshDisplayData.texture = this._getTextureData(dataPackage.textureAtlasName, meshDisplayData.path); + } + if (meshDisplayData.texture === null) { meshDisplayData.texture = this._getTextureData(dataName, meshDisplayData.path); } - else if (dataPackage !== null && dataPackage.textureAtlasName.length > 0) { - meshDisplayData.texture = this._getTextureData(dataPackage.textureAtlasName, meshDisplayData.path); - } + if (this._isSupportMesh()) { display = slot.meshDisplay; } diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 5b3a2bc5f39..65ae102123d 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -316,7 +316,7 @@ let armatureAssembler = { _handleVal |= NEED_BATCH; } - if (comp.isCachedMode()) { + if (comp.isAnimationCached()) { // Traverse input assembler. this.cacheTraverse(comp._curFrame, worldMat); } else { diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index d16affb6fd4..a7ddb017f8e 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -29,7 +29,6 @@ const RenderComponent = require('../../cocos2d/core/components/CCRenderComponent const spine = require('./lib/spine'); const Material = require('../../cocos2d/core/assets/material/CCMaterial'); const Graphics = require('../../cocos2d/core/graphics/graphics'); -const BlendFactor = require('../../cocos2d/core/platform/CCMacro').BlendFactor; let SkeletonCache = require('./skeleton-cache'); @@ -40,11 +39,11 @@ let DefaultSkinsEnum = cc.Enum({ 'default': -1 }); let DefaultAnimsEnum = cc.Enum({ '': 0 }); /** - * !#en Enum for render mode type. - * !#zh Spine渲染类型 - * @enum Skeleton.RenderMode + * !#en Enum for animation cache mode type. + * !#zh Spine动画缓存类型 + * @enum Skeleton.AnimationCacheMode */ -let RenderMode = cc.Enum({ +let AnimationCacheMode = cc.Enum({ /** * !#en The realtime mode. * !#zh 实时计算模式。 @@ -99,7 +98,7 @@ sp.Skeleton = cc.Class({ }, statics: { - RenderMode: RenderMode, + AnimationCacheMode: AnimationCacheMode, }, properties: { @@ -116,44 +115,6 @@ sp.Skeleton = cc.Class({ visible: false }, - /** - * !#en don't try to get or set srcBlendFactor,it doesn't affect,if you want to change spine blend mode,please set it in spine editor directly. - * !#zh 不要试图去获取或者设置 srcBlendFactor,没有意义,如果你想设置 spine 的 blendMode,直接在 spine 编辑器中设置即可。 - * @property srcBlendFactor - * @type {macro.BlendFactor} - */ - srcBlendFactor: { - get: function() { - return this._srcBlendFactor; - }, - set: function(value) { - // shield set _srcBlendFactor - }, - animatable: false, - type:BlendFactor, - override: true, - visible: false - }, - - /** - * !#en don't try to get or set dstBlendFactor,it doesn't affect,if you want to change spine blend mode,please set it in spine editor directly. - * !#zh 不要试图去获取或者设置 dstBlendFactor,没有意义,如果想设置 spine 的 blendMode,直接在 spine 编辑器中设置即可。 - * @property dstBlendFactor - * @type {macro.BlendFactor} - */ - dstBlendFactor: { - get: function() { - return this._dstBlendFactor; - }, - set: function(value) { - // shield set _dstBlendFactor - }, - animatable: false, - type: BlendFactor, - override: true, - visible: false - }, - /** * !#en * The skeleton data contains the skeleton information (bind pose bones, slots, draw order, @@ -207,7 +168,7 @@ sp.Skeleton = cc.Class({ */ animation: { get () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { return this._animationName; } else { var entry = this.getCurrent(0); @@ -311,20 +272,20 @@ sp.Skeleton = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.animation' }, - // Record pre render mode. - _preRenderMode: -1, - _renderMode: RenderMode.REALTIME, - _defaultRenderMode: { + // Record pre cache mode. + _preCacheMode: -1, + _cacheMode: AnimationCacheMode.REALTIME, + _defaultCacheMode: { default: 0, - type: RenderMode, + type: AnimationCacheMode, notify () { - this.setRenderMode(this._defaultRenderMode); + this.setAnimationCacheMode(this._defaultCacheMode); }, editorOnly: true, visible: true, animatable: false, - displayName: "Render Mode", - tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.render_mode' + displayName: "Animation Cache Mode", + tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.animation_cache_mode' }, /** @@ -349,7 +310,6 @@ sp.Skeleton = cc.Class({ */ premultipliedAlpha: { default: true, - formerlySerializedAs: "_premultipliedAlpha", tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.premultipliedAlpha' }, @@ -422,7 +382,7 @@ sp.Skeleton = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.skeleton.enabled_batch' }, - // Below properties will effect when render mode is SHARED_CACHE or PRIVATE_CACHE. + // Below properties will effect when cache mode is SHARED_CACHE or PRIVATE_CACHE. // accumulate time _accTime: 0, // Play times counter @@ -500,7 +460,7 @@ sp.Skeleton = cc.Class({ this.node.setContentSize(skeletonData.width, skeletonData.height); } - if (this.isCachedMode()) { + if (this.isAnimationCached()) { let skeletonInfo = this._skeletonCache.getSkeletonCache(this.skeletonData._uuid, skeletonData); this._skeleton = skeletonInfo.skeleton; this._clipper = skeletonInfo.clipper; @@ -519,7 +479,7 @@ sp.Skeleton = cc.Class({ * @param {sp.spine.SkeletonData} skeletonData */ setSlotsRange (startSlotIndex, endSlotIndex) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("Slots visible range can not be modified in cached mode."); } else { this._startSlotIndex = startSlotIndex; @@ -536,7 +496,7 @@ sp.Skeleton = cc.Class({ * @param {sp.spine.AnimationStateData} stateData */ setAnimationStateData (stateData) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("'setAnimationStateData' interface can not be invoked in cached mode."); } else { var state = new spine.AnimationState(stateData); @@ -569,7 +529,7 @@ sp.Skeleton = cc.Class({ } if (CC_JSB) { - this._renderMode = RenderMode.REALTIME; + this._cacheMode = AnimationCacheMode.REALTIME; } var material = Material.getInstantiatedBuiltinMaterial('spine', this); @@ -584,21 +544,21 @@ sp.Skeleton = cc.Class({ /** * !#en - * It's best to set render mode before set property 'dragonAsset', or will waste some cpu time. + * It's best to set cache mode before set property 'dragonAsset', or will waste some cpu time. * If set the mode in editor, then no need to worry about order problem. * !#zh * 若想切换渲染模式,最好在设置'dragonAsset'之前,先设置好渲染模式,否则有运行时开销。 * 若在编辑中设置渲染模式,则无需担心设置次序的问题。 * - * @method setRenderMode - * @param {RenderMode} renderMode + * @method setAnimationCacheMode + * @param {AnimationCacheMode} cacheMode * * @example - * armatureDisplay.setRenderMode(sp.Skeleton.RenderMode.SHARED_CACHE); + * armatureDisplay.setAnimationCacheMode(sp.Skeleton.AnimationCacheMode.SHARED_CACHE); */ - setRenderMode (renderMode) { + setAnimationCacheMode (cacheMode) { if (CC_JSB) return; - if (this._preRenderMode !== renderMode) { - this._renderMode = renderMode; + if (this._preCacheMode !== cacheMode) { + this._cacheMode = cacheMode; this._updateSkeletonData(); } }, @@ -606,18 +566,18 @@ sp.Skeleton = cc.Class({ /** * !#en Whether in cached mode. * !#zh 当前是否处于缓存模式。 - * @method isCachedMode + * @method isAnimationCached */ - isCachedMode () { + isAnimationCached () { if (CC_EDITOR) return false; - return this._renderMode !== RenderMode.REALTIME; + return this._cacheMode !== AnimationCacheMode.REALTIME; }, update (dt) { if (CC_EDITOR) return; if (this.paused) return; - if (this.isCachedMode()) { + if (this.isAnimationCached()) { // Cache mode and has animation queue. if (this._isAniComplete) { @@ -713,7 +673,7 @@ sp.Skeleton = cc.Class({ * cc.log(bone.worldX); // return -23.12; */ updateWorldTransform () { - if (!this.isCachedMode()) return; + if (!this.isAnimationCached()) return; if (this._skeleton) { this._skeleton.updateWorldTransform(); @@ -726,7 +686,7 @@ sp.Skeleton = cc.Class({ * @method setToSetupPose */ setToSetupPose () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { cc.warn("'SetToSetupPose' interface can not be invoked in cached mode."); } else { if (this._skeleton) { @@ -745,7 +705,7 @@ sp.Skeleton = cc.Class({ * @method setBonesToSetupPose */ setBonesToSetupPose () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { cc.warn("'setBonesToSetupPose' interface can not be invoked in cached mode."); } else { if (this._skeleton) { @@ -764,7 +724,7 @@ sp.Skeleton = cc.Class({ * @method setSlotsToSetupPose */ setSlotsToSetupPose () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { cc.warn("'setSlotsToSetupPose' interface can not be invoked in cached mode."); } else { if (this._skeleton) { @@ -782,7 +742,7 @@ sp.Skeleton = cc.Class({ * @param {String} animName */ updateAnimationCache (animName) { - if (!this.isCachedMode()) return; + if (!this.isAnimationCached()) return; let cache = this._skeletonCache.updateAnimationCache(this.skeletonData._uuid, animName); this._frameCache = cache || this._frameCache; }, @@ -843,7 +803,7 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.Skin} */ setSkin (skinName) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { this._skeletonCache.resetSkeleton(); this._animationName && (this.animation = this._animationName); } else { @@ -935,7 +895,7 @@ sp.Skeleton = cc.Class({ this._playTimes = loop ? 0 : 1; this._animationName = name; - if (this.isCachedMode()) { + if (this.isAnimationCached()) { if (trackIndex !== 0) { cc.warn("Track index can not greater than 0 in cached mode."); } @@ -978,7 +938,7 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.TrackEntry} */ addAnimation (trackIndex, name, loop, delay) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { if (trackIndex !== 0) { cc.warn("Track index can not greater than 0 in cached mode."); } @@ -1021,7 +981,7 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.TrackEntry} */ getCurrent (trackIndex) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("'getCurrent' interface can not be invoked in cached mode."); } else { if (this._state) { @@ -1037,7 +997,7 @@ sp.Skeleton = cc.Class({ * @method clearTracks */ clearTracks () { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("'clearTracks' interface can not be invoked in cached mode."); } else { if (this._state) { @@ -1053,7 +1013,7 @@ sp.Skeleton = cc.Class({ * @param {number} trackIndex */ clearTrack (trackIndex) { - if (this.isCachedMode()) { + if (this.isAnimationCached()) { console.warn("'clearTrack' interface can not be invoked in cached mode."); } else { if (this._state) { @@ -1246,20 +1206,20 @@ sp.Skeleton = cc.Class({ if (!data) return; if (!CC_EDITOR) { - if (this._renderMode === RenderMode.SHARED_CACHE) { + if (this._cacheMode === AnimationCacheMode.SHARED_CACHE) { this._skeletonCache = SkeletonCache.sharedCache; - } else if (this._renderMode === RenderMode.PRIVATE_CACHE) { + } else if (this._cacheMode === AnimationCacheMode.PRIVATE_CACHE) { this._skeletonCache = new SkeletonCache; } } - if (this.isCachedMode() && (this.debugBones || this.debugSlots)) { + if (this.isAnimationCached() && (this.debugBones || this.debugSlots)) { cc.warn("Debug bones or slots is invalid in cached mode"); } try { this.setSkeletonData(data); - if (!this.isCachedMode()) { + if (!this.isAnimationCached()) { this.setAnimationStateData(new spine.AnimationStateData(this._skeleton.data)); } this.defaultSkin && this.setSkin(this.defaultSkin); @@ -1268,7 +1228,7 @@ sp.Skeleton = cc.Class({ cc.warn(e); } - this._preRenderMode = this._renderMode; + this._preCacheMode = this._cacheMode; this.animation = this.defaultAnimation; }, @@ -1276,14 +1236,9 @@ sp.Skeleton = cc.Class({ // update inspector this._updateAnimEnum(); this._updateSkinEnum(); - this._updateRenderModeEnum(); Editor.Utils.refreshSelectedInspector('node', this.node.uuid); }, - _updateRenderModeEnum: CC_EDITOR && function () { - setEnumAttr(this, 'renderMode', RenderMode); - }, - _updateDebugDraw: function () { if (this.debugBones || this.debugSlots) { if (!this._debugRenderer) { @@ -1297,7 +1252,7 @@ sp.Skeleton = cc.Class({ } this._debugRenderer.node.parent = this.node; - if (this.isCachedMode()) { + if (this.isAnimationCached()) { cc.warn("Debug bones or slots is invalid in cached mode"); } } diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 827f9f4373d..4d3f0bd69a7 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -433,7 +433,6 @@ var spineAssembler = { for (let i = 0, n = locSkeleton.bones.length; i < n; i++) { bone = locSkeleton.bones[i]; - if (bone.parent == null) continue; let x = bone.data.length * bone.a + bone.worldX; let y = bone.data.length * bone.c + bone.worldY; @@ -614,7 +613,7 @@ var spineAssembler = { _handleVal |= FLAG_BATCH; } - if (comp.isCachedMode()) { + if (comp.isAnimationCached()) { // Traverse input assembler. this.cacheTraverse(worldMat); } else { diff --git a/gulp/util/utils.js b/gulp/util/utils.js index ad6dcc7f403..d308cd44984 100644 --- a/gulp/util/utils.js +++ b/gulp/util/utils.js @@ -1,6 +1,6 @@ const PLATFORM_MACROS = ['CC_EDITOR', 'CC_PREVIEW', 'CC_BUILD', 'CC_TEST']; -const FLAGS = ['jsb', 'runtime', 'wechatgame', 'wechatgameSub','baidugame', 'baidugameSub', 'qqplay', 'debug', 'nativeRenderer']; +const FLAGS = ['jsb', 'runtime', 'wechatgame', 'wechatgameSub','baidugame', 'qqplay', 'debug', 'nativeRenderer']; // generate macros for uglify's global_defs // available platforms: 'editor' | 'preview' | 'build' | 'test' @@ -36,7 +36,7 @@ exports.getMacros = function (platform, flags) { // debug macros res['CC_DEV'] = res['CC_EDITOR'] || res['CC_PREVIEW'] || res['CC_TEST']; res['CC_DEBUG'] = res['CC_DEBUG'] || res['CC_DEV']; - res['CC_SUPPORT_JIT'] = !(res['CC_WECHATGAME'] || res['CC_QQPLAY'] || res['CC_RUNTIME']); + res['CC_SUPPORT_JIT'] = !(res['CC_BAIDUGAME'] || res['CC_WECHATGAME'] || res['CC_QQPLAY'] || res['CC_RUNTIME']); return res; }; diff --git a/predefine.js b/predefine.js index 970ec54f507..b875e73439d 100644 --- a/predefine.js +++ b/predefine.js @@ -106,7 +106,7 @@ * @property {Boolean} CC_TEST - Running in the engine's unit test. */ /** - * @property {Boolean} CC_WECHATGAME - Running in the Wechat's mini game. + * @property {Boolean} CC_WECHATGAME - Running in the WeChat's mini game. */ /** * @property {Boolean} CC_QQPLAY - Running in the bricks. diff --git a/test/qunit/unit-es5/_init.js b/test/qunit/unit-es5/_init.js index 8e046b1ce61..1de2e837e65 100644 --- a/test/qunit/unit-es5/_init.js +++ b/test/qunit/unit-es5/_init.js @@ -211,9 +211,8 @@ function _resetGame (w, h) { } // Forbid render in test cc.renderer.render = function () {}; - cc.director.purgeDirector(); cc.loader.releaseAll(); - + cc.director.reset(); cc.director.runSceneImmediate(new cc.Scene()); //cc.director.pause(); } diff --git a/test/qunit/unit-es5/test-spriteRenderer.js b/test/qunit/unit-es5/test-spriteRenderer.js index effca1ff55f..96e215b378e 100644 --- a/test/qunit/unit-es5/test-spriteRenderer.js +++ b/test/qunit/unit-es5/test-spriteRenderer.js @@ -1,6 +1,13 @@ largeModule('Sprite'); +var originalAssembler = cc.Sprite._assembler; +var originalCalDynamicAtlas = cc.Sprite.prototype._calDynamicAtlas; + test('basic test', function () { + // + cc.Sprite._assembler = cc._Test._spriteWebGLAssembler; + cc.Sprite.prototype._calDynamicAtlas = function () {}; + var url = assetDir + '/button.png'; var node = new cc.Node(); @@ -143,8 +150,8 @@ if (!isPhantomJS) { var vertices = sprite._renderData._data; var uvs = sprite._spriteFrame.uvSliced; - strictEqual(uvs.length == 16, true, 'have 16 uvs'); - strictEqual(vertices.length == 20, true, 'have 20 vertices'); + strictEqual(uvs.length === 16, true, 'have 16 uvs'); + strictEqual(vertices.length === 20, true, 'have 20 vertices'); strictEqual(vertices[4].x, 0, 'x0 test success'); strictEqual(vertices[4].y, 0, 'y0 test success'); strictEqual(vertices[9].x, 5, 'x1 test success'); @@ -192,7 +199,7 @@ if (!isPhantomJS) { var vertices = sprite._renderData._data; var uvs = sprite._spriteFrame.uv; - strictEqual(vertices.length == 8, true, 'have 8 vertices'); + strictEqual(vertices.length === 8, true, 'have 8 vertices'); strictEqual(vertices[0].x, 0, 'x0 test success'); strictEqual(vertices[1].x, 40, 'x1 test success'); strictEqual(vertices[2].x, 80, 'x2 test success'); @@ -361,6 +368,10 @@ if (!isPhantomJS) { deepClose(vertices[4].y, p1.y, 0.01, 'p1 test success'); deepClose(vertices[5].x, p2.x, 0.01, 'p2 test success'); deepClose(vertices[5].y, p2.y, 0.01, 'p2 test success'); + + // + cc.Sprite._assembler = originalAssembler; + cc.Sprite.prototype._calDynamicAtlas = originalCalDynamicAtlas; }; if (spriteFrame.textureLoaded()) { testCallBack(); diff --git a/test/qunit/unit-es5/test-tween.js b/test/qunit/unit-es5/test-tween.js new file mode 100644 index 00000000000..7e40fab8645 --- /dev/null +++ b/test/qunit/unit-es5/test-tween.js @@ -0,0 +1,149 @@ +largeModule('Tween', SetupEngine); + +var tween = cc.tween; +// init a new node +function initNode(name) { + var node = new cc.Node(); + node.name = name; + node.position = cc.v2(0, 0); + node.scale = 1; + node.anchorX = 0.5; + node.anchorY = 0.5; + node.width = 100; + node.height = 100; + node.rotation = 0; + return node; +} + +asyncTest('basic test', function () { + cc.game.resume(); + var node1 = initNode('node1'); + tween(node1) + .to(1, { scale: 2 }) + .call(function () { + strictEqual(node1.scale, 2, 'tween to scale'); + }) + .by(1, { scale: 2 }) + .call(function () { + strictEqual(node1.scale, 4, 'tween by scale'); + start(); + }) + .start(); + + var obj = { a: 0 }; + tween(obj) + .to(0.5, { a: 100 }) + .call(function () { + strictEqual(obj.a, 100, 'Object propertype test'); + }) + .start(); + + var node2 = initNode('node2'); + var node3 = initNode('node3'); + let count = 0; + function check() { + if (node2.scale !== 1 && node3.scale !== 1) { + count++; + if (count === 2) { + strictEqual(node2.scale, 2, 'run tween on different target: node2'); + strictEqual(node3.scale, 2, 'run tween on different target: node3'); + } + } + } + var tmpTween = tween().to(0.5, { scale: 2 }).call(check); + // run tween on different target + tmpTween.clone(node2).start(); + tmpTween.clone(node3).start(); +}); + +function actionUpdate(action, node, t) { + if (action._actions.length <= 0) return; + let actions = action._actions; + for (let i = 0; i < actions.length; i++) { + actions[i].startWithTarget(node); + // The range of t is 0 ~ 1 + actions[i].update(t); + } +} + +test('ease test', function () { + cc.game.resume(); + // builtin easing + var node = initNode('easeNode'); + let action = tween(node).to(0.1, { scale: 2 }, { easing: 'sineOutIn' }); + actionUpdate(action, node, 0.5); + deepEqual(node.scale, 1.5, 'easeing can set value'); + + // custom easing + node.scale = 1; + action = tween(node).to(0.1, { scale: 2 }, { easing: function (t) { return t * t; } }); + actionUpdate(action, node, 0.9); + deepEqual(node.scale, 1.81, 'easeing can set calculation equation.'); + + // easing to single property + node.scale = 1; + action = tween(node) + .to(0.5, { + scale: 2, + position: { + value: cc.v2(100, 100), + easing: 'sineOutIn' + } + }); + actionUpdate(action, node, 1 / 6.0); + deepClose(node.scale, 1 + (1 / 6.0), 0.01, 'easeing can set multiple value: scale'); + deepClose(node.position, cc.v2(25, 25), 0.01, 'easeing can set multiple value: position'); + +}); + +asyncTest('progress test', function () { + cc.game.resume(); + var node = initNode('progressNode'); + // custom property progress + tween(node) + .to(0.1, { scale: 2 }, { + progress: function (start, end, current, t) { + return start + (end - start) * t; + } + }) + .call(function () { strictEqual(node.scale, 2, 'tween can set progress property'); }) + .start(); + // custom property progress to single property + node.scale = 1; + tween(node) + .to(0.5, { + scale: 2, + position: { + value: cc.v2(100, 100), + progress: function (start, end, current, t) { + return start.lerp(end, t, current); + } + } + }) + .call(function () { + strictEqual(node.scale, 2, 'custom property progress: scale not setting'); + deepEqual(node.position, cc.v2(100, 100), 'custom property progress to single property: position'); + start(); + }) + .start(); +}); + +asyncTest('reuse test', function () { + cc.game.resume(); + var scale = tween().to(0.5, { scale: 2 }); + var angle = tween().to(0.5, { rotation: 90 }); + var position = tween().to(0.5, { position: cc.v2(100, 100) }); + + var node = initNode('reuseNode'); + tween(node) + .then(scale) + .then(angle) + .then(position) + .call(function () { + strictEqual(node.scale, 2, 'reuse check: scale'); + strictEqual(node.rotation, 90, 'reuse check: rotation'); + deepEqual(node.position, cc.v2(100, 100), 'reuse check: postion'); + start(); + }) + .start(); +}); \ No newline at end of file From e6a0b608d5785b6a513f6bfb7c155f15c945e7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=BA=E6=98=8E?= Date: Mon, 11 Mar 2019 17:04:09 +0800 Subject: [PATCH 0510/1631] use image.src to release image cache on native platform (#3992) --- cocos2d/core/assets/CCTexture2D.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 86aac6f52c8..4b4bd0a2be2 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -736,9 +736,10 @@ var Texture2D = cc.Class({ _clearImage () { // wechat game platform will cache image parsed data, // so image will consume much more memory than web, releasing it - this._image.src = ""; // Release image in loader cache - cc.loader.removeItem(this._image.id); + // native image element has not image.id, release by image.src. + cc.loader.removeItem(this._image.id || this._image.src); + this._image.src = ""; } }); From c2b82b3141a7e9dd7b00dda6ef702d65817cae8d Mon Sep 17 00:00:00 2001 From: "yufang.wu" <2435731537@qq.com> Date: Tue, 12 Mar 2019 10:28:30 +0800 Subject: [PATCH 0511/1631] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20button=20API=20?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=8E=92=E7=89=88=E9=94=99=E8=AF=AF=20(#4003?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cocos2d/core/components/CCButton.js | 41 ++++++++++++++++------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/cocos2d/core/components/CCButton.js b/cocos2d/core/components/CCButton.js index 5bb8448a7ca..f26eda87fc0 100644 --- a/cocos2d/core/components/CCButton.js +++ b/cocos2d/core/components/CCButton.js @@ -85,27 +85,32 @@ const State = cc.Enum({ * User can get the current clicked node with 'event.target' from event object which is passed as parameter in the callback function of click event. * * !#zh - * 按钮组件。可以被按下,或者点击。
+ * 按钮组件。可以被按下,或者点击。 * - * 按钮可以通过修改 Transition 来设置按钮状态过渡的方式:
- * -Button.Transition.NONE // 不做任何过渡
- * -Button.Transition.COLOR // 进行颜色之间过渡
- * -Button.Transition.SPRITE // 进行精灵之间过渡
- * -Button.Transition.SCALE // 进行缩放过渡
+ * 按钮可以通过修改 Transition 来设置按钮状态过渡的方式: + * + * - Button.Transition.NONE // 不做任何过渡 + * - Button.Transition.COLOR // 进行颜色之间过渡 + * - Button.Transition.SPRITE // 进行精灵之间过渡 + * - Button.Transition.SCALE // 进行缩放过渡 * * 按钮可以绑定事件(但是必须要在按钮的 Node 上才能绑定事件):
- * // 以下事件可以在全平台上都触发
- * -cc.Node.EventType.TOUCH_START // 按下时事件
- * -cc.Node.EventType.TOUCH_Move // 按住移动后事件
- * -cc.Node.EventType.TOUCH_END // 按下后松开后事件
- * -cc.Node.EventType.TOUCH_CANCEL // 按下取消事件
- * // 以下事件只在 PC 平台上触发
- * -cc.Node.EventType.MOUSE_DOWN // 鼠标按下时事件
- * -cc.Node.EventType.MOUSE_MOVE // 鼠标按住移动后事件
- * -cc.Node.EventType.MOUSE_ENTER // 鼠标进入目标事件
- * -cc.Node.EventType.MOUSE_LEAVE // 鼠标离开目标事件
- * -cc.Node.EventType.MOUSE_UP // 鼠标松开事件
- * -cc.Node.EventType.MOUSE_WHEEL // 鼠标滚轮事件
+ * 以下事件可以在全平台上都触发: + * + * - cc.Node.EventType.TOUCH_START // 按下时事件 + * - cc.Node.EventType.TOUCH_Move // 按住移动后事件 + * - cc.Node.EventType.TOUCH_END // 按下后松开后事件 + * - cc.Node.EventType.TOUCH_CANCEL // 按下取消事件 + * + * 以下事件只在 PC 平台上触发: + * + * - cc.Node.EventType.MOUSE_DOWN // 鼠标按下时事件 + * - cc.Node.EventType.MOUSE_MOVE // 鼠标按住移动后事件 + * - cc.Node.EventType.MOUSE_ENTER // 鼠标进入目标事件 + * - cc.Node.EventType.MOUSE_LEAVE // 鼠标离开目标事件 + * - cc.Node.EventType.MOUSE_UP // 鼠标松开事件 + * - cc.Node.EventType.MOUSE_WHEEL // 鼠标滚轮事件 + * * 用户可以通过获取 __点击事件__ 回调函数的参数 event 的 target 属性获取当前点击对象。 * @class Button * @extends Component From 283fa2f1cbd776cff59ac55cff70533cd7706646 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 12 Mar 2019 11:11:46 +0800 Subject: [PATCH 0512/1631] small improve light (#3964) --- cocos2d/core/3d/CCLightComponent.js | 103 +++++++++--------- .../renderer/build/chunks/shadow-mapping.inc | 87 --------------- 2 files changed, 50 insertions(+), 140 deletions(-) delete mode 100644 cocos2d/renderer/build/chunks/shadow-mapping.inc diff --git a/cocos2d/core/3d/CCLightComponent.js b/cocos2d/core/3d/CCLightComponent.js index 297776d2fb3..f63a5825efe 100644 --- a/cocos2d/core/3d/CCLightComponent.js +++ b/cocos2d/core/3d/CCLightComponent.js @@ -36,7 +36,7 @@ const { ccclass, menu, inspector, property, executeInEditMode } = require('../pl /** * !#en The light source type * - * !#ch 光源类型 + * !#zh 光源类型 * @static * @enum LightComponent.Type */ @@ -44,7 +44,7 @@ const LightType = Enum({ /** * !#en The direction of light * - * !#ch 平行光 + * !#zh 平行光 * @property DIRECTIONAL * @readonly * @type {Number} @@ -53,7 +53,7 @@ const LightType = Enum({ /** * !#en The point of light * - * !#ch 点光源 + * !#zh 点光源 * @property POINT * @readonly * @type {Number} @@ -62,7 +62,7 @@ const LightType = Enum({ /** * !#en The spot of light * - * !#ch 聚光灯 + * !#zh 聚光灯 * @property SPOT * @readonly * @type {Number} @@ -73,7 +73,7 @@ const LightType = Enum({ /** * !#en The shadow type * - * !#ch 阴影类型 + * !#zh 阴影类型 * @static * @enum LightComponent.ShadowType */ @@ -81,25 +81,25 @@ const LightShadowType = Enum({ /** * !#en No shadows * - * !#ch 阴影关闭 + * !#zh 阴影关闭 * @property NONE * @readonly * @type {Number} */ NONE: 0, - /** - * !#en Soft shadows - * - * !#ch 软阴影 - * @property SOFT - * @readonly - * @type {Number} - */ - SOFT: 1, + // /** + // * !#en Soft shadows + // * + // * !#zh 软阴影 + // * @property SOFT + // * @readonly + // * @type {Number} + // */ + // SOFT: 1, /** * !#en Hard shadows * - * !#ch 阴硬影 + * !#zh 阴硬影 * @property HARD * @readonly * @type {Number} @@ -110,7 +110,7 @@ const LightShadowType = Enum({ /** * !#en The Light Component * - * !#ch 光源组件 + * !#zh 光源组件 * @class LightComponent * @extends CCComponent */ @@ -150,23 +150,21 @@ export default class LightComponent extends CCComponent { _shadowMinDepth = 1; @property - _shadowMaxDepth = 1000; + _shadowMaxDepth = 4096; @property _shadowDepthScale = 250; @property - _shadowFrustumSize = 50; + _shadowFrustumSize = 1024; @property _shadowBias = 0.0005; /** - * !#en The light source type - * - * !#ch 光源类型 - * - * @type {Number} + * !#en The light source type,currently we have directional, point, spot three type. + * !#zh 光源类型,目前有 平行光,聚光灯,点光源 三种类型 + * @type {LightType} */ @property({ type: LightType @@ -189,8 +187,7 @@ export default class LightComponent extends CCComponent { /** * !#en The light source color - * - * !#ch 光源颜色 + * !#zh 光源颜色 * @type {Color} */ @property @@ -206,7 +203,7 @@ export default class LightComponent extends CCComponent { /** * !#en The light source intensity * - * !#ch 光源强度 + * !#zh 光源强度 * @type {Number} */ @property @@ -222,7 +219,7 @@ export default class LightComponent extends CCComponent { /** * !#en The light range, used for spot and point light * - * !#ch 针对聚光灯和点光源设置光源范围 + * !#zh 针对聚光灯和点光源设置光源范围 * @type {Number} */ @property @@ -238,7 +235,7 @@ export default class LightComponent extends CCComponent { /** * !#en The spot light cone angle * - * !#ch 聚光灯锥角 + * !#zh 聚光灯锥角 * @type {Number} */ @property @@ -254,7 +251,7 @@ export default class LightComponent extends CCComponent { /** * !#en The spot light exponential * - * !#ch 聚光灯指数 + * !#zh 聚光灯指数 * @type {Number} */ @property @@ -270,7 +267,7 @@ export default class LightComponent extends CCComponent { /** * !#en The shadow type * - * !#ch 阴影类型 + * !#zh 阴影类型 * @type {Number} shadowType */ @property({ @@ -295,7 +292,7 @@ export default class LightComponent extends CCComponent { /** * !#en The shadow resolution * - * !#ch 阴影分辨率 + * !#zh 阴影分辨率 * * @type {Number} */ @@ -312,7 +309,7 @@ export default class LightComponent extends CCComponent { /** * !#en The shadow darkness * - * !#ch 阴影灰度值 + * !#zh 阴影灰度值 * * @type {Number} */ @@ -329,7 +326,7 @@ export default class LightComponent extends CCComponent { /** * !#en The shadow min depth * - * !#ch 阴影最小深度 + * !#zh 阴影最小深度 * * @type {Number} */ @@ -346,7 +343,7 @@ export default class LightComponent extends CCComponent { /** * !#en The shadow max depth * - * !#ch 阴影最大深度 + * !#zh 阴影最大深度 * * @type {Number} */ @@ -363,7 +360,7 @@ export default class LightComponent extends CCComponent { /** * !#en The shadow depth scale * - * !#ch 阴影深度比例 + * !#zh 阴影深度比例 * * @type {Number} */ @@ -380,7 +377,7 @@ export default class LightComponent extends CCComponent { /** * !#en The shadow frustum size * - * !#ch 阴影截锥体大小 + * !#zh 阴影截锥体大小 * * @type {Number} */ @@ -394,22 +391,22 @@ export default class LightComponent extends CCComponent { this._light.setShadowFrustumSize(val); } - /** - * !#en The shadow bias - * - * !#ch 阴影偏移量 - * - * @type {Number} - */ - @property - get shadowBias() { - return this._shadowBias; - } - - set shadowBias(val) { - this._shadowBias = val; - this._light.setShadowBias(val); - } + // /** + // * !#en The shadow bias + // * + // * !#zh 阴影偏移量 + // * + // * @type {Number} + // */ + // @property + // get shadowBias() { + // return this._shadowBias; + // } + + // set shadowBias(val) { + // this._shadowBias = val; + // this._light.setShadowBias(val); + // } static Type = LightType; diff --git a/cocos2d/renderer/build/chunks/shadow-mapping.inc b/cocos2d/renderer/build/chunks/shadow-mapping.inc deleted file mode 100644 index 4824d0e07d1..00000000000 --- a/cocos2d/renderer/build/chunks/shadow-mapping.inc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -#if _NUM_SHADOW_LIGHTS > 0 - #pragma for id in range(0, _NUM_SHADOW_LIGHTS) - uniform sampler2D _shadowMap_{id}; - uniform float _darkness_{id}; - uniform float _depthScale_{id}; - uniform float _frustumEdgeFalloff_{id}; - uniform float _bias_{id}; - uniform vec2 _texelSize_{id}; - varying vec4 pos_lightspace_{id}; - varying float vDepth_{id}; - #pragma endFor -#endif - - -float computeFallOff(float esm, vec2 coords, float frustumEdgeFalloff) { - float mask = smoothstep(1.0 - frustumEdgeFalloff, 1.0, clamp(dot(coords, coords), 0.0, 1.0)); - return mix(esm, 1.0, mask); -} - -// unused for float precision issue. -// float computeShadowESM_Unused() { -// vec2 projCoords = pos_lightspace.xy / pos_lightspace.w; -// vec2 shadowUV = projCoords * 0.5 + vec2(0.5); -// if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) { -// return 1.0; -// } -// float currentDepth = clamp(vDepth, 0.0, 1.0); -// float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, shadowUV)); -// float esm = 1.0 - clamp(exp(min(87.0, depthScale * currentDepth)) * closestDepth, 0.0, darkness); -// return computeFallOff(esm, projCoords, frustumEdgeFalloff); -// } - -float computeShadowESM(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float depthScale, float darkness, float frustumEdgeFalloff) { - vec2 projCoords = pos_lightspace.xy / pos_lightspace.w; - vec2 shadowUV = projCoords * 0.5 + vec2(0.5); - if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) { - return 1.0; - } - float currentDepth = clamp(vDepth, 0.0, 1.0); - float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, shadowUV)); - //float esm = clamp(exp(min(87.0, -depthScale * (currentDepth - closestDepth))), 1.0 - darkness, 1.0); - float esm = clamp(exp(-depthScale * (currentDepth - closestDepth)), 1.0 - darkness, 1.0); - return computeFallOff(esm, projCoords, frustumEdgeFalloff); -} - -// float computeShadowPCF(sampler2D shadowMap, vec4 pos_lightspace, float vDepth, float darkness, vec2 texelSize, float frustumEdgeFalloff) { -// vec2 projCoords = pos_lightspace.xy / pos_lightspace.w; -// vec2 shadowUV = projCoords * 0.5 + vec2(0.5); -// if (shadowUV.x < 0.0 || shadowUV.x > 1.0 || shadowUV.y < 0.0 || shadowUV.y > 1.0) { -// return 1.0; -// } -// float currentDepth = clamp(vDepth, 0.0, 1.0); -// float visibility = 1.0; -// vec2 poissonDisk[4]; -// poissonDisk[0] = vec2(-0.94201624, -0.39906216); -// poissonDisk[1] = vec2(0.94558609, -0.76890725); -// poissonDisk[2] = vec2(-0.094184101, -0.92938870); -// poissonDisk[3] = vec2(0.34495938, 0.29387760); -// if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[0] * texelSize)) < currentDepth) visibility -= 0.25; -// if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[1] * texelSize)) < currentDepth) visibility -= 0.25; -// if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[2] * texelSize)) < currentDepth) visibility -= 0.25; -// if (unpackRGBAToDepth(texture2D(shadowMap, shadowUV + poissonDisk[3] * texelSize)) < currentDepth) visibility -= 0.25; - -// return computeFallOff(min(1.0, visibility + 1.0 - darkness), projCoords, frustumEdgeFalloff); -// } - - -float computeShadow(sampler2D shadowMap, vec4 pos_lightspace, float bias) { - vec3 projCoords = pos_lightspace.xyz / pos_lightspace.w; - projCoords = projCoords * 0.5 + 0.5; - float closestDepth = unpackRGBAToDepth(texture2D(shadowMap, projCoords.xy)); - float currentDepth = projCoords.z; - float shadow = (currentDepth - bias > closestDepth) ? 0.0 : 1.0; - return shadow; -} - -float computeShadow() { - float shadow = 1.0; - #if _NUM_SHADOW_LIGHTS > 0 - #pragma for id in range(0, _NUM_SHADOW_LIGHTS) - shadow *= computeShadowESM(_shadowMap_{id}, pos_lightspace_{id}, vDepth_{id}, _depthScale_{id}, _darkness_{id}, _frustumEdgeFalloff_{id}); - #pragma endFor - #endif - return shadow; -} From 6631d6840348fa3ea1a38452dd62ff02b2c0a5b2 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Tue, 12 Mar 2019 11:52:34 +0800 Subject: [PATCH 0513/1631] Fix native spine json file missing in android instant game platform and add global time scale field (#3999) * Fix native spine json file missing in android instant game platform * Add dragon bones and spine global time scale api and fix spine call setSkeletonData may throw error bug * Add dragon bones and spine global time scale api * add api document * Adapt to old api * update annotation --- extensions/dragonbones/ArmatureDisplay.js | 3 ++- extensions/dragonbones/index.js | 21 +++++++++++++++ extensions/spine/Skeleton.js | 32 +++++++++++------------ extensions/spine/editor/spine-meta.js | 28 ++------------------ extensions/spine/index.js | 19 ++++++++++++++ extensions/spine/skeleton-data.js | 4 +++ 6 files changed, 64 insertions(+), 43 deletions(-) diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index c4a7870cb0c..01dd21541a8 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -512,7 +512,8 @@ let ArmatureDisplay = cc.Class({ this._eventTarget && this._eventTarget.emit(dragonBones.EventObject.START); } - this._accTime += dt * this.timeScale; + let globalTimeScale = dragonBones.timeScale; + this._accTime += dt * this.timeScale * globalTimeScale; let frameIdx = Math.floor(this._accTime / totalTime * frameCount); if (frameIdx >= frameCount) { diff --git a/extensions/dragonbones/index.js b/extensions/dragonbones/index.js index 0c80dae8ee2..36683f3ca10 100644 --- a/extensions/dragonbones/index.js +++ b/extensions/dragonbones/index.js @@ -46,6 +46,27 @@ if (!CC_JSB) { if (_global.dragonBones !== undefined) { + /** + * !#en + * The global time scale of DragonBones. + * !#zh + * DragonBones 全局时间缩放率。 + * @example + * dragonBones.timeScale = 0.8; + */ + dragonBones._timeScale = 1.0; + Object.defineProperty(dragonBones, 'timeScale', { + get () { + return this._timeScale; + }, + set (value) { + this._timeScale = value; + let factory = this.CCFactory.getInstance(); + factory._dragonBones.clock.timeScale = value; + }, + configurable: true, + }); + dragonBones.DisplayType = { Image : 0, Armature : 1, diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 4eea89de3b1..fc0f4ceafa2 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -461,7 +461,18 @@ sp.Skeleton = cc.Class({ this.node.setContentSize(skeletonData.width, skeletonData.height); } + if (!CC_EDITOR) { + if (this._cacheMode === AnimationCacheMode.SHARED_CACHE) { + this._skeletonCache = SkeletonCache.sharedCache; + } else if (this._cacheMode === AnimationCacheMode.PRIVATE_CACHE) { + this._skeletonCache = new SkeletonCache; + } + } + if (this.isAnimationCached()) { + if (this.debugBones || this.debugSlots) { + cc.warn("Debug bones or slots is invalid in cached mode"); + } let skeletonInfo = this._skeletonCache.getSkeletonCache(this.skeletonData._uuid, skeletonData); this._skeleton = skeletonInfo.skeleton; this._clipper = skeletonInfo.clipper; @@ -549,8 +560,8 @@ sp.Skeleton = cc.Class({ * * @method setAnimationCacheMode * @param {AnimationCacheMode} cacheMode - * * @example - * armatureDisplay.setAnimationCacheMode(sp.Skeleton.AnimationCacheMode.SHARED_CACHE); + * @example + * skeleton.setAnimationCacheMode(sp.Skeleton.AnimationCacheMode.SHARED_CACHE); */ setAnimationCacheMode (cacheMode) { if (CC_JSB) return; @@ -574,6 +585,8 @@ sp.Skeleton = cc.Class({ if (CC_EDITOR) return; if (this.paused) return; + dt *= this.timeScale * sp.timeScale; + if (this.isAnimationCached()) { // Cache mode and has animation queue. @@ -609,7 +622,7 @@ sp.Skeleton = cc.Class({ this._listener && this._listener.start && this._listener.start(this._startEntry); } - this._accTime += dt * this.timeScale; + this._accTime += dt; let frameIdx = Math.floor(this._accTime / totalTime * frameCount); if (frameIdx >= frameCount) { @@ -639,7 +652,6 @@ sp.Skeleton = cc.Class({ if (skeleton) { skeleton.update(dt); if (state) { - dt *= this.timeScale; state.update(dt); state.apply(skeleton); } @@ -1202,18 +1214,6 @@ sp.Skeleton = cc.Class({ let data = this.skeletonData.getRuntimeData(); if (!data) return; - if (!CC_EDITOR) { - if (this._cacheMode === AnimationCacheMode.SHARED_CACHE) { - this._skeletonCache = SkeletonCache.sharedCache; - } else if (this._cacheMode === AnimationCacheMode.PRIVATE_CACHE) { - this._skeletonCache = new SkeletonCache; - } - } - - if (this.isAnimationCached() && (this.debugBones || this.debugSlots)) { - cc.warn("Debug bones or slots is invalid in cached mode"); - } - try { this.setSkeletonData(data); if (!this.isAnimationCached()) { diff --git a/extensions/spine/editor/spine-meta.js b/extensions/spine/editor/spine-meta.js index 8cd4383ffb4..21455c7ea19 100644 --- a/extensions/spine/editor/spine-meta.js +++ b/extensions/spine/editor/spine-meta.js @@ -116,7 +116,6 @@ class SpineMeta extends CustomAssetMeta { constructor (assetdb) { super(assetdb); this.textures = []; - this.atlas = ''; this.scale = 1; } @@ -130,7 +129,7 @@ class SpineMeta extends CustomAssetMeta { //this.textures[0] = value; } - static version () { return '1.2.0'; } + static version () { return '1.2.1'; } static defaultType () { return 'spine'; } @@ -159,16 +158,6 @@ class SpineMeta extends CustomAssetMeta { } return false; } - - dests () { - var res = super.dests(); - // for JSB - res.push(Path.join(this._assetdb._uuidToImportPathNoExt(this.uuid), RAW_SKELETON_FILE)); - if (this.atlas) { - res.push(this._assetdb.uuidToFspath(this.atlas)); - } - return res; - } postImport (fspath, cb) { Fs.readFile(fspath, SPINE_ENCODING, (err, data) => { @@ -187,6 +176,7 @@ class SpineMeta extends CustomAssetMeta { var asset = new sp.SkeletonData(); asset.name = Path.basenameNoExt(fspath); asset.skeletonJson = json; + asset.skeletonJsonStr = data; asset.scale = this.scale; loadAtlasText(fspath, (err, res) => { @@ -209,21 +199,7 @@ class SpineMeta extends CustomAssetMeta { this.textures = textureParser.textures; asset.textures = textureParser.textures.map(Editor.serialize.asAsset); asset.textureNames = textureParser.textureNames; - // asset.atlasText = res.data; - - // save raw assets for JSB.. - - db.mkdirForAsset(this.uuid); - var rawJsonPath = Path.join(db._uuidToImportPathNoExt(this.uuid), RAW_SKELETON_FILE); - Fs.copySync(fspath, rawJsonPath); - asset._setRawAsset(RAW_SKELETON_FILE); - - var atlasUuid = db.fspathToUuid(res.atlasPath); - this.atlas = atlasUuid; // save for dest() - - // - db.saveAssetToLibrary(this.uuid, asset); cb(); }); diff --git a/extensions/spine/index.js b/extensions/spine/index.js index 0d7cf499b9d..216ae412ea6 100644 --- a/extensions/spine/index.js +++ b/extensions/spine/index.js @@ -51,6 +51,25 @@ if (CC_JSB && _global.spine === undefined) { if (_isUseSpine) { _global.sp = {}; + /** + * !#en + * The global time scale of Spine. + * !#zh + * Spine 全局时间缩放率。 + * @example + * sp.timeScale = 0.8; + */ + sp._timeScale = 1.0; + Object.defineProperty(sp, 'timeScale', { + get () { + return this._timeScale; + }, + set (value) { + this._timeScale = value; + }, + configurable: true, + }); + // The attachment type of spine. It contains three type: REGION(0), BOUNDING_BOX(1), MESH(2) and SKINNED_MESH. sp.ATTACHMENT_TYPE = { REGION: 0, diff --git a/extensions/spine/skeleton-data.js b/extensions/spine/skeleton-data.js index ee59a9f22fa..129fc18e5ab 100644 --- a/extensions/spine/skeleton-data.js +++ b/extensions/spine/skeleton-data.js @@ -44,6 +44,8 @@ var SkeletonData = cc.Class({ properties: { + // store skeleton json string for jsb + skeletonJsonStr: "", _skeletonJson: null, /** @@ -57,6 +59,8 @@ var SkeletonData = cc.Class({ }, set: function (value) { this._skeletonJson = value; + // If dynamic set skeletonJson field, auto update skeletonJsonStr field. + this.skeletonJsonStr = JSON.stringify(value); this.reset(); } }, From 6dfbca8eaf690b34a16724cac6727f4fde9a20aa Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 12 Mar 2019 11:56:32 +0800 Subject: [PATCH 0514/1631] fixed depth state not right (#4005) --- cocos2d/core/camera/CCCamera.js | 6 +++--- cocos2d/core/renderer/render-engine.js | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cocos2d/core/camera/CCCamera.js b/cocos2d/core/camera/CCCamera.js index 76866cc19e5..acb4e737f74 100644 --- a/cocos2d/core/camera/CCCamera.js +++ b/cocos2d/core/camera/CCCamera.js @@ -203,7 +203,7 @@ let Camera = cc.Class({ set (value) { this._depth = value; if (this._camera) { - this._camera.setDepth(value); + this._camera._priority = value; } } }, @@ -291,7 +291,7 @@ let Camera = cc.Class({ camera.dirty = true; camera._cullingMask = camera.view._cullingMask = 1 << cc.Node.BuiltinGroupIndex.DEBUG; - camera.setDepth(cc.macro.MAX_ZINDEX); + camera._priority = cc.macro.MAX_ZINDEX; camera.setClearFlags(0); camera.setColor(0,0,0,0); @@ -343,7 +343,7 @@ let Camera = cc.Class({ if (this._camera) { this._camera.setNode(this.node); this._camera.setClearFlags(this._clearFlags); - this._camera.setDepth(this._depth); + this._camera._priority = this._depth; this._updateBackgroundColor(); this._updateCameraMask(); this._updateTargetTexture(); diff --git a/cocos2d/core/renderer/render-engine.js b/cocos2d/core/renderer/render-engine.js index 852a6bd8457..6700336d1c3 100644 --- a/cocos2d/core/renderer/render-engine.js +++ b/cocos2d/core/renderer/render-engine.js @@ -11071,6 +11071,9 @@ var Camera = function Camera() { // this._projection = enums.PROJ_PERSPECTIVE; + // priority. the smaller one will be rendered first + this._priority = 0; + // clear options this._color = color4.new(0.2, 0.3, 0.47, 1); this._depth = 1; @@ -13664,8 +13667,8 @@ var ForwardRenderer = (function (superclass) { this._reset(); scene._cameras.sort(function (a, b) { - if (a._depth > b._depth) { return 1; } - else if (a._depth < b._depth) { return -1; } + if (a._priority > b._priority) { return 1; } + else if (a._priority < b._priority) { return -1; } else { return 0; } }); From b9caa271c75fc32edea59c64961669ca79bb722b Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Tue, 12 Mar 2019 13:57:44 +0800 Subject: [PATCH 0515/1631] fix the typesetting problem of letter font. (#4007) * fix the typesetting problem of letter font. * remove calculated lineheight --- cocos2d/core/renderer/utils/label/letter-font.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/renderer/utils/label/letter-font.js b/cocos2d/core/renderer/utils/label/letter-font.js index af14d5c2899..a56f70bdf3f 100644 --- a/cocos2d/core/renderer/utils/label/letter-font.js +++ b/cocos2d/core/renderer/utils/label/letter-font.js @@ -84,8 +84,8 @@ LetterTexture.prototype = { this._context = this._data.context; this._context.font = this._labelInfo.fontDesc; let width = textUtils.safeMeasureText(this._context, this._char); - this._width = parseFloat(width.toFixed(2)) + 2 * this._labelInfo.margin; - this._height = this._labelInfo.lineHeight; + this._width = parseFloat(width.toFixed(2)); + this._height = this._labelInfo.fontSize; if (this._canvas.width !== this._width || CC_QQPLAY) { this._canvas.width = this._width; @@ -887,10 +887,10 @@ module.exports = { _letterOffsetY = _contentSize.height; break; case macro.VerticalTextAlignment.CENTER: - _letterOffsetY = (_contentSize.height + _textDesiredHeight) / 2; + _letterOffsetY = (_contentSize.height + _textDesiredHeight) / 2 - (_lineHeight - _fontSize) / 2; break; case macro.VerticalTextAlignment.BOTTOM: - _letterOffsetY = _textDesiredHeight; + _letterOffsetY = (_contentSize.height + _textDesiredHeight) / 2 - (_lineHeight - _fontSize); break; default: break; From eddc005dfbb85526232ebb9b6c650cdc5915e8e8 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Tue, 12 Mar 2019 13:59:06 +0800 Subject: [PATCH 0516/1631] save content using cc.Asset._nativeAsset.setter, add handler of '.bin' (#3935) * save content using cc.Asset._nativeAsset.setter, add handler of '.bin' * modified API:loadResDir, should not return all SpriteFrame of SpriteAtlas --- cocos2d/core/assets/CCAsset.js | 8 ++++++-- cocos2d/core/load-pipeline/CCLoader.js | 19 +------------------ cocos2d/core/load-pipeline/downloader.js | 1 + cocos2d/core/load-pipeline/loader.js | 1 + 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/cocos2d/core/assets/CCAsset.js b/cocos2d/core/assets/CCAsset.js index 12887a87a70..bcf0a50d2d4 100644 --- a/cocos2d/core/assets/CCAsset.js +++ b/cocos2d/core/assets/CCAsset.js @@ -119,8 +119,12 @@ cc.Asset = cc.Class({ * @private */ _nativeAsset: { - get () {}, - set (obj) {} + get () { + return this._$nativeAsset; + }, + set (obj) { + this._$nativeAsset = obj; + } }, }, diff --git a/cocos2d/core/load-pipeline/CCLoader.js b/cocos2d/core/load-pipeline/CCLoader.js index f9818b7d157..36a17fe2e95 100644 --- a/cocos2d/core/load-pipeline/CCLoader.js +++ b/cocos2d/core/load-pipeline/CCLoader.js @@ -655,24 +655,7 @@ proto.loadResDir = function (url, type, progressCallback, completeCallback) { var urls = []; var uuids = resources.getUuidArray(url, type, urls); - this._loadResUuids(uuids, progressCallback, function (errors, assetRes, urlRes) { - // The spriteFrame url in spriteAtlas will be removed after build project - // To show users the exact structure in asset panel, we need to return the spriteFrame assets in spriteAtlas - let assetResLength = assetRes.length; - for (let i = 0; i < assetResLength; ++i) { - if (assetRes[i] instanceof cc.SpriteAtlas) { - let spriteFrames = assetRes[i].getSpriteFrames(); - for (let k in spriteFrames) { - let sf = spriteFrames[k]; - assetRes.push(sf); - if (urlRes) { - urlRes.push(`${urlRes[i]}/${sf.name}`); - } - } - } - } - completeCallback && completeCallback(errors, assetRes, urlRes); - }, urls); + this._loadResUuids(uuids, progressCallback, completeCallback, urls); }; /** diff --git a/cocos2d/core/load-pipeline/downloader.js b/cocos2d/core/load-pipeline/downloader.js index d95f5cc4d26..fcad40a5952 100644 --- a/cocos2d/core/load-pipeline/downloader.js +++ b/cocos2d/core/load-pipeline/downloader.js @@ -184,6 +184,7 @@ var defaultMap = { // Binary 'binary' : downloadBinary, + 'bin': downloadBinary, 'dbbin' : downloadBinary, 'default' : downloadText diff --git a/cocos2d/core/load-pipeline/loader.js b/cocos2d/core/load-pipeline/loader.js index 1d45a3227ee..ddd3714e4c8 100644 --- a/cocos2d/core/load-pipeline/loader.js +++ b/cocos2d/core/load-pipeline/loader.js @@ -143,6 +143,7 @@ var defaultMap = { // binary 'binary' : loadBinary, 'dbbin' : loadBinary, + 'bin' : loadBinary, // Font 'font' : fontLoader.loadFont, From a9e8179eb22d37b00cf805ded08ed5641dafb1fd Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Tue, 12 Mar 2019 14:50:10 +0800 Subject: [PATCH 0517/1631] Fix change to edit prefab and back, will throw error (#4008) * Fix change to edit prefab and back, will throw error * modify code style --- extensions/dragonbones/ArmatureDisplay.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/extensions/dragonbones/ArmatureDisplay.js b/extensions/dragonbones/ArmatureDisplay.js index 01dd21541a8..7e5980baa85 100644 --- a/extensions/dragonbones/ArmatureDisplay.js +++ b/extensions/dragonbones/ArmatureDisplay.js @@ -451,6 +451,14 @@ let ArmatureDisplay = cc.Class({ this._updateDebugDraw(); }, + onRestore () { + // Destroyed and restored in Editor + if (!this._material) { + this._material = new SpriteMaterial(); + this._materialCache = {}; + } + }, + /** * !#en * It's best to set cache mode before set property 'dragonAsset', or will waste some cpu time. From 3f4709908f6867e773907ddc9694554e55929f94 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 12 Mar 2019 14:57:49 +0800 Subject: [PATCH 0518/1631] improve cc.Tween (#3984) * improve cc.Tween * refine code --- cocos2d/actions/tween.js | 169 +++++++++++++++++++++++++++++++-------- 1 file changed, 136 insertions(+), 33 deletions(-) diff --git a/cocos2d/actions/tween.js b/cocos2d/actions/tween.js index d9761cfd93b..855ad4bab8a 100644 --- a/cocos2d/actions/tween.js +++ b/cocos2d/actions/tween.js @@ -13,6 +13,8 @@ let TweenAction = cc.Class({ opts.easing = cc.easing[opts.easing]; } + let relative = this._opts.relative; + for (let name in props) { let value = props[name]; @@ -25,7 +27,7 @@ let TweenAction = cc.Class({ } let isNumber = typeof value === 'number'; - if (!isNumber && (!value.lerp || (!value.add && !value.mul) || !value.clone)) { + if (!isNumber && (!value.lerp || (relative && !value.add && !value.mul) || !value.clone)) { cc.warn(`Can not animate ${name} property, because it do not have [lerp, (add|mul), clone] function.`); continue; } @@ -55,7 +57,7 @@ let TweenAction = cc.Class({ for (let name in props) { let value = target[name]; let prop = props[name]; - + if (typeof value === 'number') { prop.start = value; prop.current = value; @@ -76,7 +78,7 @@ let TweenAction = cc.Class({ let target = this.target; if (!target) return; - + let props = this._props; let progress = this._opts.progress; for (let name in props) { @@ -98,6 +100,37 @@ let TweenAction = cc.Class({ } }); +let SetAction = cc.Class({ + name: 'cc.SetAction', + extends: cc.ActionInstant, + + ctor (props) { + this._props = {}; + props !== undefined && this.init(props); + }, + + init (props) { + for (let name in props) { + this._props[name] = props[name]; + } + return true; + }, + + update () { + let props = this._props; + let target = this.target; + for (let name in props) { + target[name] = props[name]; + } + }, + + clone () { + var action = new SetAction(); + action.init(this._props); + return action; + } +}); + /** @@ -137,26 +170,26 @@ function Tween (target) { * 插入一个 action 或者 tween 到队列中 * @method then * @param {Action|Tween} other + * @return {Tween} */ Tween.prototype.then = function (other) { if (other instanceof cc.Action) { this._actions.push(other.clone()); } else { - let actions = other._actions; - for (let i = 0; i < actions.length; i++) { - this._actions.push(actions[i].clone()); - } + this._actions.push(other._union()); } return this; }; + /** * !#en * Set tween target * !#zh * 设置 tween 的 target * @method target + * @return {Tween} */ Tween.prototype.target = function (target) { this._target = target; @@ -169,15 +202,17 @@ Tween.prototype.target = function (target) { * !#zh * 运行当前 tween * @method start + * @return {Tween} */ Tween.prototype.start = function () { if (!this._target) { cc.warn('Please set target to tween first'); return this; } - if (!this._finalAction) { - this._finalAction = this._get(); + if (this._finalAction) { + cc.director.getActionManager().removeAction(this._finalAction); } + this._finalAction = this._union(); cc.director.getActionManager().addAction(this._finalAction, this._target, false); return this; }; @@ -188,6 +223,7 @@ Tween.prototype.start = function () { * !#zh * 停止当前 tween * @method stop + * @return {Tween} */ Tween.prototype.stop = function () { if (this._finalAction) { @@ -205,19 +241,28 @@ Tween.prototype.stop = function () { * 克隆当前 tween * @method clone * @param {Object} [target] + * @return {Tween} */ Tween.prototype.clone = function (target) { - let action = this._get(); + let action = this._union(); return cc.tween(target).then(action.clone()); }; /** * !#en - * Get an union action from current sequence + * Integrate all previous actions to an action. * !#zh - * 从当前队列中获取一个整合的 action + * 将之前所有的 action 整合为一个 action。 + * @return {Tween} */ -Tween.prototype._get = function () { +Tween.prototype.union = function () { + let action = this._union(); + this._actions.length = 0; + this._actions.push(action); + return this; +}; + +Tween.prototype._union = function () { let actions = this._actions; if (actions.length === 1) { @@ -230,6 +275,21 @@ Tween.prototype._get = function () { return actions; }; +let tmp_args = []; + +function wrapAction (action) { + return function () { + tmp_args.length = 0; + for (let l = arguments.length, i = 0; i < l; i++) { + let arg = tmp_args[i] = arguments[i]; + if (arg instanceof Tween) { + tmp_args[i] = arg._union(); + } + } + + return action.apply(this, tmp_args); + }; +} let actions = { /** @@ -243,6 +303,7 @@ let actions = { * @param {Object} opts * @param {Function} opts.progress * @param {Function|String} opts.easing + * @return {Tween} */ to (duration, props, opts) { opts = opts || Object.create(null); @@ -261,13 +322,27 @@ let actions = { * @param {Object} opts * @param {Function} opts.progress * @param {Function|String} opts.easing + * @return {Tween} */ by (duration, props, opts) { opts = opts || Object.create(null); opts.relative = true; return new TweenAction(duration, props, opts); }, - + + /** + * !#en + * Directly set target properties + * !#zh + * 直接设置 target 的属性 + * @method set + * @param {Object} props + * @return {Tween} + */ + set (props) { + return new SetAction(props); + }, + /** * !#en * Add an delay action @@ -275,6 +350,7 @@ let actions = { * 添加一个延时 action * @method delay * @param {Number} duration + * @return {Tween} */ delay: cc.delayTime, /** @@ -284,6 +360,7 @@ let actions = { * 添加一个回调 action * @method call * @param {Function} callback + * @return {Tween} */ call: cc.callFunc, /** @@ -292,6 +369,7 @@ let actions = { * !#zh * 添加一个隐藏 action * @method hide + * @return {Tween} */ hide: cc.hide, /** @@ -300,6 +378,7 @@ let actions = { * !#zh * 添加一个显示 action * @method show + * @return {Tween} */ show: cc.show, /** @@ -308,6 +387,7 @@ let actions = { * !#zh * 添加一个移除自己 action * @method removeSelf + * @return {Tween} */ removeSelf: cc.removeSelf, /** @@ -316,21 +396,33 @@ let actions = { * !#zh * 添加一个队列 action * @method sequence - * @param {[Action]} actions + * @param {[Action|Tween]} actions + * @return {Tween} */ - sequence: cc.sequence, + sequence: wrapAction(cc.sequence), + /** + * !#en + * Add an parallel action + * !#zh + * 添加一个并行 action + * @method sequence + * @param {[Action|Tween]} actions + * @return {Tween} + */ + parallel: wrapAction(cc.spawn) }; -// these action should integrate before actions to a sequence action as their parameters -let otherActions = { +// these action will use previous action as their parameters +let previousAsInputActions = { /** * !#en * Add an repeat action. * This action will integrate before actions to a sequence action as their parameters. * !#zh - * 添加一个重复 action,这个 action 会将之前的 action 整合成一个 sequence action 作为他的参数。 + * 添加一个重复 action,这个 action 会将前一个动作作为他的参数。 * @method repeat * @param {Number} repeatTimes + * @return {Tween} */ repeat: cc.repeat, /** @@ -338,8 +430,9 @@ let otherActions = { * Add an repeat forever action * This action will integrate before actions to a sequence action as their parameters. * !#zh - * 添加一个永久重复 action,这个 action 会将之前的 action 整合成一个 sequence action 作为他的参数。 + * 添加一个永久重复 action,这个 action 会将前一个动作作为他的参数。 * @method repeatForever + * @return {Tween} */ repeatForever: cc.repeatForever, /** @@ -347,40 +440,50 @@ let otherActions = { * Add an reverse time action. * This action will integrate before actions to a sequence action as their parameters. * !#zh - * 添加一个倒置时间 action,这个 action 会将之前的 action 整合成一个 sequence action 作为他的参数。 + * 添加一个倒置时间 action,这个 action 会将前一个动作作为他的参数。 * @method reverseTime + * @return {Tween} */ reverseTime: cc.reverseTime, }; + let keys = Object.keys(actions); for (let i = 0; i < keys.length; i++) { let key = keys[i]; Tween.prototype[key] = function () { let action = actions[key].apply(actions, arguments); this._actions.push(action); - this._finalAction = null; return this; }; } -keys = Object.keys(otherActions); +keys = Object.keys(previousAsInputActions); for (let i = 0; i < keys.length; i++) { let key = keys[i]; Tween.prototype[key] = function () { - let args = []; - for (let l = arguments.length, i = 0; i < l; i++) { - args[i] = arguments[i]; - } + let actions = this._actions; let action = arguments[0]; - if (!(action instanceof cc.Action)) { - action = this._get(); + let i = 1; + + if (action instanceof cc.Tween) { + action = action._union(); } - action = otherActions[key].apply(otherActions, [action].concat(args)); - this._actions.length = 0; - this._actions.push(action); - this._finalAction = null; + else if (!(action instanceof cc.Action)) { + action = actions[actions.length - 1]; + actions.length -= 1; + i = 0; + } + + let args = [action]; + for (let l = arguments.length; i < l; i++) { + args.push(arguments[i]); + } + + action = previousAsInputActions[key].apply(this, args); + actions.push(action); + return this; }; } From 33d25c6ab7969de53f0463bc5b6412224e625609 Mon Sep 17 00:00:00 2001 From: mac <1053210246@qq.com> Date: Tue, 12 Mar 2019 15:53:45 +0800 Subject: [PATCH 0519/1631] Fix resources field unit test failed --- cocos2d/core/load-pipeline/CCLoader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/load-pipeline/CCLoader.js b/cocos2d/core/load-pipeline/CCLoader.js index 77e2ccf42ff..a62afd9d08f 100644 --- a/cocos2d/core/load-pipeline/CCLoader.js +++ b/cocos2d/core/load-pipeline/CCLoader.js @@ -683,7 +683,7 @@ proto.loadResDir = function (url, type, mount, progressCallback, completeCallbac completeCallback = args.onComplete; var urls = []; - var uuids = resources.getUuidArray(url, type, urls); + var uuids = assetTables[mount].getUuidArray(url, type, urls); this._loadResUuids(uuids, progressCallback, completeCallback, urls); }; From 54f5c16bcf37521a49e63684fbda4ac1fc10380b Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 12 Mar 2019 18:37:49 +0800 Subject: [PATCH 0520/1631] update and deprecate some properties in CCEditBox (#3945) * update and deprecate some properties in CCEditBox * sync dom styleSheet with editbox.label styleSheet * update upgrading component * refine code * refine code again --- cocos2d/core/components/editbox/CCEditBox.js | 489 ++++++++++++------ .../core/components/editbox/WebEditBoxImpl.js | 157 +++++- editor/i18n/en/localization.js | 12 +- editor/i18n/zh/localization.js | 10 +- 4 files changed, 483 insertions(+), 185 deletions(-) diff --git a/cocos2d/core/components/editbox/CCEditBox.js b/cocos2d/core/components/editbox/CCEditBox.js index 01629005ab4..0464a8f2613 100644 --- a/cocos2d/core/components/editbox/CCEditBox.js +++ b/cocos2d/core/components/editbox/CCEditBox.js @@ -32,8 +32,6 @@ const InputMode = Types.InputMode; const InputFlag = Types.InputFlag; const KeyboardReturnType = Types.KeyboardReturnType; -const LEFT_PADDING = 2; - function capitalize (string) { return string.replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); }); } @@ -84,17 +82,81 @@ let EditBox = cc.Class({ }, /** - * !#en The background image of EditBox. - * !#zh 输入框的背景图片 + * !#en The Label component attached to the node for EditBox's input text label + * !#zh 输入框输入文本节点上挂载的 Label 组件对象 + * @property {Label} textLabel + */ + textLabel: { + tooltip: CC_DEV && 'i18n:COMPONENT.editbox.textLabel', + default: null, + type: Label, + notify (oldValue) { + if (this.textLabel && this.textLabel !== oldValue) { + this._updateTextLabel(); + this._updateLabels(); + } + }, + }, + + /** + * !en The Label component attached to the node for EditBox's placeholder text label + * !zh 输入框占位符节点上挂载的 Label 组件对象 + * @property {Label} placeholderLabel + */ + placeholderLabel: { + tooltip: CC_DEV && 'i18n:COMPONENT.editbox.placeholderLabel', + default: null, + type: Label, + notify (oldValue) { + if (this.placeholderLabel && this.placeholderLabel !== oldValue) { + this._updatePlaceholderLabel(); + this._updateLabels(); + } + }, + }, + + /** + * !#en The Sprite component attached to the node for EditBox's background + * !#zh 输入框背景节点上挂载的 Sprite 组件对象 + * @property {Sprite} background + */ + background: { + tooltip: CC_DEV && 'i18n:COMPONENT.editbox.background', + default: null, + type: cc.Sprite, + notify (oldValue) { + if (this.background && this.background !== oldValue) { + this._updateBackgroundSprite(); + } + }, + }, + + // To be removed in the future + _N$backgroundImage: { + default: undefined, + type: cc.spriteFrame, + }, + + /** + * !#en The background image of EditBox. This property will be removed in the future, use editBox.background instead please. + * !#zh 输入框的背景图片。 该属性会在将来的版本中移除,请用 editBox.background * @property {SpriteFrame} backgroundImage + * @deprecated since v2.1 */ backgroundImage: { - tooltip: CC_DEV && 'i18n:COMPONENT.editbox.backgroundImage', - default: null, - type: cc.SpriteFrame, - notify () { - this._createBackgroundSprite(); - } + get () { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.backgroundImage', 'editBox.background'); + if (!this.background) { + return null; + } + return this.background.spriteFrame; + }, + set (value) { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.backgroundImage', 'editBox.background'); + if (this.background) { + this.background.spriteFrame = value; + } + }, }, /** @@ -147,58 +209,97 @@ let EditBox = cc.Class({ tooltip: CC_DEV && 'i18n:COMPONENT.editbox.input_mode', default: InputMode.ANY, type: InputMode, - }, - - // To be removed in the future - _N$inputMode: { - default: undefined, - type: cc.Float, + notify (oldValue) { + if (this.inputMode !== oldValue) { + this._updateTextLabel(); + this._updatePlaceholderLabel(); + } + } }, /** - * !#en Font size of the input text. - * !#zh 输入框文本的字体大小 + * !#en Font size of the input text. This property will be removed in the future, use editBox.textLabel.fontSize instead please. + * !#zh 输入框文本的字体大小。 该属性会在将来的版本中移除,请使用 editBox.textLabel.fontSize。 * @property {Number} fontSize + * @deprecated since v2.1 */ fontSize: { - tooltip: CC_DEV && 'i18n:COMPONENT.editbox.font_size', - default: 20, - notify () { - if (this._textLabel) { - this._textLabel.fontSize = this.fontSize; + get () { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.fontSize', 'editBox.textLabel.fontSize'); + if (!this.textLabel) { + return null; } - } + return this.textLabel.fontSize; + }, + set (value) { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.fontSize', 'editBox.textLabel.fontSize'); + if (this.textLabel) { + this.textLabel.fontSize = value; + } + }, + }, + + // To be removed in the future + _N$fontSize: { + default: undefined, + type: cc.Float, }, /** - * !#en Change the lineHeight of displayed text. - * !#zh 输入框文本的行高。 + * !#en Change the lineHeight of displayed text. This property will be removed in the future, use editBox.textLabel.lineHeight instead. + * !#zh 输入框文本的行高。该属性会在将来的版本中移除,请使用 editBox.textLabel.lineHeight * @property {Number} lineHeight + * @deprecated since v2.1 */ lineHeight: { - tooltip: CC_DEV && 'i18n:COMPONENT.editbox.line_height', - default: 40, - notify () { - if (this._textLabel) { - this._textLabel.lineHeight = this.lineHeight; + get () { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.lineHeight', 'editBox.textLabel.lineHeight'); + if (!this.textLabel) { + return null; } - } + return this.textLabel.lineHeight; + }, + set (value) { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.lineHeight', 'editBox.textLabel.lineHeight'); + if (this.textLabel) { + this.textLabel.lineHeight = value; + } + }, + }, + + // To be removed in the future + _N$lineHeight: { + default: undefined, + type: cc.Float, }, /** - * !#en Font color of the input text. - * !#zh 输入框文本的颜色。 + * !#en Font color of the input text. This property will be removed in the future, use editBox.textLabel.node.color instead. + * !#zh 输入框文本的颜色。该属性会在将来的版本中移除,请使用 editBox.textLabel.node.color * @property {Color} fontColor + * @deprecated since v2.1 */ fontColor: { - tooltip: CC_DEV && 'i18n:COMPONENT.editbox.font_color', - default: cc.Color.WHITE, - notify () { - if (this._textLabel) { - this._textLabel.node.opacity = this.fontColor.a; - this._textLabel.node.color = this.fontColor; + get () { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.fontColor', 'editBox.textLabel.node.color'); + if (!this.textLabel) { + return null; } - } + return this.textLabel.node.color; + }, + set (value) { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.fontColor', 'editBox.textLabel.node.color'); + if (this.textLabel) { + this.textLabel.node.color = value; + this.textLabel.node.opacity = value.a; + } + }, + }, + + // To be removed in the future + _N$fontColor: { + default: undefined, + type: cc.Color, }, /** @@ -208,43 +309,80 @@ let EditBox = cc.Class({ */ placeholder: { tooltip: CC_DEV && 'i18n:COMPONENT.editbox.placeholder', - default: 'Enter text here...', - notify () { - if (this._placeholderLabel) { - this._placeholderLabel.string = this.placeholder; + get () { + if (!this.placeholderLabel) { + return ''; + } + return this.placeholderLabel.string; + }, + set (value) { + if (this.placeholderLabel) { + this.placeholderLabel.string = value; } } }, + // To be removed in the future + _N$placeholder: { + default: undefined, + type: cc.String, + }, + /** - * !#en The font size of placeholder. - * !#zh 输入框占位符的字体大小。 + * !#en The font size of placeholder. This property will be removed in the future, use editBox.placeholderLabel.fontSize instead. + * !#zh 输入框占位符的字体大小。该属性会在将来的版本中移除,请使用 editBox.placeholderLabel.fontSize * @property {Number} placeholderFontSize + * @deprecated since v2.1 */ placeholderFontSize: { - tooltip: CC_DEV && 'i18n:COMPONENT.editbox.placeholder_font_size', - default: 20, - notify () { - if (this._placeholderLabel) { - this._placeholderLabel.fontSize = this.placeholderFontSize; + get () { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.placeholderFontSize', 'editBox.placeholderLabel.fontSize'); + if (!this.placeholderLabel) { + return null; } - } + return this.placeholderLabel.fontSize; + }, + set (value) { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.placeholderFontSize', 'editBox.placeholderLabel.fontSize'); + if (this.placeholderLabel) { + this.placeholderLabel.fontSize = value; + } + }, + }, + + // To be removed in the future + _N$placeholderFontSize: { + default: undefined, + type: cc.Float, }, /** - * !#en The font color of placeholder. - * !#zh 输入框占位符的字体颜色。 + * !#en The font color of placeholder. This property will be removed in the future, use editBox.placeholderLabel.node.color instead. + * !#zh 输入框占位符的字体颜色。该属性会在将来的版本中移除,请使用 editBox.placeholderLabel.node.color * @property {Color} placeholderFontColor + * @deprecated since v2.1 */ placeholderFontColor: { - tooltip: CC_DEV && 'i18n:COMPONENT.editbox.placeholder_font_color', - default: cc.Color.GRAY, - notify () { - if (this._placeholderLabel) { - this._placeholderLabel.node.color = this.placeholderFontColor; - this._placeholderLabel.node.opacity = this.placeholderFontColor.a; + get () { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.placeholderFontColor', 'editBox.placeholderLabel.node.color'); + if (!this.placeholderLabel) { + return null; } - } + return this.placeholderLabel.node.color; + }, + set (value) { + // if (!CC_EDITOR) cc.warnID(5400, 'editBox.placeholderFontColor', 'editBox.placeholderLabel.node.color'); + if (this.placeholderLabel) { + this.placeholderLabel.node.color = value; + this.placeholderLabel.node.opacity = value.a; + } + }, + }, + + // To be removed in the future + _N$placeholderFontColor: { + default: undefined, + type: cc.Color, }, /** @@ -259,9 +397,12 @@ let EditBox = cc.Class({ maxLength: { tooltip: CC_DEV && 'i18n:COMPONENT.editbox.max_length', default: 20, - notify () { - - } + }, + + // To be removed in the future + _N$maxLength: { + default: undefined, + type: cc.Float, }, /** @@ -349,75 +490,22 @@ let EditBox = cc.Class({ }, _init () { - if (CC_EDITOR) { - this._upgradeComp(); - } + this._upgradeComp(); - this._createBackgroundSprite(); - this._createLabels(); this._isLabelVisible = true; this.node.on(cc.Node.EventType.SIZE_CHANGED, this._syncSize, this); let impl = this._impl = new EditBox._ImplClass(); impl.init(this); - this._updateString(this.string); + this._updateString(this._string); this._syncSize(); }, - _upgradeComp () { - if (this._N$returnType !== undefined) { - this.returnType = this._N$returnType; - this._N$returnType = undefined; - } - if (this._N$inputMode !== undefined) { - this.inputMode = this._N$inputMode; - this._N$inputMode = undefined; - } - }, - - _syncSize () { - let size = this.node.getContentSize(); - - this._background.node.setAnchorPoint(this.node.getAnchorPoint()); - this._background.node.setContentSize(size); - - this._updateLabelPosition(size); - if (this._impl) { - this._impl.setSize(size.width, size.height); - } - }, - - _updateLabelPosition (size) { - let node = this.node; - let offx = -node.anchorX * node.width; - let offy = -node.anchorY * node.height; - - let placeholderLabel = this._placeholderLabel; - let textLabel = this._textLabel; - - textLabel.node.setContentSize(size.width - LEFT_PADDING, size.height); - placeholderLabel.node.setContentSize(size.width - LEFT_PADDING, size.height); - - placeholderLabel.node.setPosition(offx + LEFT_PADDING, offy + size.height); - textLabel.node.setPosition(offx + LEFT_PADDING, offy + size.height); - - if (this.inputMode === InputMode.ANY){ - placeholderLabel.verticalAlign = macro.VerticalTextAlignment.TOP; - placeholderLabel.enableWrapText = true; - textLabel.verticalAlign = macro.VerticalTextAlignment.TOP; - textLabel.enableWrapText = true; - } - else { - placeholderLabel.verticalAlign = macro.VerticalTextAlignment.CENTER; - placeholderLabel.enableWrapText = false; - textLabel.verticalAlign = macro.VerticalTextAlignment.CENTER; - textLabel.enableWrapText = false; - } - }, + _updateBackgroundSprite () { + let background = this.background; - _createBackgroundSprite () { - let background = this._background; + // If background doesn't exist, create one. if (!background) { let node = this.node.getChildByName('BACKGROUND_SPRITE'); if (!node) { @@ -428,51 +516,136 @@ let EditBox = cc.Class({ if (!background) { background = node.addComponent(cc.Sprite); } - background.type = cc.Sprite.Type.SLICED; - node.parent = this.node; - this._background = background; + this.background = background; + } + + // update + background.type = cc.Sprite.Type.SLICED; + + // handle old data + if (this._N$backgroundImage !== undefined) { + background.spriteFrame = this._N$backgroundImage; + this._N$backgroundImage = undefined; } - background.spriteFrame = this.backgroundImage; }, - _createLabels () { - if (!this._textLabel) { + _updateTextLabel () { + let textLabel = this.textLabel; + + // If textLabel doesn't exist, create one. + if (!textLabel) { let node = this.node.getChildByName('TEXT_LABEL'); if (!node) { node = new cc.Node('TEXT_LABEL'); } - node.color = this.fontColor; - node.parent = this.node; - node.setAnchorPoint(0, 1); - - let textLabel = node.getComponent(Label); + textLabel = node.getComponent(Label); if (!textLabel) { textLabel = node.addComponent(Label); } - textLabel.overflow = Label.Overflow.CLAMP; - textLabel.fontSize = this.fontSize; - textLabel.lineHeight = this.lineHeight; - this._textLabel = textLabel; + node.parent = this.node; + this.textLabel = textLabel; + } + + // update + textLabel.node.setAnchorPoint(0, 1); + textLabel.overflow = Label.Overflow.CLAMP; + if (this.inputMode === InputMode.ANY) { + textLabel.verticalAlign = macro.VerticalTextAlignment.TOP; + textLabel.enableWrapText = true; + } + else { + textLabel.verticalAlign = macro.VerticalTextAlignment.CENTER; + textLabel.enableWrapText = false; + } + textLabel.string = this._updateLabelStringStyle(this._string); + + // handle old data + if (this._N$fontColor !== undefined) { + textLabel.node.color = this._N$fontColor; + textLabel.node.opacity = this._N$fontColor.a; + this._N$fontColor = undefined; + } + if (this._N$fontSize !== undefined) { + textLabel.fontSize = this._N$fontSize; + this._N$fontSize = undefined; } + if (this._N$lineHeight !== undefined) { + textLabel.lineHeight = this._N$lineHeight; + this._N$lineHeight = undefined; + } + }, - if (!this._placeholderLabel) { + _updatePlaceholderLabel () { + let placeholderLabel = this.placeholderLabel; + + // If placeholderLabel doesn't exist, create one. + if (!placeholderLabel) { let node = this.node.getChildByName('PLACEHOLDER_LABEL'); if (!node) { node = new cc.Node('PLACEHOLDER_LABEL'); } - node.color = this.placeholderFontColor; - node.parent = this.node; - node.setAnchorPoint(0, 1); - - let placeholderLabel = node.getComponent(Label); + placeholderLabel = node.getComponent(Label); if (!placeholderLabel) { placeholderLabel = node.addComponent(Label); } - placeholderLabel.overflow = Label.Overflow.CLAMP; - placeholderLabel.fontSize = this.placeholderFontSize; - placeholderLabel.string = this.placeholder; - this._placeholderLabel = placeholderLabel; + node.parent = this.node; + this.placeholderLabel = placeholderLabel; + } + + // update + placeholderLabel.node.setAnchorPoint(0, 1); + placeholderLabel.overflow = Label.Overflow.CLAMP; + if (this.inputMode === InputMode.ANY) { + placeholderLabel.verticalAlign = macro.VerticalTextAlignment.TOP; + placeholderLabel.enableWrapText = true; + } + else { + placeholderLabel.verticalAlign = macro.VerticalTextAlignment.CENTER; + placeholderLabel.enableWrapText = false; + } + placeholderLabel.string = this.placeholder; + + // handle old data + if (this._N$placeholderFontColor !== undefined) { + placeholderLabel.node.color = this._N$placeholderFontColor; + placeholderLabel.node.opacity = this._N$placeholderFontColor.a; + this._N$placeholderFontColor = undefined; + } + if (this._N$placeholderFontSize !== undefined) { + placeholderLabel.fontSize = this._N$placeholderFontSize; + this._N$placeholderFontSize = undefined; + } + }, + + _upgradeComp () { + if (this._N$returnType !== undefined) { + this.returnType = this._N$returnType; + this._N$returnType = undefined; + } + if (this._N$maxLength !== undefined) { + this.maxLength = this._N$maxLength; + this._N$maxLength = undefined; + } + if (this._N$backgroundImage !== undefined) { + this._updateBackgroundSprite(); + } + if (this._N$fontColor !== undefined || this._N$fontSize !== undefined || this._N$lineHeight !== undefined) { + this._updateTextLabel(); + } + if (this._N$placeholderFontColor !== undefined || this._N$placeholderFontSize !== undefined) { + this._updatePlaceholderLabel(); + } + if (this._N$placeholder !== undefined) { + this.placeholder = this._N$placeholder; + this._N$placeholder = undefined; + } + }, + + _syncSize () { + if (this._impl) { + let size = this.node.getContentSize(); + this._impl.setSize(size.width, size.height); } }, @@ -483,20 +656,28 @@ let EditBox = cc.Class({ _hideLabels () { this._isLabelVisible = false; - this._textLabel.node.active = false; - this._placeholderLabel.node.active = false; + if (this.textLabel) { + this.textLabel.node.active = false; + } + if (this.placeholderLabel) { + this.placeholderLabel.node.active = false; + } }, _updateLabels () { if (this._isLabelVisible) { - let displayText = this._textLabel.string; - this._textLabel.node.active = displayText !== ''; - this._placeholderLabel.node.active = displayText === ''; + let content = this._string; + if (this.textLabel) { + this.textLabel.node.active = (content !== ''); + } + if (this.placeholderLabel) { + this.placeholderLabel.node.active = (content === ''); + } } }, _updateString (text) { - let textLabel = this._textLabel; + let textLabel = this.textLabel; // Not inited yet if (!textLabel) { return; diff --git a/cocos2d/core/components/editbox/WebEditBoxImpl.js b/cocos2d/core/components/editbox/WebEditBoxImpl.js index 11d8c0ec2c0..a11fe712a64 100644 --- a/cocos2d/core/components/editbox/WebEditBoxImpl.js +++ b/cocos2d/core/components/editbox/WebEditBoxImpl.js @@ -27,6 +27,7 @@ const utils = require('../../platform/utils'); const macro = require('../../platform/CCMacro'); const Types = require('./types'); +const Label = require('../CCLabel'); const EditBox = cc.EditBox; const js = cc.js; @@ -64,7 +65,8 @@ let _autoResize = false; // This is an adapter for EditBoxImpl on web platform. // For more adapters on other platforms, please inherit from EditBoxImplBase and implement the interface. function WebEditBoxImpl () { - this._domId = ++_domCount; + this._domId = `EditBoxId_${++_domCount}`; + this._placeholderStyleSheet = null; this._elem = null; this._isTextArea = false; this._editing = false; @@ -89,6 +91,18 @@ function WebEditBoxImpl () { // event listeners this._eventListeners = {}; + + // update style sheet cache + this._textLabelFont = null; + this._textLabelFontSize = null; + this._textLabelFontColor = null; + this._textLabelAlign = null; + + this._placeholderLabelFont = null; + this._placeholderLabelFontSize = null; + this._placeholderLabelFontColor = null; + this._placeholderLabelAlign = null; + this._placeholderLineHeight = null; } js.extend(WebEditBoxImpl, EditBox._ImplClass); @@ -192,15 +206,21 @@ Object.assign(WebEditBoxImpl.prototype, { _addDomToGameContainer () { cc.game.container.appendChild(this._elem); + document.head.appendChild(this._placeholderStyleSheet); }, _removeDomFromGameContainer () { - let hasChild = utils.contains(cc.game.container, this._elem); - if (hasChild) { + let hasElem = utils.contains(cc.game.container, this._elem); + if (hasElem) { cc.game.container.removeChild(this._elem); } - + let hasStyleSheet = utils.contains(document.head, this._placeholderStyleSheet); + if (hasStyleSheet) { + document.head.removeChild(this._placeholderStyleSheet); + } + delete this._elem; + delete this._placeholderStyleSheet; }, _enableDom () { @@ -451,7 +471,8 @@ Object.assign(WebEditBoxImpl.prototype, { elem.style.position = "absolute"; elem.style.bottom = "0px"; elem.style.left = LEFT_PADDING + "px"; - elem.style.className = "cocosEditBox"; + elem.className = "cocosEditBox"; + elem.id = this._domId; if (!this._isTextArea) { elem.type = 'text'; @@ -461,6 +482,8 @@ Object.assign(WebEditBoxImpl.prototype, { elem.style.resize = 'none'; elem.style.overflow_y = 'scroll'; } + + this._placeholderStyleSheet = document.createElement('style'); }, _updateStyleSheet () { @@ -470,35 +493,137 @@ Object.assign(WebEditBoxImpl.prototype, { elem.value = delegate.string; elem.placeholder = delegate.placeholder; - // TODO: handle update cache - // update after issue solved: https://github.com/cocos-creator/2d-tasks/issues/372 - this._updateTextLabel(delegate._textLabel); - this._updatePlaceholderLabel(delegate._placeholderLabel); + this._updateTextLabel(delegate.textLabel); + this._updatePlaceholderLabel(delegate.placeholderLabel); }, _updateTextLabel (textLabel) { if (!textLabel) { return; } - let elem = this._elem; + // get font + let font = textLabel.font; + if (font && !(font instanceof cc.BitmapFont)) { + font = font._fontFamily; + } + else { + font = textLabel.fontFamily; + } + // whether need to update + if (this._textLabelFont === font + && this._textLabelFontSize === textLabel.fontSize + && this._textLabelFontColor === textLabel.fontColor + && this._textLabelAlign === textLabel.horizontalAlign) { + return; + } + + // update cache + this._textLabelFont = font; + this._textLabelFontSize = textLabel.fontSize; + this._textLabelFontColor = textLabel.fontColor; + this._textLabelAlign = textLabel.horizontalAlign; + + let elem = this._elem; // font size elem.style.fontSize = `${textLabel.fontSize}px`; - // font color elem.style.color = textLabel.node.color.toCSS('rgba'); - - // TODO: update after issue solved: https://github.com/cocos-creator/2d-tasks/issues/372 - // update color, font-family, text-align, line-height ... + // font family + elem.style.fontFamily = font; + // text-align + switch(textLabel.horizontalAlign) { + case Label.HorizontalAlign.LEFT: + elem.style.textAlign = 'left'; + break; + case Label.HorizontalAlign.CENTER: + elem.style.textAlign = 'center'; + break; + case Label.HorizontalAlign.RIGHT: + elem.style.textAlign = 'right'; + break; + } + // lineHeight + // Can't sync lineHeight property, because lineHeight would change the touch area of input }, _updatePlaceholderLabel (placeholderLabel) { if (!placeholderLabel) { return; } - let elem = this._elem; - // TODO: update after issue solved: https://github.com/cocos-creator/2d-tasks/issues/372 + // get font + let font = placeholderLabel.font; + if (font && !(font instanceof cc.BitmapFont)) { + font = placeholderLabel.font._fontFamily; + } + else { + font = placeholderLabel.fontFamily; + } + + // whether need to update + if (this._placeholderLabelFont === font + && this._placeholderLabelFontSize === placeholderLabel.fontSize + && this._placeholderLabelFontColor === placeholderLabel.fontColor + && this._placeholderLabelAlign === placeholderLabel.horizontalAlign + && this._placeholderLineHeight === placeholderLabel.lineHeight) { + return; + } + + // update cache + this._placeholderLabelFont = font; + this._placeholderLabelFontSize = placeholderLabel.fontSize; + this._placeholderLabelFontColor = placeholderLabel.fontColor; + this._placeholderLabelAlign = placeholderLabel.horizontalAlign; + this._placeholderLineHeight = placeholderLabel.lineHeight; + + let styleEl = this._placeholderStyleSheet; + // font size + let fontSize = placeholderLabel.fontSize; + // font color + let fontColor = placeholderLabel.node.color.toCSS('rgba'); + // line height + let lineHeight = placeholderLabel.lineHeight; + // horizontal align + let horizontalAlign; + switch (placeholderLabel.horizontalAlign) { + case Label.HorizontalAlign.LEFT: + horizontalAlign = 'left'; + break; + case Label.HorizontalAlign.CENTER: + horizontalAlign = 'center'; + break; + case Label.HorizontalAlign.RIGHT: + horizontalAlign = 'right'; + break; + } + + styleEl.innerHTML = ` + #${this._domId}::-webkit-input-placeholder { + text-transform: initial; + font-family: ${font}; + font-size: ${fontSize}px; + color: ${fontColor}; + line-height: ${lineHeight}px; + text-align: ${horizontalAlign}; + } + #${this._domId}::-moz-placeholder { + text-transform: initial; + font-family: ${font}; + font-size: ${fontSize}px; + color: ${fontColor}; + line-height: ${lineHeight}px; + text-align: ${horizontalAlign}; + } + #${this._domId}:-ms-input-placeholder { + text-transform: initial; + font-family: ${font}; + font-size: ${fontSize}px; + color: ${fontColor}; + line-height: ${lineHeight}px; + text-align: ${horizontalAlign}; + } + `; }, // =========================================== diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index b90ce8b773b..d4c74d9be5f 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -210,19 +210,15 @@ module.exports = { }, "editbox": { "string": "The initial input text of EditBox.", - "backgroundImage": "The background image of EditBox.", + "background": "The Sprite component attached to the node for EditBox's background.", "returnType": "The keyboard return type of EditBox. This is useful for keyboard of mobile device.", "input_flag": "Specify the input flag: password or capitalize word. ", "input_mode": "Specify the input mode: multiline or single line.", - "font_size": "The font size of input label.", - "line_height": "The line height of input label.", - "stay_on_top": "Set to true and the input is always visible and be on top of the game view, this property will be removed on v2.1", "tab_index": "Set the tabIndex of the DOM input element, only useful on Web.", - "font_color": "The font color of input label.", "placeholder": "The content string of placeholder.", - "placeholder_font_size": "The font size of placeholder label.", - "placeholder_font_color": "The font color of placeholder label.", - "max_length": "The maximize input characters." + "max_length": "The maximize input characters.", + "textLabel": "The Label component attached to the node for EditBox's input text label.", + "placeholderLabel": "The Label component attached to the node for EditBox's placeholder text label." }, "videoplayer": { "resourceType": "The resource type of VideoPlayer, currently support remote URL and local videos.", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index a7cb5e41ac9..99b2140be63 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -214,19 +214,15 @@ module.exports = { }, 'editbox': { "string": "输入框的初始输入内容,如果为空则会显示占位符的文本", - "backgroundImage": "输入框的背景图片", + "background": "输入框背景节点上挂载的 Sprite 组件对象", "input_flag": "指定输入标识:可以指定输入方式为密码或者单词首字母大写", "returnType": "指定移动设备上面回车按钮的样式", "input_mode": "指定输入模式: ANY表示多行输入,其它都是单行输入,移动平台上还可以指定键盘样式。", - "font_size": "输入框文本的字体大小", - "line_height": "输入框文本的行高", - "font_color": "输入框文本的颜色", - "stay_on_top": "设置为 True 则输入框总是可见,并且永远在游戏视图的上面,该属性会在 v2.1 中移除", "tab_index": "修改 DOM 输入元素的 tabIndex,这个属性只有在 Web 上面修改有意义。", "placeholder": "输入框占位符的文本内容", - "placeholder_font_size": "输入框占位符的字体大小", - "placeholder_font_color": "输入框占位符的字体颜色", "max_length": "输入框最大允许输入的字符个数", + "textLabel": "输入框输入文本节点上挂载的 Label 组件对象", + "placeholderLabel": "输入框占位符节点上挂载的 Label 组件对象" }, "videoplayer": { "resourceType": "视频来源,支持本地视频 URL 和远程视频 URL", From b691e598feba1ad3bb0868afa4a391985d03ed23 Mon Sep 17 00:00:00 2001 From: cary <39078800+caryliu1999@users.noreply.github.com> Date: Tue, 12 Mar 2019 18:40:27 +0800 Subject: [PATCH 0521/1631] optimize the performance of WeChat subdomain. (#3998) * optimize the performance of WeChat subdomain. * modify the context cache to utils --- cocos2d/core/components/WXSubContextView.js | 21 ++++++++++++++++-- .../canvas/render-component-handle.js | 3 +++ .../renderer/canvas/renderers/label/bmfont.js | 2 +- .../renderer/canvas/renderers/label/ttf.js | 2 +- .../canvas/renderers/sprite/simple.js | 2 +- .../canvas/renderers/sprite/sliced.js | 2 +- .../renderer/canvas/renderers/sprite/tiled.js | 3 +-- .../core/renderer/canvas/renderers/utils.js | 22 ++++++++++++++++++- editor/i18n/en/localization.js | 5 ++++- editor/i18n/zh/localization.js | 3 +++ 10 files changed, 55 insertions(+), 10 deletions(-) diff --git a/cocos2d/core/components/WXSubContextView.js b/cocos2d/core/components/WXSubContextView.js index 9e6e7b34d81..04fbbf20294 100644 --- a/cocos2d/core/components/WXSubContextView.js +++ b/cocos2d/core/components/WXSubContextView.js @@ -67,10 +67,25 @@ else { help: 'i18n:COMPONENT.help_url.wx_subcontext_view' }, + properties: { + _interval: 0, + + interval : { + get () { + return this._interval; + }, + set (value) { + this._interval = value; + }, + tooltip: CC_DEV && 'i18n:COMPONENT.wx_subcontext_view.interval' + } + }, + ctor () { this._sprite = null; this._tex = new cc.Texture2D(); this._context = null; + this._deltaTime = 0; }, onLoad () { @@ -115,10 +130,12 @@ else { this.updateSubContextViewport(); }, - update () { - if (!this._tex || !this._context) { + update (dt) { + this._deltaTime += dt; + if (!this._tex || !this._context || this._deltaTime < this._interval) { return; } + this._deltaTime = 0; this._tex.initWithElement(this._context.canvas); this._sprite._activateMaterial(); }, diff --git a/cocos2d/core/renderer/canvas/render-component-handle.js b/cocos2d/core/renderer/canvas/render-component-handle.js index 78b87d9e153..1c1e6d6056f 100644 --- a/cocos2d/core/renderer/canvas/render-component-handle.js +++ b/cocos2d/core/renderer/canvas/render-component-handle.js @@ -24,6 +24,7 @@ ****************************************************************************/ require('./renderers'); +const utils = require('./renderers/utils') let RenderComponentHandle = function (device, defaultCamera) { this._device = device; @@ -51,6 +52,8 @@ RenderComponentHandle.prototype = { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height); this._device._stats.drawcalls = 0; + //reset cache data + utils.context.reset(); }, terminate () { diff --git a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js index fdfae6720ca..e1cbb6909bd 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/bmfont.js +++ b/cocos2d/core/renderer/canvas/renderers/label/bmfont.js @@ -85,7 +85,7 @@ module.exports = js.addon({ // TODO: handle blend function // opacity - ctx.globalAlpha = node.opacity / 255; + utils.context.setGlobalAlpha(ctx, node.opacity / 255); let tex = comp._frame._texture, data = comp._renderData._data; diff --git a/cocos2d/core/renderer/canvas/renderers/label/ttf.js b/cocos2d/core/renderer/canvas/renderers/label/ttf.js index c9b52afbed6..f541a8bd886 100644 --- a/cocos2d/core/renderer/canvas/renderers/label/ttf.js +++ b/cocos2d/core/renderer/canvas/renderers/label/ttf.js @@ -69,7 +69,7 @@ module.exports = js.addon({ // TODO: handle blend function // opacity - ctx.globalAlpha = node.opacity / 255; + utils.context.setGlobalAlpha(ctx, node.opacity / 255); let tex = comp._frame._texture, data = comp._renderData._data; diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/simple.js b/cocos2d/core/renderer/canvas/renderers/sprite/simple.js index a8f540f69b7..5e24804c58a 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/simple.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/simple.js @@ -129,7 +129,7 @@ let renderer = { // TODO: handle blend function // opacity - ctx.globalAlpha = node.opacity / 255; + utils.context.setGlobalAlpha(ctx, node.opacity / 255); let tex = comp._spriteFrame._texture, data = comp._renderData._data; diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js b/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js index c65dfe90713..fb1e94d2ad8 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/sliced.js @@ -122,7 +122,7 @@ let renderer = { // TODO: handle blend function // opacity - ctx.globalAlpha = node.opacity / 255; + utils.context.setGlobalAlpha(ctx, node.opacity / 255); let tex = comp._spriteFrame._texture, data = comp._renderData._data; diff --git a/cocos2d/core/renderer/canvas/renderers/sprite/tiled.js b/cocos2d/core/renderer/canvas/renderers/sprite/tiled.js index 9138ecb6182..54844ae3b31 100644 --- a/cocos2d/core/renderer/canvas/renderers/sprite/tiled.js +++ b/cocos2d/core/renderer/canvas/renderers/sprite/tiled.js @@ -24,7 +24,6 @@ ****************************************************************************/ const utils = require('../utils'); -const simple = require('./simple'); let renderer = { createData (sprite) { @@ -50,7 +49,7 @@ let renderer = { // TODO: handle blend function // opacity - ctx.globalAlpha = node.opacity / 255; + utils.context.setGlobalAlpha(ctx, node.opacity / 255); let frame = sprite.spriteFrame; let rect = frame._rect; diff --git a/cocos2d/core/renderer/canvas/renderers/utils.js b/cocos2d/core/renderer/canvas/renderers/utils.js index 427ffae0eae..eab023eaa6a 100644 --- a/cocos2d/core/renderer/canvas/renderers/utils.js +++ b/cocos2d/core/renderer/canvas/renderers/utils.js @@ -160,4 +160,24 @@ module.exports = { let key = texture.url + (color._val & 0x00ffffff); canvasMgr.dropImage(key); } -}; \ No newline at end of file +}; + +// cache context data of device. +let _globalAlpha = -1; + +let context = { + setGlobalAlpha (ctx, alpha) { + if (_globalAlpha === alpha) { + return + } + + _globalAlpha = alpha; + ctx.globalAlpha = _globalAlpha; + }, + + reset () { + _globalAlpha = -1; + } +} + +module.exports.context = context; \ No newline at end of file diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 24adf30403e..331a68fba6c 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -395,6 +395,9 @@ module.exports = { 'column': 'Specify the TiledTile vertical coordinate,use map tile as the unit.', 'gid': 'Specify the TiledTile gid.', 'layer': 'Specify which TiledLayer the TiledTile belong to.' - } + }, + 'wx_subcontext_view': { + 'interval': 'The refresh interval of subcontext' + }, } }; \ No newline at end of file diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index ca453cc721b..a228aa9df0e 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -399,6 +399,9 @@ module.exports = { 'column': '指定 TiledTile 的纵向坐标,以地图块为单位', 'gid': '指定 TiledTile 的 gid 值', 'layer': '指定 TiledTile 属于哪一个 TiledLayer' + }, + 'wx_subcontext_view': { + 'interval': '子域界面的刷新时间间隔' } } }; \ No newline at end of file From 661f13cca1edee0f8aa14d809ce9570d2b4bea5f Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Tue, 12 Mar 2019 18:44:51 +0800 Subject: [PATCH 0522/1631] fix addAnimation default param (#4014) * fix addAnimation default param * fix tab issue --- extensions/spine/Skeleton.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index fc0f4ceafa2..01b4813dbb1 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -180,7 +180,7 @@ sp.Skeleton = cc.Class({ if (value) { this.setAnimation(0, value, this.loop); } - else { + else if (!this.isAnimationCached()) { this.clearTrack(0); this.setToSetupPose(); } @@ -662,7 +662,7 @@ sp.Skeleton = cc.Class({ // Destroyed and restored in Editor if (!this._material) { this._boundingBox = cc.rect(); - this._material = new SpineMaterial(); + this._material = new SpineMaterial(); this._materialCache = {}; } }, @@ -947,6 +947,7 @@ sp.Skeleton = cc.Class({ * @return {sp.spine.TrackEntry} */ addAnimation (trackIndex, name, loop, delay) { + delay = delay || 0; if (this.isAnimationCached()) { if (trackIndex !== 0) { cc.warn("Track index can not greater than 0 in cached mode."); @@ -954,7 +955,6 @@ sp.Skeleton = cc.Class({ this._animationQueue.push({animationName : name, loop: loop, delay : delay}); } else { if (this._skeleton) { - delay = delay || 0; var animation = this._skeleton.data.findAnimation(name); if (!animation) { cc.logID(7510, name); From eac70904e4f9c6cfc1eb034e6210bcb671ae7caf Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 12 Mar 2019 19:16:07 +0800 Subject: [PATCH 0523/1631] Fix native texture hash calculation issue (#4017) * Fix native texture hash calculation issue * User Number instead of parseInt --- cocos2d/core/assets/CCTexture2D.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/assets/CCTexture2D.js b/cocos2d/core/assets/CCTexture2D.js index 28c48d91dd1..d1377c52981 100644 --- a/cocos2d/core/assets/CCTexture2D.js +++ b/cocos2d/core/assets/CCTexture2D.js @@ -35,6 +35,7 @@ const GL_LINEAR = 9729; // gl.LINEAR const GL_REPEAT = 10497; // gl.REPEAT const GL_CLAMP_TO_EDGE = 33071; // gl.CLAMP_TO_EDGE const GL_MIRRORED_REPEAT = 33648; // gl.MIRRORED_REPEAT +const GL_RGBA = 6408; // gl.RGBA const CHAR_CODE_0 = 48; // '0' const CHAR_CODE_1 = 49; // '1' @@ -891,8 +892,14 @@ var Texture2D = cc.Class({ let wrapS = this._wrapS === WrapMode.REPEAT ? 1 : (this._wrapS === WrapMode.CLAMP_TO_EDGE ? 2 : 3); let wrapT = this._wrapT === WrapMode.REPEAT ? 1 : (this._wrapT === WrapMode.CLAMP_TO_EDGE ? 2 : 3); let pixelFormat = this._format; + let image = this._image; + if (CC_JSB && image) { + if (image._glFormat !== GL_RGBA) + pixelFormat = 0; + premultiplyAlpha = image._premultiplyAlpha; + } - this._hash = parseInt(`${minFilter}${magFilter}${pixelFormat}${wrapS}${wrapT}${hasMipmap}${premultiplyAlpha}${flipY}`); + this._hash = Number(`${minFilter}${magFilter}${pixelFormat}${wrapS}${wrapT}${hasMipmap}${premultiplyAlpha}${flipY}`); this._hashDirty = false; return this._hash; }, From 9c69a78cf0f99abbeb4d75d4e8a11956b4b74cf3 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Tue, 12 Mar 2019 19:17:17 +0800 Subject: [PATCH 0524/1631] fixed cc.Tween.repeat param (#4016) --- cocos2d/actions/tween.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cocos2d/actions/tween.js b/cocos2d/actions/tween.js index 855ad4bab8a..271fd2d9d30 100644 --- a/cocos2d/actions/tween.js +++ b/cocos2d/actions/tween.js @@ -189,6 +189,7 @@ Tween.prototype.then = function (other) { * !#zh * 设置 tween 的 target * @method target + * @param {Object} target * @return {Tween} */ Tween.prototype.target = function (target) { @@ -422,6 +423,7 @@ let previousAsInputActions = { * 添加一个重复 action,这个 action 会将前一个动作作为他的参数。 * @method repeat * @param {Number} repeatTimes + * @param {Action|Tween} [action] * @return {Tween} */ repeat: cc.repeat, @@ -432,6 +434,7 @@ let previousAsInputActions = { * !#zh * 添加一个永久重复 action,这个 action 会将前一个动作作为他的参数。 * @method repeatForever + * @param {Action|Tween} [action] * @return {Tween} */ repeatForever: cc.repeatForever, @@ -442,6 +445,7 @@ let previousAsInputActions = { * !#zh * 添加一个倒置时间 action,这个 action 会将前一个动作作为他的参数。 * @method reverseTime + * @param {Action|Tween} [action] * @return {Tween} */ reverseTime: cc.reverseTime, @@ -464,8 +468,8 @@ for (let i = 0; i < keys.length; i++) { Tween.prototype[key] = function () { let actions = this._actions; - let action = arguments[0]; - let i = 1; + let action = arguments[arguments.length - 1]; + let length = arguments.length - 1; if (action instanceof cc.Tween) { action = action._union(); @@ -473,11 +477,11 @@ for (let i = 0; i < keys.length; i++) { else if (!(action instanceof cc.Action)) { action = actions[actions.length - 1]; actions.length -= 1; - i = 0; + length += 1; } let args = [action]; - for (let l = arguments.length; i < l; i++) { + for (let i = 0; i < length; i++) { args.push(arguments[i]); } From 41d66899c236e7fa391f6bad2fed500fa23bca49 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Tue, 12 Mar 2019 20:55:24 +0800 Subject: [PATCH 0525/1631] fix merge error --- editor/i18n/en/localization.js | 4 ++-- editor/i18n/zh/localization.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 40608bbb309..4e39afd4612 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -393,10 +393,10 @@ module.exports = { 'layer': 'Specify which TiledLayer the TiledTile belong to.' }, 'wx_subcontext_view': { - 'interval': 'The refresh interval of subcontext' + 'interval': 'The refresh interval of subcontext', }, 'skeleton_animation': { - 'search_animation_clips': 'Search Animation Clips' + 'search_animation_clips': 'Search Animation Clips', }, } }; \ No newline at end of file diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 3f0d9c1cc07..ca3447b6dd5 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -397,10 +397,10 @@ module.exports = { 'layer': '指定 TiledTile 属于哪一个 TiledLayer' }, 'wx_subcontext_view': { - 'interval': '子域界面的刷新时间间隔' - } + 'interval': '子域界面的刷新时间间隔', + }, 'skeleton_animation': { - 'search_animation_clips': '搜索骨骼动画' + 'search_animation_clips': '搜索骨骼动画', }, } }; \ No newline at end of file From 686220f7b9c85c39275f50d33ea00e25c06eab7e Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 12 Mar 2019 22:06:18 +0800 Subject: [PATCH 0526/1631] upgrade tslib version (#4000) --- licenses/LICENSE_tslib.txt | 14 ++ polyfill/typescript.js | 319 +++++++++++++++++++++---------------- 2 files changed, 196 insertions(+), 137 deletions(-) create mode 100644 licenses/LICENSE_tslib.txt diff --git a/licenses/LICENSE_tslib.txt b/licenses/LICENSE_tslib.txt new file mode 100644 index 00000000000..6b23665c1ca --- /dev/null +++ b/licenses/LICENSE_tslib.txt @@ -0,0 +1,14 @@ +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ \ No newline at end of file diff --git a/polyfill/typescript.js b/polyfill/typescript.js index e17f1062cfc..b5b7c87e2e2 100644 --- a/polyfill/typescript.js +++ b/polyfill/typescript.js @@ -1,137 +1,182 @@ -// tslib 1.7.1 -var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; -window.__extends = function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); -}; -window.__assign = Object.assign || function (t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; - } - return t; - }; -window.__rest = function (s, e) { - var t = {}; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) - t[p] = s[p]; - if (s != null && typeof Object.getOwnPropertySymbols === "function") - for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) - t[p[i]] = s[p[i]]; - return t; -}; -window.__decorate = function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -}; -window.__param = function (paramIndex, decorator) { - return function (target, key) { decorator(target, key, paramIndex); } -}; -window.__metadata = function (metadataKey, metadataValue) { - if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); -}; -window.__awaiter = function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -window.__generator = function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [0, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; - -window.__exportStar = function (m, exports) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -}; - -window.__values = function (o) { - var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; - if (m) return m.call(o); - return { - next: function () { - if (o && i >= o.length) o = void 0; - return { value: o && o[i++], done: !o }; - } - }; -}; -window.__read = function (o, n) { - var m = typeof Symbol === "function" && o[Symbol.iterator]; - if (!m) return o; - var i = m.call(o), r, ar = [], e; - try { - while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); - } - catch (error) { e = { error: error }; } - finally { - try { - if (r && !r.done && (m = i["return"])) m.call(i); - } - finally { if (e) throw e.error; } - } - return ar; -}; - -window.__spread = function () { - for (var ar = [], i = 0; i < arguments.length; i++) - ar = ar.concat(__read(arguments[i])); - return ar; -}; - -window.__await = function (v) { - return this instanceof __await ? (this.v = v, this) : new __await(v); -}; - -window.__asyncGenerator = function (thisArg, _arguments, generator) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var g = generator.apply(thisArg, _arguments || []), i, q = []; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; - function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } - function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } - function fulfill(value) { resume("next", value); } - function reject(value) { resume("throw", value); } - function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } -}; - -window.__asyncDelegator = function (o) { - var i, p; - return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } -}; - -window.__asyncValues = function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator]; - return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator](); -}; +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global global, define, System, Reflect, Promise */ + +// tslib 1.9.3 + +var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + +window.__extends = function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; + +window.__assign = Object.assign || function (t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; +}; + +window.__rest = function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) + t[p[i]] = s[p[i]]; + return t; +}; + +window.__decorate = function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; + +window.__param = function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; + +window.__metadata = function (metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); +}; + +window.__awaiter = function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; + +window.__generator = function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; + +window.__exportStar = function (m, exports) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +}; + +window.__values = function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; + +window.__read = function (o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; +}; + +window.__spread = function () { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; +}; + +window.__await = function (v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); +}; + +window.__asyncGenerator = function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +}; + +window.__asyncDelegator = function (o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } +}; + +window.__asyncValues = function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +}; + +window.__makeTemplateObject = function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; + +window.__importStar = function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; + +window.__importDefault = function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; From f975e11c7d7a33263368a2972a86303e9b22ba7e Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 13 Mar 2019 10:18:40 +0800 Subject: [PATCH 0527/1631] Reset uuidToPack when reinit (#4019) --- cocos2d/core/load-pipeline/pack-downloader.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/load-pipeline/pack-downloader.js b/cocos2d/core/load-pipeline/pack-downloader.js index 2c88bace92e..dcc47a1b670 100644 --- a/cocos2d/core/load-pipeline/pack-downloader.js +++ b/cocos2d/core/load-pipeline/pack-downloader.js @@ -61,6 +61,7 @@ function error (uuid, packUuid) { module.exports = { initPacks: function (packs) { packIndices = packs; + uuidToPack = {}; for (var packUuid in packs) { var uuids = packs[packUuid]; for (var i = 0; i < uuids.length; i++) { From bf51ed209e850098f40b6535921cd20c06a0094c Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 13 Mar 2019 11:13:56 +0800 Subject: [PATCH 0528/1631] fix gulp make-tsd (#4021) --- cocos2d/core/3d/geom-utils/intersect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/3d/geom-utils/intersect.js b/cocos2d/core/3d/geom-utils/intersect.js index d809fd61b88..ea423c90410 100644 --- a/cocos2d/core/3d/geom-utils/intersect.js +++ b/cocos2d/core/3d/geom-utils/intersect.js @@ -25,7 +25,7 @@ let intersect = {}; * @method rayAabb * @param {geomUtils.Ray} ray * @param {geomUtils.Aabb} aabb - * @return Number + * @return {Number} */ intersect.rayAabb = (function () { let min = vec3.create(); From c98c85e033562a2037aeb6f04a70243b33242812 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Wed, 13 Mar 2019 13:43:18 +0800 Subject: [PATCH 0529/1631] Fix create dragonbones or spine asset by manual, uuid is empty bug (#4020) --- extensions/dragonbones/CCFactory.js | 10 +++++----- extensions/dragonbones/DragonBonesAsset.js | 19 +++++++++++++++---- .../dragonbones/DragonBonesAtlasAsset.js | 8 +++++++- extensions/spine/skeleton-data.js | 2 ++ 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/extensions/dragonbones/CCFactory.js b/extensions/dragonbones/CCFactory.js index c443762c4e0..ed8c5c0e0be 100644 --- a/extensions/dragonbones/CCFactory.js +++ b/extensions/dragonbones/CCFactory.js @@ -73,17 +73,17 @@ var CCFactory = dragonBones.CCFactory = cc.Class({ this._dragonBones.advanceTime(dt); }, + getDragonBonesDataByRawData (rawData) { + var dataParser = rawData instanceof ArrayBuffer ? BaseFactory._binaryParser : this._dataParser; + return dataParser.parseDragonBonesData(rawData, 1.0); + }, + // Build new aramture with a new display. buildArmatureDisplay (armatureName, dragonBonesName, skinName, textureAtlasName) { let armature = this.buildArmature(armatureName, dragonBonesName, skinName, textureAtlasName); return armature && armature._display; }, - parseTextureAtlasData (jsonString, texture, atlasUUID) { - var atlasJsonObj = JSON.parse(jsonString); - return this._super(atlasJsonObj, texture, atlasUUID); - }, - // Build sub armature from an exist armature component. // It will share dragonAsset and dragonAtlasAsset. // But node can not share,or will cause render error. diff --git a/extensions/dragonbones/DragonBonesAsset.js b/extensions/dragonbones/DragonBonesAsset.js index 250fe480846..5f997dc2a27 100644 --- a/extensions/dragonbones/DragonBonesAsset.js +++ b/extensions/dragonbones/DragonBonesAsset.js @@ -99,16 +99,27 @@ var DragonBonesAsset = cc.Class({ this._factory = factory; } - let armatureKey = this._uuid + "#" + atlasUUID; - let dragonBonesData = this._factory.getDragonBonesData(armatureKey); - if (dragonBonesData) return armatureKey; - let rawData = null; if (this.dragonBonesJson) { rawData = JSON.parse(this.dragonBonesJson); } else { rawData = this._nativeAsset; } + + // If create by manual, uuid is empty. + if (!this._uuid) { + let dbData = this._factory.getDragonBonesDataByRawData(rawData); + if (dbData) { + this._uuid = dbData.name; + } else { + cc.warn('dragonbones name is empty'); + } + } + + let armatureKey = this._uuid + "#" + atlasUUID; + let dragonBonesData = this._factory.getDragonBonesData(armatureKey); + if (dragonBonesData) return armatureKey; + this._factory.parseDragonBonesData(rawData, armatureKey); return armatureKey; }, diff --git a/extensions/dragonbones/DragonBonesAtlasAsset.js b/extensions/dragonbones/DragonBonesAtlasAsset.js index 086ad2143cc..122beb7fe6c 100644 --- a/extensions/dragonbones/DragonBonesAtlasAsset.js +++ b/extensions/dragonbones/DragonBonesAtlasAsset.js @@ -95,11 +95,17 @@ var DragonBonesAtlasAsset = cc.Class({ init (factory) { this._factory = factory; + + let atlasJsonObj = JSON.parse(this.atlasJson); + + // If create by manual, uuid is empty. + this._uuid = this._uuid || atlasJsonObj.name; + if (this._textureAtlasData) { factory.addTextureAtlasData(this._textureAtlasData, this._uuid); } else { - this._textureAtlasData = factory.parseTextureAtlasData(this.atlasJson, this.texture, this._uuid); + this._textureAtlasData = factory.parseTextureAtlasData(atlasJsonObj, this.texture, this._uuid); } }, diff --git a/extensions/spine/skeleton-data.js b/extensions/spine/skeleton-data.js index 129fc18e5ab..6fc8c2a3933 100644 --- a/extensions/spine/skeleton-data.js +++ b/extensions/spine/skeleton-data.js @@ -61,6 +61,8 @@ var SkeletonData = cc.Class({ this._skeletonJson = value; // If dynamic set skeletonJson field, auto update skeletonJsonStr field. this.skeletonJsonStr = JSON.stringify(value); + // If create by manual, uuid is empty. + this._uuid = this._uuid || value.skeleton.hash; this.reset(); } }, From 9c12b878e713d0b7bc952a85b6ec49c208def926 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 13 Mar 2019 13:51:15 +0800 Subject: [PATCH 0530/1631] fixed merge issue (#4022) --- cocos2d/core/components/CCLabel.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index 0c68079c4ca..f8be9f4c917 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -28,6 +28,7 @@ const macro = require('../platform/CCMacro'); const RenderComponent = require('./CCRenderComponent'); const Material = require('../assets/material/CCMaterial'); const LabelFrame = require('../renderer/utils/label/label-frame'); +const RenderFlow = require('../renderer/render-flow'); /** * !#en Enum for text alignment. @@ -525,6 +526,7 @@ let Label = cc.Class({ // Keep track of Node size this.node.on(cc.Node.EventType.SIZE_CHANGED, this._updateRenderData, this); this.node.on(cc.Node.EventType.ANCHOR_CHANGED, this._updateRenderData, this); + this.node.on(cc.Node.EventType.COLOR_CHANGED, this._updateColor, this); this._checkStringEmpty(); this._updateRenderData(true); @@ -534,6 +536,7 @@ let Label = cc.Class({ this._super(); this.node.off(cc.Node.EventType.SIZE_CHANGED, this._updateRenderData, this); this.node.off(cc.Node.EventType.ANCHOR_CHANGED, this._updateRenderData, this); + this.node.off(cc.Node.EventType.COLOR_CHANGED, this._updateColor, this); }, onDestroy () { From 41c2f76aef6a4954a4fe0d7d624177e811d5469d Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 13 Mar 2019 18:27:04 +0800 Subject: [PATCH 0531/1631] fixed label _updateColor (#4030) --- cocos2d/core/components/CCLabel.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index f8be9f4c917..4e168f19845 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -643,10 +643,7 @@ let Label = cc.Class({ _updateColor () { let font = this.font; - if (font instanceof cc.BitmapFont) { - this._super(); - } - else { + if (!(font instanceof cc.BitmapFont)) { this._updateRenderData(); this.node._renderFlag &= ~RenderFlow.FLAG_COLOR; } From a1d8c3d3630780f3382ad32a038550c4e161d28f Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Wed, 13 Mar 2019 18:27:19 +0800 Subject: [PATCH 0532/1631] Fix spine config has no skeleton field will throw error (#4029) --- extensions/spine/skeleton-data.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/spine/skeleton-data.js b/extensions/spine/skeleton-data.js index 6fc8c2a3933..aa394f28dbf 100644 --- a/extensions/spine/skeleton-data.js +++ b/extensions/spine/skeleton-data.js @@ -62,7 +62,9 @@ var SkeletonData = cc.Class({ // If dynamic set skeletonJson field, auto update skeletonJsonStr field. this.skeletonJsonStr = JSON.stringify(value); // If create by manual, uuid is empty. - this._uuid = this._uuid || value.skeleton.hash; + if (!this._uuid && value.skeleton) { + this._uuid = value.skeleton.hash; + } this.reset(); } }, From 955a6a21bc2ce23c27aa62842444c06685a8357c Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 14 Mar 2019 18:34:46 +0800 Subject: [PATCH 0533/1631] fix performance drop down on release mode (#4042) --- gulp/util/utils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gulp/util/utils.js b/gulp/util/utils.js index d308cd44984..76967582ebc 100644 --- a/gulp/util/utils.js +++ b/gulp/util/utils.js @@ -59,6 +59,7 @@ exports.getUglifyOptions = function (platform, flags) { keep_infinity: true, // reduce jsc file size typeofs: false, inline: 1, // workaround mishoo/UglifyJS2#2842 + reduce_funcs: false, }, output: { beautify: true, // really preserve_lines @@ -77,6 +78,7 @@ exports.getUglifyOptions = function (platform, flags) { global_defs: global_defs, negate_iife: false, inline: 1, // workaround mishoo/UglifyJS2#2842 + reduce_funcs: false, // keep single-use functions being cached }, output: { ascii_only: true, From d7aee810f9b0955196ff67e9dd71edb4e3e01d70 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Thu, 14 Mar 2019 21:10:10 +0800 Subject: [PATCH 0534/1631] fix typo (#4045) --- cocos2d/core/components/editbox/CCEditBox.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/components/editbox/CCEditBox.js b/cocos2d/core/components/editbox/CCEditBox.js index 0464a8f2613..a0a7866f02c 100644 --- a/cocos2d/core/components/editbox/CCEditBox.js +++ b/cocos2d/core/components/editbox/CCEditBox.js @@ -134,7 +134,7 @@ let EditBox = cc.Class({ // To be removed in the future _N$backgroundImage: { default: undefined, - type: cc.spriteFrame, + type: cc.SpriteFrame, }, /** From 52a2525eef28b5e1598e57ba0ad953e1c44d63eb Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 15 Mar 2019 15:26:10 +0800 Subject: [PATCH 0535/1631] fix video player currentTime invalid bug for engine/issues/4025 (#4049) --- cocos2d/videoplayer/video-player-impl.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cocos2d/videoplayer/video-player-impl.js b/cocos2d/videoplayer/video-player-impl.js index 4a5027ed3f9..81d5287d9aa 100644 --- a/cocos2d/videoplayer/video-player-impl.js +++ b/cocos2d/videoplayer/video-player-impl.js @@ -101,10 +101,7 @@ let VideoPlayerImpl = cc.Class({ return; } self._playing = false; - if (self._ignorePause) { - return; - } - else { + if (!self._ignorePause) { self._dispatchEvent(VideoPlayerImpl.EventType.PAUSED); } }; @@ -119,10 +116,11 @@ let VideoPlayerImpl = cc.Class({ video.addEventListener("click", cbs.click); function onCanPlay () { - if (self._loaded || self._loadedmeta || self._playing) + if (self._loaded || self._playing) return; let video = self._video; - if (video.readyState === READY_STATE.HAVE_ENOUGH_DATA) { + if (video.readyState === READY_STATE.HAVE_ENOUGH_DATA || + video.readyState === READY_STATE.HAVE_METADATA) { video.currentTime = 0; self._loaded = true; self._dispatchEvent(VideoPlayerImpl.EventType.READY_TO_PLAY); From d0ae6e2a6725fdc8940482f2ed62c3b5e75a1317 Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 15 Mar 2019 21:31:44 +0800 Subject: [PATCH 0536/1631] Fix pageview scrolling position err for 2d-tasks/issues/1228 (#4050) --- cocos2d/core/components/CCPageView.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/components/CCPageView.js b/cocos2d/core/components/CCPageView.js index b7b7242d683..dba69b5e812 100644 --- a/cocos2d/core/components/CCPageView.js +++ b/cocos2d/core/components/CCPageView.js @@ -416,6 +416,12 @@ var PageView = cc.Class({ // 刷新页面视图 _updatePageView: function () { + // 当页面数组变化时修改 content 大小 + var layout = this.content.getComponent(cc.Layout); + if (layout && layout.enabled) { + layout.updateLayout(); + } + var pageCount = this._pages.length; if (this._curPageIdx >= pageCount) { @@ -433,12 +439,6 @@ var PageView = cc.Class({ } } - // 当页面数组变化时修改 content 大小 - var layout = this.content.getComponent(cc.Layout); - if (layout && layout.enabled) { - layout.updateLayout(); - } - // 刷新 indicator 信息与状态 if (this.indicator) { this.indicator._refresh(); From e7d9c91f2bc6c3bf3c9e9891c322083b371c99f3 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Thu, 21 Mar 2019 16:47:42 +0800 Subject: [PATCH 0537/1631] Fix remove tile map layer and recover will throw error (#4076) --- cocos2d/tilemap/CCTiledLayer.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cocos2d/tilemap/CCTiledLayer.js b/cocos2d/tilemap/CCTiledLayer.js index 23da490a0c1..830115a4561 100644 --- a/cocos2d/tilemap/CCTiledLayer.js +++ b/cocos2d/tilemap/CCTiledLayer.js @@ -630,6 +630,11 @@ let TiledLayer = cc.Class({ } }, + onEnable () { + this._super(); + this._activateMaterial(); + }, + _activateMaterial () { let material = this._material; if (!material) { From f22fe5a23cdd67a991267a6ab5b376c08c9e1ab8 Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Thu, 21 Mar 2019 17:16:09 +0800 Subject: [PATCH 0538/1631] Fix dragonbones's alpha has not cascade bug (#4068) * Fix dragonbones opacity not cascade bug * Fix dragonbones opacity not cascade bug * Fix dragonbones opacity not cascade bug * Fix dragonbones opacity not cascade bug --- extensions/dragonbones/webgl-assembler.js | 28 ++++++++++++----------- extensions/spine/spine-assembler.js | 11 ++++----- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/extensions/dragonbones/webgl-assembler.js b/extensions/dragonbones/webgl-assembler.js index 37f0a257150..4daabffe255 100644 --- a/extensions/dragonbones/webgl-assembler.js +++ b/extensions/dragonbones/webgl-assembler.js @@ -36,7 +36,7 @@ let _boneColor = cc.color(255, 0, 0, 255); let _slotColor = cc.color(0, 0, 255, 255); let _nodeR, _nodeG, _nodeB, _nodeA, - _premultipliedAlpha, + _premultipliedAlpha, _multiply, _mustFlush, _buffer, _node, _renderer, _comp, _vfOffset, _indexOffset, _vertexOffset, @@ -109,18 +109,19 @@ function _getSlotMaterial (tex, blendMode) { return material; } -function _handleColor (color) { - _r = color.r * _nodeR; - _g = color.g * _nodeG; - _b = color.b * _nodeB; - _a = color.a * _nodeA; +function _handleColor (color, parentOpacity) { + _a = color.a * parentOpacity * _nodeA; + _multiply = _premultipliedAlpha? _a / 255.0 : 1.0; + _r = color.r * _nodeR * _multiply; + _g = color.g * _nodeG * _multiply; + _b = color.b * _nodeB * _multiply; _c = ((_a<<24) >>> 0) + (_b<<16) + (_g<<8) + _r; } let armatureAssembler = { updateRenderData (comp, batchData) {}, - realTimeTraverse (armature, parentMat) { + realTimeTraverse (armature, parentMat, parentOpacity) { let slots = armature._slots; let vbuf, ibuf, uintbuf; let material; @@ -132,6 +133,8 @@ let armatureAssembler = { for (let i = 0, l = slots.length; i < l; i++) { slot = slots[i]; + slotColor = slot._color; + if (!slot._visible || !slot._displayData) continue; if (parentMat) { @@ -141,7 +144,7 @@ let armatureAssembler = { } if (slot.childArmature) { - this.realTimeTraverse(slot.childArmature, slot._worldMatrix); + this.realTimeTraverse(slot.childArmature, slot._worldMatrix, parentOpacity * slotColor.a / 255); continue; } @@ -157,8 +160,7 @@ let armatureAssembler = { _renderer.material = material; } - slotColor = slot._color; - _handleColor(slotColor); + _handleColor(slotColor, parentOpacity); slotMat = slot._worldMatrix; vertices = slot._localVertices; @@ -226,7 +228,7 @@ let armatureAssembler = { let colors = frame.colors; let nowColor = colors[colorOffset++]; let maxVFOffset = nowColor.vfOffset; - _handleColor(nowColor); + _handleColor(nowColor, 1.0); for (let i = 0, n = segments.length; i < n; i++) { let segInfo = segments[i]; @@ -281,7 +283,7 @@ let armatureAssembler = { for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii+=5, frameColorOffset += 5) { if (frameColorOffset >= maxVFOffset) { nowColor = colors[colorOffset++]; - _handleColor(nowColor); + _handleColor(nowColor, 1.0); maxVFOffset = nowColor.vfOffset; } uintbuf[ii] = _c; @@ -325,7 +327,7 @@ let armatureAssembler = { let armature = comp._armature; if (!armature) return; - this.realTimeTraverse(armature, worldMat); + this.realTimeTraverse(armature, worldMat, 1.0); let graphics = comp._debugDraw; if (comp.debugBones && graphics) { diff --git a/extensions/spine/spine-assembler.js b/extensions/spine/spine-assembler.js index 1ac4ec0c4b8..09843dda58a 100644 --- a/extensions/spine/spine-assembler.js +++ b/extensions/spine/spine-assembler.js @@ -70,7 +70,7 @@ let _perVertexSize; let _perClipVertexSize; let _vertexFloatCount = 0, _vertexCount = 0, _vertexFloatOffset = 0, _vertexOffset = 0, _indexCount = 0, _indexOffset = 0, _vfOffset = 0; -let _tempr, _tempg, _tempb, _tempa; +let _tempr, _tempg, _tempb; let _inRange; let _mustFlush; let _x, _y, _m00, _m04, _m12, _m01, _m05, _m13; @@ -141,7 +141,8 @@ function _getSlotMaterial (tex, blendMode) { function _handleColor (color) { // temp rgb has multiply 255, so need divide 255; - _multiplier = _premultipliedAlpha ? color.fa / 255 : 1; + _fa = color.fa * _nodeA; + _multiplier = _premultipliedAlpha ? _fa / 255 : 1; _r = _nodeR * _multiplier; _g = _nodeG * _multiplier; _b = _nodeB * _multiplier; @@ -149,7 +150,6 @@ function _handleColor (color) { _fr = color.fr * _r; _fg = color.fg * _g; _fb = color.fb * _b; - _fa = color.fa * _nodeA; _finalColor32 = ((_fa<<24) >>> 0) + (_fb<<16) + (_fg<<8) + _fr; _dr = color.dr * _r; @@ -175,8 +175,8 @@ var spineAssembler = { uintVData = _buffer._uintVData; let offsetInfo; - _tempa = slotColor.a * attachmentColor.a * skeletonColor.a * 255; - _multiplier = _premultipliedAlpha? _tempa : 255; + _finalColor.a = slotColor.a * attachmentColor.a * skeletonColor.a * _nodeA * 255; + _multiplier = _premultipliedAlpha? _finalColor.a : 255; _tempr = _nodeR * attachmentColor.r * skeletonColor.r * _multiplier; _tempg = _nodeG * attachmentColor.g * skeletonColor.g * _multiplier; _tempb = _nodeB * attachmentColor.b * skeletonColor.b * _multiplier; @@ -184,7 +184,6 @@ var spineAssembler = { _finalColor.r = _tempr * slotColor.r; _finalColor.g = _tempg * slotColor.g; _finalColor.b = _tempb * slotColor.b; - _finalColor.a = _tempa * _nodeA; if (slot.darkColor == null) { _darkColor.set(0.0, 0, 0, 1.0); From 013f1c2de57515f202c6f4240f01b13cf25e0c38 Mon Sep 17 00:00:00 2001 From: PP Date: Fri, 22 Mar 2019 13:15:30 +0800 Subject: [PATCH 0539/1631] remove CCEditBoxImpl (#4082) --- .../core/components/editbox/CCEditBoxImpl.js | 701 ------------------ 1 file changed, 701 deletions(-) delete mode 100644 cocos2d/core/components/editbox/CCEditBoxImpl.js diff --git a/cocos2d/core/components/editbox/CCEditBoxImpl.js b/cocos2d/core/components/editbox/CCEditBoxImpl.js deleted file mode 100644 index 36fd3d6b657..00000000000 --- a/cocos2d/core/components/editbox/CCEditBoxImpl.js +++ /dev/null @@ -1,701 +0,0 @@ -/**************************************************************************** - Copyright (c) 2011-2012 cocos2d-x.org - Copyright (c) 2012 James Chen - Copyright (c) 2013-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 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 utils = require('../../platform/utils'); -const macro = require('../../platform/CCMacro'); -const Types = require('./types'); -const InputMode = Types.InputMode; -const InputFlag = Types.InputFlag; -const KeyboardReturnType = Types.KeyboardReturnType; - -// https://segmentfault.com/q/1010000002914610 -let SCROLLY = 40; -let LEFT_PADDING = 2; -let DELAY_TIME = 400; -let FOCUS_DELAY_UC = 400; -let FOCUS_DELAY_FIREFOX = 0; - -let math = cc.vmath; -let _worldMat = math.mat4.create(); -let _cameraMat = math.mat4.create(); -let _vec3 = cc.v3(); - -let _currentEditBoxImpl = null; - -// polyfill -let polyfill = { - zoomInvalid: false -}; - -if (cc.sys.OS_ANDROID === cc.sys.os && - (cc.sys.browserType === cc.sys.BROWSER_TYPE_SOUGOU || - cc.sys.browserType === cc.sys.BROWSER_TYPE_360)) { - polyfill.zoomInvalid = true; -} - -function getKeyboardReturnType (type) { - switch (type) { - case KeyboardReturnType.DEFAULT: - case KeyboardReturnType.DONE: - return 'done'; - case KeyboardReturnType.SEND: - return 'send'; - case KeyboardReturnType.SEARCH: - return 'search'; - case KeyboardReturnType.GO: - return 'go'; - case KeyboardReturnType.NEXT: - return 'next'; - } - return 'done'; -} - -let EditBoxImpl = cc.Class({ - ctor () { - this._delegate = null; - this._inputMode = -1; - this._inputFlag = -1; - this._returnType = KeyboardReturnType.DEFAULT; - this._maxLength = 50; - this._text = ''; - this._placeholderText = ''; - this._alwaysOnTop = false; - this._size = cc.size(); - this._node = null; - this._editing = false; - - this.__eventListeners = {}; - this.__fullscreen = false; - this.__autoResize = false; - this.__rotateScreen = false; - this.__orientationChanged = null; - - // matrix cache - this._m00 = 0; - this._m01 = 0; - this._m04 = 0; - this._m05 = 0; - this._m12 = 0; - this._m13 = 0; - this._w = 0; - this._h = 0; - }, - - onEnable () { - if (!this._edTxt) { - return; - } - if (this._alwaysOnTop) { - this._edTxt.style.display = ''; - } - else { - this._edTxt.style.display = 'none'; - } - }, - - onDisable () { - if (!this._edTxt) { - return; - } - this._edTxt.style.display = 'none'; - }, - - setTabIndex (index) { - if (this._edTxt) { - this._edTxt.tabIndex = index; - } - }, - - setFocus () { - this._beginEditing(); - }, - - isFocused() { - if (this._edTxt) { - return document.activeElement === this._edTxt; - } - cc.warnID(4700); - return false; - }, - - stayOnTop (flag) { - if(this._alwaysOnTop === flag || !this._edTxt) return; - - this._alwaysOnTop = flag; - - if (flag) { - this._edTxt.style.display = ''; - } else { - this._edTxt.style.display = 'none'; - } - }, - - setMaxLength (maxLength) { - if (!isNaN(maxLength)) { - if(maxLength < 0) { - //we can't set Number.MAX_VALUE to input's maxLength property - //so we use a magic number here, it should works at most use cases. - maxLength = 65535; - } - this._maxLength = maxLength; - this._edTxt && (this._edTxt.maxLength = maxLength); - } - }, - - setString (text) { - this._text = text; - this._edTxt && (this._edTxt.value = text); - }, - - getString () { - return this._text; - }, - - setPlaceholderText (text) { - this._placeholderText = text; - }, - - getPlaceholderText () { - return this._placeholderText; - }, - - setDelegate (delegate) { - this._delegate = delegate; - }, - - setInputMode (inputMode) { - if (this._inputMode === inputMode) return; - - this._inputMode = inputMode; - this.createInput(); - - this._updateDomInputType(); - this._updateSize(this._size.width, this._size.height); - }, - - setInputFlag (inputFlag) { - if (this._inputFlag === inputFlag) return; - - this._inputFlag = inputFlag; - this._updateDomInputType(); - - let textTransform = 'none'; - - if (inputFlag === InputFlag.INITIAL_CAPS_ALL_CHARACTERS) { - textTransform = 'uppercase'; - } - else if (inputFlag === InputFlag.INITIAL_CAPS_WORD) { - textTransform = 'capitalize'; - } - - if (this._edTxt) { - this._edTxt.style.textTransform = textTransform; - this._edTxt.value = this._text; - } - }, - - setReturnType (returnType) { - this._returnType = returnType; - this._updateDomInputType(); - }, - - setFontSize (fontSize) { - this._edFontSize = fontSize || this._edFontSize; - this._edTxt && (this._edTxt.style.fontSize = this._edFontSize + 'px'); - }, - - setFontColor (color) { - this._textColor = color; - this._edTxt && (this._edTxt.style.color = color.toCSS('rgba')); - }, - - setSize (width, height) { - this._size.width = width; - this._size.height = height; - this._updateSize(width, height); - }, - - setNode (node) { - this._node = node; - }, - - update () { - // TODO: find better way to update matrix - // if (this._editing) { - this._updateMatrix(); - // } - }, - - clear () { - this._node = null; - this.setDelegate(null); - this.removeDom(); - this.removeOrientationchangeEvent(); - }, - - _onTouchBegan (touch) { - - }, - - _onTouchEnded () { - this._beginEditing(); - }, - - _beginEditing () { - if (cc.sys.isMobile && !this._editing) { - // Pre adaptation add orientationchange event - this.addOrientationchangeEvent(); - } - - if (this._edTxt) { - this._edTxt.style.display = ''; - - let self = this; - function startFocus () { - self._edTxt.focus(); - } - - if (cc.sys.browserType === cc.sys.BROWSER_TYPE_UC) { - setTimeout(startFocus, FOCUS_DELAY_UC); - } - else if (cc.sys.browserType === cc.sys.BROWSER_TYPE_FIREFOX) { - setTimeout(startFocus, FOCUS_DELAY_FIREFOX); - } - else { - startFocus(); - } - } - - this._editing = true; - }, - - _endEditing () { - let self = this; - let hideDomInputAndShowLabel = function () { - if (!self._alwaysOnTop && self._edTxt) { - self._edTxt.style.display = 'none'; - } - if (self._delegate && self._delegate.editBoxEditingDidEnded) { - self._delegate.editBoxEditingDidEnded(); - } - }; - if (this._editing) { - if (cc.sys.isMobile) { - // Delay end editing adaptation to ensure virtual keyboard is disapeared - setTimeout(function () { - self._endEditingOnMobile(); - hideDomInputAndShowLabel(); - }, DELAY_TIME); - } - else { - hideDomInputAndShowLabel(); - } - } - this._editing = false; - }, - - _updateDomInputType () { - let inputMode = this._inputMode; - let edTxt = this._edTxt; - if (!edTxt) return; - - if (this._inputFlag === InputFlag.PASSWORD) { - edTxt.type = 'password'; - return; - } - - let type = edTxt.type; - if (inputMode === InputMode.EMAIL_ADDR) { - type = 'email'; - } else if(inputMode === InputMode.NUMERIC || inputMode === InputMode.DECIMAL) { - type = 'number'; - } else if(inputMode === InputMode.PHONE_NUMBER) { - type = 'number'; - edTxt.pattern = '[0-9]*'; - } else if(inputMode === InputMode.URL) { - type = 'url'; - } else { - type = 'text'; - - if (this._returnType === KeyboardReturnType.SEARCH) { - type = 'search'; - } - } - - edTxt.type = type; - }, - - _updateSize (newWidth, newHeight) { - let edTxt = this._edTxt; - if (!edTxt) return; - - edTxt.style.width = newWidth + 'px'; - edTxt.style.height = newHeight + 'px'; - }, - - _updateMatrix () { - if (!this._edTxt) return; - - let node = this._node; - node.getWorldMatrix(_worldMat); - - // check whether need to update - if (this._m00 === _worldMat.m00 && this._m01 === _worldMat.m01 && - this._m04 === _worldMat.m04 && this._m05 === _worldMat.m05 && - this._m12 === _worldMat.m12 && this._m13 === _worldMat.m13 && - this._w === node._contentSize.width && this._h === node._contentSize.height) { - return; - } - - // update matrix cache - this._m00 = _worldMat.m00; - this._m01 = _worldMat.m01; - this._m04 = _worldMat.m04; - this._m05 = _worldMat.m05; - this._m12 = _worldMat.m12; - this._m13 = _worldMat.m13; - this._w = node._contentSize.width; - this._h = node._contentSize.height; - - let scaleX = cc.view._scaleX, scaleY = cc.view._scaleY, - viewport = cc.view._viewportRect, - dpr = cc.view._devicePixelRatio; - - _vec3.x = -node._anchorPoint.x * this._w; - _vec3.y = -node._anchorPoint.y * this._h; - - math.mat4.translate(_worldMat, _worldMat, _vec3); - - // can't find camera in editor - if (CC_EDITOR) { - _cameraMat = _worldMat; - } - else { - let camera = cc.Camera.findCamera(node); - camera.getWorldToCameraMatrix(_cameraMat); - math.mat4.mul(_cameraMat, _cameraMat, _worldMat); - } - - - scaleX /= dpr; - scaleY /= dpr; - - let container = cc.game.container; - let a = _cameraMat.m00 * scaleX, b = _cameraMat.m01, c = _cameraMat.m04, d = _cameraMat.m05 * scaleY; - - let offsetX = container && container.style.paddingLeft && parseInt(container.style.paddingLeft); - offsetX += viewport.x / dpr; - let offsetY = container && container.style.paddingBottom && parseInt(container.style.paddingBottom); - offsetY += viewport.y / dpr; - let tx = _cameraMat.m12 * scaleX + offsetX, ty = _cameraMat.m13 * scaleY + offsetY; - - if (polyfill.zoomInvalid) { - this._updateSize(this._size.width * a, this._size.height * d); - a = 1; - d = 1; - } - - let matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")"; - this._edTxt.style['transform'] = matrix; - this._edTxt.style['-webkit-transform'] = matrix; - this._edTxt.style['transform-origin'] = '0px 100% 0px'; - this._edTxt.style['-webkit-transform-origin'] = '0px 100% 0px'; - }, - - _adjustEditBoxPosition () { - this._node.getWorldMatrix(_worldMat); - let y = _worldMat.m13; - let windowHeight = cc.visibleRect.height; - let windowWidth = cc.visibleRect.width; - let factor = 0.5; - if (windowWidth > windowHeight) { - factor = 0.7; - } - setTimeout(function() { - if (window.scrollY < SCROLLY && y < windowHeight * factor) { - let scrollOffset = windowHeight * factor - y - window.scrollY; - if (scrollOffset < 35) scrollOffset = 35; - if (scrollOffset > 320) scrollOffset = 320; - window.scrollTo(0, scrollOffset); - } - }, DELAY_TIME); - } -}); - -let _p = EditBoxImpl.prototype; - -_p.createInput = function() { - if (this._inputMode === InputMode.ANY) { - this._createDomTextArea(); - } - else { - this._createDomInput(); - } -}; - -// Called before editbox focus to register cc.view status -_p._beginEditingOnMobile = function () { - // add orientationchange event - this.addOrientationchangeEvent(); - - if (cc.view.isAutoFullScreenEnabled()) { - this.__fullscreen = true; - cc.view.enableAutoFullScreen(false); - cc.screen.exitFullScreen(); - } else { - this.__fullscreen = false; - } - this.__autoResize = cc.view._resizeWithBrowserSize; - cc.view.resizeWithBrowserSize(false); - _currentEditBoxImpl = this; -}; - -// Called after keyboard disappeared to readapte the game view -_p._endEditingOnMobile = function () { - if (this.__rotateScreen) { - cc.game.container.style['-webkit-transform'] = 'rotate(90deg)'; - cc.game.container.style.transform = 'rotate(90deg)'; - - let view = cc.view; - let width = view._originalDesignResolutionSize.width; - let height = view._originalDesignResolutionSize.height; - if (width > 0) { - view.setDesignResolutionSize(width, height, view._resolutionPolicy); - } - this.__rotateScreen = false; - } - - // remove orientationchange event - this.removeOrientationchangeEvent(); - - if(this.__fullscreen) { - cc.view.enableAutoFullScreen(true); - } - - // In case focus on editBox A from editBox B - // A disable resizeWithBrowserSize - // whilte B enable resizeWithBrowserSize - // Only _currentEditBoxImpl can enable resizeWithBrowserSize - if (this.__autoResize && _currentEditBoxImpl === this) { - cc.view.resizeWithBrowserSize(true); - } -}; - -function _inputValueHandle (input, editBoxImpl) { - if (input.value.length > editBoxImpl._maxLength) { - input.value = input.value.slice(0, editBoxImpl._maxLength); - } - if (editBoxImpl._delegate && editBoxImpl._delegate.editBoxTextChanged) { - if (editBoxImpl._text !== input.value) { - editBoxImpl._text = input.value; - editBoxImpl._delegate.editBoxTextChanged(editBoxImpl._text); - } - } -} - -function registerInputEventListener (tmpEdTxt, editBoxImpl, isTextarea) { - let inputLock = false; - let blurWhenComposition = false; - let cbs = editBoxImpl.__eventListeners; - cbs.compositionstart = function () { - inputLock = true; - }; - tmpEdTxt.addEventListener('compositionstart', cbs.compositionstart); - - cbs.compositionend = function () { - inputLock = false; - if (blurWhenComposition) { - // restore input value when composition not complete and blur input - this.value = editBoxImpl._text; - blurWhenComposition = false; - } - _inputValueHandle(this, editBoxImpl); - }; - tmpEdTxt.addEventListener('compositionend', cbs.compositionend); - - cbs.input = function () { - if (inputLock) { - return; - } - _inputValueHandle(this, editBoxImpl); - }; - tmpEdTxt.addEventListener('input', cbs.input); - - cbs.focus = function () { - this.style.fontSize = editBoxImpl._edFontSize + 'px'; - this.style.color = editBoxImpl._textColor.toCSS('rgba'); - // When stayOnTop, input will swallow touch event - if (editBoxImpl._alwaysOnTop) { - editBoxImpl._editing = true; - } - - if (cc.sys.isMobile) { - editBoxImpl._beginEditingOnMobile(); - } - - if (editBoxImpl._delegate && editBoxImpl._delegate.editBoxEditingDidBegan) { - editBoxImpl._delegate.editBoxEditingDidBegan(); - } - - }; - tmpEdTxt.addEventListener('focus', cbs.focus); - - cbs.keypress = function (e) { - if (e.keyCode === macro.KEY.enter) { - e.stopPropagation(); - - if (editBoxImpl._delegate && editBoxImpl._delegate.editBoxEditingReturn) { - editBoxImpl._delegate.editBoxEditingReturn(); - } - if (!isTextarea) { - editBoxImpl._text = this.value; - editBoxImpl._endEditing(); - cc.game.canvas.focus(); - } - } - }; - tmpEdTxt.addEventListener('keypress', cbs.keypress); - - cbs.blur = function () { - if (inputLock) { - blurWhenComposition = true; - } - else { - editBoxImpl._text = this.value; - } - editBoxImpl._endEditing(); - }; - tmpEdTxt.addEventListener('blur', cbs.blur); - - editBoxImpl._addDomToGameContainer(); -} - -_p._createDomInput = function () { - this.removeDom(); - - let tmpEdTxt = this._edTxt = document.createElement('input'); - tmpEdTxt.type = 'text'; - tmpEdTxt.style.fontSize = this._edFontSize + 'px'; - tmpEdTxt.style.color = '#000000'; - tmpEdTxt.style.border = 0; - tmpEdTxt.style.background = 'transparent'; - tmpEdTxt.style.width = '100%'; - tmpEdTxt.style.height = '100%'; - tmpEdTxt.style.active = 0; - tmpEdTxt.style.outline = 'medium'; - tmpEdTxt.style.padding = '0'; - tmpEdTxt.style.textTransform = 'uppercase'; - tmpEdTxt.style.display = 'none'; - tmpEdTxt.style.position = "absolute"; - tmpEdTxt.style.bottom = "0px"; - tmpEdTxt.style.left = LEFT_PADDING + "px"; - tmpEdTxt.style['-moz-appearance'] = 'textfield'; - tmpEdTxt.style.fontFamily = 'Arial'; - tmpEdTxt.className = "cocosEditBox"; - - registerInputEventListener(tmpEdTxt, this); - - return tmpEdTxt; -}; - -_p._createDomTextArea = function () { - this.removeDom(); - - let tmpEdTxt = this._edTxt = document.createElement('textarea'); - tmpEdTxt.style.fontSize = this._edFontSize + 'px'; - tmpEdTxt.style.color = '#000000'; - tmpEdTxt.style.border = 0; - tmpEdTxt.style.background = 'transparent'; - tmpEdTxt.style.width = '100%'; - tmpEdTxt.style.height = '100%'; - tmpEdTxt.style.active = 0; - tmpEdTxt.style.outline = 'medium'; - tmpEdTxt.style.padding = '0'; - tmpEdTxt.style.resize = 'none'; - tmpEdTxt.style.textTransform = 'uppercase'; - tmpEdTxt.style.overflow_y = 'scroll'; - tmpEdTxt.style.display = 'none'; - tmpEdTxt.style.position = "absolute"; - tmpEdTxt.style.bottom = "0px"; - tmpEdTxt.style.left = LEFT_PADDING + "px"; - tmpEdTxt.style.fontFamily = 'Arial'; - tmpEdTxt.className = "cocosEditBox"; - - registerInputEventListener(tmpEdTxt, this, true); - - return tmpEdTxt; -}; - -_p._addDomToGameContainer = function () { - cc.game.container.appendChild(this._edTxt); -}; - -_p.removeDom = function () { - let edTxt = this._edTxt; - if (edTxt) { - // Remove listeners - let cbs = this.__eventListeners; - edTxt.removeEventListener('compositionstart', cbs.compositionstart); - edTxt.removeEventListener('compositionend', cbs.compositionend); - edTxt.removeEventListener('input', cbs.input); - edTxt.removeEventListener('focus', cbs.focus); - edTxt.removeEventListener('keypress', cbs.keypress); - edTxt.removeEventListener('blur', cbs.blur); - cbs.compositionstart = null; - cbs.compositionend = null; - cbs.input = null; - cbs.focus = null; - cbs.keypress = null; - cbs.blur = null; - - let hasChild = utils.contains(cc.game.container, edTxt); - if (hasChild) { - cc.game.container.removeChild(edTxt); - } - } - this._edTxt = null; -}; - -_p.addOrientationchangeEvent = function () { - let self = this; - if (!self.__orientationChanged) { - self.__orientationChanged = function () { - self._adjustEditBoxPosition(); - }; - } - window.addEventListener('orientationchange', self.__orientationChanged); -}; - -_p.removeOrientationchangeEvent = function () { - if (this.__orientationChanged) { - window.removeEventListener('orientationchange', this.__orientationChanged); - this.__orientationChanged = null; - } -}; - -module.exports = EditBoxImpl; From 1707d21c24ce862633ccf4299de4dab420b81baf Mon Sep 17 00:00:00 2001 From: Knox Date: Fri, 22 Mar 2019 18:27:32 +0800 Subject: [PATCH 0540/1631] improve tooltip to label (#4090) * add actual font size tooltip to label * add spacingX tooltip to label * refine tips --- cocos2d/core/components/CCLabel.js | 12 ++++++++++-- editor/i18n/en/localization.js | 4 +++- editor/i18n/zh/localization.js | 4 +++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/components/CCLabel.js b/cocos2d/core/components/CCLabel.js index b90c3b682f6..b96d036bf5e 100644 --- a/cocos2d/core/components/CCLabel.js +++ b/cocos2d/core/components/CCLabel.js @@ -252,7 +252,8 @@ let Label = cc.Class({ readonly: true, get () { return this._actualFontSize; - } + }, + tooltip: CC_DEV && 'i18n:COMPONENT.label.actualFontSize', }, _fontSize: 40, @@ -445,6 +446,12 @@ let Label = cc.Class({ }, _spacingX: 0, + + /** + * !#en The spacing of the x axis between characters. + * !#zh 文字之间 x 轴的间距。 + * @property {Number} spacingX + */ spacingX: { get () { return this._spacingX; @@ -452,7 +459,8 @@ let Label = cc.Class({ set (value) { this._spacingX = value; this._updateRenderData(); - } + }, + tooltip: CC_DEV && 'i18n:COMPONENT.label.spacingX', }, //For compatibility with v2.0.x temporary reservation. diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 331a68fba6c..a0e47e8cf37 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -97,7 +97,9 @@ module.exports = { "wrap": "Wrap text?", "font": "What font to use", "system_font": "Whether to use the system default font", - 'cacheMode': 'The text cache mode includes the following three types: \n 1. NONE : Do not do any caching, text content is drawn once. \n 2. BITMAP: Add text as a static image to the dynamic atlas for batch merging, but not frequently dynamically Text content \n 3. CHAR: Splits text into characters and caches characters into character atlas, suitable for text content with repeated and frequently updated character content' + 'cacheMode': 'The text cache mode includes the following three types: \n 1. NONE : Do not do any caching, text content is drawn once. \n 2. BITMAP: Add text as a static image to the dynamic atlas for batch merging, but not frequently dynamically Text content \n 3. CHAR: Splits text into characters and caches characters into character atlas, suitable for text content with repeated and frequently updated character content', + 'actualFontSize': 'The actual rendering font size in shrink mode', + 'spacingX': 'The spacing of the x axis between characters', }, "progress": { "bar_sprite": "A progress bar is displayed with the Sprite node that can dynamically change the size", diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index a228aa9df0e..6a9bf6b899d 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -100,7 +100,9 @@ module.exports = { 'wrap': '是否允许自动换行', 'font': 'Label 使用的字体资源', 'system_font': '是否使用系统默认字体,选中此项会将 file 属性置空', - 'cacheMode': '文本缓存模式,包括以下三种:\n 1. NONE : 不做任何缓存,文本内容进行一次绘制 \n 2. BITMAP: 将文本作为静态图像加入动态图集进行批次合并,但是不能频繁动态修改文本内容 \n 3. CHAR: 将文本拆分为字符并且把字符纹理缓存到一张字符图集中进行复用,适用于字符内容重复并且频繁更新的文本内容' + 'cacheMode': '文本缓存模式,包括以下三种:\n 1. NONE : 不做任何缓存,文本内容进行一次绘制 \n 2. BITMAP: 将文本作为静态图像加入动态图集进行批次合并,但是不能频繁动态修改文本内容 \n 3. CHAR: 将文本拆分为字符并且把字符纹理缓存到一张字符图集中进行复用,适用于字符内容重复并且频繁更新的文本内容', + 'actualFontSize': 'SHRINK 模式下面文本实际渲染的字体大小', + 'spacingX': '文字之间 x 轴的间距', }, 'progress': { 'bar_sprite': '进度条显示用的 Sprite 节点,可以动态改变尺寸', From 5220bc12d0cf253b3cb3e15bc90bfc32adcc5f8c Mon Sep 17 00:00:00 2001 From: owen <1053210246@qq.com> Date: Fri, 22 Mar 2019 20:22:02 +0800 Subject: [PATCH 0541/1631] =?UTF-8?q?fix=20spine=20use=20multiple=20skin?= =?UTF-8?q?=20and=20use=20cache=20mode,=20won=E2=80=99t=20renderer=20bug?= =?UTF-8?q?=20(#4091)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extensions/spine/Skeleton.js | 3 ++- extensions/spine/skeleton-cache.js | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/extensions/spine/Skeleton.js b/extensions/spine/Skeleton.js index 01b4813dbb1..deaa503e49c 100644 --- a/extensions/spine/Skeleton.js +++ b/extensions/spine/Skeleton.js @@ -394,7 +394,7 @@ sp.Skeleton = cc.Class({ // Skeleton cache _skeletonCache : null, // Aimation name - _animationName : null, + _animationName : "", // Animation queue _animationQueue : [], // Head animation info of @@ -814,6 +814,7 @@ sp.Skeleton = cc.Class({ setSkin (skinName) { if (this.isAnimationCached()) { this._skeletonCache.resetSkeleton(); + this._skeletonCache.updateSkeletonSkin(this.skeletonData._uuid, skinName); this._animationName && (this.animation = this._animationName); } else { if (this._skeleton) { diff --git a/extensions/spine/skeleton-cache.js b/extensions/spine/skeleton-cache.js index 44ee0d61fe7..25d36895f93 100644 --- a/extensions/spine/skeleton-cache.js +++ b/extensions/spine/skeleton-cache.js @@ -476,6 +476,13 @@ let SkeletonCache = cc.Class({ return animationsCache[animationName]; }, + updateSkeletonSkin (uuid, skinName) { + let skeletonInfo = this._skeletonCache[uuid]; + let skeleton = skeletonInfo && skeletonInfo.skeleton; + if (!skeleton) return; + skeleton.setSkinByName(skinName); + }, + updateAnimationCache (uuid, animationName) { let skeletonInfo = this._skeletonCache[uuid]; let skeleton = skeletonInfo && skeletonInfo.skeleton; From 4058559a75526ad63f426bcc481fd245807706d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ron=20Holmstr=C3=B6m?= Date: Mon, 25 Mar 2019 05:54:06 +0200 Subject: [PATCH 0542/1631] Added