mirror of
https://gitee.com/ccc_28/level-render
synced 2025-11-15 10:38:09 +00:00
更新README,添加2025-10-27更新日志;优化层级渲染算法,支持多级分层渲染,修复虚拟列表相关bug;修改LevelRender组件以启用层级渲染;
This commit is contained in:
@@ -25,122 +25,149 @@ export default class CCCExtension {
|
||||
}
|
||||
|
||||
private static _extendRender3_x() {
|
||||
const batch2d = cclegacy[`internal`][`Batcher2D`];
|
||||
let __renderQueue: Node[][] = [];
|
||||
const Batcher2D = this.getBatcher2D();
|
||||
const batchQueue: Node[][] = [];
|
||||
|
||||
const levelSplit = (node: Node, lv: number, itemIndex) => {
|
||||
if (!__renderQueue[lv]) {
|
||||
__renderQueue[lv] = [];
|
||||
}
|
||||
__renderQueue[lv].push(node);
|
||||
lv++;
|
||||
node["__renderLv"] = lv;
|
||||
node["__levelRender"] = true;
|
||||
node["__itemIndex"] = itemIndex;
|
||||
const cs = node.children;
|
||||
for (let i = 0; i < cs.length; ++i) {
|
||||
const c = cs[i];
|
||||
if (!__renderQueue[lv]) {
|
||||
__renderQueue[lv] = [];
|
||||
}
|
||||
lv = levelSplit(c, lv, itemIndex);
|
||||
}
|
||||
return lv;
|
||||
const processNode = (batcher2D, node: Node) => {
|
||||
node["__levelRenderFlag"] = true;
|
||||
batcher2D.walk(node, 0);
|
||||
node["__levelRenderFlag"] = false;
|
||||
}
|
||||
Object.defineProperty(batch2d.prototype, "walk", {
|
||||
value: function (node: Node, level = 0) {
|
||||
if (!node[`activeInHierarchy`]) {
|
||||
return;
|
||||
}
|
||||
const children = node.children;
|
||||
const uiProps = node._uiProps;
|
||||
const render = uiProps.uiComp as UIRenderer;
|
||||
// Save opacity
|
||||
let parentOpacity = this._pOpacity === undefined ? 1 : this._pOpacity;
|
||||
if (node.parent) {
|
||||
parentOpacity = node.parent._uiProps.opacity;
|
||||
}
|
||||
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 = opacity * selfOpacity * uiProps.localOpacity;
|
||||
|
||||
// TODO Set opacity to ui property's opacity before remove it
|
||||
|
||||
if (uiProps[`setOpacity`]) {
|
||||
uiProps[`setOpacity`](opacity);
|
||||
}
|
||||
uiProps[`_opacity`] = opacity;
|
||||
if (!approx(opacity, 0, EPSILON)) {
|
||||
if (uiProps.colorDirty) {
|
||||
// Cascade color dirty state
|
||||
this._opacityDirty++;
|
||||
}
|
||||
|
||||
// Render assembler update logic
|
||||
if (render && render.enabledInHierarchy) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
if (children.length > 0 && !node._static) {
|
||||
if (!node[`__levelRender`]) {
|
||||
__renderQueue = [];
|
||||
for (let i = 0; i < children.length; ++i) {
|
||||
const child = children[i];
|
||||
if (node.parent)
|
||||
child._uiProps.colorDirty = child._uiProps.colorDirty || node.parent._uiProps.colorDirty;
|
||||
const enableLevelRender = node[`__enableLevelRender`];
|
||||
if (!enableLevelRender) {
|
||||
this.walk(child, level);
|
||||
} else {
|
||||
levelSplit(child, 0, i);
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < __renderQueue.length; ++i) {
|
||||
const list = __renderQueue[i];
|
||||
for (let j = 0; j < list.length; ++j) {
|
||||
const n = list[j];
|
||||
this.walk(n, level);
|
||||
}
|
||||
}
|
||||
__renderQueue = [];
|
||||
}
|
||||
}
|
||||
|
||||
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 ((render.stencilStage as any === Stage.ENTER_LEVEL || render.stencilStage as any === Stage.ENTER_LEVEL_INVERTED)
|
||||
&& (StencilManager.sharedManager!.getMaskStackSize() > 0)) {
|
||||
this.autoMergeBatches(this._currComponent!);
|
||||
this.resetRenderStates();
|
||||
StencilManager.sharedManager!.exitMask();
|
||||
}
|
||||
}
|
||||
level += 1;
|
||||
//入队
|
||||
const enqueue = (node: Node, layer = 0) => {
|
||||
if (!batchQueue[layer]) {
|
||||
batchQueue[layer] = [];
|
||||
}
|
||||
});
|
||||
|
||||
if (node["__levelRender"]) {
|
||||
node["__levelLayer"] = layer;
|
||||
} else {
|
||||
if (node.parent && node.parent["__levelLayer"]) {
|
||||
layer = node.parent["__levelLayer"] + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (node.activeInHierarchy) {
|
||||
const queue = batchQueue[layer];
|
||||
queue.push(node);
|
||||
}
|
||||
|
||||
|
||||
layer++;
|
||||
for (let i = 0; i < node.children.length; ++i) {
|
||||
const child = node.children[i];
|
||||
layer = enqueue(child, layer);
|
||||
}
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
//出队
|
||||
const dequeue = (batcher2D) => batchQueue.forEach(queue => queue.forEach(n => processNode(batcher2D, n)));
|
||||
|
||||
// 层级渲染
|
||||
const levelRender = (batcher2D, node: Node, layer = 0) => {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
processNode(batcher2D, node);
|
||||
node.children.forEach(children => {
|
||||
enqueue(children, layer)
|
||||
})
|
||||
|
||||
dequeue(batcher2D);
|
||||
batchQueue.forEach(q => q.length = 0);
|
||||
}
|
||||
|
||||
Batcher2D.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;
|
||||
|
||||
// Save opacity
|
||||
let parentOpacity = this._pOpacity;
|
||||
if (node.parent) {
|
||||
parentOpacity = node.parent._uiProps.opacity;
|
||||
}
|
||||
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
|
||||
if (uiProps[`setOpacity`]) {
|
||||
uiProps[`setOpacity`](opacity);
|
||||
}
|
||||
uiProps[`_opacity`] = opacity;
|
||||
if (!approx(opacity, 0, EPSILON)) {
|
||||
if (uiProps.colorDirty) {
|
||||
// Cascade color dirty state
|
||||
this._opacityDirty++;
|
||||
}
|
||||
|
||||
// Render assembler update logic
|
||||
if (render && render.enabledInHierarchy) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
const isLevelRender = node["__levelRender"] || node["__levelRenderFlag"];
|
||||
if (!isLevelRender) {
|
||||
if (children.length > 0 && !node._static) {
|
||||
for (let i = 0; i < children.length; ++i) {
|
||||
const child = children[i];
|
||||
this.walk(child, level);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!node["__levelRenderFlag"]) {
|
||||
levelRender(this, node, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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 ((render.stencilStage as any === Stage.ENTER_LEVEL || render.stencilStage as any === Stage.ENTER_LEVEL_INVERTED)
|
||||
&& (StencilManager.sharedManager!.getMaskStackSize() > 0)) {
|
||||
this.autoMergeBatches(this._currComponent!);
|
||||
this.resetRenderStates();
|
||||
StencilManager.sharedManager!.exitMask();
|
||||
}
|
||||
}
|
||||
|
||||
level += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static getBatcher2D() {
|
||||
return cclegacy["internal"]["Batcher2D"];
|
||||
}
|
||||
|
||||
private static _extendEditBoxTemp() {
|
||||
|
||||
Reference in New Issue
Block a user