实现2.4.11版本

This commit is contained in:
lujun 2023-02-09 17:25:08 +08:00
parent 70c4e8da16
commit 451f431777
210 changed files with 46766 additions and 7089 deletions

53
2.4.11/.gitignore vendored Normal file
View File

@ -0,0 +1,53 @@
#/////////////////////////////////////////////////////////////////////////////
# Fireball Projects
#/////////////////////////////////////////////////////////////////////////////
/library/
/temp/
/local/
/build/
native
#/////////////////////////////////////////////////////////////////////////////
# npm files
#/////////////////////////////////////////////////////////////////////////////
npm-debug.log
node_modules/
#/////////////////////////////////////////////////////////////////////////////
# Logs and databases
#/////////////////////////////////////////////////////////////////////////////
*.log
*.sql
*.sqlite
#/////////////////////////////////////////////////////////////////////////////
# files for debugger
#/////////////////////////////////////////////////////////////////////////////
*.sln
*.csproj
*.pidb
*.unityproj
*.suo
#/////////////////////////////////////////////////////////////////////////////
# OS generated files
#/////////////////////////////////////////////////////////////////////////////
.DS_Store
ehthumbs.db
Thumbs.db
#/////////////////////////////////////////////////////////////////////////////
# WebStorm files
#/////////////////////////////////////////////////////////////////////////////
.idea/
#//////////////////////////
# VS Code files
#//////////////////////////
.vscode/

View File

@ -0,0 +1,13 @@
{
"ver": "1.1.3",
"uuid": "67d51efb-7233-4c27-b96c-386cc3d5e810",
"importer": "folder",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}

View File

@ -0,0 +1,13 @@
{
"ver": "1.1.3",
"uuid": "0998106b-40d7-467a-aa96-9eb7bc459a51",
"importer": "folder",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}

View File

@ -0,0 +1,111 @@
//@ts-ignore
const nodeMemPool = require('./trans-pool/index').NodeMemPool
declare module cc {
export interface Node {
/**
* - private
*/
_sortingPriority:number;
/**
*
*/
sortingPriority:number;
/**
* 使 - private
*/
_sortingEnabled:boolean;
/**
* 使
*/
sortingEnabled:boolean;
}
}
if(!('sortingPriority' in cc.Node.prototype)){
Object.defineProperty(cc.Node.prototype, 'sortingPriority', {
get: function() {
return this._sortingPriority;
},
set: function(value) {
this._sortingPriority = value;
// console.log(`sortingPriority ${this.name} ${value}`);
if(CC_JSB){
this._sortingPriorityProxy[0] = value;
}
},
enumerable: true
});
Object.defineProperty(cc.Node.prototype, 'sortingEnabled', {
get: function() {
return this._sortingEnabled;
},
set: function(value) {
this._sortingEnabled = value;
// console.log(`sortingEnabled ${this.name} ${value}`);
if(CC_JSB){
this._sortingEnabledProxy[0] = value ? 1 : 0;
}
},
enumerable: true
});
}
if(CC_JSB){
//@ts-ignore
cc.Node.prototype._initDataFromPool = function(){
if (!this._spaceInfo) {
if (CC_EDITOR || CC_TEST) {
this._spaceInfo = {
trs: new Float64Array(10),
localMat: new Float64Array(16),
worldMat: new Float64Array(16),
};
} else {
this._spaceInfo = nodeMemPool.pop();
}
}
let spaceInfo = this._spaceInfo;
this._matrix = cc.mat4(spaceInfo.localMat);
cc.Mat4.identity(this._matrix);
this._worldMatrix = cc.mat4(spaceInfo.worldMat);
cc.Mat4.identity(this._worldMatrix);
this._localMatDirty = 0xffff;
this._worldMatDirty = true;
this._sortingPriorityProxy = spaceInfo.sortingPriority;
this._sortingEnabledProxy = spaceInfo.sortingEnabled;
let trs = this._trs = spaceInfo.trs;
trs[0] = 0; // position.x
trs[1] = 0; // position.y
trs[2] = 0; // position.z
trs[3] = 0; // rotation.x
trs[4] = 0; // rotation.y
trs[5] = 0; // rotation.z
trs[6] = 1; // rotation.w
trs[7] = 1; // scale.x
trs[8] = 1; // scale.y
trs[9] = 1; // scale.z
}
//@ts-ignore
cc.Node.prototype._backDataIntoPool = function() {
if (!(CC_EDITOR || CC_TEST)) {
// push back to pool
nodeMemPool.push(this._spaceInfo);
this._sortingPriorityProxy = null;
this._sortingEnabledProxy = null;
this._matrix = null;
this._worldMatrix = null;
this._trs = null;
this._spaceInfo = null;
}
}
}

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "f0c38288-db93-4468-ab2a-0e3bc2059d15",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,10 @@
declare module cc {
export interface RenderComponent {
/**
*
*/
renderPriority:number;
}
}

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "910f4c68-0289-4422-a65c-6dc64f77511e",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,153 @@
let _batcher;
let _cullingMask = 0;
/**
*
*/
let renderPriority = 0;
/**
*
*/
let rendererCache:cc.RenderComponent[] = [];
/**
*
*/
let rendererOrder:boolean = false;
/**
*
*/
function flushRendererCache(){
if(rendererCache.length > 0){
if(rendererOrder){
rendererCache.sort((a, b)=>{ return a.renderPriority - b.renderPriority; });
}
for(let render of rendererCache){
// console.log(`${render.node.name} - ${render.renderPriority}`);
//@ts-ignore
render._checkBacth(_batcher, render.node._cullingMask);
//@ts-ignore
render._assembler.fillBuffers(render, _batcher);
}
rendererCache.length = 0;
}
rendererOrder = false;
}
//@ts-ignore
cc.RenderFlow.visitRootNode = function (rootNode){
renderPriority = 0;
rendererCache.length = 0;
rendererOrder = false;
//@ts-ignore
_batcher = cc.RenderFlow.getBachther();
//@ts-ignore
cc.RenderFlow.validateRenderers();
let preCullingMask = _cullingMask;
_cullingMask = rootNode._cullingMask;
//@ts-ignore
if (rootNode._renderFlag & cc.RenderFlow.FLAG_WORLD_TRANSFORM) {
_batcher.worldMatDirty ++;
rootNode._calculWorldMatrix();
//@ts-ignore
rootNode._renderFlag &= ~cc.RenderFlow.FLAG_WORLD_TRANSFORM;
//@ts-ignore
cc.RenderFlow.flows[rootNode._renderFlag]._func(rootNode);
flushRendererCache();
_batcher.worldMatDirty --;
}
else {
//@ts-ignore
cc.RenderFlow.flows[rootNode._renderFlag]._func(rootNode);
flushRendererCache();
}
_cullingMask = preCullingMask;
}
//@ts-ignore
cc.RenderFlow.prototype._render = function (node) {
let comp = node._renderComponent;
if(comp instanceof cc.Mask){
flushRendererCache();
//@ts-ignore
comp._checkBacth(_batcher, node._cullingMask);
//@ts-ignore
comp._assembler.fillBuffers(comp, _batcher);
}else{
if (_batcher.worldMatDirty && comp._assembler.updateWorldVerts) {
comp._assembler.updateWorldVerts(comp);
}
rendererCache.push(comp);
comp.renderPriority = node._sortingEnabled ? node._sortingPriority : renderPriority;
if(renderPriority != 0){
rendererOrder = true;
}
}
this._next._func(node);
};
//@ts-ignore
cc.RenderFlow.prototype._postRender = function (node) {
let comp = node._renderComponent;
if(comp instanceof cc.Mask){
flushRendererCache();
}
comp._checkBacth(_batcher, node._cullingMask);
comp._assembler.postFillBuffers(comp, _batcher);
this._next._func(node);
};
//@ts-ignore
cc.RenderFlow.prototype._children = function (node) {
let cullingMask = _cullingMask;
let batcher = _batcher;
let preRenderPriority = renderPriority;
let parentOpacity = batcher.parentOpacity;
let opacity = (batcher.parentOpacity *= (node._opacity / 255));
renderPriority = node._sortingEnabled ? node._sortingPriority : renderPriority;
// console.log(`${node.name} ${renderPriority}`);
//@ts-ignore
let worldTransformFlag = batcher.worldMatDirty ? cc.RenderFlow.FLAG_WORLD_TRANSFORM : 0;
//@ts-ignore
let worldOpacityFlag = batcher.parentOpacityDirty ? cc.RenderFlow.FLAG_OPACITY_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 |= 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);
// @ts-ignore
cc.RenderFlow.flows[c._renderFlag]._func(c);
c._color._val = colorVal;
}
batcher.parentOpacity = parentOpacity;
renderPriority = preRenderPriority;
this._next._func(node);
};

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "d9ee1293-73e0-4588-a058-685d75be1912",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,13 @@
{
"ver": "1.1.3",
"uuid": "10d7cfa4-65ae-4b25-8725-2630ae630cd3",
"importer": "folder",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}

View File

@ -1,19 +1,18 @@
/**************************************************************************** /****************************************************************************
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2019 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited, of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You to use Cocos Creator solely to develop games on your target platforms. You shall
shall not use Cocos Creator software for developing other software or tools not use Cocos Creator software for developing other software or tools that's
that's used for developing games. You are not granted to publish, distribute, used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator. sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold. The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -23,22 +22,10 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
#pragma once
#include "cocos/cocos.h" let NodeUnit = require('./node-unit');
let NodeMemPool = require('./node-mem-pool');
/** module.exports = {
@brief The cocos2d Application. NodeMemPool: new NodeMemPool(NodeUnit)
The reason for implement as private inheritance is to hide some interface call
by Director.
*/
class Game : public cc::BaseGame {
public:
Game();
int init() override;
// bool init() override;
void onPause() override;
void onResume() override;
void onClose() override;
}; };

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "eb098cc5-0be2-48ee-8103-989d20216bda",
"importer": "javascript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,109 @@
/****************************************************************************
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
let MemPool = function (unitClass) {
this._unitClass = unitClass;
this._pool = [];
this._findOrder = [];
if (CC_JSB && CC_NATIVERENDERER) {
this._initNative();
}
};
let proto = MemPool.prototype;
proto._initNative = function () {
this._nativeMemPool = new renderer.MemPool();
};
proto._buildUnit = function (unitID) {
let unit = new this._unitClass(unitID, this);
if (CC_JSB && CC_NATIVERENDERER) {
this._nativeMemPool.updateCommonData(unitID, unit._data, unit._signData);
}
return unit;
};
proto._destroyUnit = function (unitID) {
this._pool[unitID] = null;
for (let idx = 0, n = this._findOrder.length; idx < n; idx++) {
let unit = this._findOrder[idx];
if (unit && unit.unitID == unitID) {
this._findOrder.splice(idx, 1);
break;
}
}
if (CC_JSB && CC_NATIVERENDERER) {
this._nativeMemPool.removeCommonData(unitID);
}
};
proto._findUnitID = function () {
let unitID = 0;
let pool = this._pool;
while (pool[unitID]) unitID++;
return unitID;
};
proto.pop = function () {
let findUnit = null;
let idx = 0;
let findOrder = this._findOrder;
let pool = this._pool;
for (let n = findOrder.length; idx < n; idx++) {
let unit = findOrder[idx];
if (unit && unit.hasSpace()) {
findUnit = unit;
break;
}
}
if (!findUnit) {
let unitID = this._findUnitID();
findUnit = this._buildUnit(unitID);
pool[unitID] = findUnit;
findOrder.push(findUnit);
idx = findOrder.length - 1;
}
// swap has space unit to first position, so next find will fast
let firstUnit = findOrder[0];
if (firstUnit !== findUnit) {
findOrder[0] = findUnit;
findOrder[idx] = firstUnit;
}
return findUnit.pop();
};
proto.push = function (info) {
let unit = this._pool[info.unitID];
unit.push(info.index);
if (this._findOrder.length > 1 && unit.isAllFree()) {
this._destroyUnit(info.unitID);
}
return unit;
};
module.exports = MemPool;

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "13cfc2d4-b859-42dc-917a-561662386b76",
"importer": "javascript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -1,19 +1,18 @@
/**************************************************************************** /****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2019 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited, of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You to use Cocos Creator solely to develop games on your target platforms. You shall
shall not use Cocos Creator software for developing other software or tools not use Cocos Creator software for developing other software or tools that's
that's used for developing games. You are not granted to publish, distribute, used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator. sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold. The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -23,43 +22,28 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
#include "Game.h"
#ifndef GAME_NAME let MemPool = require('./mem-pool');
#define GAME_NAME "CocosGame"; let NodeMemPool = function (unitClass) {
#endif MemPool.call(this, unitClass);
};
#ifndef SCRIPT_XXTEAKEY (function(){
#define SCRIPT_XXTEAKEY ""; let Super = function(){};
#endif Super.prototype = MemPool.prototype;
NodeMemPool.prototype = new Super();
})();
Game::Game() = default; let proto = NodeMemPool.prototype;
proto._initNative = function () {
this._nativeMemPool = new renderer.NodeMemPool();
};
int Game::init() { proto._destroyUnit = function (unitID) {
_windowInfo.title = GAME_NAME; MemPool.prototype._destroyUnit.call(this, unitID);
// configurate window size if (CC_JSB && CC_NATIVERENDERER) {
// _windowInfo.height = 600; this._nativeMemPool.removeNodeData(unitID);
// _windowInfo.width = 800; }
};
#if CC_DEBUG module.exports = NodeMemPool;
_debuggerInfo.enabled = true;
#else
_debuggerInfo.enabled = false;
#endif
_debuggerInfo.port = 6086;
_debuggerInfo.address = "0.0.0.0";
_debuggerInfo.pauseOnStart = false;
_xxteaKey = SCRIPT_XXTEAKEY;
BaseGame::init();
return 0;
}
void Game::onPause() { BaseGame::onPause(); }
void Game::onResume() { BaseGame::onResume(); }
void Game::onClose() { BaseGame::onClose(); }
CC_REGISTER_APPLICATION(Game);

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "caa4d37a-9df4-4a7b-9407-eafa3c27df76",
"importer": "javascript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,158 @@
/****************************************************************************
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
const FLOAT_ARRAY_TYPE = (CC_JSB && CC_NATIVERENDERER) ? Float32Array : Float64Array;
const FLOAT_BYTES = (CC_JSB && CC_NATIVERENDERER) ? 4 : 8;
const Uint32_Bytes = 4;
const Uint8_Bytes = 1;
// Space : [Dirty] [Size:4 Uint32]
const Dirty_Type = Uint32Array;
const Dirty_Members = 1;
const Dirty_Stride = Dirty_Members * Uint32_Bytes;
// Space : [TRS] [Size:4 * 10 Float32|Float64]
const TRS_Members = 10;
const TRS_Stride = TRS_Members * FLOAT_BYTES;
// Space : [LocalMatrix] [Size:4 * 16 Float32|Float64]
const LocalMatrix_Members = 16;
const LocalMatrix_Stride = LocalMatrix_Members * FLOAT_BYTES;
// Space : [WorldMatrix] [Size:4 * 16 Float32|Float64]
const WorldMatrix_Members = 16;
const WorldMatrix_Stride = WorldMatrix_Members * FLOAT_BYTES;
// Space : [sortingPriority] [Size:4 * 1 Float32|Float64]
const SortingPriority_Members = 1;
const SortingPriority_Stride = SortingPriority_Members * FLOAT_BYTES;
// Space : [Parent Unit] [Size:4 Uint32]
// Space : [Parent Index] [Size:4 Uint32]
const Parent_Type = Uint32Array;
const Parent_Members = 2;
const Parent_Stride = Parent_Members * Uint32_Bytes;
// Space : [ZOrder] [Size:4 Uint32]
const ZOrder_Type = Uint32Array;
const ZOrder_Members = 1;
const ZOrder_Stride = ZOrder_Members * Uint32_Bytes;
// Space : [CullingMask] [Size:4 Int32]
const CullingMask_Type = Int32Array;
const CullingMask_Members = 1;
const CullingMask_Stride = CullingMask_Members * Uint32_Bytes;
// Space : [Opacity] [Size:1 Uint8]
const Opacity_Type = Uint8Array;
const Opacity_Members = 1;
const Opacity_Stride = Opacity_Members * Uint8_Bytes;
// Space : [Is3D] [Size:1 Uint8]
const Is3D_Type = Uint8Array;
const Is3D_Members = 1;
const Is3D_Stride = Is3D_Members * Uint8_Bytes;
// Space : [sortingEnabled] [Size:1 Uint8]
const SortingEnabled_Type = Uint8Array;
const SortingEnabled_Members = 1;
const SortingEnabled_Stride = SortingEnabled_Members * Uint8_Bytes;
// Space : [NodePtr] [Size:4 * 2 Uint32]
const Node_Type = Uint32Array;
const Node_Members = 2;
// Space : [Skew] [Size:4 * 2 Float32]
const Skew_Members = 2;
const Skew_Stride = Skew_Members * FLOAT_BYTES;
let UnitBase = require('./unit-base');
let NodeUnit = function (unitID, memPool) {
UnitBase.call(this, unitID, memPool);
let contentNum = this._contentNum;
this.trsList = new FLOAT_ARRAY_TYPE(contentNum * TRS_Members);
this.localMatList = new FLOAT_ARRAY_TYPE(contentNum * LocalMatrix_Members);
this.worldMatList = new FLOAT_ARRAY_TYPE(contentNum * WorldMatrix_Members);
if (CC_JSB && CC_NATIVERENDERER) {
this.dirtyList = new Dirty_Type(contentNum * Dirty_Members);
this.parentList = new Parent_Type(contentNum * Parent_Members);
this.zOrderList = new ZOrder_Type(contentNum * ZOrder_Members);
this.cullingMaskList = new CullingMask_Type(contentNum * CullingMask_Members);
this.opacityList = new Opacity_Type(contentNum * Opacity_Members);
this.is3DList = new Is3D_Type(contentNum * Is3D_Members);
this.nodeList = new Node_Type(contentNum * Node_Members);
this.skewList = new FLOAT_ARRAY_TYPE(contentNum * Skew_Members);
this.sortingPriorityList = new FLOAT_ARRAY_TYPE(contentNum * SortingPriority_Stride);
this.sortingEnabledList = new SortingEnabled_Type(contentNum * SortingEnabled_Stride);
this._memPool._nativeMemPool.updateNodeData(
unitID,
this.dirtyList,
this.trsList,
this.localMatList,
this.worldMatList,
this.parentList,
this.zOrderList,
this.cullingMaskList,
this.opacityList,
this.is3DList,
this.nodeList,
this.skewList,
this.sortingPriorityList,
this.sortingEnabledList
);
}
for (let i = 0; i < contentNum; i ++) {
let space = this._spacesData[i];
space.trs = new FLOAT_ARRAY_TYPE(this.trsList.buffer, i * TRS_Stride, TRS_Members);
space.localMat = new FLOAT_ARRAY_TYPE(this.localMatList.buffer, i * LocalMatrix_Stride, LocalMatrix_Members);
space.worldMat = new FLOAT_ARRAY_TYPE(this.worldMatList.buffer, i * WorldMatrix_Stride, WorldMatrix_Members);
if (CC_JSB && CC_NATIVERENDERER) {
space.dirty = new Dirty_Type(this.dirtyList.buffer, i * Dirty_Stride, Dirty_Members);
space.parent = new Parent_Type(this.parentList.buffer, i * Parent_Stride, Parent_Members);
space.zOrder = new ZOrder_Type(this.zOrderList.buffer, i * ZOrder_Stride, ZOrder_Members);
space.cullingMask = new CullingMask_Type(this.cullingMaskList.buffer, i * CullingMask_Stride, CullingMask_Members);
space.opacity = new Opacity_Type(this.opacityList.buffer, i * Opacity_Stride, Opacity_Members);
space.is3D = new Is3D_Type(this.is3DList.buffer, i * Is3D_Stride, Is3D_Members);
space.skew = new FLOAT_ARRAY_TYPE(this.skewList.buffer, i * Skew_Stride, Skew_Members);
space.sortingPriority = new FLOAT_ARRAY_TYPE(this.sortingPriorityList.buffer, i * SortingPriority_Stride, SortingPriority_Members);
space.sortingEnabled = new SortingEnabled_Type(this.sortingEnabledList.buffer, i * SortingEnabled_Stride, SortingEnabled_Members);
}
}
};
(function(){
let Super = function(){};
Super.prototype = UnitBase.prototype;
NodeUnit.prototype = new Super();
})();
module.exports = NodeUnit;

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "3e3243b6-45a4-4eec-9abb-805de55e8b1f",
"importer": "javascript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,167 @@
/****************************************************************************
Copyright (c) 2019 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
// Unit has many segment, layout such as :
// Head Free Pointer + Using Segment Num + Segment 1 + Segment 2 + Segment 3 ...
// sign data format
// Space : [If Free Flag] [Size:1 Uint16]
// Space : [Next Free Index] [Size:1 Uint16]
// invalid pointer value
let POINTER_INVALID_FLAG = 0xffff;
let SPACE_FREE_FLAG = 0x0;
let SPACE_USE_FLAG = 0x1;
let POS_NEXT_FREE = 0;
let POS_FREE_FLAG = 1;
let UnitBase = function (unitID, memPool, contentNum) {
contentNum = contentNum || 128;
// set unit id
this.unitID = unitID;
this._memPool = memPool;
this._data = new Uint16Array(2);
// head of the free content index
this._data[0] = 0;
// using segment num
this._data[1] = 0;
this._contentNum = contentNum;
this._signData = new Uint16Array(this._contentNum * 2);
this._spacesData = [];
for (let i = 0; i < contentNum; i++) {
let signIndex = i * 2;
// store content block index but not sign array index
this._signData[signIndex + POS_NEXT_FREE] = i + 1;
this._signData[signIndex + POS_FREE_FLAG] = SPACE_FREE_FLAG;
this._spacesData[i] = {
index: i,
unitID: unitID,
};
}
// last one has no next space;
this._signData[(contentNum - 1) * 2] = POINTER_INVALID_FLAG;
};
let UnitBaseProto = UnitBase.prototype;
UnitBaseProto.hasSpace = function () {
return this._data[0] !== POINTER_INVALID_FLAG;
};
UnitBaseProto.isAllFree = function () {
return this._data[1] == 0;
};
// pop space from unit
UnitBaseProto.pop = function () {
let headFreeIndex = this._data[0];
if (headFreeIndex === POINTER_INVALID_FLAG) return null;
let index = headFreeIndex;
let signIndex = index * 2;
let space = this._spacesData[index];
// set use flag
this._signData[signIndex + POS_FREE_FLAG] = SPACE_USE_FLAG;
// store new next free space index
this._data[0] = this._signData[signIndex + POS_NEXT_FREE];
// add using segment num
this._data[1]++;
return space;
};
// push back to unit
UnitBaseProto.push = function (index) {
let signIndex = index * 2;
// set free flag
this._signData[signIndex + POS_FREE_FLAG] = SPACE_FREE_FLAG;
// store head free index to the space
this._signData[signIndex + POS_NEXT_FREE] = this._data[0];
// update head free index
this._data[0] = index;
// sub using segment num
this._data[1]--;
};
// dump all space info
UnitBaseProto.dump = function () {
let spaceNum = 0;
let index = this._data[0];
let freeStr = "";
while (index != POINTER_INVALID_FLAG) {
spaceNum ++;
freeStr += index + "->";
index = this._signData[index * 2 + POS_NEXT_FREE];
}
let usingNum = 0;
let usingStr = "";
let contentNum = this._contentNum;
for (let i = 0; i < contentNum; i++) {
let freeFlag = this._signData[i * 2 + POS_FREE_FLAG];
if (freeFlag == SPACE_USE_FLAG) {
usingNum ++;
usingStr += i + "->";
}
}
let totalNum = spaceNum + usingNum;
console.log(
"unitID:", this.unitID,
"spaceNum:", spaceNum,
"calc using num:", usingNum,
'store using num:', this._data[1],
'calc total num:', totalNum,
'actually total num:', this._contentNum
);
console.log("free info:", freeStr);
console.log("using info:", usingStr);
if (usingNum != this._data[1]) {
cc.error(
'using num error',
"calc using num:", usingNum,
'store using num:', this._data[1]
);
}
if (spaceNum + usingNum != this._contentNum) {
cc.error(
'total num error',
'calc total num:', totalNum,
'actually total num:', this._contentNum
);
}
};
module.exports = UnitBase;

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "b1e0a00c-ca02-49ba-9561-19c4ca3078df",
"importer": "javascript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "8f6e89ff-d851-45d4-bab8-d32cd5371760",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,55 @@
import { ORDER_IN_LAYER_MAX, SortingLayer } from './sorting-define';
const { ccclass, property, disallowMultiple, executeInEditMode } = cc._decorator;
@ccclass('lcc-ui/SortingGroup')
@disallowMultiple()
@executeInEditMode()
export class SortingGroup extends cc.Component {
/**
*
*/
@property({type: cc.Enum(SortingLayer)})
private _sortingLayer:SortingLayer = SortingLayer.DEFAULT;
/**
*
*/
@property({type: cc.Enum(SortingLayer)})
get sortingLayer(){
return this._sortingLayer;
}
set sortingLayer(value:SortingLayer){
this._sortingLayer = value;
// this.node.sortingPriority = Math.sign(this._sortingLayer) * (Math.abs(this._sortingLayer) * ORDER_IN_LAYER_MAX + this._orderInLayer);
}
/**
*
*/
@property({ type:cc.Float, min: 0, max : ORDER_IN_LAYER_MAX })
private _orderInLayer:number = 0;
/**
*
*/
@property({ type:cc.Float, min: 0, max : ORDER_IN_LAYER_MAX })
get orderInLayer(){
return this._orderInLayer;
}
set orderInLayer(value:number){
this._orderInLayer = value;
// this.node.sortingPriority = Math.sign(this._sortingLayer) * (Math.abs(this._sortingLayer) * ORDER_IN_LAYER_MAX + this._orderInLayer);
}
onEnable(){
this.node.sortingPriority = Math.sign(this._sortingLayer) * (Math.abs(this._sortingLayer) * ORDER_IN_LAYER_MAX + this._orderInLayer);
this.node.sortingEnabled = true;
}
onDisable(){
this.node.sortingPriority = 0;
this.node.sortingEnabled = false;
}
}

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "ac8d9166-422c-4cd3-a0be-0bdcddb52da2",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

13
2.4.11/assets/test.meta Normal file
View File

@ -0,0 +1,13 @@
{
"ver": "1.1.3",
"uuid": "d29d0f8f-d7b1-4b60-a834-224ebe63fb72",
"importer": "folder",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}

View File

@ -0,0 +1,13 @@
{
"ver": "1.1.3",
"uuid": "b5d585a3-e6d1-4710-aa13-dc6f42f7bbd1",
"importer": "folder",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
{
"ver": "1.3.2",
"uuid": "5319446a-3497-48fc-99a7-9806589fd3c6",
"importer": "prefab",
"optimizationPolicy": "AUTO",
"asyncLoadAssets": false,
"readonly": false,
"subMetas": {}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
{
"ver": "1.3.2",
"uuid": "77b9c6bb-79b1-4086-86fa-ac30b56d67cc",
"importer": "prefab",
"optimizationPolicy": "AUTO",
"asyncLoadAssets": false,
"readonly": false,
"subMetas": {}
}

View File

@ -0,0 +1,13 @@
{
"ver": "1.1.3",
"uuid": "e2dc59cc-2d8b-4b93-adab-48a29cdcf581",
"importer": "folder",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
{
"ver": "1.3.2",
"uuid": "c6ba3258-b873-4d4f-b31a-60f4c79e523a",
"importer": "scene",
"asyncLoadAssets": false,
"autoReleaseAssets": false,
"subMetas": {}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
{
"ver": "1.3.2",
"uuid": "6b1f9620-447d-4dcc-aeac-09aca68c29e7",
"importer": "scene",
"asyncLoadAssets": false,
"autoReleaseAssets": false,
"subMetas": {}
}

View File

@ -0,0 +1,13 @@
{
"ver": "1.1.3",
"uuid": "845ea615-d321-4ea5-ab0e-4c6292a58d18",
"importer": "folder",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}

View File

@ -0,0 +1,43 @@
// Learn TypeScript:
// - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
// - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
// - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html
const {ccclass, property} = cc._decorator;
@ccclass
export default class ListTestItem extends cc.Component {
@property({type: cc.Label})
rankText:cc.Label = null;
@property({type: cc.Label})
goldText:cc.Label = null;
@property({type: cc.Sprite})
flagImage:cc.Sprite = null;
@property({type: cc.Label})
levelText:cc.Label = null;
@property({type: cc.ProgressBar})
levelBar:cc.ProgressBar = null;
@property({type: cc.Label})
descText:cc.Label = null;
@property({type: cc.Node})
uiOpacity:cc.Node = null;
randomData(index:number, flagSpriteFrame:cc.SpriteFrame){
this.rankText.string = String(index);
this.goldText.string = String(Math.floor(1000 + Math.random()* 1000));
this.flagImage.spriteFrame = flagSpriteFrame;
this.levelText.string = `lv.${Math.floor(Math.random()* 100)}`;
this.levelBar.progress = Math.random();
this.descText.string = `什么也没留下 - ${index}`;
this.uiOpacity.opacity = 100 + Math.floor(Math.random() * 155);
}
}

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "9f5387d6-696a-4491-82ea-1a443403ed3c",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,28 @@
import ListTestItem from "./list-test-item";
const { ccclass, property } = cc._decorator;
@ccclass
export class TestScene extends cc.Component {
@property({type:cc.Prefab})
listTestItemPrefab:cc.Prefab = null;
@property({type:cc.Node})
listContent:cc.Node = null;
@property({type:[cc.SpriteFrame]})
flagSpriteFrames:cc.SpriteFrame[] = [];
@property
listItemMax:number = 200;
start() {
for(let i = 0; i < this.listItemMax; i++){
let node = cc.instantiate(this.listTestItemPrefab);
node.parent = this.listContent;
let item = node.getComponent(ListTestItem);
item?.randomData(i + 1, this.flagSpriteFrames[Math.floor(Math.random() * this.flagSpriteFrames.length)])
}
}
}

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "66495605-543c-44a7-b208-dfc48bdce8b8",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,13 @@
{
"ver": "1.1.3",
"uuid": "0927e59d-b693-4ac2-9e53-0eeffbd0e543",
"importer": "folder",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}

View File

@ -0,0 +1,3 @@
{
"__type__": "cc.SpriteAtlas"
}

View File

@ -0,0 +1,23 @@
{
"ver": "1.2.5",
"uuid": "42c27816-9000-4fb5-a99e-5aea6002d77b",
"importer": "auto-atlas",
"maxWidth": 1024,
"maxHeight": 1024,
"padding": 2,
"compressionLevel": 6,
"allowRotation": true,
"forceSquared": false,
"powerOfTwo": false,
"algorithm": "MaxRects",
"format": "png",
"quality": 80,
"contourBleed": true,
"paddingBleed": true,
"filterUnused": true,
"packable": false,
"premultiplyAlpha": false,
"filterMode": "bilinear",
"platformSettings": {},
"subMetas": {}
}

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "a095424e-cf6f-4be2-a7b1-34a3ccc2f2ec",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 105,
"height": 100,
"platformSettings": {},
"subMetas": {
"box-1": {
"ver": "1.0.6",
"uuid": "1e6042b1-be42-4958-aed1-1b837ad8b6ab",
"importer": "sprite-frame",
"rawTextureUuid": "a095424e-cf6f-4be2-a7b1-34a3ccc2f2ec",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 105,
"height": 100,
"rawWidth": 105,
"rawHeight": 100,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 873 B

After

Width:  |  Height:  |  Size: 873 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "3a1e47f2-e0c6-48af-8c8c-e48f9f95a7d5",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 171,
"height": 27,
"platformSettings": {},
"subMetas": {
"box-2": {
"ver": "1.0.6",
"uuid": "48a96f63-2eeb-4165-a0ca-654da41ec4ae",
"importer": "sprite-frame",
"rawTextureUuid": "3a1e47f2-e0c6-48af-8c8c-e48f9f95a7d5",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 171,
"height": 27,
"rawWidth": 171,
"rawHeight": 27,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 451 B

After

Width:  |  Height:  |  Size: 451 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "02a30094-7497-4650-81e0-0c49c1c28a2a",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 171,
"height": 27,
"platformSettings": {},
"subMetas": {
"box-3": {
"ver": "1.0.6",
"uuid": "6b84a7e0-d31a-42ab-90de-bb04c9ea0d2f",
"importer": "sprite-frame",
"rawTextureUuid": "02a30094-7497-4650-81e0-0c49c1c28a2a",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 171,
"height": 27,
"rawWidth": 171,
"rawHeight": 27,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "a218f909-f8aa-4325-9d22-af05af387299",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 240,
"height": 241,
"platformSettings": {},
"subMetas": {
"box-4": {
"ver": "1.0.6",
"uuid": "f122dcc2-a3bf-4eb3-a7a1-e93654669f51",
"importer": "sprite-frame",
"rawTextureUuid": "a218f909-f8aa-4325-9d22-af05af387299",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0.5,
"offsetY": 0.5,
"trimX": 5,
"trimY": 5,
"width": 231,
"height": 230,
"rawWidth": 240,
"rawHeight": 241,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 952 B

After

Width:  |  Height:  |  Size: 952 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "b77831b2-df3a-4606-9a8e-0423d0a664a5",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 240,
"height": 241,
"platformSettings": {},
"subMetas": {
"box-5": {
"ver": "1.0.6",
"uuid": "9b9dc23d-1001-44d7-9c36-a7d960f7a49d",
"importer": "sprite-frame",
"rawTextureUuid": "b77831b2-df3a-4606-9a8e-0423d0a664a5",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0.5,
"offsetY": 0.5,
"trimX": 5,
"trimY": 5,
"width": 231,
"height": 230,
"rawWidth": 240,
"rawHeight": 241,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 200 B

After

Width:  |  Height:  |  Size: 200 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "2f2e41cc-a8a8-4438-9ff2-014f9282ed06",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 70,
"height": 32,
"platformSettings": {},
"subMetas": {
"box-6": {
"ver": "1.0.6",
"uuid": "f195da9c-9b72-4765-9535-724d8383e63e",
"importer": "sprite-frame",
"rawTextureUuid": "2f2e41cc-a8a8-4438-9ff2-014f9282ed06",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 70,
"height": 32,
"rawWidth": 70,
"rawHeight": 32,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 105 B

After

Width:  |  Height:  |  Size: 105 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "1fe24969-ad78-4ca9-b410-4ba370b3a890",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 63,
"height": 43,
"platformSettings": {},
"subMetas": {
"box-7": {
"ver": "1.0.6",
"uuid": "f625fa33-7315-4748-89a5-cf48448980c9",
"importer": "sprite-frame",
"rawTextureUuid": "1fe24969-ad78-4ca9-b410-4ba370b3a890",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 63,
"height": 43,
"rawWidth": 63,
"rawHeight": 43,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "5849d769-7609-4f98-9510-fb88660f795a",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 64,
"height": 41,
"platformSettings": {},
"subMetas": {
"box-8": {
"ver": "1.0.6",
"uuid": "2e46e265-3945-4ae5-99d4-8f4eb56f391a",
"importer": "sprite-frame",
"rawTextureUuid": "5849d769-7609-4f98-9510-fb88660f795a",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 64,
"height": 41,
"rawWidth": 64,
"rawHeight": 41,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 153 B

After

Width:  |  Height:  |  Size: 153 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "240b0fb6-a282-4b50-881f-559e9d9363e4",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 63,
"height": 29,
"platformSettings": {},
"subMetas": {
"box-9": {
"ver": "1.0.6",
"uuid": "157e8a85-da38-415f-93f2-ccda0b947415",
"importer": "sprite-frame",
"rawTextureUuid": "240b0fb6-a282-4b50-881f-559e9d9363e4",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 63,
"height": 29,
"rawWidth": 63,
"rawHeight": 29,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 569 B

After

Width:  |  Height:  |  Size: 569 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "78813583-64ea-4df9-90dc-410129a1d07d",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 210,
"height": 80,
"platformSettings": {},
"subMetas": {
"btn-black": {
"ver": "1.0.6",
"uuid": "ea1039ee-663b-4557-be34-c1c9adf6a822",
"importer": "sprite-frame",
"rawTextureUuid": "78813583-64ea-4df9-90dc-410129a1d07d",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 210,
"height": 80,
"rawWidth": 210,
"rawHeight": 80,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 838 B

After

Width:  |  Height:  |  Size: 838 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "acd864b8-87e0-46c3-aaaa-d8585dd24570",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 68,
"height": 36,
"platformSettings": {},
"subMetas": {
"btn-white-2": {
"ver": "1.0.6",
"uuid": "f7af8780-666e-4912-b0f4-963319c0afb4",
"importer": "sprite-frame",
"rawTextureUuid": "acd864b8-87e0-46c3-aaaa-d8585dd24570",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 68,
"height": 36,
"rawWidth": 68,
"rawHeight": 36,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 809 B

After

Width:  |  Height:  |  Size: 809 B

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "954ea7ef-12bb-43aa-8077-ed7a567b460c",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 214,
"height": 84,
"platformSettings": {},
"subMetas": {
"btn-white": {
"ver": "1.0.6",
"uuid": "b8da036a-31c8-4ea9-8332-e33929b16e38",
"importer": "sprite-frame",
"rawTextureUuid": "954ea7ef-12bb-43aa-8077-ed7a567b460c",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 1,
"trimY": 1,
"width": 212,
"height": 82,
"rawWidth": 214,
"rawHeight": 84,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "ca4624dc-b082-4c76-871d-c96cb21fc8fd",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 249,
"height": 249,
"platformSettings": {},
"subMetas": {
"circle-countdown": {
"ver": "1.0.6",
"uuid": "097e1875-d5b0-43cc-8aad-64ae21d92aac",
"importer": "sprite-frame",
"rawTextureUuid": "ca4624dc-b082-4c76-871d-c96cb21fc8fd",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 2,
"trimY": 2,
"width": 245,
"height": 245,
"rawWidth": 249,
"rawHeight": 249,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "0e81c7eb-0241-43a9-b503-0f91db7e0f37",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 84,
"height": 84,
"platformSettings": {},
"subMetas": {
"flag-disconnection": {
"ver": "1.0.6",
"uuid": "9f408d81-d67e-4968-b885-0edece9785f3",
"importer": "sprite-frame",
"rawTextureUuid": "0e81c7eb-0241-43a9-b503-0f91db7e0f37",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0.5,
"offsetY": 0,
"trimX": 2,
"trimY": 2,
"width": 81,
"height": 80,
"rawWidth": 84,
"rawHeight": 84,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "d3490a01-c27e-4704-950f-dcd87a95d179",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 84,
"height": 84,
"platformSettings": {},
"subMetas": {
"flag-eliminated": {
"ver": "1.0.6",
"uuid": "4528c934-0086-44da-8923-a956a624cb75",
"importer": "sprite-frame",
"rawTextureUuid": "d3490a01-c27e-4704-950f-dcd87a95d179",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0.5,
"offsetY": 0,
"trimX": 2,
"trimY": 2,
"width": 81,
"height": 80,
"rawWidth": 84,
"rawHeight": 84,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "eaa9875d-572c-46ea-b275-f0bd36cc6697",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 84,
"height": 84,
"platformSettings": {},
"subMetas": {
"flag-escape": {
"ver": "1.0.6",
"uuid": "5dde49b3-365a-4e01-b7a5-a079116b7d7c",
"importer": "sprite-frame",
"rawTextureUuid": "eaa9875d-572c-46ea-b275-f0bd36cc6697",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0.5,
"offsetY": 0,
"trimX": 2,
"trimY": 2,
"width": 81,
"height": 80,
"rawWidth": 84,
"rawHeight": 84,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,38 @@
{
"ver": "2.3.7",
"uuid": "bc529642-594d-4486-aafb-bfd2d3edf02c",
"importer": "texture",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"width": 60,
"height": 61,
"platformSettings": {},
"subMetas": {
"gold": {
"ver": "1.0.6",
"uuid": "f74c16b3-291b-41b4-8542-9b85fbca505b",
"importer": "sprite-frame",
"rawTextureUuid": "bc529642-594d-4486-aafb-bfd2d3edf02c",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 60,
"height": 61,
"rawWidth": 60,
"rawHeight": 61,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

32207
2.4.11/creator.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

15
2.4.11/jsconfig.json Normal file
View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"experimentalDecorators": true
},
"exclude": [
"node_modules",
".vscode",
"library",
"local",
"settings",
"temp"
]
}

View File

@ -0,0 +1,397 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#include "ModelBatcher.hpp"
#include "RenderFlow.hpp"
#include "StencilManager.hpp"
#include "assembler/RenderDataList.hpp"
#include "NodeProxy.hpp"
#include <algorithm>
RENDERER_BEGIN
#define INIT_MODEL_LENGTH 16
ModelBatcher::ModelBatcher(RenderFlow* flow)
: _flow(flow)
, _modelOffset(0)
, _cullingMask(0)
, _walking(false)
, _currEffect(nullptr)
, _buffer(nullptr)
, _useModel(false)
, _node(nullptr)
{
for (int i = 0; i < INIT_MODEL_LENGTH; i++)
{
_modelPool.push_back(new Model());
}
_rendererCache.reserve(1024);
_stencilMgr = StencilManager::getInstance();
}
ModelBatcher::~ModelBatcher()
{
setCurrentEffect(nullptr);
setNode(nullptr);
for (int i = 0; i < _modelPool.size(); i++)
{
auto model = _modelPool[i];
delete model;
}
_modelPool.clear();
for (auto iter = _buffers.begin(); iter != _buffers.end(); ++iter)
{
MeshBuffer *buffer = iter->second;
delete buffer;
}
_buffers.clear();
}
void ModelBatcher::reset()
{
for (int i = 0; i < _modelOffset; ++i)
{
Model* model = _modelPool[i];
model->reset();
}
_flow->getRenderScene()->removeModels();
_modelOffset = 0;
for (auto iter : _buffers)
{
iter.second->reset();
}
_buffer = nullptr;
_commitState = CommitState::None;
setCurrentEffect(nullptr);
setNode(nullptr);
_ia.clear();
_cullingMask = 0;
_walking = false;
_useModel = false;
_modelMat.set(Mat4::IDENTITY);
_stencilMgr->reset();
}
void ModelBatcher::changeCommitState(CommitState state)
{
if (_commitState == state) return;
switch(_commitState)
{
case CommitState::Custom:
flushIA();
break;
case CommitState::Common:
flush();
break;
default:
break;
}
setCurrentEffect(nullptr);
_commitState = state;
}
void ModelBatcher::commit(NodeProxy* node, Assembler* assembler, int cullingMask)
{
changeCommitState(CommitState::Common);
bool useModel = assembler->getUseModel();
bool ignoreWorldMatrix = assembler->isIgnoreWorldMatrix();
auto customWorldMat = assembler->getCustomWorldMatrix();
customWorldMat = customWorldMat ? customWorldMat : &node->getWorldMatrix();
const Mat4& worldMat = useModel && !ignoreWorldMatrix ? *customWorldMat : Mat4::IDENTITY;
auto asmDirty = assembler->isDirty(AssemblerBase::VERTICES_OPACITY_CHANGED);
auto nodeDirty = node->isDirty(RenderFlow::NODE_OPACITY_CHANGED);
auto needUpdateOpacity = (asmDirty || nodeDirty) && !assembler->isIgnoreOpacityFlag();
for (std::size_t i = 0, l = assembler->getIACount(); i < l; ++i)
{
assembler->beforeFillBuffers(i);
EffectVariant* effect = assembler->getEffect(i);
if (!effect) continue;
if (_currEffect == nullptr ||
_currEffect->getHash() != effect->getHash() ||
_cullingMask != cullingMask || useModel)
{
// Break auto batch
flush();
setNode(_useModel ? node : nullptr);
setCurrentEffect(effect);
_modelMat.set(worldMat);
_useModel = useModel;
_cullingMask = cullingMask;
}
if (needUpdateOpacity)
{
assembler->updateOpacity(i, node->getRealOpacity());
}
assembler->fillBuffers(node, this, i);
}
}
void ModelBatcher::commitIA(NodeProxy* node, CustomAssembler* assembler, int cullingMask)
{
changeCommitState(CommitState::Custom);
EffectVariant* effect = assembler->getEffect(0);
if (!effect) return;
auto customIA = assembler->getIA(0);
if (!customIA) return;
std::size_t iaCount = assembler->getIACount();
bool useModel = assembler->getUseModel();
auto customWorldMat = assembler->getCustomWorldMatrix();
customWorldMat = customWorldMat ? customWorldMat : &node->getWorldMatrix();
const Mat4& worldMat = useModel ? *customWorldMat : Mat4::IDENTITY;
if (_currEffect == nullptr ||
_currEffect->getHash() != effect->getHash() ||
_cullingMask != cullingMask || useModel ||
!_ia.isMergeable(*customIA))
{
flushIA();
setNode(_useModel ? node : nullptr);
setCurrentEffect(effect);
_modelMat.set(worldMat);
_useModel = useModel;
_cullingMask = cullingMask;
_ia.setVertexBuffer(customIA->getVertexBuffer());
_ia.setIndexBuffer(customIA->getIndexBuffer());
_ia.setStart(customIA->getStart());
_ia.setCount(0);
}
for (std::size_t i = 0; i < iaCount; i++ )
{
customIA = assembler->getIA(i);
effect = assembler->getEffect(i);
if (!effect) continue;
if (i > 0)
{
flushIA();
setNode(_useModel ? node : nullptr);
setCurrentEffect(effect);
_modelMat.set(worldMat);
_useModel = useModel;
_cullingMask = cullingMask;
_ia.setVertexBuffer(customIA->getVertexBuffer());
_ia.setIndexBuffer(customIA->getIndexBuffer());
_ia.setStart(customIA->getStart());
_ia.setCount(0);
}
_ia.setCount(_ia.getCount() + customIA->getCount());
}
}
void ModelBatcher::flushIA()
{
if (_commitState != CommitState::Custom)
{
return;
}
if (!_walking || !_currEffect || _ia.getCount() <= 0)
{
_ia.clear();
return;
}
// Stencil manager process
_stencilMgr->handleEffect(_currEffect);
// Generate model
Model* model = nullptr;
if (_modelOffset >= _modelPool.size())
{
model = new Model();
_modelPool.push_back(model);
}
else
{
model = _modelPool[_modelOffset];
}
_modelOffset++;
model->setWorldMatix(_modelMat);
model->setCullingMask(_cullingMask);
model->setEffect(_currEffect);
model->setNode(_node);
model->setInputAssembler(_ia);
_ia.clear();
_flow->getRenderScene()->addModel(model);
}
void ModelBatcher::flush()
{
if (_commitState != CommitState::Common)
{
return;
}
if (!_walking || !_currEffect || !_buffer)
{
return;
}
int indexStart = _buffer->getIndexStart();
int indexOffset = _buffer->getIndexOffset();
int indexCount = indexOffset - indexStart;
if (indexCount <= 0)
{
return;
}
_ia.setVertexBuffer(_buffer->getVertexBuffer());
_ia.setIndexBuffer(_buffer->getIndexBuffer());
_ia.setStart(indexStart);
_ia.setCount(indexCount);
// Stencil manager process
_stencilMgr->handleEffect(_currEffect);
// Generate model
Model* model = nullptr;
if (_modelOffset >= _modelPool.size())
{
model = new Model();
_modelPool.push_back(model);
}
else
{
model = _modelPool[_modelOffset];
}
_modelOffset++;
model->setWorldMatix(_modelMat);
model->setCullingMask(_cullingMask);
model->setEffect(_currEffect);
model->setNode(_node);
model->setInputAssembler(_ia);
_ia.clear();
_flow->getRenderScene()->addModel(model);
_buffer->updateOffset();
}
void ModelBatcher::startBatch()
{
reset();
_walking = true;
}
void ModelBatcher::terminateBatch()
{
flush();
flushIA();
for (auto iter : _buffers)
{
iter.second->uploadData();
}
_walking = false;
}
void ModelBatcher::setNode(NodeProxy* node)
{
if (_node == node)
{
return;
}
CC_SAFE_RELEASE(_node);
_node = node;
CC_SAFE_RETAIN(_node);
}
void ModelBatcher::setCurrentEffect(EffectVariant* effect)
{
if (_currEffect == effect)
{
return;
}
CC_SAFE_RELEASE(_currEffect);
_currEffect = effect;
CC_SAFE_RETAIN(_currEffect);
};
MeshBuffer* ModelBatcher::getBuffer(VertexFormat* fmt)
{
if (_buffer != nullptr && fmt == _buffer->_vertexFmt)
{
return _buffer;
}
MeshBuffer* buffer = nullptr;
auto iter = _buffers.find(fmt);
if (iter == _buffers.end())
{
buffer = new MeshBuffer(this, fmt);
_buffers.emplace(fmt, buffer);
}
else
{
buffer = iter->second;
}
return buffer;
}
void ModelBatcher::flushRendererCache(){
if(_rendererCache.size() > 0){
if(_rendererOrder){
std::stable_sort(_rendererCache.begin(), _rendererCache.end(), [](NodeProxy* a, NodeProxy* b) { return a->getRenderPriority() < b->getRenderPriority(); });
}
CCLOGINFO("flushRendererCache : %d", _rendererCache.size());
for(std::vector<NodeProxy*>::iterator it = _rendererCache.begin(); it != _rendererCache.end(); it++){
NodeProxy* node = *it;
CCLOGINFO("%s %d", node->getName().c_str(), node->getRenderPriority());
node->getAssembler()->handle(node, this, _flow->getRenderScene());
}
_rendererCache.clear();
}
_rendererOrder = false;
}
RENDERER_END

View File

@ -0,0 +1,178 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include <map>
#include "../Macro.h"
#include "assembler/Assembler.hpp"
#include "assembler/CustomAssembler.hpp"
#include "MeshBuffer.hpp"
#include "../renderer/Renderer.h"
#include "math/CCMath.h"
RENDERER_BEGIN
class RenderFlow;
class StencilManager;
/**
* @addtogroup scene
* @{
*/
/**
* @brief ModelBatcher is responsible for transforming node's render handles into final render datas.
* It collects render data, batches different render handle together into Models and submits to render Scene.
*/
class ModelBatcher
{
public:
enum CommitState {
None,
Common,
Custom,
};
/**
* @brief The constructor.
*/
ModelBatcher(RenderFlow* flow);
/**
* @brief The destructor.
*/
~ModelBatcher();
/**
* @brief Reset all render buffer.
*/
void reset();
/**
* @brief Commit a render handle to the model batcher
* @param[in] node The node which owns the render handle
* @param[in] handle The render handle contains render datas
*/
void commit(NodeProxy* node, Assembler* handle, int cullingMask);
/**
* @brief Commit a custom render handle to the model batcher
* @param[in] node The node which owns the render handle
* @param[in] handle The custom render handle contains render datas
*/
void commitIA(NodeProxy* node, CustomAssembler* handle, int cullingMask);
/**
* @brief This method should be invoked before commit any render handles each frame.
* It notifies the model batcher to get ready for constructing Models
*/
void startBatch();
/**
* @brief Flush all cached render data into a new Model and add the Model to render Scene.
*/
void flush();
/**
* @brief Finished Custom input assmebler batch and add the Model to render Scene.
*/
void flushIA();
/**
* @brief Add new input assembler into current input assembler.
*/
void flushIA(InputAssembler* customIA);
/**
* @brief This method should be invoked after committed all render handles each frame.
*/
void terminateBatch();
/**
* @brief Gets a suitable MeshBuffer for the given VertexFormat.
* Render datas arranged in different VertexFormat can't share the same buffer.
* @param[in] fmt The VertexFormat
*/
MeshBuffer* getBuffer(VertexFormat* fmt);
/**
* @brief Gets the current MeshBuffer.
*/
const MeshBuffer* getCurrentBuffer() const { return _buffer; };
/**
* @brief Sets the current MeshBuffer.
* @param[in] buffer
*/
void setCurrentBuffer(MeshBuffer* buffer) { _buffer = buffer; };
/**
* @brief Gets the global RenderFlow pointer.
*/
RenderFlow* getFlow() const { return _flow; };
void setNode(NodeProxy* node);
void setCullingMask(int cullingMask) { _cullingMask = cullingMask; }
void setCurrentEffect(EffectVariant* effect);
void setUseModel(bool useModel) { _useModel = useModel; }
void changeCommitState(CommitState state);
void setSortingPriority(float_t value){
_sortingPriority = value;
}
float_t getSortingPriority() const {
return _sortingPriority;
}
void setRendererOrder(bool value){
_rendererOrder = value;
}
bool getRendererOrder() const {
return _rendererOrder;
}
void pushRendererCache(NodeProxy*value){
_rendererCache.push_back(value);
}
void flushRendererCache();
private:
int _modelOffset = 0;
int _cullingMask = 0;
bool _useModel = false;
bool _walking = false;
cocos2d::Mat4 _modelMat;
CommitState _commitState = CommitState::None;
NodeProxy* _node = nullptr;
MeshBuffer* _buffer = nullptr;
EffectVariant* _currEffect = nullptr;
RenderFlow* _flow = nullptr;
StencilManager* _stencilMgr = nullptr;
InputAssembler _ia;
std::vector<Model*> _modelPool;
std::unordered_map<VertexFormat*, MeshBuffer*> _buffers;
float_t _sortingPriority = 0;
bool _rendererOrder = false;
std::vector<NodeProxy*> _rendererCache;
};
// end of scene group
/// @}
RENDERER_END

View File

@ -0,0 +1,196 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#include "NodeMemPool.hpp"
#include "base/ccMacros.h"
RENDERER_BEGIN
UnitNode::UnitNode()
{
}
UnitNode::~UnitNode()
{
unset(&dirty, (uint8_t**)&dirtyData, &dirtyLen);
unset(&trs, (uint8_t**)&trsData, &trsLen);
unset(&localMat, (uint8_t**)&localMatData, &localMatLen);
unset(&worldMat, (uint8_t**)&worldMatData, &worldMatLen);
unset(&parent, (uint8_t**)&parentData, &parentLen);
unset(&zOrder, (uint8_t**)&zOrderData, &zOrderLen);
unset(&cullingMask, (uint8_t**)&cullingMaskData, &cullingMaskLen);
unset(&opacity, (uint8_t**)&opacityData, &opacityLen);
unset(&is3D, (uint8_t**)&is3DData, &is3DLen);
unset(&node, (uint8_t**)&nodeData, &nodeLen);
unset(&skew, (uint8_t**)&skewData, &skewLen);
}
void UnitNode::setDirty(se::Object* jsData)
{
set(&dirty, (uint8_t**)&dirtyData, &dirtyLen, jsData);
}
void UnitNode::setTRS(se::Object* jsData)
{
set(&trs, (uint8_t**)&trsData, &trsLen, jsData);
}
void UnitNode::setLocalMat(se::Object* jsData)
{
set(&localMat, (uint8_t**)&localMatData, &localMatLen, jsData);
}
void UnitNode::setWorldMat(se::Object* jsData)
{
set(&worldMat, (uint8_t**)&worldMatData, &worldMatLen, jsData);
}
void UnitNode::setParent(se::Object* jsData)
{
set(&parent, (uint8_t**)&parentData, &parentLen, jsData);
}
void UnitNode::setZOrder(se::Object* jsData)
{
set(&zOrder, (uint8_t**)&zOrderData, &zOrderLen, jsData);
}
void UnitNode::setCullingMask(se::Object* jsData)
{
set(&cullingMask, (uint8_t**)&cullingMaskData, &cullingMaskLen, jsData);
}
void UnitNode::setOpacity(se::Object* jsData)
{
set(&opacity, (uint8_t**)&opacityData, &opacityLen, jsData);
}
void UnitNode::setIs3D(se::Object* jsData)
{
set(&is3D, (uint8_t**)&is3DData, &is3DLen, jsData);
}
void UnitNode::setNode(se::Object *jsData)
{
set(&node, (uint8_t**)&nodeData, &nodeLen, jsData);
}
void UnitNode::setSkew(se::Object* jsData)
{
set(&skew, (uint8_t**)&skewData, &skewLen, jsData);
}
void UnitNode::setSortingPriority(se::Object* jsData){
set(&sortingPriority, (uint8_t**)&sortingPriorityData, &sortingPriorityLen, jsData);
}
void UnitNode::setSortingEnabled(se::Object* jsData){
set(&sortingEnabled, (uint8_t**)&sortingEnabledData, &sortingEnabledLen, jsData);
}
NodeMemPool* NodeMemPool::_instance = nullptr;
NodeMemPool::NodeMemPool()
{
_instance = this;
}
NodeMemPool::~NodeMemPool()
{
for(auto it = _nodePool.begin(); it != _nodePool.end(); it++)
{
if (*it)
{
delete (*it);
}
}
_nodePool.clear();
_instance = nullptr;
}
const std::vector<UnitNode*>& NodeMemPool::getNodePool() const
{
return _nodePool;
}
void NodeMemPool::removeNodeData(std::size_t unitID)
{
CCASSERT(unitID < _nodePool.size(), "NodeMemPool removeNodeData unitID can not be rather than pool size");
auto unit = _nodePool[unitID];
if (unit)
{
delete unit;
_nodePool[unitID] = nullptr;
}
}
UnitNode* NodeMemPool::getUnit(std::size_t unitID) const
{
CCASSERT(unitID < _nodePool.size(), "NodeMemPool getUnit unitID can not be rather than pool size");
return _nodePool[unitID];
}
void NodeMemPool::updateNodeData(std::size_t unitID, se_object_ptr dirty, se_object_ptr trs, se_object_ptr localMat, se_object_ptr worldMat, se_object_ptr parent, se_object_ptr zOrder, se_object_ptr cullingMask, se_object_ptr opacity, se_object_ptr is3D, se_object_ptr node, se_object_ptr skew, se_object_ptr sortingPriority, se_object_ptr sortingEnabled)
{
// UnitID may equal to node pool size, then node pool must increase size.
CCASSERT(unitID <= _nodePool.size(), "NodeMemPool updateNodeData unitID can not be rather than pool size");
UnitNode* unit = nullptr;
if (unitID == _nodePool.size())
{
unit = new UnitNode;
_nodePool.push_back(unit);
}
else if (unitID < _nodePool.size())
{
unit = _nodePool[unitID];
if(!unit)
{
unit = new UnitNode;
_nodePool[unitID] = unit;
}
}
else
{
return;
}
unit->unitID = unitID;
unit->setDirty(dirty);
unit->setTRS(trs);
unit->setLocalMat(localMat);
unit->setWorldMat(worldMat);
unit->setParent(parent);
unit->setZOrder(zOrder);
unit->setCullingMask(cullingMask);
unit->setOpacity(opacity);
unit->setIs3D(is3D);
unit->setNode(node);
unit->setSkew(skew);
unit->setSortingPriority(sortingPriority);
unit->setSortingEnabled(sortingEnabled);
}
RENDERER_END

View File

@ -0,0 +1,217 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "MemPool.hpp"
#include "math/Mat4.h"
RENDERER_BEGIN
class NodeProxy;
struct TRS {
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
float qx = 0.0f;
float qy = 0.0f;
float qz = 0.0f;
float qw = 0.0f;
float sx = 0.0f;
float sy = 0.0f;
float sz = 0.0f;
};
#define PARENT_INVALID 0xffffffff
struct ParentInfo {
uint32_t unitID = 0;
uint32_t index = 0;
};
struct Skew {
float_t x = 0.0f;
float_t y = 0.0f;
};
class UnitNode: public UnitBase {
public:
UnitNode();
virtual ~UnitNode();
void setDirty(se::Object* jsData);
void setTRS(se::Object* jsData);
void setLocalMat(se::Object* jsData);
void setWorldMat(se::Object* jsData);
void setParent(se::Object* jsData);
void setZOrder(se::Object* jsData);
void setCullingMask(se::Object* jsData);
void setOpacity(se::Object* jsData);
void setIs3D(se::Object* jsData);
void setNode(se::Object* jsData);
void setLevel(se::Object* jsData);
void setSkew(se::Object* jsData);
void setSortingPriority(se::Object* jsData);
void setSortingEnabled(se::Object* jsData);
uint32_t* getDirty(std::size_t index) const
{
return dirtyData + index;
}
TRS* getTRS(std::size_t index) const
{
return (TRS*)trsData + index;
}
cocos2d::Mat4* getLocalMat(std::size_t index) const
{
return (cocos2d::Mat4*)localMatData + index;
}
cocos2d::Mat4* getWorldMat(std::size_t index) const
{
return (cocos2d::Mat4*)worldMatData + index;
}
ParentInfo* getParent(std::size_t index) const
{
return (ParentInfo*)parentData + index;
}
int32_t* getZOrder(std::size_t index) const
{
return zOrderData + index;
}
int32_t* getCullingMask(std::size_t index) const
{
return cullingMaskData + index;
}
uint8_t* getOpacity(std::size_t index) const
{
return opacityData + index;
}
uint8_t* getIs3D(std::size_t index) const
{
return is3DData + index;
}
uint64_t* getNode(std::size_t index) const
{
return nodeData + index;
}
Skew* getSkew(std::size_t index) const
{
return (Skew*)skewData + index;
}
float_t* getSortingPriority(std::size_t index) const
{
return (float_t*)sortingPriorityData + index;
}
uint8_t* getSortingEnabled(std::size_t index) const
{
return sortingEnabledData + index;
}
protected:
se::Object* dirty = nullptr;
uint32_t* dirtyData = nullptr;
std::size_t dirtyLen = 0;
se::Object* trs = nullptr;
float_t* trsData = nullptr;
std::size_t trsLen = 0;
se::Object* localMat = nullptr;
float_t* localMatData = nullptr;
std::size_t localMatLen = 0;
se::Object* worldMat = nullptr;
float_t* worldMatData = nullptr;
std::size_t worldMatLen = 0;
se::Object* parent = nullptr;
uint32_t* parentData = nullptr;
std::size_t parentLen = 0;
se::Object* zOrder = nullptr;
int32_t* zOrderData = nullptr;
std::size_t zOrderLen = 0;
se::Object* cullingMask = nullptr;
int32_t* cullingMaskData = nullptr;
std::size_t cullingMaskLen = 0;
se::Object* opacity = nullptr;
uint8_t* opacityData = nullptr;
std::size_t opacityLen = 0;
se::Object* is3D = nullptr;
uint8_t* is3DData = nullptr;
std::size_t is3DLen = 0;
se::Object* node = nullptr;
uint64_t* nodeData = nullptr;
std::size_t nodeLen = 0;
se::Object* skew = nullptr;
float_t* skewData = nullptr;
std::size_t skewLen = 0;
se::Object* sortingPriority = nullptr;
float_t* sortingPriorityData = nullptr;
std::size_t sortingPriorityLen = 0;
se::Object* sortingEnabled = nullptr;
uint8_t* sortingEnabledData = nullptr;
std::size_t sortingEnabledLen = 0;
};
class NodeMemPool: public MemPool {
public:
NodeMemPool();
virtual ~NodeMemPool();
static NodeMemPool* getInstance()
{
return _instance;
}
void removeNodeData(std::size_t unitID);
void updateNodeData(std::size_t unitID, se_object_ptr dirty, se_object_ptr trs, se_object_ptr localMat, se_object_ptr worldMat, se_object_ptr parent, se_object_ptr zOrder, se_object_ptr cullingMask, se_object_ptr opacity, se_object_ptr is3D, se_object_ptr node, se_object_ptr skew, se_object_ptr sortingPriority, se_object_ptr sortingEnabled);
UnitNode* getUnit(std::size_t unitID) const;
const std::vector<UnitNode*>& getNodePool() const;
private:
static NodeMemPool* _instance;
std::vector<UnitNode*> _nodePool;
};
RENDERER_END

View File

@ -0,0 +1,633 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#include "NodeProxy.hpp"
#include <string>
#include "ModelBatcher.hpp"
#include "../renderer/Scene.h"
#include "base/ccMacros.h"
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
#include "cocos/scripting/js-bindings/manual/jsb_conversions.hpp"
#include "cocos/scripting/js-bindings/auto/jsb_renderer_auto.hpp"
#include "NodeMemPool.hpp"
#include <math.h>
#include "RenderFlow.hpp"
#include "assembler/AssemblerSprite.hpp"
RENDERER_BEGIN
uint32_t NodeProxy::_globalRenderOrder = 0;
NodeProxy::NodeProxy(std::size_t unitID, std::size_t index, const std::string& id, const std::string& name)
{
traverseHandle = render;
_id = id;
_unitID = unitID;
_index = index;
_name = name;
NodeMemPool* pool = NodeMemPool::getInstance();
CCASSERT(pool, "NodeProxy constructor NodeMemPool is null");
UnitNode* unit = pool->getUnit(unitID);
CCASSERT(unit, "NodeProxy constructor unit is null");
UnitCommon* common = pool->getCommonUnit(unitID);
_signData = common->getSignData(_index);
_dirty = unit->getDirty(index);
*_dirty &= ~RenderFlow::PRE_CALCULATE_VERTICES;
_trs = unit->getTRS(index);
_localMat = unit->getLocalMat(index);
_worldMat = unit->getWorldMat(index);
_parentInfo = unit->getParent(index);
_parentInfo->unitID = PARENT_INVALID;
_parentInfo->index = PARENT_INVALID;
_localZOrder = unit->getZOrder(index);
_cullingMask = unit->getCullingMask(index);
_opacity = unit->getOpacity(index);
_is3DNode = unit->getIs3D(index);
_skew = unit->getSkew(index);
_sortingPriority = unit->getSortingPriority(index);
_sortingEnabled = unit->getSortingEnabled(index);
uint64_t* self = unit->getNode(index);
*self = (uint64_t)this;
}
NodeProxy::~NodeProxy()
{
for (auto& child : _children)
{
child->_parent = nullptr;
}
CC_SAFE_RELEASE(_assembler);
}
void NodeProxy::destroyImmediately()
{
if (_parent)
{
_parent->removeChild(this);
}
RenderFlow::getInstance()->removeNodeLevel(_level, _worldMat);
CC_SAFE_RELEASE_NULL(_assembler);
_level = NODE_LEVEL_INVALID;
_dirty = nullptr;
_trs = nullptr;
_localMat = nullptr;
_worldMat = nullptr;
_parentInfo = nullptr;
_localZOrder = nullptr;
_cullingMask = nullptr;
_opacity = nullptr;
_is3DNode = nullptr;
_skew = nullptr;
_sortingPriority = nullptr;
_sortingEnabled = nullptr;
}
// lazy allocs
void NodeProxy::childrenAlloc()
{
_children.reserve(4);
}
void NodeProxy::addChild(NodeProxy* child)
{
if (child == nullptr)
{
CCLOGWARN("Argument must be non-nil");
return;
}
if (child->_parent != nullptr)
{
CCLOGWARN("child already added. It can't be added again");
return;
}
auto assertNotSelfChild
( [ this, child ]() -> bool
{
for ( NodeProxy* parent( this ); parent != nullptr;
parent = parent->getParent() )
if ( parent == child )
return false;
return true;
} );
(void)assertNotSelfChild;
if (!assertNotSelfChild())
{
CCLOGWARN("A node cannot be the child of his own children" );
return;
}
if (_children.empty())
{
this->childrenAlloc();
}
_children.pushBack(child);
child->setParent(this);
}
void NodeProxy::detachChild(NodeProxy *child, ssize_t childIndex)
{
// set parent nil at the end
child->setParent(nullptr);
_children.erase(childIndex);
}
void NodeProxy::removeChild(NodeProxy* child)
{
// explicit nil handling
if (_children.empty())
{
return;
}
ssize_t index = _children.getIndex(child);
if( index != CC_INVALID_INDEX )
this->detachChild( child, index );
}
void NodeProxy::removeAllChildren()
{
// not using detachChild improves speed here
for (const auto& child : _children)
{
// set parent nil at the end
child->setParent(nullptr);
}
_children.clear();
}
NodeProxy* NodeProxy::getChildByName(std::string childName)
{
for (auto child : _children)
{
if (child->_name == childName)
{
return child;
}
}
return nullptr;
}
NodeProxy* NodeProxy::getChildByID(std::string id)
{
for (auto child : _children)
{
if (child->_id == id)
{
return child;
}
}
return nullptr;
}
void NodeProxy::notifyUpdateParent()
{
if (_parentInfo->index == PARENT_INVALID)
{
if (_parent)
{
_parent->removeChild(this);
}
updateLevel();
return;
}
NodeMemPool* pool = NodeMemPool::getInstance();
CCASSERT(pool, "NodeProxy updateParent NodeMemPool is null");
UnitNode* unit = pool->getUnit(_parentInfo->unitID);
CCASSERT(unit, "NodeProxy updateParent unit is null");
uint64_t* parentAddrs = unit->getNode(_parentInfo->index);
NodeProxy* parent = (NodeProxy*)*parentAddrs;
CCASSERT(parent, "NodeProxy updateParent parent is null");
if (parent != _parent) {
if (_parent)
{
_parent->removeChild(this);
}
parent->addChild(this);
updateLevel();
}
}
void NodeProxy::updateLevel()
{
static RenderFlow::LevelInfo levelInfo;
auto renderFlow = RenderFlow::getInstance();
renderFlow->removeNodeLevel(_level, _worldMat);
levelInfo.dirty = _dirty;
levelInfo.localMat = _localMat;
levelInfo.worldMat = _worldMat;
levelInfo.opacity = _opacity;
levelInfo.realOpacity = &_realOpacity;
if (_parent)
{
_level = _parent->_level + 1;
levelInfo.parentWorldMat = _parent->_worldMat;
levelInfo.parentDirty = _parent->_dirty;
levelInfo.parentRealOpacity = &_parent->_realOpacity;
}
else
{
_level = 0;
levelInfo.parentWorldMat = nullptr;
levelInfo.parentDirty = nullptr;
levelInfo.parentRealOpacity = nullptr;
}
renderFlow->insertNodeLevel(_level, levelInfo);
for (auto it = _children.begin(); it != _children.end(); it++)
{
(*it)->updateLevel();
}
}
void NodeProxy::setLocalZOrder(int zOrder)
{
if (*_localZOrder != zOrder)
{
*_localZOrder = zOrder;
if (_parent != nullptr)
{
*_parent->_dirty |= RenderFlow::REORDER_CHILDREN;
}
}
}
void NodeProxy::reorderChildren()
{
if (*_dirty & RenderFlow::REORDER_CHILDREN)
{
#if CC_64BITS
std::sort(std::begin(_children), std::end(_children), [](NodeProxy* n1, NodeProxy* n2) {
return (*n1->_localZOrder < *n2->_localZOrder);
});
#else
std::stable_sort(std::begin(_children), std::end(_children), [](NodeProxy* n1, NodeProxy* n2) {
return *n1->_localZOrder < *n2->_localZOrder;
});
#endif
*_dirty &= ~RenderFlow::REORDER_CHILDREN;
}
}
void NodeProxy::setAssembler(AssemblerBase* assembler)
{
if (assembler == _assembler) return;
CC_SAFE_RELEASE(_assembler);
_assembler = assembler;
CC_SAFE_RETAIN(_assembler);
auto assemblerSprite = dynamic_cast<AssemblerSprite*>(_assembler);
if (assemblerSprite)
{
*_dirty |= RenderFlow::PRE_CALCULATE_VERTICES;
}
else
{
*_dirty &= ~RenderFlow::PRE_CALCULATE_VERTICES;
}
}
void NodeProxy::clearAssembler()
{
CC_SAFE_RELEASE_NULL(_assembler);
*_dirty &= ~RenderFlow::PRE_CALCULATE_VERTICES;
}
AssemblerBase* NodeProxy::getAssembler() const
{
return _assembler;
}
void NodeProxy::getPosition(cocos2d::Vec3* out) const
{
out->x = _trs->x;
out->y = _trs->y;
out->z = _trs->z;
}
void NodeProxy::getRotation(cocos2d::Quaternion* out) const
{
out->x = _trs->qx;
out->y = _trs->qy;
out->z = _trs->qz;
out->w = _trs->qw;
}
void NodeProxy::getScale(cocos2d::Vec3* out) const
{
out->x = _trs->sx;
out->y = _trs->sy;
out->z = _trs->sz;
}
void NodeProxy::getWorldRotation(cocos2d::Quaternion* out) const
{
getRotation(out);
cocos2d::Quaternion rot;
NodeProxy* curr = _parent;
while (curr != nullptr)
{
curr->getRotation(&rot);
Quaternion::multiply(rot, *out, out);
curr = curr->getParent();
}
}
void NodeProxy::getWorldPosition(cocos2d::Vec3* out) const
{
getPosition(out);
cocos2d::Vec3 pos;
cocos2d::Quaternion rot;
cocos2d::Vec3 scale;
NodeProxy* curr = _parent;
while (curr != nullptr)
{
curr->getPosition(&pos);
curr->getRotation(&rot);
curr->getScale(&scale);
out->multiply(scale);
out->transformQuat(rot);
out->add(pos);
curr = curr->getParent();
}
}
void NodeProxy::getWorldRT(cocos2d::Mat4* out) const
{
cocos2d::Vec3 opos(_trs->x, _trs->y, _trs->z);
cocos2d::Quaternion orot(_trs->qx, _trs->qy, _trs->qz, _trs->qw);
cocos2d::Vec3 pos;
cocos2d::Quaternion rot;
cocos2d::Vec3 scale;
NodeProxy* curr = _parent;
while (curr != nullptr)
{
curr->getPosition(&pos);
curr->getRotation(&rot);
curr->getScale(&scale);
opos.multiply(scale);
opos.transformQuat(rot);
opos.add(pos);
Quaternion::multiply(rot, orot, &orot);
curr = curr->getParent();
}
out->setIdentity();
out->translate(opos);
cocos2d::Mat4 quatMat;
cocos2d::Mat4::createRotation(orot, &quatMat);
out->multiply(quatMat);
}
void NodeProxy::setOpacity(uint8_t opacity)
{
if (*_opacity != opacity)
{
*_opacity = opacity;
*_dirty |= RenderFlow::OPACITY;
}
}
void NodeProxy::updateRealOpacity()
{
bool selfOpacityDirty = *_dirty & RenderFlow::OPACITY;
if (_parent)
{
if (selfOpacityDirty || *_parent->_dirty & RenderFlow::NODE_OPACITY_CHANGED)
{
_realOpacity = *_opacity * _parent->getRealOpacity() / 255.0f;
*_dirty &= ~RenderFlow::OPACITY;
*_dirty |= RenderFlow::NODE_OPACITY_CHANGED;
}
}
else
{
if (selfOpacityDirty)
{
_realOpacity = *_opacity;
*_dirty &= ~RenderFlow::OPACITY;
*_dirty |= RenderFlow::NODE_OPACITY_CHANGED;
}
}
}
void NodeProxy::updateWorldMatrix()
{
if (!_updateWorldMatrix) return;
bool selfWorldDirty = *_dirty & RenderFlow::WORLD_TRANSFORM;
if (_parent)
{
if (selfWorldDirty || *_parent->_dirty & RenderFlow::WORLD_TRANSFORM_CHANGED)
{
cocos2d::Mat4::multiply(_parent->getWorldMatrix(), *_localMat, _worldMat);
*_dirty &= ~RenderFlow::WORLD_TRANSFORM;
*_dirty |= RenderFlow::WORLD_TRANSFORM_CHANGED;
}
}
else if (selfWorldDirty)
{
*_worldMat = *_localMat;
*_dirty &= ~RenderFlow::WORLD_TRANSFORM;
*_dirty |= RenderFlow::WORLD_TRANSFORM_CHANGED;
}
}
void NodeProxy::updateWorldMatrix(const cocos2d::Mat4& worldMatrix)
{
*_worldMat = worldMatrix;
*_dirty &= ~RenderFlow::WORLD_TRANSFORM;
*_dirty |= RenderFlow::WORLD_TRANSFORM_CHANGED;
}
void NodeProxy::updateLocalMatrix()
{
bool skew = std::abs(_skew->x - 0.0f) > MATH_EPSILON || std::abs(_skew->y - 0.0f) > MATH_EPSILON;
if (*_dirty & RenderFlow::LOCAL_TRANSFORM || skew)
{
_localMat->setIdentity();
// Transform = Translate * Rotation * Scale;
cocos2d::Quaternion q(_trs->qx, _trs->qy, _trs->qz, _trs->qw);
if (*_is3DNode)
{
_localMat->translate(_trs->x, _trs->y, _trs->z);
_localMat->rotate(q);
_localMat->scale(_trs->sx, _trs->sy, _trs->sz);
}
else
{
_localMat->translate(_trs->x, _trs->y, 0);
_localMat->rotate(q);
_localMat->scale(_trs->sx, _trs->sy, 1);
}
if (skew)
{
auto& m = _localMat->m;
auto a = m[0];
auto b = m[1];
auto c = m[4];
auto d = m[5];
auto skx = (float)tanf(CC_DEGREES_TO_RADIANS(_skew->x));
auto sky = (float)tanf(CC_DEGREES_TO_RADIANS(_skew->y));
m[0] = a + c * sky;
m[1] = b + d * sky;
m[4] = c + a * skx;
m[5] = d + b * skx;
}
*_dirty &= ~RenderFlow::LOCAL_TRANSFORM;
*_dirty |= RenderFlow::WORLD_TRANSFORM;
}
}
void NodeProxy::render(NodeProxy* node, ModelBatcher* batcher, Scene* scene)
{
node->_renderOrder = _globalRenderOrder++;
if (!node->_needVisit || node->_realOpacity == 0) return;
float_t preSortingPriority = batcher->getSortingPriority();
batcher->setSortingPriority(node->getSortingEnabled() ? node->getSortingPriority() : preSortingPriority);
bool needRender = *node->_dirty & RenderFlow::RENDER;
if (node->_needRender != needRender)
{
if (node->_assembler) node->_assembler->enableDirty(AssemblerBase::VERTICES_OPACITY_CHANGED);
node->_needRender = needRender;
}
// pre render
if (node->_assembler && needRender) {
if(node->_assembler->isMaskAssembler()){
batcher->flushRendererCache();
node->_assembler->handle(node, batcher, scene);
}else{
batcher->pushRendererCache(node);
node->setRenderPriority(batcher->getSortingPriority());
if(batcher->getSortingPriority() != 0){
batcher->setRendererOrder(true);
}
}
}
node->reorderChildren();
for (const auto& child : node->_children)
{
auto traverseHandle = child->traverseHandle;
traverseHandle(child, batcher, scene);
}
// post render
bool needPostRender = *(node->_dirty) & RenderFlow::POST_RENDER;
if (node->_assembler && needPostRender){
if(node->_assembler->isMaskAssembler()){
batcher->flushRendererCache();
}
node->_assembler->postHandle(node, batcher, scene);
}
batcher->setSortingPriority(preSortingPriority);
}
void NodeProxy::visit(NodeProxy* node, ModelBatcher* batcher, Scene* scene)
{
node->_renderOrder = _globalRenderOrder++;
if (!node->_needVisit) return;
node->updateRealOpacity();
if (node->_realOpacity == 0)
{
return;
}
node->updateLocalMatrix();
node->updateWorldMatrix();
float_t preSortingPriority = batcher->getSortingPriority();
batcher->setSortingPriority(node->getSortingEnabled() ? node->getSortingPriority() : preSortingPriority);
bool needRender = *(node->_dirty) & RenderFlow::RENDER;
if (node->_needRender != needRender)
{
if (node->_assembler) node->_assembler->enableDirty(AssemblerBase::VERTICES_OPACITY_CHANGED);
node->_needRender = needRender;
}
// pre render
if (node->_assembler && needRender){
if(node->_assembler->isMaskAssembler()){
batcher->flushRendererCache();
node->_assembler->handle(node, batcher, scene);
}else{
batcher->pushRendererCache(node);
node->setRenderPriority(batcher->getSortingPriority());
if(batcher->getSortingPriority() != 0){
batcher->setRendererOrder(true);
}
}
}
node->reorderChildren();
for (const auto& child : node->_children)
{
visit(child, batcher, scene);
}
// post render
bool needPostRender = *(node->_dirty) & RenderFlow::POST_RENDER;
if (node->_assembler && needPostRender){
if(node->_assembler->isMaskAssembler()){
batcher->flushRendererCache();
}
node->_assembler->postHandle(node, batcher, scene);
}
batcher->setSortingPriority(preSortingPriority);
}
RENDERER_END

View File

@ -0,0 +1,379 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include <string>
#include <map>
#include "../Macro.h"
#include "base/CCRef.h"
#include "base/ccTypes.h"
#include "base/CCVector.h"
#include "base/CCMap.h"
#include "math/CCMath.h"
#include "assembler/AssemblerBase.hpp"
#include "MemPool.hpp"
#include <functional>
namespace se {
class Object;
}
RENDERER_BEGIN
class ModelBatcher;
class Scene;
struct TRS;
struct ParentInfo;
struct Skew;
/**
* @addtogroup scene
* @{
*/
/**
* @brief NodeProxy is a cpp delegator of js Node.\n
* It synchronize the hierarchy from js node tree, update the transform each frame, and manages assembler which represent the render component.\n
* JS API: renderer.NodeProxy
@code
let node = new cc.Node();
// NodeProxy is automatically created by cc.Node
let proxy = node._proxy;
@endcode
*/
class NodeProxy : public Ref
{
public:
typedef std::function<void(NodeProxy*, ModelBatcher*, Scene*)> TraverseFunc;
/*
* @brief Visit the node but do not transform position.
*/
static void render(NodeProxy* node, ModelBatcher* batcher, Scene* scene);
/*
* @brief Visit the node as a ordinary node but not a root node.
*/
static void visit(NodeProxy* node, ModelBatcher* batcher, Scene* scene);
/*
* @brief Reset global render order.
*/
static void resetGlobalRenderOrder() { _globalRenderOrder = 0; }
/*
* @brief The default constructor.
*/
NodeProxy(std::size_t unitID, std::size_t index, const std::string& id, const std::string& name);
/*
* @brief The destructor.
*/
~NodeProxy();
/*
* @brief destroy node data immediately .
*/
void destroyImmediately();
/*
* @brief If js node has been destroy.
*/
bool isValid() { return _trs != nullptr; }
/// @{
/// @name Hierarchy
/**
* @brief Adds child node proxy to the node proxy.
* @param[in] child A child node proxy pointer.
*/
void addChild(NodeProxy * child);
/**
* @brief Removes child node proxy from the node proxy.
* @param[in] child A child node proxy pointer.
*/
void removeChild(NodeProxy* child);
/**
* @brief Removes all child node proxies from the current one.
*/
void removeAllChildren();
/**
* @brief Update parent by parent unitId and index.
*/
void notifyUpdateParent();
/**
* @brief Sets the node proxy parent.
* @param[in] parent.
*/
inline void setParent(NodeProxy* parent) { _parent = parent; };
/**
* @brief Gets the node proxy parent.
* @return Parent.
*/
inline NodeProxy* getParent() const { return _parent; };
/**
* @brief Gets the node proxy all children.
* @return Children container.
*/
inline const Vector<NodeProxy*>& getChildren() const { return _children; };
/**
* @brief Gets the node proxy child count.
* @return Child count.
*/
inline size_t getChildrenCount() const { return _children.size(); };
/**
* @brief Gets a child node by name.
* @return Child node.
*/
NodeProxy* getChildByName(std::string childName);
/**
* @brief Gets a child node by runtime id.
* @return Child node.
*/
NodeProxy* getChildByID(std::string id);
/**
* @brief Sets the node proxy's local zorder.
* @param[in] zOrder The value of zorder.
*/
void setLocalZOrder(int zOrder);
/// @} end of Hierarchy
/*
* @brief Gets the world matrix.
* @return World matrix.
*/
inline const cocos2d::Mat4& getWorldMatrix() const { return *_worldMat; };
/*
* @brief Gets the local matrix.
* @return Local matrix.
*/
inline const cocos2d::Mat4& getLocalMatrix() const { return *_localMat; };
/*
* @brief Gets the position.
* @param[out] out The position vector
*/
void getPosition(cocos2d::Vec3* out) const;
/*
* @brief Gets the rotation.
* @param[out] out The rotation quaternion.
*/
void getRotation(cocos2d::Quaternion* out) const;
/*
* @brief Gets the scale.
* @param[out] out The scale vector.
*/
void getScale(cocos2d::Vec3* out) const;
/*
* @brief Gets world rotation.
* @param[out] out The rotation quaternion.
*/
void getWorldRotation(cocos2d::Quaternion* out) const;
/*
* @brief Gets the position in world coordinates.
* @param[out] out The world position vector.
*/
void getWorldPosition(cocos2d::Vec3* out) const;
/*
* @brief Gets the matrix contains the world rotation and translation.
* @param[out] out The matrix to store datas.
*/
void getWorldRT(cocos2d::Mat4* out) const;
/**
* @brief Gets the node's opacity.
*/
inline uint8_t getOpacity() const { return *_opacity; };
/**
* @brief Sets the node's opacity.
*/
void setOpacity(uint8_t opacity);
/**
* @brief Updates opacity from parent.
*/
void updateRealOpacity();
/**
* @brief Gets the node's realOpacity.
*/
inline const uint8_t getRealOpacity() const {return _realOpacity;};
/**
* @brief Gets the node's group id, this controls which camera can see the node.
*/
inline int getCullingMask() const { return *_cullingMask; };
/**
* @brief Sets the node's group id.
* @param[in] groupID The group id
*/
inline void setCullingMask(int cullingMask) { *_cullingMask = cullingMask; };
/**
* @brief Gets the node's name.
* This equals to the one in JS node, helps to debug in cpp.
* @return name
*/
inline const std::string& getName() const { return _name; };
/**
* @brief Sets the node's name.
* The name should be updated once JS node's name changes.
* @param[in] name
*/
inline void setName(const std::string& name) { _name = name; };
/**
* @brief Sets the node's 3D state.
* @param[in] is3DNode
*/
inline void set3DNode(bool is3DNode) { *_is3DNode = is3DNode ? 0x1 : 0x0; };
/**
* @brief Sets a system handle to the node proxy, system handle will be invoked during node's visit process.
* @param[in] handle The system handle pointer.
*/
void setAssembler(AssemblerBase* assembler);
/**
* @brief Removes a system handle from node proxy by system id.
* @param[in] sysid The system id.
*/
void clearAssembler();
/**
* @brief Gets the system handle by system id.
* @param[in] sysid The system id.
* @return The system handle object or nullptr if not exist
*/
AssemblerBase* getAssembler() const;
/*
* @brief Enables visit.
*/
void enableVisit(bool value) { _needVisit = value; }
/*
* @brief Disables visit.
*/
void disableVisit() { _needVisit = false; }
/*
* @brief Updates local matrix.
*/
void updateLocalMatrix();
/*
* @brief Updates world matrix.
*/
void updateWorldMatrix();
/*
* @brief Updates world matrix with provide matrix.
*/
void updateWorldMatrix(const cocos2d::Mat4& worldMatrix);
/*
* @brief Enables calc world matrix.
*/
void enableUpdateWorldMatrix(bool value) { _updateWorldMatrix = value; }
/*
* @brief Gets node runtime id
*/
const std::string& getID() const { return _id; }
/*
* @brief Gets node dirty
*/
uint32_t* getDirty() const { return _dirty; }
/*
* @brief Is node flag dirty
*/
bool isDirty(uint32_t flag) const { return *_dirty & flag; }
/*
* @brief Gets render order
*/
uint32_t getRenderOrder () { return _renderOrder; }
/*
* @brief switch traverse interface to visit
*/
void switchTraverseToVisit() { traverseHandle = visit; }
/*
* @brief switch traverse interface to render
*/
void switchTraverseToRender() { traverseHandle = render; }
/*
* @brief traverse handle
*/
TraverseFunc traverseHandle = nullptr;
float_t getRenderPriority() const { return _renderPriority; }
void setRenderPriority(float_t value) { _renderPriority = value; };
bool getSortingEnabled() { return *_sortingEnabled != 0; }
float_t getSortingPriority() const { return *_sortingPriority ; }
protected:
void updateLevel();
void childrenAlloc();
void detachChild(NodeProxy* child, ssize_t childIndex);
void reorderChildren();
private:
bool _needVisit = true;
bool _updateWorldMatrix = true;
bool _needRender = false;
uint8_t _realOpacity = 255;
std::string _id = "";
std::string _name = "";
std::size_t _level = 0;
uint32_t* _dirty = nullptr;
TRS* _trs = nullptr;
cocos2d::Mat4* _localMat = nullptr;
cocos2d::Mat4* _worldMat = nullptr;
ParentInfo* _parentInfo = nullptr;
int32_t* _localZOrder = nullptr;
int32_t* _cullingMask = nullptr;
uint8_t* _opacity = nullptr;
uint8_t* _is3DNode = nullptr;
Skew* _skew = nullptr;
float_t* _sortingPriority = nullptr;
uint8_t* _sortingEnabled = nullptr;
std::size_t _unitID = 0;
std::size_t _index = 0;
Sign* _signData = nullptr;
NodeProxy* _parent = nullptr; ///< weak reference to parent node
cocos2d::Vector<NodeProxy*> _children; ///< array of children nodes
AssemblerBase* _assembler = nullptr;
uint32_t _renderOrder = 0;
static uint32_t _globalRenderOrder;
float_t _renderPriority = 0;
};
// end of scene group
/// @}
RENDERER_END

View File

@ -0,0 +1,381 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#include "RenderFlow.hpp"
#include "NodeMemPool.hpp"
#include "assembler/AssemblerSprite.hpp"
#if USE_MIDDLEWARE
#include "MiddlewareManager.h"
#endif
#define SUB_RENDER_THREAD_COUNT 1
#define RENDER_THREAD_COUNT (SUB_RENDER_THREAD_COUNT + 1)
RENDERER_BEGIN
const uint32_t InitLevelCount = 3;
const uint32_t InitLevelNodeCount = 100;
const uint32_t LocalMat_Use_Thread_Unit_Count = 5;
const uint32_t WorldMat_Use_Thread_Node_count = 500;
RenderFlow* RenderFlow::_instance = nullptr;
RenderFlow::RenderFlow(DeviceGraphics* device, Scene* scene, ForwardRenderer* forward)
: _device(device)
, _scene(scene)
, _forward(forward)
{
_instance = this;
_batcher = new ModelBatcher(this);
#if SUB_RENDER_THREAD_COUNT > 0
_paralleTask = new ParallelTask();
_paralleTask->init(SUB_RENDER_THREAD_COUNT);
for (uint32_t i = 0; i < SUB_RENDER_THREAD_COUNT; i++)
{
_paralleTask->pushTask(i, [this](int tid){
switch(_parallelStage)
{
case ParallelStage::LOCAL_MAT:
calculateLocalMatrix(tid);
break;
case ParallelStage::WORLD_MAT:
calculateLevelWorldMatrix(tid, _parallelStage);
break;
default:
break;
}
});
}
#endif
_levelInfoArr.resize(InitLevelCount);
for (auto i = 0; i < InitLevelCount; i++)
{
_levelInfoArr[i].reserve(InitLevelNodeCount);
}
}
RenderFlow::~RenderFlow()
{
CC_SAFE_DELETE(_paralleTask);
CC_SAFE_DELETE(_batcher);
}
void RenderFlow::removeNodeLevel(std::size_t level, cocos2d::Mat4* worldMat)
{
if (level >= _levelInfoArr.size()) return;
auto& levelInfos = _levelInfoArr[level];
for(auto it = levelInfos.begin(); it != levelInfos.end(); it++)
{
if (it->worldMat == worldMat)
{
levelInfos.erase(it);
return;
}
}
}
void RenderFlow::insertNodeLevel(std::size_t level, const LevelInfo& levelInfo)
{
if (level >= _levelInfoArr.size())
{
_levelInfoArr.resize(level + 1);
}
auto& levelInfos = _levelInfoArr[level];
levelInfos.push_back(levelInfo);
}
void RenderFlow::calculateLocalMatrix(int tid)
{
const uint16_t SPACE_FREE_FLAG = 0x0;
cocos2d::Mat4 matTemp;
NodeMemPool* instance = NodeMemPool::getInstance();
CCASSERT(instance, "RenderFlow calculateLocalMatrix NodeMemPool is null");
auto& commonList = instance->getCommonList();
auto& nodePool = instance->getNodePool();
UnitCommon* commonUnit = nullptr;
uint16_t usingNum = 0;
std::size_t contentNum = 0;
Sign* signData = nullptr;
UnitNode* nodeUnit = nullptr;
uint32_t* dirty = nullptr;
cocos2d::Mat4* localMat = nullptr;
TRS* trs = nullptr;
uint8_t* is3D = nullptr;
cocos2d::Quaternion* quat = nullptr;
float trsZ = 0.0f, trsSZ = 0.0f;
std::size_t begin = 0, end = commonList.size();
std::size_t fieldSize = end / RENDER_THREAD_COUNT;
if (tid >= 0)
{
begin = tid * fieldSize;
if (tid < RENDER_THREAD_COUNT - 1)
{
end = (tid + 1) * fieldSize;
}
}
for(auto i = begin; i < end; i++)
{
commonUnit = commonList[i];
if (!commonUnit) continue;
usingNum = commonUnit->getUsingNum();
if (usingNum == 0) continue;
contentNum = commonUnit->getContentNum();
signData = commonUnit->getSignData(0);
nodeUnit = nodePool[commonUnit->unitID];
dirty = nodeUnit->getDirty(0);
localMat = nodeUnit->getLocalMat(0);
trs = nodeUnit->getTRS(0);
is3D = nodeUnit->getIs3D(0);
NodeProxy** nodeProxy = (NodeProxy**)nodeUnit->getNode(0);
for (auto j = 0; j < contentNum; j++, localMat ++, trs ++, is3D ++, signData++, dirty++, nodeProxy++)
{
if (signData->freeFlag == SPACE_FREE_FLAG) continue;
// reset world transform changed flag
*dirty &= ~(WORLD_TRANSFORM_CHANGED | NODE_OPACITY_CHANGED);
if (!(*dirty & LOCAL_TRANSFORM)) continue;
localMat->setIdentity();
trsZ = *is3D ? trs->z : 0;
localMat->translate(trs->x, trs->y, trsZ);
quat = (cocos2d::Quaternion*)&(trs->qx);
cocos2d::Mat4::createRotation(*quat, &matTemp);
cocos2d::Mat4::multiply(*localMat, matTemp, localMat);
trsSZ = *is3D ? trs->sz : 1;
cocos2d::Mat4::createScale(trs->sx, trs->sy, trsSZ, &matTemp);
cocos2d::Mat4::multiply(*localMat, matTemp, localMat);
*dirty &= ~LOCAL_TRANSFORM;
*dirty |= WORLD_TRANSFORM;
}
}
}
void RenderFlow::calculateLevelWorldMatrix(int tid, int stage)
{
if (_curLevel >= _levelInfoArr.size())
{
return;
}
auto& levelInfos = _levelInfoArr[_curLevel];
std::size_t begin = 0, end = levelInfos.size();
std::size_t fieldSize = end / RENDER_THREAD_COUNT;
if (tid >= 0)
{
begin = tid * fieldSize;
if (tid < RENDER_THREAD_COUNT - 1)
{
end = (tid + 1) * fieldSize;
}
}
for(std::size_t index = begin; index < end; index++)
{
auto& info = levelInfos[index];
auto dirty = info.dirty;
auto parentDirty = info.parentDirty;
auto selfWorldDirty = *dirty & WORLD_TRANSFORM;
auto selfOpacityDirty = *dirty & OPACITY;
if (parentDirty)
{
if ((*parentDirty & WORLD_TRANSFORM_CHANGED) || selfWorldDirty)
{
cocos2d::Mat4::multiply(*info.parentWorldMat, *info.localMat, info.worldMat);
*dirty |= WORLD_TRANSFORM_CHANGED;
*dirty &= ~WORLD_TRANSFORM;
}
if ((*parentDirty & NODE_OPACITY_CHANGED) || selfOpacityDirty)
{
*info.realOpacity = *info.opacity * *info.parentRealOpacity / 255.0f;
*dirty |= NODE_OPACITY_CHANGED;
*dirty &= ~OPACITY;
}
}
else
{
if (selfWorldDirty)
{
*info.worldMat = *info.localMat;
*dirty |= WORLD_TRANSFORM_CHANGED;
*dirty &= ~WORLD_TRANSFORM;
}
if (selfOpacityDirty)
{
*info.realOpacity = *info.opacity;
*dirty |= NODE_OPACITY_CHANGED;
*dirty &= ~OPACITY;
}
}
}
}
void RenderFlow::calculateWorldMatrix()
{
for(std::size_t level = 0, n = _levelInfoArr.size(); level < n; level++)
{
auto& levelInfos = _levelInfoArr[level];
for(std::size_t index = 0, count = levelInfos.size(); index < count; index++)
{
auto& info = levelInfos[index];
auto selfWorldDirty = *info.dirty & WORLD_TRANSFORM;
auto selfOpacityDirty = *info.dirty & OPACITY;
if (info.parentDirty)
{
if ((*info.parentDirty & WORLD_TRANSFORM_CHANGED) || selfWorldDirty)
{
cocos2d::Mat4::multiply(*info.parentWorldMat, *info.localMat, info.worldMat);
*info.dirty |= WORLD_TRANSFORM_CHANGED;
*info.dirty &= ~WORLD_TRANSFORM;
}
if ((*info.parentDirty & NODE_OPACITY_CHANGED) || selfOpacityDirty)
{
*info.realOpacity = *info.opacity * *info.parentRealOpacity / 255.0f;
*info.dirty |= NODE_OPACITY_CHANGED;
*info.dirty &= ~OPACITY;
}
}
else
{
if (selfWorldDirty)
{
*info.worldMat = *info.localMat;
*info.dirty |= WORLD_TRANSFORM_CHANGED;
*info.dirty &= ~WORLD_TRANSFORM;
}
if (selfOpacityDirty)
{
*info.realOpacity = *info.opacity;
*info.dirty |= NODE_OPACITY_CHANGED;
*info.dirty &= ~OPACITY;
}
}
}
}
}
void RenderFlow::render(NodeProxy* scene, float deltaTime, Camera *camera)
{
if (scene != nullptr)
{
#if USE_MIDDLEWARE
// udpate middleware before render
middleware::MiddlewareManager::getInstance()->update(deltaTime);
#endif
#if SUB_RENDER_THREAD_COUNT > 0
int mainThreadTid = RENDER_THREAD_COUNT - 1;
NodeMemPool* instance = NodeMemPool::getInstance();
auto& commonList = instance->getCommonList();
if (commonList.size() < LocalMat_Use_Thread_Unit_Count)
{
_parallelStage = ParallelStage::NONE;
calculateLocalMatrix();
}
else
{
_parallelStage = ParallelStage::LOCAL_MAT;
_paralleTask->beginAllThreads();
calculateLocalMatrix(mainThreadTid);
_paralleTask->waitAllThreads();
}
_curLevel = 0;
for(auto count = _levelInfoArr.size(); _curLevel < count; _curLevel++)
{
auto& levelInfos = _levelInfoArr[_curLevel];
if (levelInfos.size() < WorldMat_Use_Thread_Node_count)
{
_parallelStage = ParallelStage::NONE;
calculateLevelWorldMatrix();
}
else
{
_parallelStage = ParallelStage::WORLD_MAT;
_paralleTask->beginAllThreads();
calculateLevelWorldMatrix(mainThreadTid);
_paralleTask->waitAllThreads();
}
}
#else
calculateLocalMatrix();
calculateWorldMatrix();
#endif
_batcher->startBatch();
_batcher->setSortingPriority(0);
_batcher->setRendererOrder(false);
#if USE_MIDDLEWARE
// render middleware
middleware::MiddlewareManager::getInstance()->render(deltaTime);
#endif
scene->resetGlobalRenderOrder();
auto traverseHandle = scene->traverseHandle;
traverseHandle(scene, _batcher, _scene);
_batcher->terminateBatch();
if (camera) {
_forward->renderCamera(camera, _scene);
}
else {
_forward->render(_scene, deltaTime);
}
}
}
void RenderFlow::visit(NodeProxy* rootNode)
{
NodeProxy::visit(rootNode, _batcher, _scene);
}
RENDERER_END

View File

@ -0,0 +1,180 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "../Macro.h"
#include "NodeProxy.hpp"
#include "ModelBatcher.hpp"
#include "../renderer/Scene.h"
#include "../renderer/ForwardRenderer.h"
#include "../gfx/DeviceGraphics.h"
#include "ParallelTask.hpp"
RENDERER_BEGIN
/**
* @addtogroup scene
* @{
*/
/**
* @brief This class is responsible for the rendering process.\n
* It visits the node tree, let nodes commit their render handles, starts the device level rendering process with ForwardRenderer.\n
* JS API: renderer.RenderFlow
@code
// You actually shouldn't create RenderFlow by yourself, you can
let renderFlow = cc.RenderFlow._nativeFlow;
@endcode
*/
#define NODE_LEVEL_INVALID 0xffffffff
class RenderFlow
{
public:
enum RenderFlowFlag {
// sync js render flag
DONOTHING = 1 << 0,
BREAK_FLOW = 1 << 1,
LOCAL_TRANSFORM = 1 << 2,
WORLD_TRANSFORM = 1 << 3,
TRANSFORM = LOCAL_TRANSFORM | WORLD_TRANSFORM,
UPDATE_RENDER_DATA = 1 << 4,
OPACITY = 1 << 5,
COLOR = 1 << 6,
RENDER = 1 << 7,
CHILDREN = 1 << 8,
POST_RENDER = 1 << 9,
FINAL = 1 << 10,
PRE_CALCULATE_VERTICES = 1 << 28,
// native render flag
REORDER_CHILDREN = 1 << 29,
// world matrix changed
WORLD_TRANSFORM_CHANGED = 1 << 30,
// cascade opacity changed
NODE_OPACITY_CHANGED = 1 << 31,
};
enum ParallelStage {
NONE = 1 << 0,
LOCAL_MAT = 1 << 1,
WORLD_MAT = 1 << 2,
CALC_VERTICES = 1 << 3,
};
struct LevelInfo{
uint32_t* dirty = nullptr;
uint32_t* parentDirty = nullptr;
cocos2d::Mat4* parentWorldMat = nullptr;
uint8_t* parentRealOpacity = nullptr;
cocos2d::Mat4* localMat = nullptr;
cocos2d::Mat4* worldMat = nullptr;
uint8_t* opacity = nullptr;
uint8_t* realOpacity = nullptr;
};
static RenderFlow *getInstance()
{
return _instance;
}
/*
* @brief The constructor.
* @param[in] device
* @param[in] scene
* @param[in] forward
*/
RenderFlow(DeviceGraphics* device, Scene* scene, ForwardRenderer* forward);
/*
* @brief The destructor.
*/
~RenderFlow();
/*
* @brief Gets the ModelBatcher which is responsible for collecting render Models.
*/
ModelBatcher* getModelBatcher() const { return _batcher; };
/*
* @brief Gets the DeviceGraphics using by the current RenderFlow.
*/
DeviceGraphics* getDevice() const { return _device; };
/*
* @brief Gets the render Scene which manages all render Models.
*/
Scene* getRenderScene() const { return _scene; };
/**
* @brief Render the scene specified by its root node.
* @param[in] scene The root node.
*/
void render(NodeProxy* scene, float deltaTime, Camera *camera = nullptr);
/**
* @brief Visit a node tree.
*/
void visit(NodeProxy* rootNode);
/**
* @brief Calculate local matrix.
* @param[in] tid It must rather than -1 if enable multiple thread.
*/
void calculateLocalMatrix(int tid = -1);
/**
* @brief Calculate world matrix.
*/
void calculateWorldMatrix();
/**
* @brief Calculate world matrix by level.
* @param[in] tid Thread id.
* @param[level] level Node level.
*/
void calculateLevelWorldMatrix(int tid = -1, int stage = -1);
/**
* @brief remove node level
*/
void removeNodeLevel(std::size_t level, cocos2d::Mat4* worldMat);
/**
* @brief insert node level
*/
void insertNodeLevel(std::size_t level, const LevelInfo& levelInfo);
private:
static RenderFlow *_instance;
ModelBatcher* _batcher = nullptr;
Scene* _scene = nullptr;
DeviceGraphics* _device = nullptr;
ForwardRenderer* _forward = nullptr;
std::size_t _curLevel = 0;
std::vector<std::vector<LevelInfo>> _levelInfoArr;
ParallelStage _parallelStage = ParallelStage::NONE;
ParallelTask* _paralleTask = nullptr;
};
// end of scene group
/// @}
RENDERER_END

View File

@ -0,0 +1,69 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#include "AssemblerBase.hpp"
RENDERER_BEGIN
AssemblerBase::AssemblerBase()
{
}
AssemblerBase::~AssemblerBase()
{
if (_jsDirty)
{
_jsDirty->unroot();
_jsDirty->decRef();
_jsDirty = nullptr;
}
_dirty = nullptr;
_dirtyLen = 0;
clearCustomWorldMatirx();
}
void AssemblerBase::setDirty(se_object_ptr jsDirty)
{
if (_jsDirty == jsDirty) return;
if (_jsDirty)
{
_jsDirty->unroot();
_jsDirty->decRef();
_jsDirty = nullptr;
}
if (jsDirty == nullptr) return;
_jsDirty = jsDirty;
_jsDirty->root();
_jsDirty->incRef();
_dirty = nullptr;
_dirtyLen = 0;
_jsDirty->getTypedArrayData((uint8_t**)&_dirty, &_dirtyLen);
}
RENDERER_END

View File

@ -0,0 +1,193 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "../../Macro.h"
#include <stdint.h>
#include "base/CCVector.h"
#include "../../renderer/Effect.h"
#include "scripting/js-bindings/jswrapper/Object.hpp"
#include "math/Mat4.h"
RENDERER_BEGIN
class NodeProxy;
class ModelBatcher;
class Scene;
/**
* @addtogroup scene
* @{
*/
/**
* @brief Base class for all assembler
* A assembler could take actions during node visit process, before and after all children visit.
*/
class AssemblerBase: public cocos2d::Ref
{
public:
enum AssemblerFlag {
VERTICES_OPACITY_CHANGED = 1 << 0,
VERTICES_DIRTY = 1 << 1,
};
AssemblerBase();
virtual ~AssemblerBase();
/**
* @brief Callback which will be invoked before visiting child nodes.
* @param[in] node The node being processed.
* @param[in] batcher
* @param[in] scene
*/
virtual void handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) {}
/**
* @brief Callback which will be invoked after visiting child nodes.
* @param[in] node The node being processed.
* @param[in] batcher
* @param[in] scene
*/
virtual void postHandle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) {}
/**
* @brief Gets whether the current handle should use model matrix uniform during rendering
*/
bool getUseModel() const
{
return _useModel;
}
/**
* @brief Sets whether the current handle should use model matrix uniform during rendering
*/
void setUseModel(bool useModel)
{
_useModel = useModel;
}
/**
* @brief Gets custom world matrix
*/
const cocos2d::Mat4* getCustomWorldMatrix() const
{
return _worldMatrix;
}
/**
* @brief Sets custom world matrix
*/
void setCustomWorldMatrix(const cocos2d::Mat4& matrix)
{
if (!_worldMatrix)
{
_worldMatrix = new cocos2d::Mat4();
}
*_worldMatrix = matrix;
}
/**
* @brief Clear custom world matrix
*/
void clearCustomWorldMatirx()
{
if (_worldMatrix)
{
delete _worldMatrix;
_worldMatrix = nullptr;
}
}
/**
* @brief Sync script dirty flag.
*/
void setDirty(se_object_ptr jsDirty);
/**
* @brief Changes dirty flag.
*/
void enableDirty(uint32_t flag)
{
if (_dirty)
{
*_dirty |= flag;
}
}
/**
* @brief Changes dirty flag.
*/
void disableDirty(uint32_t flag)
{
if (_dirty)
{
*_dirty &= ~flag;
}
}
/**
* @brief Is flag dirty.
*/
bool isDirty(uint32_t flag)
{
if (_dirty)
{
return *_dirty & flag;
}
return false;
}
/**
* @brief Resets data.
*/
virtual void reset() {}
bool isMaskAssembler() const
{
return _isMaskAssembler;
}
void setMaskAssembler()
{
_isMaskAssembler = true;
}
protected:
se::Object* _jsDirty = nullptr;
uint32_t* _dirty = nullptr;
std::size_t _dirtyLen = 0;
bool _useModel = false;
cocos2d::Mat4* _worldMatrix = nullptr;
bool _isMaskAssembler = false;
};
// end of scene group
/// @}
RENDERER_END

View File

@ -0,0 +1,92 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#include "MaskAssembler.hpp"
#include "../ModelBatcher.hpp"
#include "../StencilManager.hpp"
#include "../../Macro.h"
RENDERER_BEGIN
MaskAssembler::MaskAssembler()
{
setMaskAssembler();
}
MaskAssembler::~MaskAssembler()
{
CC_SAFE_RELEASE(_renderSubHandle);
CC_SAFE_RELEASE(_clearSubHandle);
}
void MaskAssembler::setRenderSubHandle(Assembler* renderSubHandle)
{
if (_renderSubHandle == renderSubHandle) return;
CC_SAFE_RELEASE(_renderSubHandle);
_renderSubHandle = renderSubHandle;
CC_SAFE_RETAIN(_renderSubHandle);
}
void MaskAssembler::setClearSubHandle(Assembler* clearSubHandle)
{
if (_clearSubHandle == clearSubHandle) return;
CC_SAFE_RELEASE(_clearSubHandle);
_clearSubHandle = clearSubHandle;
CC_SAFE_RETAIN(_clearSubHandle);
}
void MaskAssembler::handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene)
{
batcher->flush();
batcher->flushIA();
StencilManager* instance = StencilManager::getInstance();
instance->pushMask(_inverted);
instance->clear();
batcher->commit(node, _clearSubHandle, node->getCullingMask());
batcher->flush();
instance->enterLevel();
if (_imageStencil)
{
batcher->commit(node, this, node->getCullingMask());
}
else if (_renderSubHandle)
{
_renderSubHandle->handle(node, batcher, scene);
}
batcher->flush();
instance->enableMask();
}
void MaskAssembler::postHandle(NodeProxy *node, ModelBatcher *batcher, Scene *scene)
{
batcher->flush();
batcher->flushIA();
batcher->setCurrentEffect(getEffect(0));
StencilManager::getInstance()->exitMask();
}
RENDERER_END

View File

@ -0,0 +1,62 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include <stdio.h>
#include "Assembler.hpp"
#include "../MeshBuffer.hpp"
#include "math/CCMath.h"
#include "SimpleSprite2D.hpp"
class ModelBatcher;
RENDERER_BEGIN
class MaskAssembler: public SimpleSprite2D
{
public:
MaskAssembler();
virtual ~MaskAssembler();
virtual void handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override;
virtual void postHandle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override;
void setMaskInverted(bool inverted) { _inverted = inverted; };
bool getMaskInverted() { return _inverted; };
void setRenderSubHandle(Assembler* renderSubHandle);
void setClearSubHandle(Assembler* clearSubHandle);
void setImageStencil(bool isImageStencil) { _imageStencil = isImageStencil; };
protected:
bool _inverted = false;
bool _imageStencil = false;
private:
Assembler* _renderSubHandle = nullptr;
Assembler* _clearSubHandle = nullptr;
};
RENDERER_END

View File

@ -0,0 +1 @@
cocos creator 2.4.11

8
2.4.11/project.json Normal file
View File

@ -0,0 +1,8 @@
{
"engine": "cocos-creator-js",
"packages": "packages",
"name": "lcc-ui-sorting-group-2.4.x-demo",
"id": "e7de0a0e-0144-4f35-98b5-dfc103ea8611",
"version": "2.4.11",
"isNew": false
}

View File

@ -0,0 +1,55 @@
{
"title": "lcc-ui-sorting-group-2_4_x-demo",
"packageName": "org.cocos2d.demo",
"startScene": "c6ba3258-b873-4d4f-b31a-60f4c79e523a",
"excludeScenes": [],
"orientation": {
"landscapeRight": true,
"landscapeLeft": true,
"portrait": false,
"upsideDown": false
},
"webOrientation": "landscape",
"inlineSpriteFrames": true,
"inlineSpriteFrames_native": true,
"mainCompressionType": "default",
"mainIsRemote": false,
"optimizeHotUpdate": false,
"md5Cache": true,
"nativeMd5Cache": true,
"encryptJs": true,
"xxteaKey": "176efd2d-6dc3-43",
"zipCompressJs": true,
"fb-instant-games": {},
"android": {
"packageName": "com.lcc.sorting.test",
"REMOTE_SERVER_ROOT": ""
},
"ios": {
"packageName": "org.cocos2d.demo",
"REMOTE_SERVER_ROOT": "",
"ios_enable_jit": true
},
"mac": {
"packageName": "org.cocos2d.demo",
"REMOTE_SERVER_ROOT": "",
"width": 1280,
"height": 720
},
"win32": {
"REMOTE_SERVER_ROOT": "",
"width": 1280,
"height": 720
},
"android-instant": {
"packageName": "org.cocos2d.demo",
"REMOTE_SERVER_ROOT": "",
"pathPattern": "",
"scheme": "https",
"host": "",
"skipRecord": false,
"recordPath": ""
},
"appBundle": false,
"agreements": {}
}

View File

@ -0,0 +1,37 @@
{
"group-list": [
"default"
],
"collision-matrix": [
[
true
]
],
"excluded-modules": [
"3D Physics/Builtin"
],
"preview-port": 7456,
"design-resolution-width": 1920,
"design-resolution-height": 1080,
"fit-width": false,
"fit-height": true,
"use-project-simulator-setting": false,
"simulator-orientation": false,
"use-customize-simulator": true,
"simulator-resolution": {
"width": 960,
"height": 640
},
"clear-simulator-cache": true,
"facebook": {
"enable": false,
"appID": "",
"live": {
"enable": false
},
"audience": {
"enable": false
}
},
"last-module-event-record-time": 1675838102527
}

View File

@ -0,0 +1,6 @@
{
"game": {
"name": "未知游戏",
"appid": "UNKNOW"
}
}

19
2.4.11/tsconfig.json Normal file
View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [ "es2015", "es2017", "dom" ],
"target": "es5",
"experimentalDecorators": true,
"skipLibCheck": true,
"outDir": "temp/vscode-dist",
"forceConsistentCasingInFileNames": true
},
"exclude": [
"node_modules",
"library",
"local",
"temp",
"build",
"settings"
]
}

View File

Some files were not shown because too many files have changed in this diff Show More