第一次

This commit is contained in:
lujun
2023-02-05 20:31:26 +08:00
commit fe21ffdc65
66 changed files with 8178 additions and 0 deletions

View File

@@ -0,0 +1,228 @@
import { clamp, gfx,Node,RenderData,UI,StencilManager,UIRenderer } from 'cc';
import { JSB } from 'cc/env';
declare module 'cc' {
interface UIRenderer {
/**
* 排序优先级
*/
sortingPriority:number;
/**
* 排序透明度
*/
sortingOpacity:number;
}
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;
}
}
const UI_initialize = UI.prototype.initialize;
UI.prototype.initialize = function(){
this.rendererCache = [];
this.rendererOrder = false;
return UI_initialize.call(this);
}
UI.prototype.flushRendererCache = function(){
const rendererCache = this.rendererCache;
if(rendererCache.length > 0){
if(this.rendererOrder){
rendererCache.sort((a, b)=>{ return a.sortingPriority - b.sortingPriority; });
}
for(let render of rendererCache){
render.fillBuffers(this);
if(render.sortingOpacity >= 0){
updateOpacity(render.renderData, render.sortingOpacity);
const buffer = render.renderData.getMeshBuffer();
if (buffer) {
buffer.setDirty();
}
}
}
rendererCache.length = 0;
}
this.rendererOrder = false;
}
UI.prototype.update = function() {
if (JSB) {
return;
}
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){
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);
// 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.sortingPriority = render.sortingPriority ?? 0;
if(render.sortingPriority != 0){
this.rendererOrder = true;
}
if (this._opacityDirty && render && !render.useVertexOpacity && render.renderData && render.renderData.vertexCount > 0) {
render.sortingOpacity = opacity;
}else{
render.sortingOpacity = -1;
}
}
}
if (children.length > 0 && !node._static) {
for (let i = 0; i < children.length; ++i) {
const child = children[i];
this.walk(child, level);
}
}
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;
};

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "eebde562-6799-4fbd-9138-5f4755bdd7d7",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,23 @@
/**
* 排序层级
*/
export enum SortingLayer {
//-- 自定义,在此之上,小于 DEFAULT 的层级
/**
* 默认层级在没有应用排序的UI渲染上的默认层级
*/
DEFAULT = 0,
//-- 自定义,在此之下,大于 DEFAULT 的层级
// 测试定义,可以直接移除
TEST_LIST_ITEM = 1,
}
/**
* 在层级中最大排序值
*/
export const ORDER_IN_LAYER_MAX = 100000;

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "ac000892-443c-41be-8b49-35e002bb1213",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,38 @@
import { _decorator, Component, Node, ccenum, CCInteger, CCFloat, Enum, director, UI, UIRenderer } from 'cc';
import { ORDER_IN_LAYER_MAX, SortingLayer } from './sorting-define';
const { ccclass, property, type, disallowMultiple, requireComponent } = _decorator;
@ccclass('lcc-ui/SortingGroup')
@requireComponent(UIRenderer)
@disallowMultiple
export class SortingGroup extends Component {
/**
* 排序层
*/
@type(Enum(SortingLayer))
sortingLayer:SortingLayer = SortingLayer.DEFAULT;
/**
* 排序值
*/
@property({ type:CCFloat, min: 0, max : ORDER_IN_LAYER_MAX })
orderInLayer:number = 0;
/**
* UI渲染器
*/
private _uiRenderer:UIRenderer = null;
onLoad(){
this._uiRenderer = this.getComponent(UIRenderer);
}
onEnable(){
this._uiRenderer.sortingPriority = Math.sign(this.sortingLayer) * (Math.abs(this.sortingLayer) * ORDER_IN_LAYER_MAX + this.orderInLayer);
}
onDisable(){
this._uiRenderer.sortingPriority = SortingLayer.DEFAULT * ORDER_IN_LAYER_MAX;
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "5c8c905a-57e5-40d5-9de9-2be66c8b709b",
"files": [],
"subMetas": {},
"userData": {}
}