[engine] 多纹理渲染 - 支持 cc.Label(not char cache mode)、cc.RichText、cc.Sprite、cc.MotionStreak 组件

This commit is contained in:
SmallMain 2022-06-25 00:43:02 +08:00
parent 7d0519ed68
commit 1b236db58e
32 changed files with 1438 additions and 141 deletions

View File

@ -192,7 +192,7 @@ let Label = cc.Class({
editor: CC_EDITOR && {
menu: 'i18n:MAIN_MENU.component.renderers/Label',
help: 'i18n:COMPONENT.help_url.label',
inspector: 'packages://inspector/inspectors/comps/label.js',
inspector: 'packages://service-pack/inspectors/comps/label.js',
},
properties: {
@ -578,6 +578,11 @@ let Label = cc.Class({
},
tooltip: CC_DEV && 'i18n:COMPONENT.label.underline_height',
},
autoSwitchMaterial: {
type: RenderComponent.EnableType,
default: RenderComponent.EnableType.GLOBAL,
},
},
statics: {
@ -782,7 +787,25 @@ let Label = cc.Class({
}
if (!this._frame) return;
material && material.setProperty('texture', this._frame._texture);
if (material) {
// 根据材质更新 uniform
const isMultiMaterial = material.material.isMultiSupport();
if (isMultiMaterial) {
// 贴图在 updateRenderData 才确定下来
// if (texture) this._updateMultiTexId(material, texture);
this._texIdDirty = true;
} else {
material.setProperty('texture', this._frame._texture);
}
// 根据材质更新 assembler
if (this._assembler) {
if ((isMultiMaterial && !this._assembler.isMulti) || !isMultiMaterial && this._assembler.isMulti) {
RenderComponent.prototype._resetAssembler.call(this);
}
}
}
BlendFunc.prototype._updateMaterial.call(this);
},

View File

@ -161,6 +161,10 @@ var MotionStreak = cc.Class({
if (this._texture === value) return;
this._texture = value;
// 自动切换材质
this._checkSwitchMaterial();
this._updateMaterial();
},
type: cc.Texture2D,
@ -210,6 +214,25 @@ var MotionStreak = cc.Class({
},
animatable: false,
tooltip: CC_DEV && 'i18n:COMPONENT.motionStreak.fastMode'
},
autoSwitchMaterial: {
type: RenderComponent.EnableType,
default: RenderComponent.EnableType.GLOBAL,
},
},
__preload() {
this._super();
this._checkSwitchMaterial();
},
_checkSwitchMaterial() {
if (this._assembler) {
const material = this._materials[0];
if (!material) return;
if (!this._texture) return;
this._assembler.checkAndSwitchMaterial(this, this._texture, material);
}
},
@ -220,7 +243,32 @@ var MotionStreak = cc.Class({
_updateMaterial () {
let material = this.getMaterial(0);
material && material.setProperty('texture', this._texture);
// 根据材质更新 uniform
const isMultiMaterial = material.material.isMultiSupport();
if (isMultiMaterial) {
if (!this._texture) return;
this._updateMultiTexId(material, this._texture);
} else {
const textureImpl = this._texture && this._texture.getImpl();
if (material.getProperty('texture') !== textureImpl) {
material.setProperty('texture', this._texture);
}
}
// 根据材质更新 assembler
if (this._assembler) {
if ((isMultiMaterial && !this._assembler.isMulti) || !isMultiMaterial && this._assembler.isMulti) {
this._resetAssembler();
}
}
// texId
if (isMultiMaterial && this._texIdDirty && this._assembler) {
if (!this._texture) return;
this._assembler.updateTexId(this);
this._texIdDirty = false;
}
BlendFunc.prototype._updateMaterial.call(this);
},

View File

@ -33,6 +33,32 @@ const Material = require('../assets/material/CCMaterial');
let _temp_color = new Color();
/**
* !#en enable type
* !#zh 启用类型
* @enum RenderComponent.EnableType
*/
var EnableType = cc.Enum({
/**
* !#en Global.
* !#zh 使用全局值
* @property {Number} GLOBAL
*/
GLOBAL: 0,
/**
* !#en Enable.
* !#zh 开启
* @property {Number} ENABLE
*/
ENABLE: 1,
/**
* !#en Disable.
* !#zh 关闭
* @property {Number} DISABLE
*/
DISABLE: 2,
});
/**
* !#en
* Base class for components which supports rendering features.
@ -51,6 +77,10 @@ let RenderComponent = cc.Class({
disallowMultiple: true
},
statics: {
EnableType: EnableType,
},
properties: {
_materials: {
default: [],
@ -78,12 +108,16 @@ let RenderComponent = cc.Class({
ctor () {
this._vertsDirty = true;
this._texIdDirty = true;
this._texId = 0;
this._assembler = null;
},
_resetAssembler () {
Assembler.init(this);
this._updateColor();
// 切换 Assembler 时texId 与 vDatas 数据不同步
this._texId = 0;
this.setVertsDirty();
},
@ -252,7 +286,43 @@ let RenderComponent = cc.Class({
renderer.material = material;
renderer.cullingMask = cullingMask;
}
}
},
_updateMultiTexId(material, texture) {
const multi = material.material.getMultiHandler();
const spTexture = texture;
const nSpTexture = spTexture.getImpl();
// 快速检查插槽上的贴图是否相同
// 如果是当作普通材质使用multi.getTexture(this._texId) !== nSpTexture 会一直为 true
const same = this._texId === 0
? material.getProperty('texture') !== nSpTexture
: multi.getTexture(this._texId) !== nSpTexture;
if (same) {
// 如果材质变体被修改了,则直接跳过位置检查
const isChanged = Object.prototype.hasOwnProperty.call(material._effect._passes['0']._properties, 'texture');
const texId = isChanged ? -1 : multi.getIndex(nSpTexture);
if (texId !== -1) {
// 插槽位置不对,则更新位置
this._texId = texId;
this._texIdDirty = true;
} else {
// 插槽根本没有该纹理,则修改变体的 texture
material.setProperty('texture', spTexture);
if (this._texId !== 0) {
this._texId = 0;
this._texIdDirty = true;
}
// cc.warn('renderComponent use multi-material but not has valid property.');
}
} else {
this._texIdDirty = false;
}
},
});
cc.RenderComponent = module.exports = RenderComponent;

View File

@ -28,6 +28,7 @@ const js = require('../platform/js');
const macro = require('../platform/CCMacro');
const textUtils = require('../utils/text-utils');
const HtmlTextParser = require('../utils/html-text-parser');
import MaterialVariant from '../assets/material/material-variant';
const _htmlTextParser = new HtmlTextParser();
const HorizontalAlign = macro.TextAlignment;
@ -36,6 +37,8 @@ const RichTextChildName = "RICHTEXT_CHILD";
const RichTextChildImageName = "RICHTEXT_Image_CHILD";
const CacheMode = cc.Label.CacheMode;
const RenderComponent = require('./CCRenderComponent');
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
@ -130,7 +133,7 @@ let RichText = cc.Class({
editor: CC_EDITOR && {
menu: 'i18n:MAIN_MENU.component.renderers/RichText',
help: 'i18n:COMPONENT.help_url.richtext',
inspector: 'packages://inspector/inspectors/comps/richtext.js',
inspector: 'packages://service-pack/inspectors/comps/richtext.js',
executeInEditMode: true
},
@ -347,6 +350,30 @@ let RichText = cc.Class({
this.handleTouchEvent ? this._addEventListeners() : this._removeEventListeners();
}
}
},
autoSwitchMaterial: {
type: RenderComponent.EnableType,
default: RenderComponent.EnableType.GLOBAL,
notify: function (oldValue) {
if (this.autoSwitchMaterial === oldValue) return;
for (let i = 0; i < this._labelSegments.length; i++) {
const labelComponent = this._labelSegments[i].getComponent(cc.Label);
if (labelComponent) {
labelComponent.autoSwitchMaterial = this.autoSwitchMaterial;
}
const spriteComponent = this._labelSegments[i].getComponent(cc.Sprite);
if (spriteComponent) {
spriteComponent.autoSwitchMaterial = this.autoSwitchMaterial;
}
}
for (let i = 0; i < this._labelSegmentsCache.length; i++) {
const labelComponent = this._labelSegmentsCache[i].getComponent(cc.Label);
if (labelComponent) {
labelComponent.autoSwitchMaterial = this.autoSwitchMaterial;
}
}
}
}
},
@ -653,6 +680,8 @@ let RichText = cc.Class({
let spriteNode = new cc.PrivateNode(RichTextChildImageName);
spriteNode._objFlags |= cc.Object.Flags.DontSave;
let spriteComponent = spriteNode.addComponent(cc.Sprite);
spriteComponent.autoSwitchMaterial = this.autoSwitchMaterial;
switch (richTextElement.style.imageAlign)
{
case 'top':
@ -945,6 +974,7 @@ let RichText = cc.Class({
labelComponent.cacheMode = this.cacheMode;
labelComponent.autoSwitchMaterial = this.autoSwitchMaterial;
let isAsset = this.font instanceof cc.Font;
if (isAsset && !this._isSystemFontUsed) {
labelComponent.font = this.font;

View File

@ -160,7 +160,7 @@ var Sprite = cc.Class({
editor: CC_EDITOR && {
menu: 'i18n:MAIN_MENU.component.renderers/Sprite',
help: 'i18n:COMPONENT.help_url.sprite',
inspector: 'packages://inspector/inspectors/comps/sprite.js',
inspector: 'packages://service-pack/inspectors/comps/sprite.js',
},
properties: {
@ -386,7 +386,12 @@ var Sprite = cc.Class({
animatable: false,
type: SizeMode,
tooltip: CC_DEV && 'i18n:COMPONENT.sprite.size_mode'
}
},
autoSwitchMaterial: {
type: RenderComponent.EnableType,
default: RenderComponent.EnableType.GLOBAL,
},
},
statics: {
@ -465,9 +470,25 @@ var Sprite = cc.Class({
if (oldDefine !== undefined && !oldDefine) {
material.define('USE_TEXTURE', true);
}
let textureImpl = texture && texture.getImpl();
if (material.getProperty('texture') !== textureImpl) {
material.setProperty('texture', texture);
// 根据材质更新 uniform
const isMultiMaterial = material.material.isMultiSupport();
if (isMultiMaterial) {
// 在 assembler 中进行更新性能会更好,不需要每次 setSpriteFrame 都更新,并且动态图集会导致两次触发
// if (texture) this._updateMultiTexId(material, texture);
this._texIdDirty = true;
} else {
const textureImpl = texture && texture.getImpl();
if (material.getProperty('texture') !== textureImpl) {
material.setProperty('texture', texture);
}
}
// 根据材质更新 assembler
if (this._assembler) {
if ((isMultiMaterial && !this._assembler.isMulti) || !isMultiMaterial && this._assembler.isMulti) {
this._resetAssembler();
}
}
}

View File

@ -384,9 +384,9 @@ cc.macro = {
* 是否使用原生的文本渲染机制, 布局和编辑器有差异.
*
* @property {Boolean} ENABLE_NATIVE_TTF_RENDERER
* @default true
* @default false
*/
ENABLE_NATIVE_TTF_RENDERER: true
ENABLE_NATIVE_TTF_RENDERER: false
};

View File

@ -130,22 +130,13 @@ export default class Assembler2D extends Assembler {
}
}
packToDynamicAtlas (comp, frame) {
if (CC_TEST) return;
if (!frame._original && dynamicAtlasManager && frame._texture.packable && frame._texture.loaded) {
let packedFrame = dynamicAtlasManager.insertSpriteFrame(frame);
if (packedFrame) {
frame._setDynamicAtlasFrame(packedFrame);
}
}
let material = comp._materials[0];
if (!material) return;
if (material.getProperty('texture') !== frame._texture._texture) {
// texture was packed to dynamic atlas, should update uvs
comp._vertsDirty = true;
comp._updateMaterial();
updateTexId(comp) {
const texId = comp._texId;
let texIdOffset = this.texIdOffset;
let floatsPerVert = this.floatsPerVert;
let verts = this._renderData.vDatas[0];
for (let i = 0, l = verts.length; i < l; i++) {
verts[floatsPerVert * i + texIdOffset] = texId;
}
}
}
@ -158,6 +149,8 @@ cc.js.addon(Assembler2D.prototype, {
uvOffset: 2,
colorOffset: 4,
isMulti: false,
});
cc.Assembler2D = Assembler2D;

View File

@ -1,5 +1,6 @@
import { vfmtPosUvColor } from './webgl/vertex-format';
import assemblerPool from './assembler-pool';
import dynamicAtlasManager from './utils/dynamic-atlas/manager';
export default class Assembler {
constructor () {
@ -12,12 +13,67 @@ export default class Assembler {
updateRenderData (comp) {
}
updateRenderDataForSwitchMaterial(comp) {
}
fillBuffers (comp, renderer) {
}
getVfmt () {
return vfmtPosUvColor;
}
packDynamicAtlasAndCheckMaterial(comp, frame) {
if (CC_TEST) return false;
if (!frame._original && dynamicAtlasManager && frame._texture.packable && frame._texture.loaded) {
let packedFrame = dynamicAtlasManager.insertSpriteFrame(frame);
if (packedFrame) {
frame._setDynamicAtlasFrame(packedFrame);
}
}
const material = comp._materials[0];
if (!material) return false;
// 自动切换材质
if (this.checkAndSwitchMaterial(comp, frame._texture, material)) {
return true;
}
if (material.material.isMultiSupport()) {
comp._texIdDirty = true;
} else {
if (material.getProperty('texture') !== frame._texture._texture) {
// texture was packed to dynamic atlas, should update uvs
comp._vertsDirty = true;
comp._updateMaterial();
}
}
return false;
}
checkAndSwitchMaterial(comp, texture, material) {
const autoSwitchMaterial = comp.autoSwitchMaterial;
if ((cc.sp.autoSwitchMaterial && autoSwitchMaterial === 0) || autoSwitchMaterial === 1) {
if (texture._multiMaterial) {
if (material.material !== texture._multiMaterial) {
// 避免在 Native 平台时再次进入渲染待刷新队列
if (CC_JSB) comp.node._inJsbDirtyList = true;
comp.setMaterial(0, texture._multiMaterial);
if (CC_JSB) comp.node._inJsbDirtyList = false;
// setMaterial 中会置 comp._texIdDirty = true;
if (!this.isMulti) {
comp._assembler.updateRenderDataForSwitchMaterial(comp);
return true;
}
}
}
}
}
}

View File

@ -84,7 +84,29 @@ export default class BmfontAssembler extends Assembler2D {
_comp = comp;
this._reserveQuads(comp, comp.string.toString().length);
this._updateFontFamily(comp);
const assemblerChanged = this._updateFontFamily(comp);
// 打包到动态图集时可能会切换 Assembler
if (!assemblerChanged) {
this._aftUpdateRenderData(comp);
}
return assemblerChanged;
}
_preUpdateRenderData(comp) {
_comp = comp;
this._reserveQuads(comp, comp.string.toString().length);
let fontAsset = comp.font;
_spriteFrame = fontAsset.spriteFrame;
_fntConfig = fontAsset._fntConfig;
shareLabelInfo.fontAtlas = fontAsset._fontDefDictionary;
}
_aftUpdateRenderData(comp) {
this._updateProperties(comp);
this._updateLabelInfo(comp);
this._updateContent();
@ -108,7 +130,7 @@ export default class BmfontAssembler extends Assembler2D {
_fntConfig = fontAsset._fntConfig;
shareLabelInfo.fontAtlas = fontAsset._fontDefDictionary;
this.packToDynamicAtlas(comp, _spriteFrame);
return this.packDynamicAtlasAndCheckMaterial(comp, _spriteFrame);
}
_updateLabelInfo() {

View File

@ -100,14 +100,23 @@ export default class TTFAssembler extends Assembler2D {
updateRenderData (comp) {
super.updateRenderData(comp);
if (!comp._vertsDirty) return;
if (!comp._vertsDirty) return false;
this._updateProperties(comp);
this._calculateLabelFont();
this._updateLabelDimensions();
this._updateTexture(comp);
this._calDynamicAtlas(comp);
const assemblerChanged = this._calDynamicAtlas(comp);
// 打包到动态图集时可能会切换 Assembler
if (!assemblerChanged) {
this._aftUpdateRenderData(comp);
}
return assemblerChanged;
}
_aftUpdateRenderData(comp) {
comp._actualFontSize = _fontSize;
comp.node.setContentSize(_nodeContentSize);
@ -336,14 +345,14 @@ export default class TTFAssembler extends Assembler2D {
}
_calDynamicAtlas (comp) {
if(comp.cacheMode !== Label.CacheMode.BITMAP) return;
if(comp.cacheMode !== Label.CacheMode.BITMAP) return false;
let frame = comp._frame;
// Delete cache in atlas.
deleteFromDynamicAtlas(comp, frame);
if (!frame._original) {
frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height));
}
this.packToDynamicAtlas(comp, frame);
return this.packDynamicAtlasAndCheckMaterial(comp, frame);
}
_updateLabelDimensions () {

View File

@ -30,3 +30,4 @@ require('./mask-assembler');
require('./graphics');
require('./label');
require('./motion-streak');
require('./motion-streak-multi');

View File

@ -0,0 +1,73 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import WebglBmfontAssembler from '../2d/bmfont';
import { vfmtPosUvColorTexId } from '../../../../webgl/vertex-format';
export default class MultiWebglBmfontAssembler extends WebglBmfontAssembler {
initData () {
let data = this._renderData;
data.createFlexData(0, this.verticesCount, this.indicesCount, this.getVfmt());
}
getVfmt() {
return vfmtPosUvColorTexId;
}
getBuffer() {
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
updateRenderData(comp) {
super.updateRenderData(comp);
if (comp._texIdDirty) {
comp._updateMultiTexId(comp.getMaterial(0), comp._frame._texture);
}
// 不进行 Dirty 判断,文本可能会变化,但是纹理不会变
this.updateTexId(comp);
comp._texIdDirty = false;
}
updateRenderDataForSwitchMaterial(comp) {
super._preUpdateRenderData(comp);
super._aftUpdateRenderData(comp);
if (comp._texIdDirty) {
comp._updateMultiTexId(comp.getMaterial(0), comp._frame._texture);
}
// 不进行 Dirty 判断,文本可能会变化,但是纹理不会变
this.updateTexId(comp);
comp._texIdDirty = false;
if (CC_JSB) this._aftUpdateRenderDataForNative();
}
}
MultiWebglBmfontAssembler.prototype.floatsPerVert = 6;
MultiWebglBmfontAssembler.prototype.texIdOffset = 5;
MultiWebglBmfontAssembler.prototype.isMulti = true;

View File

@ -0,0 +1,74 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import WebglTTFAssembler from '../2d/ttf';
import { vfmtPosUvColorTexId } from '../../../../webgl/vertex-format';
export default class MultiWebglTTFAssembler extends WebglTTFAssembler {
initData() {
let data = this._renderData;
data.createFlexData(0, this.verticesCount, this.indicesCount, this.getVfmt());
const indices = data.iDatas[0];
data.initQuadIndices(indices);
}
getVfmt() {
return vfmtPosUvColorTexId;
}
getBuffer() {
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
updateRenderData(comp) {
super.updateRenderData(comp);
if (comp._texIdDirty) {
comp._updateMultiTexId(comp.getMaterial(0), comp._frame._texture);
}
// 不进行 Dirty 判断,文本可能会变化,但是纹理不会变
this.updateTexId(comp);
comp._texIdDirty = false;
}
updateRenderDataForSwitchMaterial(comp) {
super._aftUpdateRenderData(comp);
if (comp._texIdDirty) {
comp._updateMultiTexId(comp.getMaterial(0), comp._frame._texture);
}
// 不进行 Dirty 判断,文本可能会变化,但是纹理不会变
this.updateTexId(comp);
comp._texIdDirty = false;
if (CC_JSB) this._aftUpdateRenderDataForNative();
}
}
MultiWebglTTFAssembler.prototype.floatsPerVert = 6;
MultiWebglTTFAssembler.prototype.texIdOffset = 5;
MultiWebglTTFAssembler.prototype.isMulti = true;

View File

@ -34,6 +34,9 @@ import TTF3D from './3d/ttf';
import Bmfont3D from './3d/bmfont';
import Letter3D from './3d/letter';
import TTFMulti from './2d-multi/ttf';
import BmfontMulti from './2d-multi/bmfont';
let NativeTTF = undefined;
if(CC_JSB) {
NativeTTF = require("./2d/nativeTTF");
@ -69,10 +72,13 @@ Label._canvasPool = {
Assembler.register(cc.Label, {
getConstructor(label) {
let is3DNode = label.node.is3DNode;
let ctor = is3DNode ? TTF3D : TTF;
const material = label.getMaterials()[0];
let isMultiMaterial = material && material.material.isMultiSupport();
let ctor = is3DNode ? TTF3D : (isMultiMaterial ? TTFMulti : TTF);
if (label.font instanceof cc.BitmapFont) {
ctor = is3DNode ? Bmfont3D : Bmfont;
ctor = is3DNode ? Bmfont3D : (isMultiMaterial ? BmfontMulti : Bmfont);
} else if (label.cacheMode === Label.CacheMode.CHAR) {
if(CC_JSB && !is3DNode && !!jsb.LabelRenderer && label.font instanceof cc.TTFFont && label._useNativeTTF()){
@ -94,5 +100,8 @@ Assembler.register(cc.Label, {
TTF3D,
Bmfont3D,
Letter3D,
NativeTTF
NativeTTF,
TTFMulti,
BmfontMulti
});

View File

@ -0,0 +1,269 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import MotionStreakAssembler from "./motion-streak";
import { vfmtPosUvColorTexId } from '../../webgl/vertex-format';
const MotionStreak = require('../../../components/CCMotionStreak');
const RenderFlow = require('../../render-flow');
function Point (point, dir) {
this.point = point || cc.v2();
this.dir = dir || cc.v2();
this.distance = 0;
this.time = 0;
}
Point.prototype.setPoint = function (x, y) {
this.point.x = x;
this.point.y = y;
};
Point.prototype.setDir = function (x, y) {
this.dir.x = x;
this.dir.y = y;
};
let _normal = cc.v2();
let _vec2 = cc.v2();
function normal (out, dir) {
//get perpendicular
out.x = -dir.y;
out.y = dir.x;
return out
}
export default class MultiMotionStreakAssembler extends MotionStreakAssembler {
initData() {
this._renderData.createFlexData(0, 16, (16 - 2) * 3, this.getVfmt());
}
getVfmt() {
return vfmtPosUvColorTexId;
}
getBuffer() {
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
update (comp, dt) {
if (CC_EDITOR && !comp.preview) return;
let stroke = comp._stroke / 2;
let node = comp.node;
let matrix = node._worldMatrix.m;
let tx = matrix[12], ty = matrix[13];
let points = comp._points;
let lastPos = comp._lastWPos;
let fadeTime = comp._fadeTime;
let moved = lastPos.x !== tx || lastPos.y !== ty;
if (moved) {
let cur;
let newHead = false;
if (points.length === 0) {
// new
let prev = new Point();
prev.setPoint(lastPos.x, lastPos.y);
this._tailShortenTime = prev.time = fadeTime;
points.push(prev);
cur = new Point();
points.unshift(cur);
}
else {
// check moved distance
cur = points[0];
let prev = points[1];
let difx = prev.point.x - tx;
let dify = prev.point.y - ty;
newHead = ((difx*difx + dify*dify) >= comp.minSeg*comp.minSeg);
}
// update head
cur.setPoint(tx, ty);
cur.time = fadeTime + dt;
let prev = points[1];
cur.distance = cur.point.sub(prev.point, _vec2).mag();
_vec2.normalizeSelf();
cur.setDir(_vec2.x, _vec2.y);
let prevIsTail = points.length === 2;
if (prevIsTail) {
prev.setDir(_vec2.x, _vec2.y);
}
if (newHead) {
let point = new Point(cur.point.clone(), cur.dir.clone());
point.distance = cur.distance;
point.time = cur.time;
points.unshift(point);
}
}
lastPos.x = tx;
lastPos.y = ty;
if (points.length < 2) {
return;
}
// cc.log(points.map(x => x.time.toFixed(2)).reverse().join(' '), ',', this._tailShortenTime.toFixed(2));
let color = comp._color, ca = color.a;
let crgb = (color.b<<16) | (color.g<<8) | color.r;
let verticesCount = 0;
let indicesCount = 0;
let flexBuffer = this._renderData._flexBuffer;
flexBuffer.reserve(points.length*2, (points.length-1)*6);
let vData = flexBuffer.vData;
let uintVData = flexBuffer.uintVData;
let vertsOffset = 6;
for (let i = points.length - 1; i >=0 ; i--) {
let p = points[i];
let point = p.point;
let dir = p.dir;
p.time -= dt;
let isLast = i === points.length - 1;
if (p.time <= 0) {
if (isLast && i - 1 >= 0) {
this._tailShortenTime = points[i - 1].time - dt;
}
points.splice(i, 1);
continue;
}
let progress = p.time / fadeTime;
if (isLast) {
let next = points[i - 1];
if (!next) {
points.splice(i, 1);
continue;
}
let nextIsStatic = points.length >= 3;
if (nextIsStatic) {
let segmentProgress = p.time / this._tailShortenTime;
if (segmentProgress <= 1) {
point.x = next.point.x - next.distance * next.dir.x * segmentProgress;
point.y = next.point.y - next.distance * next.dir.y * segmentProgress;
}
}
else {
this._tailShortenTime = p.time;
}
}
normal(_normal, dir);
let da = progress * ca;
let c = ((da<<24) >>> 0) | crgb;
let offset = verticesCount * vertsOffset;
vData[offset] = point.x + _normal.x * stroke;
vData[offset + 1] = point.y + _normal.y * stroke;
vData[offset + 2] = 1;
vData[offset + 3] = progress;
uintVData[offset + 4] = c;
vData[offset + 5] = comp._texId;
offset += vertsOffset;
vData[offset] = point.x - _normal.x * stroke;
vData[offset + 1] = point.y - _normal.y * stroke;
vData[offset + 2] = 0;
vData[offset + 3] = progress;
uintVData[offset + 4] = c;
vData[offset + 5] = comp._texId;
verticesCount += 2;
}
indicesCount = verticesCount <= 2 ? 0 : (verticesCount - 2) * 3;
flexBuffer.used(verticesCount, indicesCount);
}
fillBuffers (comp, renderer) {
let { vData, usedVertices, usedIndices, usedVerticesFloats } = this._renderData._flexBuffer;
let buffer = this.getBuffer(renderer);
let offsetInfo = buffer.request(usedVertices, usedIndices);
// buffer data may be realloc, need get reference after request.
// fill vertices
let vertexOffset = offsetInfo.byteOffset >> 2,
vbuf = buffer._vData;
if (vData.length + vertexOffset > vbuf.length) {
vbuf.set(vData.subarray(0, usedVerticesFloats), vertexOffset);
}
else {
vbuf.set(vData, vertexOffset);
}
// fill indices
let ibuf = buffer._iData,
indiceOffset = offsetInfo.indiceOffset,
vertexId = offsetInfo.vertexOffset;
// index buffer
for (let i = 0, l = usedVertices; i < l; i += 2) {
let start = vertexId + i;
ibuf[indiceOffset++] = start;
ibuf[indiceOffset++] = start + 2;
ibuf[indiceOffset++] = start + 1;
ibuf[indiceOffset++] = start + 1;
ibuf[indiceOffset++] = start + 2;
ibuf[indiceOffset++] = start + 3;
}
comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA;
}
}
MotionStreakAssembler.register(MotionStreak, {
getConstructor(comp) {
const material = comp.getMaterials()[0];
let isMultiMaterial = material && material.material.isMultiSupport();
return isMultiMaterial ? MultiMotionStreakAssembler : MotionStreakAssembler;
},
MotionStreakAssembler,
MultiMotionStreakAssembler
});
MultiMotionStreakAssembler.prototype.floatsPerVert = 6;
MultiMotionStreakAssembler.prototype.texIdOffset = 5;
MultiMotionStreakAssembler.prototype.isMulti = true;

View File

@ -25,7 +25,6 @@
import Assembler2D from '../../assembler-2d';
const MotionStreak = require('../../../components/CCMotionStreak');
const RenderFlow = require('../../render-flow');
function Point (point, dir) {
@ -267,5 +266,3 @@ export default class MotionStreakAssembler extends Assembler2D {
comp.node._renderFlag |= RenderFlow.FLAG_UPDATE_RENDER_DATA;
}
}
MotionStreakAssembler.register(MotionStreak, MotionStreakAssembler);

View File

@ -0,0 +1,101 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import { vfmtPosUvColorTexId } from '../../../../webgl/vertex-format';
import BarFilledAssembler from '../2d/bar-filled';
export default class BarFilledAssemblerMulti extends BarFilledAssembler {
initData() {
let data = this._renderData;
data.createFlexData(0, this.verticesCount, this.indicesCount, this.getVfmt());
const indices = data.iDatas[0];
data.initQuadIndices(indices);
}
getVfmt() {
return vfmtPosUvColorTexId;
}
getBuffer() {
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
updateRenderData (sprite) {
super.updateRenderData(sprite);
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite._spriteFrame._texture);
if (sprite._texIdDirty) {
this.updateTexId(sprite);
sprite._texIdDirty = false;
}
}
}
updateRenderDataForSwitchMaterial(sprite) {
if (sprite._vertsDirty) {
let fillStart = sprite._fillStart;
let fillRange = sprite._fillRange;
if (fillRange < 0) {
fillStart += fillRange;
fillRange = -fillRange;
}
fillRange = fillStart + fillRange;
fillStart = fillStart > 1.0 ? 1.0 : fillStart;
fillStart = fillStart < 0.0 ? 0.0 : fillStart;
fillRange = fillRange > 1.0 ? 1.0 : fillRange;
fillRange = fillRange < 0.0 ? 0.0 : fillRange;
fillRange = fillRange - fillStart;
fillRange = fillRange < 0 ? 0 : fillRange;
let fillEnd = fillStart + fillRange;
fillEnd = fillEnd > 1 ? 1 : fillEnd;
this.updateUVs(sprite, fillStart, fillEnd);
this.updateVerts(sprite, fillStart, fillEnd);
sprite._vertsDirty = false;
}
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite._spriteFrame._texture);
if (sprite._texIdDirty) {
this.updateTexId(sprite);
sprite._texIdDirty = false;
}
}
if (CC_JSB) this._aftUpdateRenderDataForNative();
}
}
BarFilledAssemblerMulti.prototype.floatsPerVert = 6;
BarFilledAssemblerMulti.prototype.texIdOffset = 5;
BarFilledAssemblerMulti.prototype.isMulti = true;

View File

@ -0,0 +1,96 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import { vfmtPosUvColorTexId } from '../../../../webgl/vertex-format';
import MeshSpriteAssembler from '../2d/mesh';
export default class MultiMeshSpriteAssembler extends MeshSpriteAssembler {
getVfmt() {
return vfmtPosUvColorTexId;
}
getBuffer() {
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
updateRenderData(sprite) {
let frame = sprite.spriteFrame;
super.updateRenderData(sprite);
if (frame) {
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), frame._texture);
}
// 不进行 Dirty 判断Mesh 可能会变化,但是纹理不会变
this.updateTexId(sprite);
sprite._texIdDirty = false;
}
}
updateRenderDataForSwitchMaterial(sprite) {
let frame = sprite.spriteFrame;
if (frame) {
let vertices = frame.vertices;
if (vertices) {
this.verticesCount = vertices.x.length;
this.indicesCount = vertices.triangles.length;
let renderData = this._renderData;
let flexBuffer = renderData._flexBuffer;
if (flexBuffer.reserve(this.verticesCount, this.indicesCount)) {
this.updateColor(sprite);
sprite._vertsDirty = true;
}
flexBuffer.used(this.verticesCount, this.indicesCount);
this.updateIndices(vertices.triangles);
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
this.updateWorldVerts(sprite);
sprite._vertsDirty = false;
}
}
}
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), frame._texture);
}
// 不进行 Dirty 判断Mesh 可能会变化,但是纹理不会变
this.updateTexId(sprite);
sprite._texIdDirty = false;
if (CC_JSB) this._aftUpdateRenderDataForNative();
}
}
MultiMeshSpriteAssembler.prototype.floatsPerVert = 6;
MultiMeshSpriteAssembler.prototype.texIdOffset = 5;
MultiMeshSpriteAssembler.prototype.isMulti = true;

View File

@ -0,0 +1,72 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import { vfmtPosUvColorTexId } from '../../../../webgl/vertex-format';
import RadialFilledAssembler from '../2d/radial-filled';
export default class MultiRadialFilledAssembler extends RadialFilledAssembler {
initData (sprite) {
this._renderData.createFlexData(0, 4, 6, this.getVfmt());
this.updateIndices();
}
getVfmt() {
return vfmtPosUvColorTexId;
}
getBuffer() {
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
updateRenderData (sprite) {
super.updateRenderData(sprite);
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite.spriteFrame._texture);
}
// 不进行 Dirty 判断Mesh 可能会变化,但是纹理不会变
this.updateTexId(sprite);
sprite._texIdDirty = false;
}
updateRenderDataForSwitchMaterial(sprite) {
this._aftUpdateRenderData(sprite);
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite.spriteFrame._texture);
}
// 不进行 Dirty 判断Mesh 可能会变化,但是纹理不会变
this.updateTexId(sprite);
sprite._texIdDirty = false;
if (CC_JSB) this._aftUpdateRenderDataForNative();
}
}
MultiRadialFilledAssembler.prototype.floatsPerVert = 6;
MultiRadialFilledAssembler.prototype.texIdOffset = 5;
MultiRadialFilledAssembler.prototype.isMulti = true;

View File

@ -0,0 +1,78 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import { vfmtPosUvColorTexId } from '../../../../webgl/vertex-format';
import SimpleSpriteAssembler from '../2d/simple';
export default class MultiSimpleSpriteAssembler extends SimpleSpriteAssembler {
initData() {
let data = this._renderData;
data.createFlexData(0, this.verticesCount, this.indicesCount, this.getVfmt());
const indices = data.iDatas[0];
data.initQuadIndices(indices);
}
getVfmt() {
return vfmtPosUvColorTexId;
}
getBuffer() {
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
updateRenderData (sprite) {
super.updateRenderData(sprite);
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite._spriteFrame._texture);
if (sprite._texIdDirty) {
this.updateTexId(sprite);
sprite._texIdDirty = false;
}
}
}
updateRenderDataForSwitchMaterial(sprite) {
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
sprite._vertsDirty = false;
}
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite._spriteFrame._texture);
if (sprite._texIdDirty) {
this.updateTexId(sprite);
sprite._texIdDirty = false;
}
}
if (CC_JSB) this._aftUpdateRenderDataForNative();
}
}
MultiSimpleSpriteAssembler.prototype.floatsPerVert = 6;
MultiSimpleSpriteAssembler.prototype.texIdOffset = 5;
MultiSimpleSpriteAssembler.prototype.isMulti = true;

View File

@ -0,0 +1,91 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import { vfmtPosUvColorTexId } from '../../../../webgl/vertex-format';
import SlicedAssembler from '../2d/sliced';
export default class MultiSlicedAssembler extends SlicedAssembler {
initData (sprite) {
if (this._renderData.meshCount > 0) return;
this._renderData.createFlexData(0, this.verticesCount, this.indicesCount, this.getVfmt());
let indices = this._renderData.iDatas[0];
let indexOffset = 0;
for (let r = 0; r < 3; ++r) {
for (let c = 0; c < 3; ++c) {
let start = r * 4 + c;
indices[indexOffset++] = start;
indices[indexOffset++] = start + 1;
indices[indexOffset++] = start + 4;
indices[indexOffset++] = start + 1;
indices[indexOffset++] = start + 5;
indices[indexOffset++] = start + 4;
}
}
}
getVfmt() {
return vfmtPosUvColorTexId;
}
getBuffer() {
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
updateRenderData (sprite) {
super.updateRenderData(sprite);
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite._spriteFrame._texture);
if (sprite._texIdDirty) {
this.updateTexId(sprite);
sprite._texIdDirty = false;
}
}
}
updateRenderDataForSwitchMaterial(sprite) {
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
sprite._vertsDirty = false;
}
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite._spriteFrame._texture);
if (sprite._texIdDirty) {
this.updateTexId(sprite);
sprite._texIdDirty = false;
}
}
if (CC_JSB) this._aftUpdateRenderDataForNative();
}
}
MultiSlicedAssembler.prototype.floatsPerVert = 6;
MultiSlicedAssembler.prototype.texIdOffset = 5;
MultiSlicedAssembler.prototype.isMulti = true;

View File

@ -0,0 +1,101 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
import { vfmtPosUvColorTexId } from '../../../../webgl/vertex-format';
import TiledAssembler from '../2d/tiled';
export default class MultiTiledAssembler extends TiledAssembler {
getVfmt() {
return vfmtPosUvColorTexId;
}
getBuffer() {
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
updateRenderData(sprite) {
super.updateRenderData(sprite);
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite.spriteFrame._texture);
}
// 不进行 Dirty 判断Mesh 可能会变化,但是纹理不会变
this.updateTexId(sprite);
sprite._texIdDirty = false;
}
updateRenderDataForSwitchMaterial(sprite) {
let frame = sprite._spriteFrame;
let node = sprite.node;
let contentWidth = this.contentWidth = Math.abs(node.width);
let contentHeight = this.contentHeight = Math.abs(node.height);
let rect = frame._rect;
let leftWidth = frame.insetLeft, rightWidth = frame.insetRight, centerWidth = rect.width - leftWidth - rightWidth,
topHeight = frame.insetTop, bottomHeight = frame.insetBottom, centerHeight = rect.height - topHeight - bottomHeight;
this.sizableWidth = contentWidth - leftWidth - rightWidth;
this.sizableHeight = contentHeight - topHeight - bottomHeight;
this.sizableWidth = this.sizableWidth > 0 ? this.sizableWidth : 0;
this.sizableHeight = this.sizableHeight > 0 ? this.sizableHeight : 0;
let hRepeat = this.hRepeat = centerWidth === 0 ? this.sizableWidth : this.sizableWidth / centerWidth;
let vRepeat = this.vRepeat = centerHeight === 0 ? this.sizableHeight : this.sizableHeight / centerHeight;
let row = this.row = Math.ceil(vRepeat + 2);
let col = this.col = Math.ceil(hRepeat + 2);
// update data property
let count = row * col;
this.verticesCount = count * 4;
this.indicesCount = count * 6;
let renderData = this._renderData;
let flexBuffer = renderData._flexBuffer;
if (flexBuffer.reserve(this.verticesCount, this.indicesCount)) {
this._updateIndices();
this.updateColor(sprite);
}
flexBuffer.used(this.verticesCount, this.indicesCount);
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
sprite._vertsDirty = false;
}
if (sprite._texIdDirty) {
sprite._updateMultiTexId(sprite.getMaterial(0), sprite.spriteFrame._texture);
}
// 不进行 Dirty 判断Mesh 可能会变化,但是纹理不会变
this.updateTexId(sprite);
sprite._texIdDirty = false;
if (CC_JSB) this._aftUpdateRenderDataForNative();
}
}
MultiTiledAssembler.prototype.floatsPerVert = 6;
MultiTiledAssembler.prototype.texIdOffset = 5;
MultiTiledAssembler.prototype.isMulti = true;

View File

@ -31,37 +31,40 @@ const FillType = Sprite.FillType;
export default class BarFilledAssembler extends Assembler2D {
updateRenderData (sprite) {
let frame = sprite._spriteFrame;
this.packToDynamicAtlas(sprite, frame);
const assemblerChanged = this.packDynamicAtlasAndCheckMaterial(sprite, frame);
if (!sprite._vertsDirty) {
return;
// 打包到动态图集时可能会切换 Assembler
if (!assemblerChanged) {
if (sprite._vertsDirty) {
let fillStart = sprite._fillStart;
let fillRange = sprite._fillRange;
if (fillRange < 0) {
fillStart += fillRange;
fillRange = -fillRange;
}
fillRange = fillStart + fillRange;
fillStart = fillStart > 1.0 ? 1.0 : fillStart;
fillStart = fillStart < 0.0 ? 0.0 : fillStart;
fillRange = fillRange > 1.0 ? 1.0 : fillRange;
fillRange = fillRange < 0.0 ? 0.0 : fillRange;
fillRange = fillRange - fillStart;
fillRange = fillRange < 0 ? 0 : fillRange;
let fillEnd = fillStart + fillRange;
fillEnd = fillEnd > 1 ? 1 : fillEnd;
this.updateUVs(sprite, fillStart, fillEnd);
this.updateVerts(sprite, fillStart, fillEnd);
sprite._vertsDirty = false;
}
}
let fillStart = sprite._fillStart;
let fillRange = sprite._fillRange;
if (fillRange < 0) {
fillStart += fillRange;
fillRange = -fillRange;
}
fillRange = fillStart + fillRange;
fillStart = fillStart > 1.0 ? 1.0 : fillStart;
fillStart = fillStart < 0.0 ? 0.0 : fillStart;
fillRange = fillRange > 1.0 ? 1.0 : fillRange;
fillRange = fillRange < 0.0 ? 0.0 : fillRange;
fillRange = fillRange - fillStart;
fillRange = fillRange < 0 ? 0 : fillRange;
let fillEnd = fillStart + fillRange;
fillEnd = fillEnd > 1 ? 1 : fillEnd;
this.updateUVs(sprite, fillStart, fillEnd);
this.updateVerts(sprite, fillStart, fillEnd);
sprite._vertsDirty = false;
return assemblerChanged;
}
updateUVs (sprite, fillStart, fillEnd) {

View File

@ -31,33 +31,39 @@ export default class MeshSpriteAssembler extends Assembler2D {
}
updateRenderData (sprite) {
this.packToDynamicAtlas(sprite, sprite._spriteFrame);
let frame = sprite.spriteFrame;
if (frame) {
let vertices = frame.vertices;
if (vertices) {
this.verticesCount = vertices.x.length;
this.indicesCount = vertices.triangles.length;
let renderData = this._renderData;
let flexBuffer = renderData._flexBuffer;
if (flexBuffer.reserve(this.verticesCount, this.indicesCount)) {
this.updateColor(sprite);
sprite._vertsDirty = true;
}
flexBuffer.used(this.verticesCount, this.indicesCount);
const assemblerChanged = this.packDynamicAtlasAndCheckMaterial(sprite, frame);
this.updateIndices(vertices.triangles);
// 打包到动态图集时可能会切换 Assembler
if (!assemblerChanged) {
if (frame) {
let vertices = frame.vertices;
if (vertices) {
this.verticesCount = vertices.x.length;
this.indicesCount = vertices.triangles.length;
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
this.updateWorldVerts(sprite);
sprite._vertsDirty = false;
let renderData = this._renderData;
let flexBuffer = renderData._flexBuffer;
if (flexBuffer.reserve(this.verticesCount, this.indicesCount)) {
this.updateColor(sprite);
sprite._vertsDirty = true;
}
flexBuffer.used(this.verticesCount, this.indicesCount);
this.updateIndices(vertices.triangles);
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
this.updateWorldVerts(sprite);
sprite._vertsDirty = false;
}
}
}
}
return assemblerChanged;
}
updateIndices (triangles) {

View File

@ -179,7 +179,18 @@ export default class RadialFilledAssembler extends Assembler2D {
super.updateRenderData(sprite);
let frame = sprite.spriteFrame;
this.packToDynamicAtlas(sprite, frame);
const assemblerChanged = this.packDynamicAtlasAndCheckMaterial(sprite, frame);
// 打包到动态图集时可能会切换 Assembler
if (!assemblerChanged) {
this._aftUpdateRenderData(sprite);
}
return assemblerChanged;
}
_aftUpdateRenderData(sprite) {
let frame = sprite.spriteFrame;
if (sprite._vertsDirty) {
let fillStart = sprite._fillStart;

View File

@ -27,13 +27,18 @@ import Assembler2D from '../../../../assembler-2d';
export default class SimpleSpriteAssembler extends Assembler2D {
updateRenderData (sprite) {
this.packToDynamicAtlas(sprite, sprite._spriteFrame);
const assemblerChanged = this.packDynamicAtlasAndCheckMaterial(sprite, sprite._spriteFrame);
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
sprite._vertsDirty = false;
// 打包到动态图集时可能会切换 Assembler
if (!assemblerChanged) {
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
sprite._vertsDirty = false;
}
}
return assemblerChanged;
}
updateUVs (sprite) {

View File

@ -52,13 +52,18 @@ export default class SlicedAssembler extends Assembler2D {
updateRenderData (sprite) {
let frame = sprite._spriteFrame;
this.packToDynamicAtlas(sprite, frame);
const assemblerChanged = this.packDynamicAtlasAndCheckMaterial(sprite, frame);
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
sprite._vertsDirty = false;
// 打包到动态图集时可能会切换 Assembler
if (!assemblerChanged) {
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
sprite._vertsDirty = false;
}
}
return assemblerChanged;
}
updateVerts (sprite) {

View File

@ -59,42 +59,47 @@ export default class TiledAssembler extends Assembler2D {
updateRenderData (sprite) {
let frame = sprite._spriteFrame;
this.packToDynamicAtlas(sprite, frame);
const assemblerChanged = this.packDynamicAtlasAndCheckMaterial(sprite, frame);
let node = sprite.node;
// 打包到动态图集时可能会切换 Assembler
if (!assemblerChanged) {
let node = sprite.node;
let contentWidth = this.contentWidth = Math.abs(node.width);
let contentHeight = this.contentHeight = Math.abs(node.height);
let rect = frame._rect;
let leftWidth = frame.insetLeft, rightWidth = frame.insetRight, centerWidth = rect.width - leftWidth - rightWidth,
topHeight = frame.insetTop, bottomHeight = frame.insetBottom, centerHeight = rect.height - topHeight - bottomHeight;
this.sizableWidth = contentWidth - leftWidth - rightWidth;
this.sizableHeight = contentHeight - topHeight - bottomHeight;
this.sizableWidth = this.sizableWidth > 0 ? this.sizableWidth : 0;
this.sizableHeight = this.sizableHeight > 0 ? this.sizableHeight : 0;
let hRepeat = this.hRepeat = centerWidth === 0 ? this.sizableWidth : this.sizableWidth / centerWidth;
let vRepeat = this.vRepeat = centerHeight === 0 ? this.sizableHeight : this.sizableHeight / centerHeight;
let row = this.row = Math.ceil(vRepeat + 2);
let col = this.col = Math.ceil(hRepeat + 2);
let contentWidth = this.contentWidth = Math.abs(node.width);
let contentHeight = this.contentHeight = Math.abs(node.height);
let rect = frame._rect;
let leftWidth = frame.insetLeft, rightWidth = frame.insetRight, centerWidth = rect.width - leftWidth - rightWidth,
topHeight = frame.insetTop, bottomHeight = frame.insetBottom, centerHeight = rect.height - topHeight - bottomHeight;
this.sizableWidth = contentWidth - leftWidth - rightWidth;
this.sizableHeight = contentHeight - topHeight - bottomHeight;
this.sizableWidth = this.sizableWidth > 0 ? this.sizableWidth : 0;
this.sizableHeight = this.sizableHeight > 0 ? this.sizableHeight : 0;
let hRepeat = this.hRepeat = centerWidth === 0 ? this.sizableWidth : this.sizableWidth / centerWidth;
let vRepeat = this.vRepeat = centerHeight === 0 ? this.sizableHeight : this.sizableHeight / centerHeight;
let row = this.row = Math.ceil(vRepeat + 2);
let col = this.col = Math.ceil(hRepeat + 2);
// update data property
let count = row * col;
this.verticesCount = count * 4;
this.indicesCount = count * 6;
// update data property
let count = row * col;
this.verticesCount = count * 4;
this.indicesCount = count * 6;
let renderData = this._renderData;
let flexBuffer = renderData._flexBuffer;
if (flexBuffer.reserve(this.verticesCount, this.indicesCount)) {
this._updateIndices();
this.updateColor(sprite);
let renderData = this._renderData;
let flexBuffer = renderData._flexBuffer;
if (flexBuffer.reserve(this.verticesCount, this.indicesCount)) {
this._updateIndices();
this.updateColor(sprite);
}
flexBuffer.used(this.verticesCount, this.indicesCount);
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
sprite._vertsDirty = false;
}
}
flexBuffer.used(this.verticesCount, this.indicesCount);
if (sprite._vertsDirty) {
this.updateUVs(sprite);
this.updateVerts(sprite);
sprite._vertsDirty = false;
}
return assemblerChanged;
}
updateVerts (sprite) {

View File

@ -15,27 +15,36 @@ import RadialFilled3D from "./3d/radial-filled";
import BarFilled3D from "./3d/bar-filled";
import Mesh3D from './3d/mesh';
import SimpleMulti from "./2d-multi/simple";
import SlicedMulti from "./2d-multi/sliced";
import TiledMulti from "./2d-multi/tiled";
import RadialFilledMulti from "./2d-multi/radial-filled";
import BarFilledMulti from "./2d-multi/bar-filled";
import MeshMulti from "./2d-multi/mesh";
let ctor = {
getConstructor(sprite) {
let is3DNode = sprite.node.is3DNode;
const material = sprite.getMaterials()[0];
let isMultiMaterial = material && material.material.isMultiSupport();
let ctor = is3DNode ? Simple3D : Simple;
let ctor = is3DNode ? Simple3D : (isMultiMaterial ? SimpleMulti : Simple);
switch (sprite.type) {
case Type.SLICED:
ctor = is3DNode ? Sliced3D : Sliced;
ctor = is3DNode ? Sliced3D : (isMultiMaterial ? SlicedMulti : Sliced);
break;
case Type.TILED:
ctor = is3DNode ? Tiled3D : Tiled;
ctor = is3DNode ? Tiled3D : (isMultiMaterial ? TiledMulti : Tiled);
break;
case Type.FILLED:
if (sprite._fillType === FillType.RADIAL) {
ctor = is3DNode ? RadialFilled3D : RadialFilled;
ctor = is3DNode ? RadialFilled3D : (isMultiMaterial ? RadialFilledMulti : RadialFilled);
} else {
ctor = is3DNode ? BarFilled3D : BarFilled;
ctor = is3DNode ? BarFilled3D : (isMultiMaterial ? BarFilledMulti : BarFilled);
}
break;
case Type.MESH:
ctor = is3DNode ? Mesh3D : Mesh;
ctor = is3DNode ? Mesh3D : (isMultiMaterial ? MeshMulti : Mesh);
break;
}
@ -55,6 +64,13 @@ let ctor = {
RadialFilled3D,
BarFilled3D,
Mesh3D,
SimpleMulti,
SlicedMulti,
TiledMulti,
RadialFilledMulti,
BarFilledMulti,
MeshMulti,
};
Assembler.register(cc.Sprite, ctor);

View File

@ -41,6 +41,15 @@ var vfmtPosUvColor = new gfx.VertexFormat([
vfmtPosUvColor.name = 'vfmtPosUvColor';
gfx.VertexFormat.XY_UV_Color = vfmtPosUvColor;
var vfmtPosUvColorTexId = new gfx.VertexFormat([
{ name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
{ name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
{ name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true },
{ name: gfx.ATTR_TEX_ID, type: gfx.ATTR_TYPE_FLOAT32, num: 1 },
]);
vfmtPosUvColorTexId.name = 'vfmtPosUvColorTexId';
gfx.VertexFormat.XY_UV_Color_TexId = vfmtPosUvColorTexId;
var vfmtPosUvTwoColor = new gfx.VertexFormat([
{ name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
{ name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
@ -76,5 +85,6 @@ module.exports = {
vfmtPosUvTwoColor,
vfmtPosUv,
vfmtPosColor,
vfmtPos
vfmtPos,
vfmtPosUvColorTexId
};

View File

@ -178,6 +178,7 @@ export const enums = {
ATTR_TEX_COORD6: 'a_texCoord6',
ATTR_TEX_COORD7: 'a_texCoord7',
ATTR_TEX_COORD8: 'a_texCoord8',
ATTR_TEX_ID: 'a_texId',
// vertex attribute type

View File

@ -164,7 +164,8 @@
"name": "MotionStreak",
"entries": [
"./cocos2d/core/components/CCMotionStreak.js",
"./cocos2d/core/renderer/webgl/assemblers/motion-streak.js"
"./cocos2d/core/renderer/webgl/assemblers/motion-streak.js",
"./cocos2d/core/renderer/webgl/assemblers/motion-streak-multi.js"
],
"dependencies": ["WebGL Renderer"]
},