mirror of
https://gitee.com/nomat/lcc-ui-sorting-group-demo.git
synced 2025-12-08 14:58:50 +00:00
实现2.4.11版本
This commit is contained in:
12
3.6.3/assets/lcc-ui-sorting-group/engine-extend.meta
Normal file
12
3.6.3/assets/lcc-ui-sorting-group/engine-extend.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "e9f90997-b8f8-43b8-8afc-26a0d75357f6",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
71
3.6.3/assets/lcc-ui-sorting-group/engine-extend/node.jsb.ts
Normal file
71
3.6.3/assets/lcc-ui-sorting-group/engine-extend/node.jsb.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { director, Layers, misc, utils } from "cc";
|
||||
import { MeshRenderer } from "cc";
|
||||
import { profiler } from "cc";
|
||||
import { CCObject } from "cc";
|
||||
import { game } from "cc";
|
||||
import { Material } from "cc";
|
||||
import { Profiler } from "cc";
|
||||
import { Node } from "cc";
|
||||
import { JSB } from "cc/env";
|
||||
|
||||
const _constants = {
|
||||
fontSize: 23,
|
||||
quadHeight: 0.4,
|
||||
segmentsPerLine: 8,
|
||||
textureWidth: 256,
|
||||
textureHeight: 256,
|
||||
};
|
||||
|
||||
if(JSB){
|
||||
//@ts-ignore
|
||||
const Node_ctor = Node.prototype._ctor;
|
||||
//@ts-ignore
|
||||
Node.prototype._ctor = function (name?: string) {
|
||||
Node_ctor.call(this, name);
|
||||
|
||||
const sharedArrayBuffer = this._getSharedArrayBufferObject();
|
||||
// Uint32Array with 3 elements: eventMask, layer, dirtyFlags
|
||||
this._sharedUint32Arr = new Uint32Array(sharedArrayBuffer, 0, 3);
|
||||
// Int32Array with 1 element: siblingIndex
|
||||
this._sharedInt32Arr = new Int32Array(sharedArrayBuffer, 12, 1);
|
||||
// uiSortingPriority
|
||||
this._sharedFloatArr = new Float32Array(sharedArrayBuffer, 16, 1);
|
||||
// Uint8Array with 3 elements: activeInHierarchy, active, static, uiSortingEnabled
|
||||
this._sharedUint8Arr = new Uint8Array(sharedArrayBuffer, 20, 4);
|
||||
|
||||
this._sharedUint32Arr[1] = Layers.Enum.DEFAULT; // this._sharedUint32Arr[1] is layer
|
||||
};
|
||||
|
||||
Object.defineProperty(Node.prototype, 'uiSortingEnabled', {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get (): Readonly<Boolean> {
|
||||
return this._sharedUint8Arr[3] != 0; // Uint8, 1: active
|
||||
},
|
||||
set (v) {
|
||||
this._sharedUint8Arr[3] = (v ? 1 : 0); // Uint8, 1: active
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(Node.prototype, 'uiSortingPriority', {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get (): Readonly<number> {
|
||||
return this._sharedFloatArr[0];
|
||||
},
|
||||
set (v) {
|
||||
this._sharedFloatArr[0] = v;
|
||||
},
|
||||
});
|
||||
|
||||
// 左下角调试节点创建过早,重新创建
|
||||
//@ts-ignore
|
||||
if (profiler._rootNode && profiler._rootNode.isValid){
|
||||
//@ts-ignore
|
||||
profiler._rootNode.destroy();
|
||||
//@ts-ignore
|
||||
profiler._rootNode = null;
|
||||
|
||||
profiler.generateNode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "29c6a480-4d9e-413e-8a39-0f0f9a59a19c",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { UIRenderer } from "cc";
|
||||
|
||||
declare module 'cc' {
|
||||
interface UIRenderer {
|
||||
|
||||
/**
|
||||
* 渲染优先级
|
||||
*/
|
||||
renderPriority:number;
|
||||
|
||||
/**
|
||||
* 渲染透明度
|
||||
*/
|
||||
renderOpacity:number;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "1969969e-8406-4e32-a252-fa63557cd43f",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { UITransform } from "cc";
|
||||
import { JSB } from "cc/env";
|
||||
|
||||
declare module 'cc' {
|
||||
interface UITransform {
|
||||
|
||||
/**
|
||||
* 排序优先级 - private
|
||||
*/
|
||||
_sortingPriority:number;
|
||||
|
||||
/**
|
||||
* 排序优先级
|
||||
*/
|
||||
sortingPriority:number;
|
||||
|
||||
/**
|
||||
* 排序优使能 - private
|
||||
*/
|
||||
_sortingEnabled:boolean;
|
||||
|
||||
/**
|
||||
* 排序优使能
|
||||
*/
|
||||
sortingEnabled:boolean;
|
||||
}
|
||||
}
|
||||
|
||||
if(!('sortingPriority' in UITransform.prototype)){
|
||||
Object.defineProperty(UITransform.prototype, 'sortingPriority', {
|
||||
get: function() {
|
||||
return this._sortingPriority;
|
||||
},
|
||||
set: function(value) {
|
||||
this._sortingPriority = value;
|
||||
if(JSB){
|
||||
this.node.uiSortingPriority = value;
|
||||
}
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(UITransform.prototype, 'sortingEnabled', {
|
||||
get: function() {
|
||||
return this._sortingEnabled;
|
||||
},
|
||||
set: function(value) {
|
||||
this._sortingEnabled = value;
|
||||
if(JSB){
|
||||
this.node.uiSortingEnabled = value;
|
||||
}
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "421d8e4a-74d5-4851-a739-de22c13f87e3",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
214
3.6.3/assets/lcc-ui-sorting-group/engine-extend/ui.ts
Normal file
214
3.6.3/assets/lcc-ui-sorting-group/engine-extend/ui.ts
Normal file
@@ -0,0 +1,214 @@
|
||||
import { clamp, gfx,Node,RenderData,UI,StencilManager,UIRenderer, renderer } from 'cc';
|
||||
import { JSB } from 'cc/env';
|
||||
|
||||
declare module 'cc' {
|
||||
interface UI {
|
||||
|
||||
/**
|
||||
* 渲染器缓存
|
||||
*/
|
||||
rendererCache:UIRenderer[];
|
||||
|
||||
/**
|
||||
* 渲染器排序
|
||||
*/
|
||||
rendererOrder:boolean;
|
||||
|
||||
/**
|
||||
* 刷新渲染缓存
|
||||
*/
|
||||
flushRendererCache();
|
||||
}
|
||||
}
|
||||
|
||||
export enum _cocos_2d_renderer_stencil_manager__Stage {
|
||||
DISABLED = 0,
|
||||
CLEAR = 1,
|
||||
ENTER_LEVEL = 2,
|
||||
ENABLED = 3,
|
||||
EXIT_LEVEL = 4,
|
||||
CLEAR_INVERTED = 5,
|
||||
ENTER_LEVEL_INVERTED = 6
|
||||
}
|
||||
|
||||
export function updateOpacity (renderData: RenderData, opacity: number) {
|
||||
const vfmt = renderData.vertexFormat;
|
||||
const vb = renderData.chunk.vb;
|
||||
let attr; let format; let stride;
|
||||
// Color component offset
|
||||
let offset = 0;
|
||||
for (let i = 0; i < vfmt.length; ++i) {
|
||||
attr = vfmt[i];
|
||||
format = gfx.FormatInfos[attr.format];
|
||||
if (format.hasAlpha) {
|
||||
stride = renderData.floatStride;
|
||||
if (format.size / format.count === 1) {
|
||||
const alpha = ~~clamp(Math.round(opacity * 255), 0, 255);
|
||||
// Uint color RGBA8
|
||||
for (let color = offset; color < vb.length; color += stride) {
|
||||
vb[color] = ((vb[color] & 0xffffff00) | alpha) >>> 0;
|
||||
}
|
||||
} else if (format.size / format.count === 4) {
|
||||
// RGBA32 color, alpha at position 3
|
||||
for (let alpha = offset + 3; alpha < vb.length; alpha += stride) {
|
||||
vb[alpha] = opacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
offset += format.size >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
UI.prototype.flushRendererCache = function(){
|
||||
const rendererCache = this.rendererCache;
|
||||
if(rendererCache.length > 0){
|
||||
if(this.rendererOrder){
|
||||
rendererCache.sort((a, b)=>{ return a.renderPriority - b.renderPriority; });
|
||||
}
|
||||
// console.log(`flushRendererCache ${rendererCache.length}`);
|
||||
for(let render of rendererCache){
|
||||
// console.log(`${render.node.name} render hash ${render.renderPriority}`);
|
||||
render.fillBuffers(this);
|
||||
if(render.renderOpacity >= 0){
|
||||
updateOpacity(render.renderData, render.renderOpacity);
|
||||
const buffer = render.renderData.getMeshBuffer();
|
||||
if (buffer) {
|
||||
buffer.setDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
rendererCache.length = 0;
|
||||
}
|
||||
this.rendererOrder = false;
|
||||
}
|
||||
|
||||
UI.prototype.update = function() {
|
||||
if (JSB) {
|
||||
return;
|
||||
}
|
||||
this.rendererCache = this.rendererCache ?? [];
|
||||
this.rendererOrder = false;
|
||||
const screens = this._screens;
|
||||
let offset = 0;
|
||||
for (let i = 0; i < screens.length; ++i) {
|
||||
const screen = screens[i];
|
||||
const scene = screen._getRenderScene();
|
||||
if (!screen.enabledInHierarchy || !scene) {
|
||||
continue;
|
||||
}
|
||||
// Reset state and walk
|
||||
this._opacityDirty = 0;
|
||||
this._pOpacity = 1;
|
||||
|
||||
this.walk(screen.node);
|
||||
this.flushRendererCache();
|
||||
|
||||
this.autoMergeBatches(this._currComponent!);
|
||||
this.resetRenderStates();
|
||||
|
||||
let batchPriority = 0;
|
||||
if (this._batches.length > offset) {
|
||||
for (; offset < this._batches.length; ++offset) {
|
||||
const batch = this._batches.array[offset];
|
||||
|
||||
if (batch.model) {
|
||||
const subModels = batch.model.subModels;
|
||||
for (let j = 0; j < subModels.length; j++) {
|
||||
subModels[j].priority = batchPriority++;
|
||||
}
|
||||
} else {
|
||||
batch.descriptorSet = this._descriptorSetCache.getDescriptorSet(batch);
|
||||
}
|
||||
scene.addBatch(batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UI.prototype.walk = function(node: Node, level = 0, sortingPriority = 0){
|
||||
if (!node.activeInHierarchy) {
|
||||
return;
|
||||
}
|
||||
const children = node.children;
|
||||
const uiProps = node._uiProps;
|
||||
const render = uiProps.uiComp as UIRenderer;
|
||||
const stencilEnterLevel = render && (render.stencilStage === _cocos_2d_renderer_stencil_manager__Stage.ENTER_LEVEL || render.stencilStage === _cocos_2d_renderer_stencil_manager__Stage.ENTER_LEVEL_INVERTED);
|
||||
const transform = uiProps.uiTransformComp;
|
||||
sortingPriority = (transform && transform._sortingEnabled) ? transform._sortingPriority : sortingPriority;
|
||||
|
||||
// Save opacity
|
||||
const parentOpacity = this._pOpacity;
|
||||
let opacity = parentOpacity;
|
||||
// TODO Always cascade ui property's local opacity before remove it
|
||||
const selfOpacity = render && render.color ? render.color.a / 255 : 1;
|
||||
this._pOpacity = opacity *= selfOpacity * uiProps.localOpacity;
|
||||
// TODO Set opacity to ui property's opacity before remove it
|
||||
// @ts-expect-error temporary force set, will be removed with ui property's opacity
|
||||
uiProps._opacity = opacity;
|
||||
if (uiProps.colorDirty) {
|
||||
// Cascade color dirty state
|
||||
this._opacityDirty++;
|
||||
}
|
||||
|
||||
// Render assembler update logic
|
||||
if (render && render.enabledInHierarchy) {
|
||||
if(stencilEnterLevel){
|
||||
this.flushRendererCache();
|
||||
|
||||
render.fillBuffers(this);// for rendering
|
||||
|
||||
// Update cascaded opacity to vertex buffer
|
||||
if (this._opacityDirty && render && !render.useVertexOpacity && render.renderData && render.renderData.vertexCount > 0) {
|
||||
// HARD COUPLING
|
||||
updateOpacity(render.renderData, opacity);
|
||||
const buffer = render.renderData.getMeshBuffer();
|
||||
if (buffer) {
|
||||
buffer.setDirty();
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.rendererCache.push(render);
|
||||
render.renderPriority = sortingPriority;
|
||||
if(sortingPriority != 0){
|
||||
this.rendererOrder = true;
|
||||
}
|
||||
if (this._opacityDirty && render && !render.useVertexOpacity && render.renderData && render.renderData.vertexCount > 0) {
|
||||
render.renderOpacity = opacity;
|
||||
}else{
|
||||
render.renderOpacity = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (children.length > 0 && !node._static) {
|
||||
for (let i = 0; i < children.length; ++i) {
|
||||
const child = children[i];
|
||||
this.walk(child, level, sortingPriority);
|
||||
}
|
||||
}
|
||||
|
||||
if (uiProps.colorDirty) {
|
||||
// Reduce cascaded color dirty state
|
||||
this._opacityDirty--;
|
||||
// Reset color dirty
|
||||
uiProps.colorDirty = false;
|
||||
}
|
||||
// Restore opacity
|
||||
this._pOpacity = parentOpacity;
|
||||
// Post render assembler update logic
|
||||
// ATTENTION: Will also reset colorDirty inside postUpdateAssembler
|
||||
if (render && render.enabledInHierarchy) {
|
||||
render.postUpdateAssembler(this);
|
||||
if (stencilEnterLevel
|
||||
&& (StencilManager.sharedManager!.getMaskStackSize() > 0)) {
|
||||
|
||||
this.flushRendererCache();
|
||||
|
||||
this.autoMergeBatches(this._currComponent!);
|
||||
this.resetRenderStates();
|
||||
StencilManager.sharedManager!.exitMask();
|
||||
}
|
||||
}
|
||||
|
||||
level += 1;
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "3892765a-558a-4ad4-a128-11b51b68d962",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
23
3.6.3/assets/lcc-ui-sorting-group/sorting-define.ts
Normal file
23
3.6.3/assets/lcc-ui-sorting-group/sorting-define.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
/**
|
||||
* 排序层级
|
||||
*/
|
||||
export enum SortingLayer {
|
||||
|
||||
//-- 自定义,在此之上,小于 DEFAULT 的层级
|
||||
|
||||
/**
|
||||
* 默认层级,在没有应用排序的UI渲染上的默认层级 *不要修改此枚举*
|
||||
*/
|
||||
DEFAULT = 0,
|
||||
|
||||
//-- 自定义,在此之下,大于 DEFAULT 的层级
|
||||
|
||||
// 测试定义,可以直接移除
|
||||
TEST_LIST_ITEM = 1,
|
||||
}
|
||||
|
||||
/**
|
||||
* 在层级中最大排序值
|
||||
*/
|
||||
export const ORDER_IN_LAYER_MAX = 100000;
|
||||
9
3.6.3/assets/lcc-ui-sorting-group/sorting-define.ts.meta
Normal file
9
3.6.3/assets/lcc-ui-sorting-group/sorting-define.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "ac000892-443c-41be-8b49-35e002bb1213",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
62
3.6.3/assets/lcc-ui-sorting-group/sorting-group.ts
Normal file
62
3.6.3/assets/lcc-ui-sorting-group/sorting-group.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
import { _decorator, Component, Node, ccenum, CCInteger, CCFloat, Enum, director, UI, UIRenderer, UITransform } from 'cc';
|
||||
import { ORDER_IN_LAYER_MAX, SortingLayer } from './sorting-define';
|
||||
const { ccclass, property, type, disallowMultiple, requireComponent, executeInEditMode } = _decorator;
|
||||
|
||||
@ccclass('lcc-ui/SortingGroup')
|
||||
@requireComponent(UITransform)
|
||||
@disallowMultiple(true)
|
||||
@executeInEditMode(true)
|
||||
export class SortingGroup extends Component {
|
||||
/**
|
||||
* 排序层
|
||||
*/
|
||||
@type(Enum(SortingLayer))
|
||||
private _sortingLayer:SortingLayer = SortingLayer.DEFAULT;
|
||||
|
||||
/**
|
||||
* 排序层
|
||||
*/
|
||||
@type(Enum(SortingLayer))
|
||||
get sortingLayer(){
|
||||
return this._sortingLayer;
|
||||
}
|
||||
set sortingLayer(value:SortingLayer){
|
||||
this._sortingLayer = value;
|
||||
this._uiTransform.sortingPriority = Math.sign(this._sortingLayer) * (Math.abs(this._sortingLayer) * ORDER_IN_LAYER_MAX + this._orderInLayer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
@property({ type:CCFloat, min: 0, max : ORDER_IN_LAYER_MAX })
|
||||
private _orderInLayer:number = 0;
|
||||
|
||||
/**
|
||||
* 排序值
|
||||
*/
|
||||
@property({ type:CCFloat, min: 0, max : ORDER_IN_LAYER_MAX })
|
||||
get orderInLayer(){
|
||||
return this._orderInLayer;
|
||||
}
|
||||
set orderInLayer(value:number){
|
||||
this._orderInLayer = value;
|
||||
this._uiTransform.sortingPriority = Math.sign(this._sortingLayer) * (Math.abs(this._sortingLayer) * ORDER_IN_LAYER_MAX + this._orderInLayer);
|
||||
}
|
||||
|
||||
private _uiTransform:UITransform = null;
|
||||
|
||||
onLoad(){
|
||||
this._uiTransform = this.getComponent(UITransform);
|
||||
}
|
||||
|
||||
onEnable(){
|
||||
this._uiTransform.sortingPriority = Math.sign(this._sortingLayer) * (Math.abs(this._sortingLayer) * ORDER_IN_LAYER_MAX + this._orderInLayer);
|
||||
this._uiTransform.sortingEnabled = true;
|
||||
}
|
||||
|
||||
onDisable(){
|
||||
this._uiTransform.sortingPriority = 0;
|
||||
this._uiTransform.sortingEnabled = false;
|
||||
}
|
||||
}
|
||||
9
3.6.3/assets/lcc-ui-sorting-group/sorting-group.ts.meta
Normal file
9
3.6.3/assets/lcc-ui-sorting-group/sorting-group.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "5c8c905a-57e5-40d5-9de9-2be66c8b709b",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user